##// END OF EJS Templates
log: fix crash on empty revision with --copies switch...
Yuya Nishihara -
r37794:141017c7 default
parent child Browse files
Show More
@@ -1,5672 +1,5672 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 )
22 )
23 from . import (
23 from . import (
24 archival,
24 archival,
25 bookmarks,
25 bookmarks,
26 bundle2,
26 bundle2,
27 changegroup,
27 changegroup,
28 cmdutil,
28 cmdutil,
29 copies,
29 copies,
30 debugcommands as debugcommandsmod,
30 debugcommands as debugcommandsmod,
31 destutil,
31 destutil,
32 dirstateguard,
32 dirstateguard,
33 discovery,
33 discovery,
34 encoding,
34 encoding,
35 error,
35 error,
36 exchange,
36 exchange,
37 extensions,
37 extensions,
38 formatter,
38 formatter,
39 graphmod,
39 graphmod,
40 hbisect,
40 hbisect,
41 help,
41 help,
42 hg,
42 hg,
43 lock as lockmod,
43 lock as lockmod,
44 logcmdutil,
44 logcmdutil,
45 merge as mergemod,
45 merge as mergemod,
46 obsolete,
46 obsolete,
47 obsutil,
47 obsutil,
48 patch,
48 patch,
49 phases,
49 phases,
50 pycompat,
50 pycompat,
51 rcutil,
51 rcutil,
52 registrar,
52 registrar,
53 revsetlang,
53 revsetlang,
54 rewriteutil,
54 rewriteutil,
55 scmutil,
55 scmutil,
56 server,
56 server,
57 streamclone,
57 streamclone,
58 tags as tagsmod,
58 tags as tagsmod,
59 templatekw,
59 templatekw,
60 ui as uimod,
60 ui as uimod,
61 util,
61 util,
62 wireprotoserver,
62 wireprotoserver,
63 )
63 )
64 from .utils import (
64 from .utils import (
65 dateutil,
65 dateutil,
66 procutil,
66 procutil,
67 stringutil,
67 stringutil,
68 )
68 )
69
69
70 release = lockmod.release
70 release = lockmod.release
71
71
72 table = {}
72 table = {}
73 table.update(debugcommandsmod.command._table)
73 table.update(debugcommandsmod.command._table)
74
74
75 command = registrar.command(table)
75 command = registrar.command(table)
76 INTENT_READONLY = registrar.INTENT_READONLY
76 INTENT_READONLY = registrar.INTENT_READONLY
77
77
78 # common command options
78 # common command options
79
79
80 globalopts = [
80 globalopts = [
81 ('R', 'repository', '',
81 ('R', 'repository', '',
82 _('repository root directory or name of overlay bundle file'),
82 _('repository root directory or name of overlay bundle file'),
83 _('REPO')),
83 _('REPO')),
84 ('', 'cwd', '',
84 ('', 'cwd', '',
85 _('change working directory'), _('DIR')),
85 _('change working directory'), _('DIR')),
86 ('y', 'noninteractive', None,
86 ('y', 'noninteractive', None,
87 _('do not prompt, automatically pick the first choice for all prompts')),
87 _('do not prompt, automatically pick the first choice for all prompts')),
88 ('q', 'quiet', None, _('suppress output')),
88 ('q', 'quiet', None, _('suppress output')),
89 ('v', 'verbose', None, _('enable additional output')),
89 ('v', 'verbose', None, _('enable additional output')),
90 ('', 'color', '',
90 ('', 'color', '',
91 # i18n: 'always', 'auto', 'never', and 'debug' are keywords
91 # i18n: 'always', 'auto', 'never', and 'debug' are keywords
92 # and should not be translated
92 # and should not be translated
93 _("when to colorize (boolean, always, auto, never, or debug)"),
93 _("when to colorize (boolean, always, auto, never, or debug)"),
94 _('TYPE')),
94 _('TYPE')),
95 ('', 'config', [],
95 ('', 'config', [],
96 _('set/override config option (use \'section.name=value\')'),
96 _('set/override config option (use \'section.name=value\')'),
97 _('CONFIG')),
97 _('CONFIG')),
98 ('', 'debug', None, _('enable debugging output')),
98 ('', 'debug', None, _('enable debugging output')),
99 ('', 'debugger', None, _('start debugger')),
99 ('', 'debugger', None, _('start debugger')),
100 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
100 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
101 _('ENCODE')),
101 _('ENCODE')),
102 ('', 'encodingmode', encoding.encodingmode,
102 ('', 'encodingmode', encoding.encodingmode,
103 _('set the charset encoding mode'), _('MODE')),
103 _('set the charset encoding mode'), _('MODE')),
104 ('', 'traceback', None, _('always print a traceback on exception')),
104 ('', 'traceback', None, _('always print a traceback on exception')),
105 ('', 'time', None, _('time how long the command takes')),
105 ('', 'time', None, _('time how long the command takes')),
106 ('', 'profile', None, _('print command execution profile')),
106 ('', 'profile', None, _('print command execution profile')),
107 ('', 'version', None, _('output version information and exit')),
107 ('', 'version', None, _('output version information and exit')),
108 ('h', 'help', None, _('display help and exit')),
108 ('h', 'help', None, _('display help and exit')),
109 ('', 'hidden', False, _('consider hidden changesets')),
109 ('', 'hidden', False, _('consider hidden changesets')),
110 ('', 'pager', 'auto',
110 ('', 'pager', 'auto',
111 _("when to paginate (boolean, always, auto, or never)"), _('TYPE')),
111 _("when to paginate (boolean, always, auto, or never)"), _('TYPE')),
112 ]
112 ]
113
113
114 dryrunopts = cmdutil.dryrunopts
114 dryrunopts = cmdutil.dryrunopts
115 confirmopts = cmdutil.confirmopts
115 confirmopts = cmdutil.confirmopts
116 remoteopts = cmdutil.remoteopts
116 remoteopts = cmdutil.remoteopts
117 walkopts = cmdutil.walkopts
117 walkopts = cmdutil.walkopts
118 commitopts = cmdutil.commitopts
118 commitopts = cmdutil.commitopts
119 commitopts2 = cmdutil.commitopts2
119 commitopts2 = cmdutil.commitopts2
120 formatteropts = cmdutil.formatteropts
120 formatteropts = cmdutil.formatteropts
121 templateopts = cmdutil.templateopts
121 templateopts = cmdutil.templateopts
122 logopts = cmdutil.logopts
122 logopts = cmdutil.logopts
123 diffopts = cmdutil.diffopts
123 diffopts = cmdutil.diffopts
124 diffwsopts = cmdutil.diffwsopts
124 diffwsopts = cmdutil.diffwsopts
125 diffopts2 = cmdutil.diffopts2
125 diffopts2 = cmdutil.diffopts2
126 mergetoolopts = cmdutil.mergetoolopts
126 mergetoolopts = cmdutil.mergetoolopts
127 similarityopts = cmdutil.similarityopts
127 similarityopts = cmdutil.similarityopts
128 subrepoopts = cmdutil.subrepoopts
128 subrepoopts = cmdutil.subrepoopts
129 debugrevlogopts = cmdutil.debugrevlogopts
129 debugrevlogopts = cmdutil.debugrevlogopts
130
130
131 # Commands start here, listed alphabetically
131 # Commands start here, listed alphabetically
132
132
133 @command('^add',
133 @command('^add',
134 walkopts + subrepoopts + dryrunopts,
134 walkopts + subrepoopts + dryrunopts,
135 _('[OPTION]... [FILE]...'),
135 _('[OPTION]... [FILE]...'),
136 inferrepo=True)
136 inferrepo=True)
137 def add(ui, repo, *pats, **opts):
137 def add(ui, repo, *pats, **opts):
138 """add the specified files on the next commit
138 """add the specified files on the next commit
139
139
140 Schedule files to be version controlled and added to the
140 Schedule files to be version controlled and added to the
141 repository.
141 repository.
142
142
143 The files will be added to the repository at the next commit. To
143 The files will be added to the repository at the next commit. To
144 undo an add before that, see :hg:`forget`.
144 undo an add before that, see :hg:`forget`.
145
145
146 If no names are given, add all files to the repository (except
146 If no names are given, add all files to the repository (except
147 files matching ``.hgignore``).
147 files matching ``.hgignore``).
148
148
149 .. container:: verbose
149 .. container:: verbose
150
150
151 Examples:
151 Examples:
152
152
153 - New (unknown) files are added
153 - New (unknown) files are added
154 automatically by :hg:`add`::
154 automatically by :hg:`add`::
155
155
156 $ ls
156 $ ls
157 foo.c
157 foo.c
158 $ hg status
158 $ hg status
159 ? foo.c
159 ? foo.c
160 $ hg add
160 $ hg add
161 adding foo.c
161 adding foo.c
162 $ hg status
162 $ hg status
163 A foo.c
163 A foo.c
164
164
165 - Specific files to be added can be specified::
165 - Specific files to be added can be specified::
166
166
167 $ ls
167 $ ls
168 bar.c foo.c
168 bar.c foo.c
169 $ hg status
169 $ hg status
170 ? bar.c
170 ? bar.c
171 ? foo.c
171 ? foo.c
172 $ hg add bar.c
172 $ hg add bar.c
173 $ hg status
173 $ hg status
174 A bar.c
174 A bar.c
175 ? foo.c
175 ? foo.c
176
176
177 Returns 0 if all files are successfully added.
177 Returns 0 if all files are successfully added.
178 """
178 """
179
179
180 m = scmutil.match(repo[None], pats, pycompat.byteskwargs(opts))
180 m = scmutil.match(repo[None], pats, pycompat.byteskwargs(opts))
181 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
181 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
182 return rejected and 1 or 0
182 return rejected and 1 or 0
183
183
184 @command('addremove',
184 @command('addremove',
185 similarityopts + subrepoopts + walkopts + dryrunopts,
185 similarityopts + subrepoopts + walkopts + dryrunopts,
186 _('[OPTION]... [FILE]...'),
186 _('[OPTION]... [FILE]...'),
187 inferrepo=True)
187 inferrepo=True)
188 def addremove(ui, repo, *pats, **opts):
188 def addremove(ui, repo, *pats, **opts):
189 """add all new files, delete all missing files
189 """add all new files, delete all missing files
190
190
191 Add all new files and remove all missing files from the
191 Add all new files and remove all missing files from the
192 repository.
192 repository.
193
193
194 Unless names are given, new files are ignored if they match any of
194 Unless names are given, new files are ignored if they match any of
195 the patterns in ``.hgignore``. As with add, these changes take
195 the patterns in ``.hgignore``. As with add, these changes take
196 effect at the next commit.
196 effect at the next commit.
197
197
198 Use the -s/--similarity option to detect renamed files. This
198 Use the -s/--similarity option to detect renamed files. This
199 option takes a percentage between 0 (disabled) and 100 (files must
199 option takes a percentage between 0 (disabled) and 100 (files must
200 be identical) as its parameter. With a parameter greater than 0,
200 be identical) as its parameter. With a parameter greater than 0,
201 this compares every removed file with every added file and records
201 this compares every removed file with every added file and records
202 those similar enough as renames. Detecting renamed files this way
202 those similar enough as renames. Detecting renamed files this way
203 can be expensive. After using this option, :hg:`status -C` can be
203 can be expensive. After using this option, :hg:`status -C` can be
204 used to check which files were identified as moved or renamed. If
204 used to check which files were identified as moved or renamed. If
205 not specified, -s/--similarity defaults to 100 and only renames of
205 not specified, -s/--similarity defaults to 100 and only renames of
206 identical files are detected.
206 identical files are detected.
207
207
208 .. container:: verbose
208 .. container:: verbose
209
209
210 Examples:
210 Examples:
211
211
212 - A number of files (bar.c and foo.c) are new,
212 - A number of files (bar.c and foo.c) are new,
213 while foobar.c has been removed (without using :hg:`remove`)
213 while foobar.c has been removed (without using :hg:`remove`)
214 from the repository::
214 from the repository::
215
215
216 $ ls
216 $ ls
217 bar.c foo.c
217 bar.c foo.c
218 $ hg status
218 $ hg status
219 ! foobar.c
219 ! foobar.c
220 ? bar.c
220 ? bar.c
221 ? foo.c
221 ? foo.c
222 $ hg addremove
222 $ hg addremove
223 adding bar.c
223 adding bar.c
224 adding foo.c
224 adding foo.c
225 removing foobar.c
225 removing foobar.c
226 $ hg status
226 $ hg status
227 A bar.c
227 A bar.c
228 A foo.c
228 A foo.c
229 R foobar.c
229 R foobar.c
230
230
231 - A file foobar.c was moved to foo.c without using :hg:`rename`.
231 - A file foobar.c was moved to foo.c without using :hg:`rename`.
232 Afterwards, it was edited slightly::
232 Afterwards, it was edited slightly::
233
233
234 $ ls
234 $ ls
235 foo.c
235 foo.c
236 $ hg status
236 $ hg status
237 ! foobar.c
237 ! foobar.c
238 ? foo.c
238 ? foo.c
239 $ hg addremove --similarity 90
239 $ hg addremove --similarity 90
240 removing foobar.c
240 removing foobar.c
241 adding foo.c
241 adding foo.c
242 recording removal of foobar.c as rename to foo.c (94% similar)
242 recording removal of foobar.c as rename to foo.c (94% similar)
243 $ hg status -C
243 $ hg status -C
244 A foo.c
244 A foo.c
245 foobar.c
245 foobar.c
246 R foobar.c
246 R foobar.c
247
247
248 Returns 0 if all files are successfully added.
248 Returns 0 if all files are successfully added.
249 """
249 """
250 opts = pycompat.byteskwargs(opts)
250 opts = pycompat.byteskwargs(opts)
251 if not opts.get('similarity'):
251 if not opts.get('similarity'):
252 opts['similarity'] = '100'
252 opts['similarity'] = '100'
253 matcher = scmutil.match(repo[None], pats, opts)
253 matcher = scmutil.match(repo[None], pats, opts)
254 return scmutil.addremove(repo, matcher, "", opts)
254 return scmutil.addremove(repo, matcher, "", opts)
255
255
256 @command('^annotate|blame',
256 @command('^annotate|blame',
257 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
257 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
258 ('', 'follow', None,
258 ('', 'follow', None,
259 _('follow copies/renames and list the filename (DEPRECATED)')),
259 _('follow copies/renames and list the filename (DEPRECATED)')),
260 ('', 'no-follow', None, _("don't follow copies and renames")),
260 ('', 'no-follow', None, _("don't follow copies and renames")),
261 ('a', 'text', None, _('treat all files as text')),
261 ('a', 'text', None, _('treat all files as text')),
262 ('u', 'user', None, _('list the author (long with -v)')),
262 ('u', 'user', None, _('list the author (long with -v)')),
263 ('f', 'file', None, _('list the filename')),
263 ('f', 'file', None, _('list the filename')),
264 ('d', 'date', None, _('list the date (short with -q)')),
264 ('d', 'date', None, _('list the date (short with -q)')),
265 ('n', 'number', None, _('list the revision number (default)')),
265 ('n', 'number', None, _('list the revision number (default)')),
266 ('c', 'changeset', None, _('list the changeset')),
266 ('c', 'changeset', None, _('list the changeset')),
267 ('l', 'line-number', None, _('show line number at the first appearance')),
267 ('l', 'line-number', None, _('show line number at the first appearance')),
268 ('', 'skip', [], _('revision to not display (EXPERIMENTAL)'), _('REV')),
268 ('', 'skip', [], _('revision to not display (EXPERIMENTAL)'), _('REV')),
269 ] + diffwsopts + walkopts + formatteropts,
269 ] + diffwsopts + walkopts + formatteropts,
270 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
270 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
271 inferrepo=True)
271 inferrepo=True)
272 def annotate(ui, repo, *pats, **opts):
272 def annotate(ui, repo, *pats, **opts):
273 """show changeset information by line for each file
273 """show changeset information by line for each file
274
274
275 List changes in files, showing the revision id responsible for
275 List changes in files, showing the revision id responsible for
276 each line.
276 each line.
277
277
278 This command is useful for discovering when a change was made and
278 This command is useful for discovering when a change was made and
279 by whom.
279 by whom.
280
280
281 If you include --file, --user, or --date, the revision number is
281 If you include --file, --user, or --date, the revision number is
282 suppressed unless you also include --number.
282 suppressed unless you also include --number.
283
283
284 Without the -a/--text option, annotate will avoid processing files
284 Without the -a/--text option, annotate will avoid processing files
285 it detects as binary. With -a, annotate will annotate the file
285 it detects as binary. With -a, annotate will annotate the file
286 anyway, although the results will probably be neither useful
286 anyway, although the results will probably be neither useful
287 nor desirable.
287 nor desirable.
288
288
289 Returns 0 on success.
289 Returns 0 on success.
290 """
290 """
291 opts = pycompat.byteskwargs(opts)
291 opts = pycompat.byteskwargs(opts)
292 if not pats:
292 if not pats:
293 raise error.Abort(_('at least one filename or pattern is required'))
293 raise error.Abort(_('at least one filename or pattern is required'))
294
294
295 if opts.get('follow'):
295 if opts.get('follow'):
296 # --follow is deprecated and now just an alias for -f/--file
296 # --follow is deprecated and now just an alias for -f/--file
297 # to mimic the behavior of Mercurial before version 1.5
297 # to mimic the behavior of Mercurial before version 1.5
298 opts['file'] = True
298 opts['file'] = True
299
299
300 rev = opts.get('rev')
300 rev = opts.get('rev')
301 if rev:
301 if rev:
302 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
302 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
303 ctx = scmutil.revsingle(repo, rev)
303 ctx = scmutil.revsingle(repo, rev)
304
304
305 rootfm = ui.formatter('annotate', opts)
305 rootfm = ui.formatter('annotate', opts)
306 if ui.quiet:
306 if ui.quiet:
307 datefunc = dateutil.shortdate
307 datefunc = dateutil.shortdate
308 else:
308 else:
309 datefunc = dateutil.datestr
309 datefunc = dateutil.datestr
310 if ctx.rev() is None:
310 if ctx.rev() is None:
311 def hexfn(node):
311 def hexfn(node):
312 if node is None:
312 if node is None:
313 return None
313 return None
314 else:
314 else:
315 return rootfm.hexfunc(node)
315 return rootfm.hexfunc(node)
316 if opts.get('changeset'):
316 if opts.get('changeset'):
317 # omit "+" suffix which is appended to node hex
317 # omit "+" suffix which is appended to node hex
318 def formatrev(rev):
318 def formatrev(rev):
319 if rev is None:
319 if rev is None:
320 return '%d' % ctx.p1().rev()
320 return '%d' % ctx.p1().rev()
321 else:
321 else:
322 return '%d' % rev
322 return '%d' % rev
323 else:
323 else:
324 def formatrev(rev):
324 def formatrev(rev):
325 if rev is None:
325 if rev is None:
326 return '%d+' % ctx.p1().rev()
326 return '%d+' % ctx.p1().rev()
327 else:
327 else:
328 return '%d ' % rev
328 return '%d ' % rev
329 def formathex(hex):
329 def formathex(hex):
330 if hex is None:
330 if hex is None:
331 return '%s+' % rootfm.hexfunc(ctx.p1().node())
331 return '%s+' % rootfm.hexfunc(ctx.p1().node())
332 else:
332 else:
333 return '%s ' % hex
333 return '%s ' % hex
334 else:
334 else:
335 hexfn = rootfm.hexfunc
335 hexfn = rootfm.hexfunc
336 formatrev = formathex = pycompat.bytestr
336 formatrev = formathex = pycompat.bytestr
337
337
338 opmap = [('user', ' ', lambda x: x.fctx.user(), ui.shortuser),
338 opmap = [('user', ' ', lambda x: x.fctx.user(), ui.shortuser),
339 ('number', ' ', lambda x: x.fctx.rev(), formatrev),
339 ('number', ' ', lambda x: x.fctx.rev(), formatrev),
340 ('changeset', ' ', lambda x: hexfn(x.fctx.node()), formathex),
340 ('changeset', ' ', lambda x: hexfn(x.fctx.node()), formathex),
341 ('date', ' ', lambda x: x.fctx.date(), util.cachefunc(datefunc)),
341 ('date', ' ', lambda x: x.fctx.date(), util.cachefunc(datefunc)),
342 ('file', ' ', lambda x: x.fctx.path(), pycompat.bytestr),
342 ('file', ' ', lambda x: x.fctx.path(), pycompat.bytestr),
343 ('line_number', ':', lambda x: x.lineno, pycompat.bytestr),
343 ('line_number', ':', lambda x: x.lineno, pycompat.bytestr),
344 ]
344 ]
345 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
345 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
346
346
347 if (not opts.get('user') and not opts.get('changeset')
347 if (not opts.get('user') and not opts.get('changeset')
348 and not opts.get('date') and not opts.get('file')):
348 and not opts.get('date') and not opts.get('file')):
349 opts['number'] = True
349 opts['number'] = True
350
350
351 linenumber = opts.get('line_number') is not None
351 linenumber = opts.get('line_number') is not None
352 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
352 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
353 raise error.Abort(_('at least one of -n/-c is required for -l'))
353 raise error.Abort(_('at least one of -n/-c is required for -l'))
354
354
355 ui.pager('annotate')
355 ui.pager('annotate')
356
356
357 if rootfm.isplain():
357 if rootfm.isplain():
358 def makefunc(get, fmt):
358 def makefunc(get, fmt):
359 return lambda x: fmt(get(x))
359 return lambda x: fmt(get(x))
360 else:
360 else:
361 def makefunc(get, fmt):
361 def makefunc(get, fmt):
362 return get
362 return get
363 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
363 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
364 if opts.get(op)]
364 if opts.get(op)]
365 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
365 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
366 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
366 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
367 if opts.get(op))
367 if opts.get(op))
368
368
369 def bad(x, y):
369 def bad(x, y):
370 raise error.Abort("%s: %s" % (x, y))
370 raise error.Abort("%s: %s" % (x, y))
371
371
372 m = scmutil.match(ctx, pats, opts, badfn=bad)
372 m = scmutil.match(ctx, pats, opts, badfn=bad)
373
373
374 follow = not opts.get('no_follow')
374 follow = not opts.get('no_follow')
375 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
375 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
376 whitespace=True)
376 whitespace=True)
377 skiprevs = opts.get('skip')
377 skiprevs = opts.get('skip')
378 if skiprevs:
378 if skiprevs:
379 skiprevs = scmutil.revrange(repo, skiprevs)
379 skiprevs = scmutil.revrange(repo, skiprevs)
380
380
381 for abs in ctx.walk(m):
381 for abs in ctx.walk(m):
382 fctx = ctx[abs]
382 fctx = ctx[abs]
383 rootfm.startitem()
383 rootfm.startitem()
384 rootfm.data(abspath=abs, path=m.rel(abs))
384 rootfm.data(abspath=abs, path=m.rel(abs))
385 if not opts.get('text') and fctx.isbinary():
385 if not opts.get('text') and fctx.isbinary():
386 rootfm.plain(_("%s: binary file\n")
386 rootfm.plain(_("%s: binary file\n")
387 % ((pats and m.rel(abs)) or abs))
387 % ((pats and m.rel(abs)) or abs))
388 continue
388 continue
389
389
390 fm = rootfm.nested('lines', tmpl='{rev}: {line}')
390 fm = rootfm.nested('lines', tmpl='{rev}: {line}')
391 lines = fctx.annotate(follow=follow, skiprevs=skiprevs,
391 lines = fctx.annotate(follow=follow, skiprevs=skiprevs,
392 diffopts=diffopts)
392 diffopts=diffopts)
393 if not lines:
393 if not lines:
394 fm.end()
394 fm.end()
395 continue
395 continue
396 formats = []
396 formats = []
397 pieces = []
397 pieces = []
398
398
399 for f, sep in funcmap:
399 for f, sep in funcmap:
400 l = [f(n) for n in lines]
400 l = [f(n) for n in lines]
401 if fm.isplain():
401 if fm.isplain():
402 sizes = [encoding.colwidth(x) for x in l]
402 sizes = [encoding.colwidth(x) for x in l]
403 ml = max(sizes)
403 ml = max(sizes)
404 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
404 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
405 else:
405 else:
406 formats.append(['%s' for x in l])
406 formats.append(['%s' for x in l])
407 pieces.append(l)
407 pieces.append(l)
408
408
409 for f, p, n in zip(zip(*formats), zip(*pieces), lines):
409 for f, p, n in zip(zip(*formats), zip(*pieces), lines):
410 fm.startitem()
410 fm.startitem()
411 fm.context(fctx=n.fctx)
411 fm.context(fctx=n.fctx)
412 fm.write(fields, "".join(f), *p)
412 fm.write(fields, "".join(f), *p)
413 if n.skip:
413 if n.skip:
414 fmt = "* %s"
414 fmt = "* %s"
415 else:
415 else:
416 fmt = ": %s"
416 fmt = ": %s"
417 fm.write('line', fmt, n.text)
417 fm.write('line', fmt, n.text)
418
418
419 if not lines[-1].text.endswith('\n'):
419 if not lines[-1].text.endswith('\n'):
420 fm.plain('\n')
420 fm.plain('\n')
421 fm.end()
421 fm.end()
422
422
423 rootfm.end()
423 rootfm.end()
424
424
425 @command('archive',
425 @command('archive',
426 [('', 'no-decode', None, _('do not pass files through decoders')),
426 [('', 'no-decode', None, _('do not pass files through decoders')),
427 ('p', 'prefix', '', _('directory prefix for files in archive'),
427 ('p', 'prefix', '', _('directory prefix for files in archive'),
428 _('PREFIX')),
428 _('PREFIX')),
429 ('r', 'rev', '', _('revision to distribute'), _('REV')),
429 ('r', 'rev', '', _('revision to distribute'), _('REV')),
430 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
430 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
431 ] + subrepoopts + walkopts,
431 ] + subrepoopts + walkopts,
432 _('[OPTION]... DEST'))
432 _('[OPTION]... DEST'))
433 def archive(ui, repo, dest, **opts):
433 def archive(ui, repo, dest, **opts):
434 '''create an unversioned archive of a repository revision
434 '''create an unversioned archive of a repository revision
435
435
436 By default, the revision used is the parent of the working
436 By default, the revision used is the parent of the working
437 directory; use -r/--rev to specify a different revision.
437 directory; use -r/--rev to specify a different revision.
438
438
439 The archive type is automatically detected based on file
439 The archive type is automatically detected based on file
440 extension (to override, use -t/--type).
440 extension (to override, use -t/--type).
441
441
442 .. container:: verbose
442 .. container:: verbose
443
443
444 Examples:
444 Examples:
445
445
446 - create a zip file containing the 1.0 release::
446 - create a zip file containing the 1.0 release::
447
447
448 hg archive -r 1.0 project-1.0.zip
448 hg archive -r 1.0 project-1.0.zip
449
449
450 - create a tarball excluding .hg files::
450 - create a tarball excluding .hg files::
451
451
452 hg archive project.tar.gz -X ".hg*"
452 hg archive project.tar.gz -X ".hg*"
453
453
454 Valid types are:
454 Valid types are:
455
455
456 :``files``: a directory full of files (default)
456 :``files``: a directory full of files (default)
457 :``tar``: tar archive, uncompressed
457 :``tar``: tar archive, uncompressed
458 :``tbz2``: tar archive, compressed using bzip2
458 :``tbz2``: tar archive, compressed using bzip2
459 :``tgz``: tar archive, compressed using gzip
459 :``tgz``: tar archive, compressed using gzip
460 :``uzip``: zip archive, uncompressed
460 :``uzip``: zip archive, uncompressed
461 :``zip``: zip archive, compressed using deflate
461 :``zip``: zip archive, compressed using deflate
462
462
463 The exact name of the destination archive or directory is given
463 The exact name of the destination archive or directory is given
464 using a format string; see :hg:`help export` for details.
464 using a format string; see :hg:`help export` for details.
465
465
466 Each member added to an archive file has a directory prefix
466 Each member added to an archive file has a directory prefix
467 prepended. Use -p/--prefix to specify a format string for the
467 prepended. Use -p/--prefix to specify a format string for the
468 prefix. The default is the basename of the archive, with suffixes
468 prefix. The default is the basename of the archive, with suffixes
469 removed.
469 removed.
470
470
471 Returns 0 on success.
471 Returns 0 on success.
472 '''
472 '''
473
473
474 opts = pycompat.byteskwargs(opts)
474 opts = pycompat.byteskwargs(opts)
475 rev = opts.get('rev')
475 rev = opts.get('rev')
476 if rev:
476 if rev:
477 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
477 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
478 ctx = scmutil.revsingle(repo, rev)
478 ctx = scmutil.revsingle(repo, rev)
479 if not ctx:
479 if not ctx:
480 raise error.Abort(_('no working directory: please specify a revision'))
480 raise error.Abort(_('no working directory: please specify a revision'))
481 node = ctx.node()
481 node = ctx.node()
482 dest = cmdutil.makefilename(ctx, dest)
482 dest = cmdutil.makefilename(ctx, dest)
483 if os.path.realpath(dest) == repo.root:
483 if os.path.realpath(dest) == repo.root:
484 raise error.Abort(_('repository root cannot be destination'))
484 raise error.Abort(_('repository root cannot be destination'))
485
485
486 kind = opts.get('type') or archival.guesskind(dest) or 'files'
486 kind = opts.get('type') or archival.guesskind(dest) or 'files'
487 prefix = opts.get('prefix')
487 prefix = opts.get('prefix')
488
488
489 if dest == '-':
489 if dest == '-':
490 if kind == 'files':
490 if kind == 'files':
491 raise error.Abort(_('cannot archive plain files to stdout'))
491 raise error.Abort(_('cannot archive plain files to stdout'))
492 dest = cmdutil.makefileobj(ctx, dest)
492 dest = cmdutil.makefileobj(ctx, dest)
493 if not prefix:
493 if not prefix:
494 prefix = os.path.basename(repo.root) + '-%h'
494 prefix = os.path.basename(repo.root) + '-%h'
495
495
496 prefix = cmdutil.makefilename(ctx, prefix)
496 prefix = cmdutil.makefilename(ctx, prefix)
497 match = scmutil.match(ctx, [], opts)
497 match = scmutil.match(ctx, [], opts)
498 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
498 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
499 match, prefix, subrepos=opts.get('subrepos'))
499 match, prefix, subrepos=opts.get('subrepos'))
500
500
501 @command('backout',
501 @command('backout',
502 [('', 'merge', None, _('merge with old dirstate parent after backout')),
502 [('', 'merge', None, _('merge with old dirstate parent after backout')),
503 ('', 'commit', None,
503 ('', 'commit', None,
504 _('commit if no conflicts were encountered (DEPRECATED)')),
504 _('commit if no conflicts were encountered (DEPRECATED)')),
505 ('', 'no-commit', None, _('do not commit')),
505 ('', 'no-commit', None, _('do not commit')),
506 ('', 'parent', '',
506 ('', 'parent', '',
507 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
507 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
508 ('r', 'rev', '', _('revision to backout'), _('REV')),
508 ('r', 'rev', '', _('revision to backout'), _('REV')),
509 ('e', 'edit', False, _('invoke editor on commit messages')),
509 ('e', 'edit', False, _('invoke editor on commit messages')),
510 ] + mergetoolopts + walkopts + commitopts + commitopts2,
510 ] + mergetoolopts + walkopts + commitopts + commitopts2,
511 _('[OPTION]... [-r] REV'))
511 _('[OPTION]... [-r] REV'))
512 def backout(ui, repo, node=None, rev=None, **opts):
512 def backout(ui, repo, node=None, rev=None, **opts):
513 '''reverse effect of earlier changeset
513 '''reverse effect of earlier changeset
514
514
515 Prepare a new changeset with the effect of REV undone in the
515 Prepare a new changeset with the effect of REV undone in the
516 current working directory. If no conflicts were encountered,
516 current working directory. If no conflicts were encountered,
517 it will be committed immediately.
517 it will be committed immediately.
518
518
519 If REV is the parent of the working directory, then this new changeset
519 If REV is the parent of the working directory, then this new changeset
520 is committed automatically (unless --no-commit is specified).
520 is committed automatically (unless --no-commit is specified).
521
521
522 .. note::
522 .. note::
523
523
524 :hg:`backout` cannot be used to fix either an unwanted or
524 :hg:`backout` cannot be used to fix either an unwanted or
525 incorrect merge.
525 incorrect merge.
526
526
527 .. container:: verbose
527 .. container:: verbose
528
528
529 Examples:
529 Examples:
530
530
531 - Reverse the effect of the parent of the working directory.
531 - Reverse the effect of the parent of the working directory.
532 This backout will be committed immediately::
532 This backout will be committed immediately::
533
533
534 hg backout -r .
534 hg backout -r .
535
535
536 - Reverse the effect of previous bad revision 23::
536 - Reverse the effect of previous bad revision 23::
537
537
538 hg backout -r 23
538 hg backout -r 23
539
539
540 - Reverse the effect of previous bad revision 23 and
540 - Reverse the effect of previous bad revision 23 and
541 leave changes uncommitted::
541 leave changes uncommitted::
542
542
543 hg backout -r 23 --no-commit
543 hg backout -r 23 --no-commit
544 hg commit -m "Backout revision 23"
544 hg commit -m "Backout revision 23"
545
545
546 By default, the pending changeset will have one parent,
546 By default, the pending changeset will have one parent,
547 maintaining a linear history. With --merge, the pending
547 maintaining a linear history. With --merge, the pending
548 changeset will instead have two parents: the old parent of the
548 changeset will instead have two parents: the old parent of the
549 working directory and a new child of REV that simply undoes REV.
549 working directory and a new child of REV that simply undoes REV.
550
550
551 Before version 1.7, the behavior without --merge was equivalent
551 Before version 1.7, the behavior without --merge was equivalent
552 to specifying --merge followed by :hg:`update --clean .` to
552 to specifying --merge followed by :hg:`update --clean .` to
553 cancel the merge and leave the child of REV as a head to be
553 cancel the merge and leave the child of REV as a head to be
554 merged separately.
554 merged separately.
555
555
556 See :hg:`help dates` for a list of formats valid for -d/--date.
556 See :hg:`help dates` for a list of formats valid for -d/--date.
557
557
558 See :hg:`help revert` for a way to restore files to the state
558 See :hg:`help revert` for a way to restore files to the state
559 of another revision.
559 of another revision.
560
560
561 Returns 0 on success, 1 if nothing to backout or there are unresolved
561 Returns 0 on success, 1 if nothing to backout or there are unresolved
562 files.
562 files.
563 '''
563 '''
564 wlock = lock = None
564 wlock = lock = None
565 try:
565 try:
566 wlock = repo.wlock()
566 wlock = repo.wlock()
567 lock = repo.lock()
567 lock = repo.lock()
568 return _dobackout(ui, repo, node, rev, **opts)
568 return _dobackout(ui, repo, node, rev, **opts)
569 finally:
569 finally:
570 release(lock, wlock)
570 release(lock, wlock)
571
571
572 def _dobackout(ui, repo, node=None, rev=None, **opts):
572 def _dobackout(ui, repo, node=None, rev=None, **opts):
573 opts = pycompat.byteskwargs(opts)
573 opts = pycompat.byteskwargs(opts)
574 if opts.get('commit') and opts.get('no_commit'):
574 if opts.get('commit') and opts.get('no_commit'):
575 raise error.Abort(_("cannot use --commit with --no-commit"))
575 raise error.Abort(_("cannot use --commit with --no-commit"))
576 if opts.get('merge') and opts.get('no_commit'):
576 if opts.get('merge') and opts.get('no_commit'):
577 raise error.Abort(_("cannot use --merge with --no-commit"))
577 raise error.Abort(_("cannot use --merge with --no-commit"))
578
578
579 if rev and node:
579 if rev and node:
580 raise error.Abort(_("please specify just one revision"))
580 raise error.Abort(_("please specify just one revision"))
581
581
582 if not rev:
582 if not rev:
583 rev = node
583 rev = node
584
584
585 if not rev:
585 if not rev:
586 raise error.Abort(_("please specify a revision to backout"))
586 raise error.Abort(_("please specify a revision to backout"))
587
587
588 date = opts.get('date')
588 date = opts.get('date')
589 if date:
589 if date:
590 opts['date'] = dateutil.parsedate(date)
590 opts['date'] = dateutil.parsedate(date)
591
591
592 cmdutil.checkunfinished(repo)
592 cmdutil.checkunfinished(repo)
593 cmdutil.bailifchanged(repo)
593 cmdutil.bailifchanged(repo)
594 node = scmutil.revsingle(repo, rev).node()
594 node = scmutil.revsingle(repo, rev).node()
595
595
596 op1, op2 = repo.dirstate.parents()
596 op1, op2 = repo.dirstate.parents()
597 if not repo.changelog.isancestor(node, op1):
597 if not repo.changelog.isancestor(node, op1):
598 raise error.Abort(_('cannot backout change that is not an ancestor'))
598 raise error.Abort(_('cannot backout change that is not an ancestor'))
599
599
600 p1, p2 = repo.changelog.parents(node)
600 p1, p2 = repo.changelog.parents(node)
601 if p1 == nullid:
601 if p1 == nullid:
602 raise error.Abort(_('cannot backout a change with no parents'))
602 raise error.Abort(_('cannot backout a change with no parents'))
603 if p2 != nullid:
603 if p2 != nullid:
604 if not opts.get('parent'):
604 if not opts.get('parent'):
605 raise error.Abort(_('cannot backout a merge changeset'))
605 raise error.Abort(_('cannot backout a merge changeset'))
606 p = repo.lookup(opts['parent'])
606 p = repo.lookup(opts['parent'])
607 if p not in (p1, p2):
607 if p not in (p1, p2):
608 raise error.Abort(_('%s is not a parent of %s') %
608 raise error.Abort(_('%s is not a parent of %s') %
609 (short(p), short(node)))
609 (short(p), short(node)))
610 parent = p
610 parent = p
611 else:
611 else:
612 if opts.get('parent'):
612 if opts.get('parent'):
613 raise error.Abort(_('cannot use --parent on non-merge changeset'))
613 raise error.Abort(_('cannot use --parent on non-merge changeset'))
614 parent = p1
614 parent = p1
615
615
616 # the backout should appear on the same branch
616 # the backout should appear on the same branch
617 branch = repo.dirstate.branch()
617 branch = repo.dirstate.branch()
618 bheads = repo.branchheads(branch)
618 bheads = repo.branchheads(branch)
619 rctx = scmutil.revsingle(repo, hex(parent))
619 rctx = scmutil.revsingle(repo, hex(parent))
620 if not opts.get('merge') and op1 != node:
620 if not opts.get('merge') and op1 != node:
621 dsguard = dirstateguard.dirstateguard(repo, 'backout')
621 dsguard = dirstateguard.dirstateguard(repo, 'backout')
622 try:
622 try:
623 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
623 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
624 'backout')
624 'backout')
625 stats = mergemod.update(repo, parent, True, True, node, False)
625 stats = mergemod.update(repo, parent, True, True, node, False)
626 repo.setparents(op1, op2)
626 repo.setparents(op1, op2)
627 dsguard.close()
627 dsguard.close()
628 hg._showstats(repo, stats)
628 hg._showstats(repo, stats)
629 if stats.unresolvedcount:
629 if stats.unresolvedcount:
630 repo.ui.status(_("use 'hg resolve' to retry unresolved "
630 repo.ui.status(_("use 'hg resolve' to retry unresolved "
631 "file merges\n"))
631 "file merges\n"))
632 return 1
632 return 1
633 finally:
633 finally:
634 ui.setconfig('ui', 'forcemerge', '', '')
634 ui.setconfig('ui', 'forcemerge', '', '')
635 lockmod.release(dsguard)
635 lockmod.release(dsguard)
636 else:
636 else:
637 hg.clean(repo, node, show_stats=False)
637 hg.clean(repo, node, show_stats=False)
638 repo.dirstate.setbranch(branch)
638 repo.dirstate.setbranch(branch)
639 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
639 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
640
640
641 if opts.get('no_commit'):
641 if opts.get('no_commit'):
642 msg = _("changeset %s backed out, "
642 msg = _("changeset %s backed out, "
643 "don't forget to commit.\n")
643 "don't forget to commit.\n")
644 ui.status(msg % short(node))
644 ui.status(msg % short(node))
645 return 0
645 return 0
646
646
647 def commitfunc(ui, repo, message, match, opts):
647 def commitfunc(ui, repo, message, match, opts):
648 editform = 'backout'
648 editform = 'backout'
649 e = cmdutil.getcommiteditor(editform=editform,
649 e = cmdutil.getcommiteditor(editform=editform,
650 **pycompat.strkwargs(opts))
650 **pycompat.strkwargs(opts))
651 if not message:
651 if not message:
652 # we don't translate commit messages
652 # we don't translate commit messages
653 message = "Backed out changeset %s" % short(node)
653 message = "Backed out changeset %s" % short(node)
654 e = cmdutil.getcommiteditor(edit=True, editform=editform)
654 e = cmdutil.getcommiteditor(edit=True, editform=editform)
655 return repo.commit(message, opts.get('user'), opts.get('date'),
655 return repo.commit(message, opts.get('user'), opts.get('date'),
656 match, editor=e)
656 match, editor=e)
657 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
657 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
658 if not newnode:
658 if not newnode:
659 ui.status(_("nothing changed\n"))
659 ui.status(_("nothing changed\n"))
660 return 1
660 return 1
661 cmdutil.commitstatus(repo, newnode, branch, bheads)
661 cmdutil.commitstatus(repo, newnode, branch, bheads)
662
662
663 def nice(node):
663 def nice(node):
664 return '%d:%s' % (repo.changelog.rev(node), short(node))
664 return '%d:%s' % (repo.changelog.rev(node), short(node))
665 ui.status(_('changeset %s backs out changeset %s\n') %
665 ui.status(_('changeset %s backs out changeset %s\n') %
666 (nice(repo.changelog.tip()), nice(node)))
666 (nice(repo.changelog.tip()), nice(node)))
667 if opts.get('merge') and op1 != node:
667 if opts.get('merge') and op1 != node:
668 hg.clean(repo, op1, show_stats=False)
668 hg.clean(repo, op1, show_stats=False)
669 ui.status(_('merging with changeset %s\n')
669 ui.status(_('merging with changeset %s\n')
670 % nice(repo.changelog.tip()))
670 % nice(repo.changelog.tip()))
671 try:
671 try:
672 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
672 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
673 'backout')
673 'backout')
674 return hg.merge(repo, hex(repo.changelog.tip()))
674 return hg.merge(repo, hex(repo.changelog.tip()))
675 finally:
675 finally:
676 ui.setconfig('ui', 'forcemerge', '', '')
676 ui.setconfig('ui', 'forcemerge', '', '')
677 return 0
677 return 0
678
678
679 @command('bisect',
679 @command('bisect',
680 [('r', 'reset', False, _('reset bisect state')),
680 [('r', 'reset', False, _('reset bisect state')),
681 ('g', 'good', False, _('mark changeset good')),
681 ('g', 'good', False, _('mark changeset good')),
682 ('b', 'bad', False, _('mark changeset bad')),
682 ('b', 'bad', False, _('mark changeset bad')),
683 ('s', 'skip', False, _('skip testing changeset')),
683 ('s', 'skip', False, _('skip testing changeset')),
684 ('e', 'extend', False, _('extend the bisect range')),
684 ('e', 'extend', False, _('extend the bisect range')),
685 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
685 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
686 ('U', 'noupdate', False, _('do not update to target'))],
686 ('U', 'noupdate', False, _('do not update to target'))],
687 _("[-gbsr] [-U] [-c CMD] [REV]"))
687 _("[-gbsr] [-U] [-c CMD] [REV]"))
688 def bisect(ui, repo, rev=None, extra=None, command=None,
688 def bisect(ui, repo, rev=None, extra=None, command=None,
689 reset=None, good=None, bad=None, skip=None, extend=None,
689 reset=None, good=None, bad=None, skip=None, extend=None,
690 noupdate=None):
690 noupdate=None):
691 """subdivision search of changesets
691 """subdivision search of changesets
692
692
693 This command helps to find changesets which introduce problems. To
693 This command helps to find changesets which introduce problems. To
694 use, mark the earliest changeset you know exhibits the problem as
694 use, mark the earliest changeset you know exhibits the problem as
695 bad, then mark the latest changeset which is free from the problem
695 bad, then mark the latest changeset which is free from the problem
696 as good. Bisect will update your working directory to a revision
696 as good. Bisect will update your working directory to a revision
697 for testing (unless the -U/--noupdate option is specified). Once
697 for testing (unless the -U/--noupdate option is specified). Once
698 you have performed tests, mark the working directory as good or
698 you have performed tests, mark the working directory as good or
699 bad, and bisect will either update to another candidate changeset
699 bad, and bisect will either update to another candidate changeset
700 or announce that it has found the bad revision.
700 or announce that it has found the bad revision.
701
701
702 As a shortcut, you can also use the revision argument to mark a
702 As a shortcut, you can also use the revision argument to mark a
703 revision as good or bad without checking it out first.
703 revision as good or bad without checking it out first.
704
704
705 If you supply a command, it will be used for automatic bisection.
705 If you supply a command, it will be used for automatic bisection.
706 The environment variable HG_NODE will contain the ID of the
706 The environment variable HG_NODE will contain the ID of the
707 changeset being tested. The exit status of the command will be
707 changeset being tested. The exit status of the command will be
708 used to mark revisions as good or bad: status 0 means good, 125
708 used to mark revisions as good or bad: status 0 means good, 125
709 means to skip the revision, 127 (command not found) will abort the
709 means to skip the revision, 127 (command not found) will abort the
710 bisection, and any other non-zero exit status means the revision
710 bisection, and any other non-zero exit status means the revision
711 is bad.
711 is bad.
712
712
713 .. container:: verbose
713 .. container:: verbose
714
714
715 Some examples:
715 Some examples:
716
716
717 - start a bisection with known bad revision 34, and good revision 12::
717 - start a bisection with known bad revision 34, and good revision 12::
718
718
719 hg bisect --bad 34
719 hg bisect --bad 34
720 hg bisect --good 12
720 hg bisect --good 12
721
721
722 - advance the current bisection by marking current revision as good or
722 - advance the current bisection by marking current revision as good or
723 bad::
723 bad::
724
724
725 hg bisect --good
725 hg bisect --good
726 hg bisect --bad
726 hg bisect --bad
727
727
728 - mark the current revision, or a known revision, to be skipped (e.g. if
728 - mark the current revision, or a known revision, to be skipped (e.g. if
729 that revision is not usable because of another issue)::
729 that revision is not usable because of another issue)::
730
730
731 hg bisect --skip
731 hg bisect --skip
732 hg bisect --skip 23
732 hg bisect --skip 23
733
733
734 - skip all revisions that do not touch directories ``foo`` or ``bar``::
734 - skip all revisions that do not touch directories ``foo`` or ``bar``::
735
735
736 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
736 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
737
737
738 - forget the current bisection::
738 - forget the current bisection::
739
739
740 hg bisect --reset
740 hg bisect --reset
741
741
742 - use 'make && make tests' to automatically find the first broken
742 - use 'make && make tests' to automatically find the first broken
743 revision::
743 revision::
744
744
745 hg bisect --reset
745 hg bisect --reset
746 hg bisect --bad 34
746 hg bisect --bad 34
747 hg bisect --good 12
747 hg bisect --good 12
748 hg bisect --command "make && make tests"
748 hg bisect --command "make && make tests"
749
749
750 - see all changesets whose states are already known in the current
750 - see all changesets whose states are already known in the current
751 bisection::
751 bisection::
752
752
753 hg log -r "bisect(pruned)"
753 hg log -r "bisect(pruned)"
754
754
755 - see the changeset currently being bisected (especially useful
755 - see the changeset currently being bisected (especially useful
756 if running with -U/--noupdate)::
756 if running with -U/--noupdate)::
757
757
758 hg log -r "bisect(current)"
758 hg log -r "bisect(current)"
759
759
760 - see all changesets that took part in the current bisection::
760 - see all changesets that took part in the current bisection::
761
761
762 hg log -r "bisect(range)"
762 hg log -r "bisect(range)"
763
763
764 - you can even get a nice graph::
764 - you can even get a nice graph::
765
765
766 hg log --graph -r "bisect(range)"
766 hg log --graph -r "bisect(range)"
767
767
768 See :hg:`help revisions.bisect` for more about the `bisect()` predicate.
768 See :hg:`help revisions.bisect` for more about the `bisect()` predicate.
769
769
770 Returns 0 on success.
770 Returns 0 on success.
771 """
771 """
772 # backward compatibility
772 # backward compatibility
773 if rev in "good bad reset init".split():
773 if rev in "good bad reset init".split():
774 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
774 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
775 cmd, rev, extra = rev, extra, None
775 cmd, rev, extra = rev, extra, None
776 if cmd == "good":
776 if cmd == "good":
777 good = True
777 good = True
778 elif cmd == "bad":
778 elif cmd == "bad":
779 bad = True
779 bad = True
780 else:
780 else:
781 reset = True
781 reset = True
782 elif extra:
782 elif extra:
783 raise error.Abort(_('incompatible arguments'))
783 raise error.Abort(_('incompatible arguments'))
784
784
785 incompatibles = {
785 incompatibles = {
786 '--bad': bad,
786 '--bad': bad,
787 '--command': bool(command),
787 '--command': bool(command),
788 '--extend': extend,
788 '--extend': extend,
789 '--good': good,
789 '--good': good,
790 '--reset': reset,
790 '--reset': reset,
791 '--skip': skip,
791 '--skip': skip,
792 }
792 }
793
793
794 enabled = [x for x in incompatibles if incompatibles[x]]
794 enabled = [x for x in incompatibles if incompatibles[x]]
795
795
796 if len(enabled) > 1:
796 if len(enabled) > 1:
797 raise error.Abort(_('%s and %s are incompatible') %
797 raise error.Abort(_('%s and %s are incompatible') %
798 tuple(sorted(enabled)[0:2]))
798 tuple(sorted(enabled)[0:2]))
799
799
800 if reset:
800 if reset:
801 hbisect.resetstate(repo)
801 hbisect.resetstate(repo)
802 return
802 return
803
803
804 state = hbisect.load_state(repo)
804 state = hbisect.load_state(repo)
805
805
806 # update state
806 # update state
807 if good or bad or skip:
807 if good or bad or skip:
808 if rev:
808 if rev:
809 nodes = [repo[i].node() for i in scmutil.revrange(repo, [rev])]
809 nodes = [repo[i].node() for i in scmutil.revrange(repo, [rev])]
810 else:
810 else:
811 nodes = [repo.lookup('.')]
811 nodes = [repo.lookup('.')]
812 if good:
812 if good:
813 state['good'] += nodes
813 state['good'] += nodes
814 elif bad:
814 elif bad:
815 state['bad'] += nodes
815 state['bad'] += nodes
816 elif skip:
816 elif skip:
817 state['skip'] += nodes
817 state['skip'] += nodes
818 hbisect.save_state(repo, state)
818 hbisect.save_state(repo, state)
819 if not (state['good'] and state['bad']):
819 if not (state['good'] and state['bad']):
820 return
820 return
821
821
822 def mayupdate(repo, node, show_stats=True):
822 def mayupdate(repo, node, show_stats=True):
823 """common used update sequence"""
823 """common used update sequence"""
824 if noupdate:
824 if noupdate:
825 return
825 return
826 cmdutil.checkunfinished(repo)
826 cmdutil.checkunfinished(repo)
827 cmdutil.bailifchanged(repo)
827 cmdutil.bailifchanged(repo)
828 return hg.clean(repo, node, show_stats=show_stats)
828 return hg.clean(repo, node, show_stats=show_stats)
829
829
830 displayer = logcmdutil.changesetdisplayer(ui, repo, {})
830 displayer = logcmdutil.changesetdisplayer(ui, repo, {})
831
831
832 if command:
832 if command:
833 changesets = 1
833 changesets = 1
834 if noupdate:
834 if noupdate:
835 try:
835 try:
836 node = state['current'][0]
836 node = state['current'][0]
837 except LookupError:
837 except LookupError:
838 raise error.Abort(_('current bisect revision is unknown - '
838 raise error.Abort(_('current bisect revision is unknown - '
839 'start a new bisect to fix'))
839 'start a new bisect to fix'))
840 else:
840 else:
841 node, p2 = repo.dirstate.parents()
841 node, p2 = repo.dirstate.parents()
842 if p2 != nullid:
842 if p2 != nullid:
843 raise error.Abort(_('current bisect revision is a merge'))
843 raise error.Abort(_('current bisect revision is a merge'))
844 if rev:
844 if rev:
845 node = repo[scmutil.revsingle(repo, rev, node)].node()
845 node = repo[scmutil.revsingle(repo, rev, node)].node()
846 try:
846 try:
847 while changesets:
847 while changesets:
848 # update state
848 # update state
849 state['current'] = [node]
849 state['current'] = [node]
850 hbisect.save_state(repo, state)
850 hbisect.save_state(repo, state)
851 status = ui.system(command, environ={'HG_NODE': hex(node)},
851 status = ui.system(command, environ={'HG_NODE': hex(node)},
852 blockedtag='bisect_check')
852 blockedtag='bisect_check')
853 if status == 125:
853 if status == 125:
854 transition = "skip"
854 transition = "skip"
855 elif status == 0:
855 elif status == 0:
856 transition = "good"
856 transition = "good"
857 # status < 0 means process was killed
857 # status < 0 means process was killed
858 elif status == 127:
858 elif status == 127:
859 raise error.Abort(_("failed to execute %s") % command)
859 raise error.Abort(_("failed to execute %s") % command)
860 elif status < 0:
860 elif status < 0:
861 raise error.Abort(_("%s killed") % command)
861 raise error.Abort(_("%s killed") % command)
862 else:
862 else:
863 transition = "bad"
863 transition = "bad"
864 state[transition].append(node)
864 state[transition].append(node)
865 ctx = repo[node]
865 ctx = repo[node]
866 ui.status(_('changeset %d:%s: %s\n') % (ctx.rev(), ctx,
866 ui.status(_('changeset %d:%s: %s\n') % (ctx.rev(), ctx,
867 transition))
867 transition))
868 hbisect.checkstate(state)
868 hbisect.checkstate(state)
869 # bisect
869 # bisect
870 nodes, changesets, bgood = hbisect.bisect(repo, state)
870 nodes, changesets, bgood = hbisect.bisect(repo, state)
871 # update to next check
871 # update to next check
872 node = nodes[0]
872 node = nodes[0]
873 mayupdate(repo, node, show_stats=False)
873 mayupdate(repo, node, show_stats=False)
874 finally:
874 finally:
875 state['current'] = [node]
875 state['current'] = [node]
876 hbisect.save_state(repo, state)
876 hbisect.save_state(repo, state)
877 hbisect.printresult(ui, repo, state, displayer, nodes, bgood)
877 hbisect.printresult(ui, repo, state, displayer, nodes, bgood)
878 return
878 return
879
879
880 hbisect.checkstate(state)
880 hbisect.checkstate(state)
881
881
882 # actually bisect
882 # actually bisect
883 nodes, changesets, good = hbisect.bisect(repo, state)
883 nodes, changesets, good = hbisect.bisect(repo, state)
884 if extend:
884 if extend:
885 if not changesets:
885 if not changesets:
886 extendnode = hbisect.extendrange(repo, state, nodes, good)
886 extendnode = hbisect.extendrange(repo, state, nodes, good)
887 if extendnode is not None:
887 if extendnode is not None:
888 ui.write(_("Extending search to changeset %d:%s\n")
888 ui.write(_("Extending search to changeset %d:%s\n")
889 % (extendnode.rev(), extendnode))
889 % (extendnode.rev(), extendnode))
890 state['current'] = [extendnode.node()]
890 state['current'] = [extendnode.node()]
891 hbisect.save_state(repo, state)
891 hbisect.save_state(repo, state)
892 return mayupdate(repo, extendnode.node())
892 return mayupdate(repo, extendnode.node())
893 raise error.Abort(_("nothing to extend"))
893 raise error.Abort(_("nothing to extend"))
894
894
895 if changesets == 0:
895 if changesets == 0:
896 hbisect.printresult(ui, repo, state, displayer, nodes, good)
896 hbisect.printresult(ui, repo, state, displayer, nodes, good)
897 else:
897 else:
898 assert len(nodes) == 1 # only a single node can be tested next
898 assert len(nodes) == 1 # only a single node can be tested next
899 node = nodes[0]
899 node = nodes[0]
900 # compute the approximate number of remaining tests
900 # compute the approximate number of remaining tests
901 tests, size = 0, 2
901 tests, size = 0, 2
902 while size <= changesets:
902 while size <= changesets:
903 tests, size = tests + 1, size * 2
903 tests, size = tests + 1, size * 2
904 rev = repo.changelog.rev(node)
904 rev = repo.changelog.rev(node)
905 ui.write(_("Testing changeset %d:%s "
905 ui.write(_("Testing changeset %d:%s "
906 "(%d changesets remaining, ~%d tests)\n")
906 "(%d changesets remaining, ~%d tests)\n")
907 % (rev, short(node), changesets, tests))
907 % (rev, short(node), changesets, tests))
908 state['current'] = [node]
908 state['current'] = [node]
909 hbisect.save_state(repo, state)
909 hbisect.save_state(repo, state)
910 return mayupdate(repo, node)
910 return mayupdate(repo, node)
911
911
912 @command('bookmarks|bookmark',
912 @command('bookmarks|bookmark',
913 [('f', 'force', False, _('force')),
913 [('f', 'force', False, _('force')),
914 ('r', 'rev', '', _('revision for bookmark action'), _('REV')),
914 ('r', 'rev', '', _('revision for bookmark action'), _('REV')),
915 ('d', 'delete', False, _('delete a given bookmark')),
915 ('d', 'delete', False, _('delete a given bookmark')),
916 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
916 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
917 ('i', 'inactive', False, _('mark a bookmark inactive')),
917 ('i', 'inactive', False, _('mark a bookmark inactive')),
918 ] + formatteropts,
918 ] + formatteropts,
919 _('hg bookmarks [OPTIONS]... [NAME]...'))
919 _('hg bookmarks [OPTIONS]... [NAME]...'))
920 def bookmark(ui, repo, *names, **opts):
920 def bookmark(ui, repo, *names, **opts):
921 '''create a new bookmark or list existing bookmarks
921 '''create a new bookmark or list existing bookmarks
922
922
923 Bookmarks are labels on changesets to help track lines of development.
923 Bookmarks are labels on changesets to help track lines of development.
924 Bookmarks are unversioned and can be moved, renamed and deleted.
924 Bookmarks are unversioned and can be moved, renamed and deleted.
925 Deleting or moving a bookmark has no effect on the associated changesets.
925 Deleting or moving a bookmark has no effect on the associated changesets.
926
926
927 Creating or updating to a bookmark causes it to be marked as 'active'.
927 Creating or updating to a bookmark causes it to be marked as 'active'.
928 The active bookmark is indicated with a '*'.
928 The active bookmark is indicated with a '*'.
929 When a commit is made, the active bookmark will advance to the new commit.
929 When a commit is made, the active bookmark will advance to the new commit.
930 A plain :hg:`update` will also advance an active bookmark, if possible.
930 A plain :hg:`update` will also advance an active bookmark, if possible.
931 Updating away from a bookmark will cause it to be deactivated.
931 Updating away from a bookmark will cause it to be deactivated.
932
932
933 Bookmarks can be pushed and pulled between repositories (see
933 Bookmarks can be pushed and pulled between repositories (see
934 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
934 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
935 diverged, a new 'divergent bookmark' of the form 'name@path' will
935 diverged, a new 'divergent bookmark' of the form 'name@path' will
936 be created. Using :hg:`merge` will resolve the divergence.
936 be created. Using :hg:`merge` will resolve the divergence.
937
937
938 Specifying bookmark as '.' to -m or -d options is equivalent to specifying
938 Specifying bookmark as '.' to -m or -d options is equivalent to specifying
939 the active bookmark's name.
939 the active bookmark's name.
940
940
941 A bookmark named '@' has the special property that :hg:`clone` will
941 A bookmark named '@' has the special property that :hg:`clone` will
942 check it out by default if it exists.
942 check it out by default if it exists.
943
943
944 .. container:: verbose
944 .. container:: verbose
945
945
946 Examples:
946 Examples:
947
947
948 - create an active bookmark for a new line of development::
948 - create an active bookmark for a new line of development::
949
949
950 hg book new-feature
950 hg book new-feature
951
951
952 - create an inactive bookmark as a place marker::
952 - create an inactive bookmark as a place marker::
953
953
954 hg book -i reviewed
954 hg book -i reviewed
955
955
956 - create an inactive bookmark on another changeset::
956 - create an inactive bookmark on another changeset::
957
957
958 hg book -r .^ tested
958 hg book -r .^ tested
959
959
960 - rename bookmark turkey to dinner::
960 - rename bookmark turkey to dinner::
961
961
962 hg book -m turkey dinner
962 hg book -m turkey dinner
963
963
964 - move the '@' bookmark from another branch::
964 - move the '@' bookmark from another branch::
965
965
966 hg book -f @
966 hg book -f @
967 '''
967 '''
968 force = opts.get(r'force')
968 force = opts.get(r'force')
969 rev = opts.get(r'rev')
969 rev = opts.get(r'rev')
970 delete = opts.get(r'delete')
970 delete = opts.get(r'delete')
971 rename = opts.get(r'rename')
971 rename = opts.get(r'rename')
972 inactive = opts.get(r'inactive')
972 inactive = opts.get(r'inactive')
973
973
974 if delete and rename:
974 if delete and rename:
975 raise error.Abort(_("--delete and --rename are incompatible"))
975 raise error.Abort(_("--delete and --rename are incompatible"))
976 if delete and rev:
976 if delete and rev:
977 raise error.Abort(_("--rev is incompatible with --delete"))
977 raise error.Abort(_("--rev is incompatible with --delete"))
978 if rename and rev:
978 if rename and rev:
979 raise error.Abort(_("--rev is incompatible with --rename"))
979 raise error.Abort(_("--rev is incompatible with --rename"))
980 if not names and (delete or rev):
980 if not names and (delete or rev):
981 raise error.Abort(_("bookmark name required"))
981 raise error.Abort(_("bookmark name required"))
982
982
983 if delete or rename or names or inactive:
983 if delete or rename or names or inactive:
984 with repo.wlock(), repo.lock(), repo.transaction('bookmark') as tr:
984 with repo.wlock(), repo.lock(), repo.transaction('bookmark') as tr:
985 if delete:
985 if delete:
986 names = pycompat.maplist(repo._bookmarks.expandname, names)
986 names = pycompat.maplist(repo._bookmarks.expandname, names)
987 bookmarks.delete(repo, tr, names)
987 bookmarks.delete(repo, tr, names)
988 elif rename:
988 elif rename:
989 if not names:
989 if not names:
990 raise error.Abort(_("new bookmark name required"))
990 raise error.Abort(_("new bookmark name required"))
991 elif len(names) > 1:
991 elif len(names) > 1:
992 raise error.Abort(_("only one new bookmark name allowed"))
992 raise error.Abort(_("only one new bookmark name allowed"))
993 rename = repo._bookmarks.expandname(rename)
993 rename = repo._bookmarks.expandname(rename)
994 bookmarks.rename(repo, tr, rename, names[0], force, inactive)
994 bookmarks.rename(repo, tr, rename, names[0], force, inactive)
995 elif names:
995 elif names:
996 bookmarks.addbookmarks(repo, tr, names, rev, force, inactive)
996 bookmarks.addbookmarks(repo, tr, names, rev, force, inactive)
997 elif inactive:
997 elif inactive:
998 if len(repo._bookmarks) == 0:
998 if len(repo._bookmarks) == 0:
999 ui.status(_("no bookmarks set\n"))
999 ui.status(_("no bookmarks set\n"))
1000 elif not repo._activebookmark:
1000 elif not repo._activebookmark:
1001 ui.status(_("no active bookmark\n"))
1001 ui.status(_("no active bookmark\n"))
1002 else:
1002 else:
1003 bookmarks.deactivate(repo)
1003 bookmarks.deactivate(repo)
1004 else: # show bookmarks
1004 else: # show bookmarks
1005 bookmarks.printbookmarks(ui, repo, **opts)
1005 bookmarks.printbookmarks(ui, repo, **opts)
1006
1006
1007 @command('branch',
1007 @command('branch',
1008 [('f', 'force', None,
1008 [('f', 'force', None,
1009 _('set branch name even if it shadows an existing branch')),
1009 _('set branch name even if it shadows an existing branch')),
1010 ('C', 'clean', None, _('reset branch name to parent branch name')),
1010 ('C', 'clean', None, _('reset branch name to parent branch name')),
1011 ('r', 'rev', [], _('change branches of the given revs (EXPERIMENTAL)')),
1011 ('r', 'rev', [], _('change branches of the given revs (EXPERIMENTAL)')),
1012 ],
1012 ],
1013 _('[-fC] [NAME]'))
1013 _('[-fC] [NAME]'))
1014 def branch(ui, repo, label=None, **opts):
1014 def branch(ui, repo, label=None, **opts):
1015 """set or show the current branch name
1015 """set or show the current branch name
1016
1016
1017 .. note::
1017 .. note::
1018
1018
1019 Branch names are permanent and global. Use :hg:`bookmark` to create a
1019 Branch names are permanent and global. Use :hg:`bookmark` to create a
1020 light-weight bookmark instead. See :hg:`help glossary` for more
1020 light-weight bookmark instead. See :hg:`help glossary` for more
1021 information about named branches and bookmarks.
1021 information about named branches and bookmarks.
1022
1022
1023 With no argument, show the current branch name. With one argument,
1023 With no argument, show the current branch name. With one argument,
1024 set the working directory branch name (the branch will not exist
1024 set the working directory branch name (the branch will not exist
1025 in the repository until the next commit). Standard practice
1025 in the repository until the next commit). Standard practice
1026 recommends that primary development take place on the 'default'
1026 recommends that primary development take place on the 'default'
1027 branch.
1027 branch.
1028
1028
1029 Unless -f/--force is specified, branch will not let you set a
1029 Unless -f/--force is specified, branch will not let you set a
1030 branch name that already exists.
1030 branch name that already exists.
1031
1031
1032 Use -C/--clean to reset the working directory branch to that of
1032 Use -C/--clean to reset the working directory branch to that of
1033 the parent of the working directory, negating a previous branch
1033 the parent of the working directory, negating a previous branch
1034 change.
1034 change.
1035
1035
1036 Use the command :hg:`update` to switch to an existing branch. Use
1036 Use the command :hg:`update` to switch to an existing branch. Use
1037 :hg:`commit --close-branch` to mark this branch head as closed.
1037 :hg:`commit --close-branch` to mark this branch head as closed.
1038 When all heads of a branch are closed, the branch will be
1038 When all heads of a branch are closed, the branch will be
1039 considered closed.
1039 considered closed.
1040
1040
1041 Returns 0 on success.
1041 Returns 0 on success.
1042 """
1042 """
1043 opts = pycompat.byteskwargs(opts)
1043 opts = pycompat.byteskwargs(opts)
1044 revs = opts.get('rev')
1044 revs = opts.get('rev')
1045 if label:
1045 if label:
1046 label = label.strip()
1046 label = label.strip()
1047
1047
1048 if not opts.get('clean') and not label:
1048 if not opts.get('clean') and not label:
1049 if revs:
1049 if revs:
1050 raise error.Abort(_("no branch name specified for the revisions"))
1050 raise error.Abort(_("no branch name specified for the revisions"))
1051 ui.write("%s\n" % repo.dirstate.branch())
1051 ui.write("%s\n" % repo.dirstate.branch())
1052 return
1052 return
1053
1053
1054 with repo.wlock():
1054 with repo.wlock():
1055 if opts.get('clean'):
1055 if opts.get('clean'):
1056 label = repo[None].p1().branch()
1056 label = repo[None].p1().branch()
1057 repo.dirstate.setbranch(label)
1057 repo.dirstate.setbranch(label)
1058 ui.status(_('reset working directory to branch %s\n') % label)
1058 ui.status(_('reset working directory to branch %s\n') % label)
1059 elif label:
1059 elif label:
1060
1060
1061 scmutil.checknewlabel(repo, label, 'branch')
1061 scmutil.checknewlabel(repo, label, 'branch')
1062 if revs:
1062 if revs:
1063 return cmdutil.changebranch(ui, repo, revs, label)
1063 return cmdutil.changebranch(ui, repo, revs, label)
1064
1064
1065 if not opts.get('force') and label in repo.branchmap():
1065 if not opts.get('force') and label in repo.branchmap():
1066 if label not in [p.branch() for p in repo[None].parents()]:
1066 if label not in [p.branch() for p in repo[None].parents()]:
1067 raise error.Abort(_('a branch of the same name already'
1067 raise error.Abort(_('a branch of the same name already'
1068 ' exists'),
1068 ' exists'),
1069 # i18n: "it" refers to an existing branch
1069 # i18n: "it" refers to an existing branch
1070 hint=_("use 'hg update' to switch to it"))
1070 hint=_("use 'hg update' to switch to it"))
1071
1071
1072 repo.dirstate.setbranch(label)
1072 repo.dirstate.setbranch(label)
1073 ui.status(_('marked working directory as branch %s\n') % label)
1073 ui.status(_('marked working directory as branch %s\n') % label)
1074
1074
1075 # find any open named branches aside from default
1075 # find any open named branches aside from default
1076 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1076 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1077 if n != "default" and not c]
1077 if n != "default" and not c]
1078 if not others:
1078 if not others:
1079 ui.status(_('(branches are permanent and global, '
1079 ui.status(_('(branches are permanent and global, '
1080 'did you want a bookmark?)\n'))
1080 'did you want a bookmark?)\n'))
1081
1081
1082 @command('branches',
1082 @command('branches',
1083 [('a', 'active', False,
1083 [('a', 'active', False,
1084 _('show only branches that have unmerged heads (DEPRECATED)')),
1084 _('show only branches that have unmerged heads (DEPRECATED)')),
1085 ('c', 'closed', False, _('show normal and closed branches')),
1085 ('c', 'closed', False, _('show normal and closed branches')),
1086 ] + formatteropts,
1086 ] + formatteropts,
1087 _('[-c]'),
1087 _('[-c]'),
1088 intents={INTENT_READONLY})
1088 intents={INTENT_READONLY})
1089 def branches(ui, repo, active=False, closed=False, **opts):
1089 def branches(ui, repo, active=False, closed=False, **opts):
1090 """list repository named branches
1090 """list repository named branches
1091
1091
1092 List the repository's named branches, indicating which ones are
1092 List the repository's named branches, indicating which ones are
1093 inactive. If -c/--closed is specified, also list branches which have
1093 inactive. If -c/--closed is specified, also list branches which have
1094 been marked closed (see :hg:`commit --close-branch`).
1094 been marked closed (see :hg:`commit --close-branch`).
1095
1095
1096 Use the command :hg:`update` to switch to an existing branch.
1096 Use the command :hg:`update` to switch to an existing branch.
1097
1097
1098 Returns 0.
1098 Returns 0.
1099 """
1099 """
1100
1100
1101 opts = pycompat.byteskwargs(opts)
1101 opts = pycompat.byteskwargs(opts)
1102 ui.pager('branches')
1102 ui.pager('branches')
1103 fm = ui.formatter('branches', opts)
1103 fm = ui.formatter('branches', opts)
1104 hexfunc = fm.hexfunc
1104 hexfunc = fm.hexfunc
1105
1105
1106 allheads = set(repo.heads())
1106 allheads = set(repo.heads())
1107 branches = []
1107 branches = []
1108 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1108 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1109 isactive = False
1109 isactive = False
1110 if not isclosed:
1110 if not isclosed:
1111 openheads = set(repo.branchmap().iteropen(heads))
1111 openheads = set(repo.branchmap().iteropen(heads))
1112 isactive = bool(openheads & allheads)
1112 isactive = bool(openheads & allheads)
1113 branches.append((tag, repo[tip], isactive, not isclosed))
1113 branches.append((tag, repo[tip], isactive, not isclosed))
1114 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1114 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1115 reverse=True)
1115 reverse=True)
1116
1116
1117 for tag, ctx, isactive, isopen in branches:
1117 for tag, ctx, isactive, isopen in branches:
1118 if active and not isactive:
1118 if active and not isactive:
1119 continue
1119 continue
1120 if isactive:
1120 if isactive:
1121 label = 'branches.active'
1121 label = 'branches.active'
1122 notice = ''
1122 notice = ''
1123 elif not isopen:
1123 elif not isopen:
1124 if not closed:
1124 if not closed:
1125 continue
1125 continue
1126 label = 'branches.closed'
1126 label = 'branches.closed'
1127 notice = _(' (closed)')
1127 notice = _(' (closed)')
1128 else:
1128 else:
1129 label = 'branches.inactive'
1129 label = 'branches.inactive'
1130 notice = _(' (inactive)')
1130 notice = _(' (inactive)')
1131 current = (tag == repo.dirstate.branch())
1131 current = (tag == repo.dirstate.branch())
1132 if current:
1132 if current:
1133 label = 'branches.current'
1133 label = 'branches.current'
1134
1134
1135 fm.startitem()
1135 fm.startitem()
1136 fm.write('branch', '%s', tag, label=label)
1136 fm.write('branch', '%s', tag, label=label)
1137 rev = ctx.rev()
1137 rev = ctx.rev()
1138 padsize = max(31 - len("%d" % rev) - encoding.colwidth(tag), 0)
1138 padsize = max(31 - len("%d" % rev) - encoding.colwidth(tag), 0)
1139 fmt = ' ' * padsize + ' %d:%s'
1139 fmt = ' ' * padsize + ' %d:%s'
1140 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1140 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1141 label='log.changeset changeset.%s' % ctx.phasestr())
1141 label='log.changeset changeset.%s' % ctx.phasestr())
1142 fm.context(ctx=ctx)
1142 fm.context(ctx=ctx)
1143 fm.data(active=isactive, closed=not isopen, current=current)
1143 fm.data(active=isactive, closed=not isopen, current=current)
1144 if not ui.quiet:
1144 if not ui.quiet:
1145 fm.plain(notice)
1145 fm.plain(notice)
1146 fm.plain('\n')
1146 fm.plain('\n')
1147 fm.end()
1147 fm.end()
1148
1148
1149 @command('bundle',
1149 @command('bundle',
1150 [('f', 'force', None, _('run even when the destination is unrelated')),
1150 [('f', 'force', None, _('run even when the destination is unrelated')),
1151 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1151 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1152 _('REV')),
1152 _('REV')),
1153 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1153 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1154 _('BRANCH')),
1154 _('BRANCH')),
1155 ('', 'base', [],
1155 ('', 'base', [],
1156 _('a base changeset assumed to be available at the destination'),
1156 _('a base changeset assumed to be available at the destination'),
1157 _('REV')),
1157 _('REV')),
1158 ('a', 'all', None, _('bundle all changesets in the repository')),
1158 ('a', 'all', None, _('bundle all changesets in the repository')),
1159 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1159 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1160 ] + remoteopts,
1160 ] + remoteopts,
1161 _('[-f] [-t BUNDLESPEC] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1161 _('[-f] [-t BUNDLESPEC] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1162 def bundle(ui, repo, fname, dest=None, **opts):
1162 def bundle(ui, repo, fname, dest=None, **opts):
1163 """create a bundle file
1163 """create a bundle file
1164
1164
1165 Generate a bundle file containing data to be transferred to another
1165 Generate a bundle file containing data to be transferred to another
1166 repository.
1166 repository.
1167
1167
1168 To create a bundle containing all changesets, use -a/--all
1168 To create a bundle containing all changesets, use -a/--all
1169 (or --base null). Otherwise, hg assumes the destination will have
1169 (or --base null). Otherwise, hg assumes the destination will have
1170 all the nodes you specify with --base parameters. Otherwise, hg
1170 all the nodes you specify with --base parameters. Otherwise, hg
1171 will assume the repository has all the nodes in destination, or
1171 will assume the repository has all the nodes in destination, or
1172 default-push/default if no destination is specified, where destination
1172 default-push/default if no destination is specified, where destination
1173 is the repository you provide through DEST option.
1173 is the repository you provide through DEST option.
1174
1174
1175 You can change bundle format with the -t/--type option. See
1175 You can change bundle format with the -t/--type option. See
1176 :hg:`help bundlespec` for documentation on this format. By default,
1176 :hg:`help bundlespec` for documentation on this format. By default,
1177 the most appropriate format is used and compression defaults to
1177 the most appropriate format is used and compression defaults to
1178 bzip2.
1178 bzip2.
1179
1179
1180 The bundle file can then be transferred using conventional means
1180 The bundle file can then be transferred using conventional means
1181 and applied to another repository with the unbundle or pull
1181 and applied to another repository with the unbundle or pull
1182 command. This is useful when direct push and pull are not
1182 command. This is useful when direct push and pull are not
1183 available or when exporting an entire repository is undesirable.
1183 available or when exporting an entire repository is undesirable.
1184
1184
1185 Applying bundles preserves all changeset contents including
1185 Applying bundles preserves all changeset contents including
1186 permissions, copy/rename information, and revision history.
1186 permissions, copy/rename information, and revision history.
1187
1187
1188 Returns 0 on success, 1 if no changes found.
1188 Returns 0 on success, 1 if no changes found.
1189 """
1189 """
1190 opts = pycompat.byteskwargs(opts)
1190 opts = pycompat.byteskwargs(opts)
1191 revs = None
1191 revs = None
1192 if 'rev' in opts:
1192 if 'rev' in opts:
1193 revstrings = opts['rev']
1193 revstrings = opts['rev']
1194 revs = scmutil.revrange(repo, revstrings)
1194 revs = scmutil.revrange(repo, revstrings)
1195 if revstrings and not revs:
1195 if revstrings and not revs:
1196 raise error.Abort(_('no commits to bundle'))
1196 raise error.Abort(_('no commits to bundle'))
1197
1197
1198 bundletype = opts.get('type', 'bzip2').lower()
1198 bundletype = opts.get('type', 'bzip2').lower()
1199 try:
1199 try:
1200 bundlespec = exchange.parsebundlespec(repo, bundletype, strict=False)
1200 bundlespec = exchange.parsebundlespec(repo, bundletype, strict=False)
1201 except error.UnsupportedBundleSpecification as e:
1201 except error.UnsupportedBundleSpecification as e:
1202 raise error.Abort(pycompat.bytestr(e),
1202 raise error.Abort(pycompat.bytestr(e),
1203 hint=_("see 'hg help bundlespec' for supported "
1203 hint=_("see 'hg help bundlespec' for supported "
1204 "values for --type"))
1204 "values for --type"))
1205 cgversion = bundlespec.contentopts["cg.version"]
1205 cgversion = bundlespec.contentopts["cg.version"]
1206
1206
1207 # Packed bundles are a pseudo bundle format for now.
1207 # Packed bundles are a pseudo bundle format for now.
1208 if cgversion == 's1':
1208 if cgversion == 's1':
1209 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1209 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1210 hint=_("use 'hg debugcreatestreamclonebundle'"))
1210 hint=_("use 'hg debugcreatestreamclonebundle'"))
1211
1211
1212 if opts.get('all'):
1212 if opts.get('all'):
1213 if dest:
1213 if dest:
1214 raise error.Abort(_("--all is incompatible with specifying "
1214 raise error.Abort(_("--all is incompatible with specifying "
1215 "a destination"))
1215 "a destination"))
1216 if opts.get('base'):
1216 if opts.get('base'):
1217 ui.warn(_("ignoring --base because --all was specified\n"))
1217 ui.warn(_("ignoring --base because --all was specified\n"))
1218 base = ['null']
1218 base = ['null']
1219 else:
1219 else:
1220 base = scmutil.revrange(repo, opts.get('base'))
1220 base = scmutil.revrange(repo, opts.get('base'))
1221 if cgversion not in changegroup.supportedoutgoingversions(repo):
1221 if cgversion not in changegroup.supportedoutgoingversions(repo):
1222 raise error.Abort(_("repository does not support bundle version %s") %
1222 raise error.Abort(_("repository does not support bundle version %s") %
1223 cgversion)
1223 cgversion)
1224
1224
1225 if base:
1225 if base:
1226 if dest:
1226 if dest:
1227 raise error.Abort(_("--base is incompatible with specifying "
1227 raise error.Abort(_("--base is incompatible with specifying "
1228 "a destination"))
1228 "a destination"))
1229 common = [repo[rev].node() for rev in base]
1229 common = [repo[rev].node() for rev in base]
1230 heads = [repo[r].node() for r in revs] if revs else None
1230 heads = [repo[r].node() for r in revs] if revs else None
1231 outgoing = discovery.outgoing(repo, common, heads)
1231 outgoing = discovery.outgoing(repo, common, heads)
1232 else:
1232 else:
1233 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1233 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1234 dest, branches = hg.parseurl(dest, opts.get('branch'))
1234 dest, branches = hg.parseurl(dest, opts.get('branch'))
1235 other = hg.peer(repo, opts, dest)
1235 other = hg.peer(repo, opts, dest)
1236 revs = [repo[r].hex() for r in revs]
1236 revs = [repo[r].hex() for r in revs]
1237 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1237 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1238 heads = revs and map(repo.lookup, revs) or revs
1238 heads = revs and map(repo.lookup, revs) or revs
1239 outgoing = discovery.findcommonoutgoing(repo, other,
1239 outgoing = discovery.findcommonoutgoing(repo, other,
1240 onlyheads=heads,
1240 onlyheads=heads,
1241 force=opts.get('force'),
1241 force=opts.get('force'),
1242 portable=True)
1242 portable=True)
1243
1243
1244 if not outgoing.missing:
1244 if not outgoing.missing:
1245 scmutil.nochangesfound(ui, repo, not base and outgoing.excluded)
1245 scmutil.nochangesfound(ui, repo, not base and outgoing.excluded)
1246 return 1
1246 return 1
1247
1247
1248 if cgversion == '01': #bundle1
1248 if cgversion == '01': #bundle1
1249 bversion = 'HG10' + bundlespec.wirecompression
1249 bversion = 'HG10' + bundlespec.wirecompression
1250 bcompression = None
1250 bcompression = None
1251 elif cgversion in ('02', '03'):
1251 elif cgversion in ('02', '03'):
1252 bversion = 'HG20'
1252 bversion = 'HG20'
1253 bcompression = bundlespec.wirecompression
1253 bcompression = bundlespec.wirecompression
1254 else:
1254 else:
1255 raise error.ProgrammingError(
1255 raise error.ProgrammingError(
1256 'bundle: unexpected changegroup version %s' % cgversion)
1256 'bundle: unexpected changegroup version %s' % cgversion)
1257
1257
1258 # TODO compression options should be derived from bundlespec parsing.
1258 # TODO compression options should be derived from bundlespec parsing.
1259 # This is a temporary hack to allow adjusting bundle compression
1259 # This is a temporary hack to allow adjusting bundle compression
1260 # level without a) formalizing the bundlespec changes to declare it
1260 # level without a) formalizing the bundlespec changes to declare it
1261 # b) introducing a command flag.
1261 # b) introducing a command flag.
1262 compopts = {}
1262 compopts = {}
1263 complevel = ui.configint('experimental',
1263 complevel = ui.configint('experimental',
1264 'bundlecomplevel.' + bundlespec.compression)
1264 'bundlecomplevel.' + bundlespec.compression)
1265 if complevel is None:
1265 if complevel is None:
1266 complevel = ui.configint('experimental', 'bundlecomplevel')
1266 complevel = ui.configint('experimental', 'bundlecomplevel')
1267 if complevel is not None:
1267 if complevel is not None:
1268 compopts['level'] = complevel
1268 compopts['level'] = complevel
1269
1269
1270 # Allow overriding the bundling of obsmarker in phases through
1270 # Allow overriding the bundling of obsmarker in phases through
1271 # configuration while we don't have a bundle version that include them
1271 # configuration while we don't have a bundle version that include them
1272 if repo.ui.configbool('experimental', 'evolution.bundle-obsmarker'):
1272 if repo.ui.configbool('experimental', 'evolution.bundle-obsmarker'):
1273 bundlespec.contentopts['obsolescence'] = True
1273 bundlespec.contentopts['obsolescence'] = True
1274 if repo.ui.configbool('experimental', 'bundle-phases'):
1274 if repo.ui.configbool('experimental', 'bundle-phases'):
1275 bundlespec.contentopts['phases'] = True
1275 bundlespec.contentopts['phases'] = True
1276
1276
1277 bundle2.writenewbundle(ui, repo, 'bundle', fname, bversion, outgoing,
1277 bundle2.writenewbundle(ui, repo, 'bundle', fname, bversion, outgoing,
1278 bundlespec.contentopts, compression=bcompression,
1278 bundlespec.contentopts, compression=bcompression,
1279 compopts=compopts)
1279 compopts=compopts)
1280
1280
1281 @command('cat',
1281 @command('cat',
1282 [('o', 'output', '',
1282 [('o', 'output', '',
1283 _('print output to file with formatted name'), _('FORMAT')),
1283 _('print output to file with formatted name'), _('FORMAT')),
1284 ('r', 'rev', '', _('print the given revision'), _('REV')),
1284 ('r', 'rev', '', _('print the given revision'), _('REV')),
1285 ('', 'decode', None, _('apply any matching decode filter')),
1285 ('', 'decode', None, _('apply any matching decode filter')),
1286 ] + walkopts + formatteropts,
1286 ] + walkopts + formatteropts,
1287 _('[OPTION]... FILE...'),
1287 _('[OPTION]... FILE...'),
1288 inferrepo=True,
1288 inferrepo=True,
1289 intents={INTENT_READONLY})
1289 intents={INTENT_READONLY})
1290 def cat(ui, repo, file1, *pats, **opts):
1290 def cat(ui, repo, file1, *pats, **opts):
1291 """output the current or given revision of files
1291 """output the current or given revision of files
1292
1292
1293 Print the specified files as they were at the given revision. If
1293 Print the specified files as they were at the given revision. If
1294 no revision is given, the parent of the working directory is used.
1294 no revision is given, the parent of the working directory is used.
1295
1295
1296 Output may be to a file, in which case the name of the file is
1296 Output may be to a file, in which case the name of the file is
1297 given using a template string. See :hg:`help templates`. In addition
1297 given using a template string. See :hg:`help templates`. In addition
1298 to the common template keywords, the following formatting rules are
1298 to the common template keywords, the following formatting rules are
1299 supported:
1299 supported:
1300
1300
1301 :``%%``: literal "%" character
1301 :``%%``: literal "%" character
1302 :``%s``: basename of file being printed
1302 :``%s``: basename of file being printed
1303 :``%d``: dirname of file being printed, or '.' if in repository root
1303 :``%d``: dirname of file being printed, or '.' if in repository root
1304 :``%p``: root-relative path name of file being printed
1304 :``%p``: root-relative path name of file being printed
1305 :``%H``: changeset hash (40 hexadecimal digits)
1305 :``%H``: changeset hash (40 hexadecimal digits)
1306 :``%R``: changeset revision number
1306 :``%R``: changeset revision number
1307 :``%h``: short-form changeset hash (12 hexadecimal digits)
1307 :``%h``: short-form changeset hash (12 hexadecimal digits)
1308 :``%r``: zero-padded changeset revision number
1308 :``%r``: zero-padded changeset revision number
1309 :``%b``: basename of the exporting repository
1309 :``%b``: basename of the exporting repository
1310 :``\\``: literal "\\" character
1310 :``\\``: literal "\\" character
1311
1311
1312 Returns 0 on success.
1312 Returns 0 on success.
1313 """
1313 """
1314 opts = pycompat.byteskwargs(opts)
1314 opts = pycompat.byteskwargs(opts)
1315 rev = opts.get('rev')
1315 rev = opts.get('rev')
1316 if rev:
1316 if rev:
1317 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
1317 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
1318 ctx = scmutil.revsingle(repo, rev)
1318 ctx = scmutil.revsingle(repo, rev)
1319 m = scmutil.match(ctx, (file1,) + pats, opts)
1319 m = scmutil.match(ctx, (file1,) + pats, opts)
1320 fntemplate = opts.pop('output', '')
1320 fntemplate = opts.pop('output', '')
1321 if cmdutil.isstdiofilename(fntemplate):
1321 if cmdutil.isstdiofilename(fntemplate):
1322 fntemplate = ''
1322 fntemplate = ''
1323
1323
1324 if fntemplate:
1324 if fntemplate:
1325 fm = formatter.nullformatter(ui, 'cat', opts)
1325 fm = formatter.nullformatter(ui, 'cat', opts)
1326 else:
1326 else:
1327 ui.pager('cat')
1327 ui.pager('cat')
1328 fm = ui.formatter('cat', opts)
1328 fm = ui.formatter('cat', opts)
1329 with fm:
1329 with fm:
1330 return cmdutil.cat(ui, repo, ctx, m, fm, fntemplate, '',
1330 return cmdutil.cat(ui, repo, ctx, m, fm, fntemplate, '',
1331 **pycompat.strkwargs(opts))
1331 **pycompat.strkwargs(opts))
1332
1332
1333 @command('^clone',
1333 @command('^clone',
1334 [('U', 'noupdate', None, _('the clone will include an empty working '
1334 [('U', 'noupdate', None, _('the clone will include an empty working '
1335 'directory (only a repository)')),
1335 'directory (only a repository)')),
1336 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1336 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1337 _('REV')),
1337 _('REV')),
1338 ('r', 'rev', [], _('do not clone everything, but include this changeset'
1338 ('r', 'rev', [], _('do not clone everything, but include this changeset'
1339 ' and its ancestors'), _('REV')),
1339 ' and its ancestors'), _('REV')),
1340 ('b', 'branch', [], _('do not clone everything, but include this branch\'s'
1340 ('b', 'branch', [], _('do not clone everything, but include this branch\'s'
1341 ' changesets and their ancestors'), _('BRANCH')),
1341 ' changesets and their ancestors'), _('BRANCH')),
1342 ('', 'pull', None, _('use pull protocol to copy metadata')),
1342 ('', 'pull', None, _('use pull protocol to copy metadata')),
1343 ('', 'uncompressed', None,
1343 ('', 'uncompressed', None,
1344 _('an alias to --stream (DEPRECATED)')),
1344 _('an alias to --stream (DEPRECATED)')),
1345 ('', 'stream', None,
1345 ('', 'stream', None,
1346 _('clone with minimal data processing')),
1346 _('clone with minimal data processing')),
1347 ] + remoteopts,
1347 ] + remoteopts,
1348 _('[OPTION]... SOURCE [DEST]'),
1348 _('[OPTION]... SOURCE [DEST]'),
1349 norepo=True)
1349 norepo=True)
1350 def clone(ui, source, dest=None, **opts):
1350 def clone(ui, source, dest=None, **opts):
1351 """make a copy of an existing repository
1351 """make a copy of an existing repository
1352
1352
1353 Create a copy of an existing repository in a new directory.
1353 Create a copy of an existing repository in a new directory.
1354
1354
1355 If no destination directory name is specified, it defaults to the
1355 If no destination directory name is specified, it defaults to the
1356 basename of the source.
1356 basename of the source.
1357
1357
1358 The location of the source is added to the new repository's
1358 The location of the source is added to the new repository's
1359 ``.hg/hgrc`` file, as the default to be used for future pulls.
1359 ``.hg/hgrc`` file, as the default to be used for future pulls.
1360
1360
1361 Only local paths and ``ssh://`` URLs are supported as
1361 Only local paths and ``ssh://`` URLs are supported as
1362 destinations. For ``ssh://`` destinations, no working directory or
1362 destinations. For ``ssh://`` destinations, no working directory or
1363 ``.hg/hgrc`` will be created on the remote side.
1363 ``.hg/hgrc`` will be created on the remote side.
1364
1364
1365 If the source repository has a bookmark called '@' set, that
1365 If the source repository has a bookmark called '@' set, that
1366 revision will be checked out in the new repository by default.
1366 revision will be checked out in the new repository by default.
1367
1367
1368 To check out a particular version, use -u/--update, or
1368 To check out a particular version, use -u/--update, or
1369 -U/--noupdate to create a clone with no working directory.
1369 -U/--noupdate to create a clone with no working directory.
1370
1370
1371 To pull only a subset of changesets, specify one or more revisions
1371 To pull only a subset of changesets, specify one or more revisions
1372 identifiers with -r/--rev or branches with -b/--branch. The
1372 identifiers with -r/--rev or branches with -b/--branch. The
1373 resulting clone will contain only the specified changesets and
1373 resulting clone will contain only the specified changesets and
1374 their ancestors. These options (or 'clone src#rev dest') imply
1374 their ancestors. These options (or 'clone src#rev dest') imply
1375 --pull, even for local source repositories.
1375 --pull, even for local source repositories.
1376
1376
1377 In normal clone mode, the remote normalizes repository data into a common
1377 In normal clone mode, the remote normalizes repository data into a common
1378 exchange format and the receiving end translates this data into its local
1378 exchange format and the receiving end translates this data into its local
1379 storage format. --stream activates a different clone mode that essentially
1379 storage format. --stream activates a different clone mode that essentially
1380 copies repository files from the remote with minimal data processing. This
1380 copies repository files from the remote with minimal data processing. This
1381 significantly reduces the CPU cost of a clone both remotely and locally.
1381 significantly reduces the CPU cost of a clone both remotely and locally.
1382 However, it often increases the transferred data size by 30-40%. This can
1382 However, it often increases the transferred data size by 30-40%. This can
1383 result in substantially faster clones where I/O throughput is plentiful,
1383 result in substantially faster clones where I/O throughput is plentiful,
1384 especially for larger repositories. A side-effect of --stream clones is
1384 especially for larger repositories. A side-effect of --stream clones is
1385 that storage settings and requirements on the remote are applied locally:
1385 that storage settings and requirements on the remote are applied locally:
1386 a modern client may inherit legacy or inefficient storage used by the
1386 a modern client may inherit legacy or inefficient storage used by the
1387 remote or a legacy Mercurial client may not be able to clone from a
1387 remote or a legacy Mercurial client may not be able to clone from a
1388 modern Mercurial remote.
1388 modern Mercurial remote.
1389
1389
1390 .. note::
1390 .. note::
1391
1391
1392 Specifying a tag will include the tagged changeset but not the
1392 Specifying a tag will include the tagged changeset but not the
1393 changeset containing the tag.
1393 changeset containing the tag.
1394
1394
1395 .. container:: verbose
1395 .. container:: verbose
1396
1396
1397 For efficiency, hardlinks are used for cloning whenever the
1397 For efficiency, hardlinks are used for cloning whenever the
1398 source and destination are on the same filesystem (note this
1398 source and destination are on the same filesystem (note this
1399 applies only to the repository data, not to the working
1399 applies only to the repository data, not to the working
1400 directory). Some filesystems, such as AFS, implement hardlinking
1400 directory). Some filesystems, such as AFS, implement hardlinking
1401 incorrectly, but do not report errors. In these cases, use the
1401 incorrectly, but do not report errors. In these cases, use the
1402 --pull option to avoid hardlinking.
1402 --pull option to avoid hardlinking.
1403
1403
1404 Mercurial will update the working directory to the first applicable
1404 Mercurial will update the working directory to the first applicable
1405 revision from this list:
1405 revision from this list:
1406
1406
1407 a) null if -U or the source repository has no changesets
1407 a) null if -U or the source repository has no changesets
1408 b) if -u . and the source repository is local, the first parent of
1408 b) if -u . and the source repository is local, the first parent of
1409 the source repository's working directory
1409 the source repository's working directory
1410 c) the changeset specified with -u (if a branch name, this means the
1410 c) the changeset specified with -u (if a branch name, this means the
1411 latest head of that branch)
1411 latest head of that branch)
1412 d) the changeset specified with -r
1412 d) the changeset specified with -r
1413 e) the tipmost head specified with -b
1413 e) the tipmost head specified with -b
1414 f) the tipmost head specified with the url#branch source syntax
1414 f) the tipmost head specified with the url#branch source syntax
1415 g) the revision marked with the '@' bookmark, if present
1415 g) the revision marked with the '@' bookmark, if present
1416 h) the tipmost head of the default branch
1416 h) the tipmost head of the default branch
1417 i) tip
1417 i) tip
1418
1418
1419 When cloning from servers that support it, Mercurial may fetch
1419 When cloning from servers that support it, Mercurial may fetch
1420 pre-generated data from a server-advertised URL or inline from the
1420 pre-generated data from a server-advertised URL or inline from the
1421 same stream. When this is done, hooks operating on incoming changesets
1421 same stream. When this is done, hooks operating on incoming changesets
1422 and changegroups may fire more than once, once for each pre-generated
1422 and changegroups may fire more than once, once for each pre-generated
1423 bundle and as well as for any additional remaining data. In addition,
1423 bundle and as well as for any additional remaining data. In addition,
1424 if an error occurs, the repository may be rolled back to a partial
1424 if an error occurs, the repository may be rolled back to a partial
1425 clone. This behavior may change in future releases.
1425 clone. This behavior may change in future releases.
1426 See :hg:`help -e clonebundles` for more.
1426 See :hg:`help -e clonebundles` for more.
1427
1427
1428 Examples:
1428 Examples:
1429
1429
1430 - clone a remote repository to a new directory named hg/::
1430 - clone a remote repository to a new directory named hg/::
1431
1431
1432 hg clone https://www.mercurial-scm.org/repo/hg/
1432 hg clone https://www.mercurial-scm.org/repo/hg/
1433
1433
1434 - create a lightweight local clone::
1434 - create a lightweight local clone::
1435
1435
1436 hg clone project/ project-feature/
1436 hg clone project/ project-feature/
1437
1437
1438 - clone from an absolute path on an ssh server (note double-slash)::
1438 - clone from an absolute path on an ssh server (note double-slash)::
1439
1439
1440 hg clone ssh://user@server//home/projects/alpha/
1440 hg clone ssh://user@server//home/projects/alpha/
1441
1441
1442 - do a streaming clone while checking out a specified version::
1442 - do a streaming clone while checking out a specified version::
1443
1443
1444 hg clone --stream http://server/repo -u 1.5
1444 hg clone --stream http://server/repo -u 1.5
1445
1445
1446 - create a repository without changesets after a particular revision::
1446 - create a repository without changesets after a particular revision::
1447
1447
1448 hg clone -r 04e544 experimental/ good/
1448 hg clone -r 04e544 experimental/ good/
1449
1449
1450 - clone (and track) a particular named branch::
1450 - clone (and track) a particular named branch::
1451
1451
1452 hg clone https://www.mercurial-scm.org/repo/hg/#stable
1452 hg clone https://www.mercurial-scm.org/repo/hg/#stable
1453
1453
1454 See :hg:`help urls` for details on specifying URLs.
1454 See :hg:`help urls` for details on specifying URLs.
1455
1455
1456 Returns 0 on success.
1456 Returns 0 on success.
1457 """
1457 """
1458 opts = pycompat.byteskwargs(opts)
1458 opts = pycompat.byteskwargs(opts)
1459 if opts.get('noupdate') and opts.get('updaterev'):
1459 if opts.get('noupdate') and opts.get('updaterev'):
1460 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1460 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1461
1461
1462 r = hg.clone(ui, opts, source, dest,
1462 r = hg.clone(ui, opts, source, dest,
1463 pull=opts.get('pull'),
1463 pull=opts.get('pull'),
1464 stream=opts.get('stream') or opts.get('uncompressed'),
1464 stream=opts.get('stream') or opts.get('uncompressed'),
1465 revs=opts.get('rev'),
1465 revs=opts.get('rev'),
1466 update=opts.get('updaterev') or not opts.get('noupdate'),
1466 update=opts.get('updaterev') or not opts.get('noupdate'),
1467 branch=opts.get('branch'),
1467 branch=opts.get('branch'),
1468 shareopts=opts.get('shareopts'))
1468 shareopts=opts.get('shareopts'))
1469
1469
1470 return r is None
1470 return r is None
1471
1471
1472 @command('^commit|ci',
1472 @command('^commit|ci',
1473 [('A', 'addremove', None,
1473 [('A', 'addremove', None,
1474 _('mark new/missing files as added/removed before committing')),
1474 _('mark new/missing files as added/removed before committing')),
1475 ('', 'close-branch', None,
1475 ('', 'close-branch', None,
1476 _('mark a branch head as closed')),
1476 _('mark a branch head as closed')),
1477 ('', 'amend', None, _('amend the parent of the working directory')),
1477 ('', 'amend', None, _('amend the parent of the working directory')),
1478 ('s', 'secret', None, _('use the secret phase for committing')),
1478 ('s', 'secret', None, _('use the secret phase for committing')),
1479 ('e', 'edit', None, _('invoke editor on commit messages')),
1479 ('e', 'edit', None, _('invoke editor on commit messages')),
1480 ('i', 'interactive', None, _('use interactive mode')),
1480 ('i', 'interactive', None, _('use interactive mode')),
1481 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1481 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1482 _('[OPTION]... [FILE]...'),
1482 _('[OPTION]... [FILE]...'),
1483 inferrepo=True)
1483 inferrepo=True)
1484 def commit(ui, repo, *pats, **opts):
1484 def commit(ui, repo, *pats, **opts):
1485 """commit the specified files or all outstanding changes
1485 """commit the specified files or all outstanding changes
1486
1486
1487 Commit changes to the given files into the repository. Unlike a
1487 Commit changes to the given files into the repository. Unlike a
1488 centralized SCM, this operation is a local operation. See
1488 centralized SCM, this operation is a local operation. See
1489 :hg:`push` for a way to actively distribute your changes.
1489 :hg:`push` for a way to actively distribute your changes.
1490
1490
1491 If a list of files is omitted, all changes reported by :hg:`status`
1491 If a list of files is omitted, all changes reported by :hg:`status`
1492 will be committed.
1492 will be committed.
1493
1493
1494 If you are committing the result of a merge, do not provide any
1494 If you are committing the result of a merge, do not provide any
1495 filenames or -I/-X filters.
1495 filenames or -I/-X filters.
1496
1496
1497 If no commit message is specified, Mercurial starts your
1497 If no commit message is specified, Mercurial starts your
1498 configured editor where you can enter a message. In case your
1498 configured editor where you can enter a message. In case your
1499 commit fails, you will find a backup of your message in
1499 commit fails, you will find a backup of your message in
1500 ``.hg/last-message.txt``.
1500 ``.hg/last-message.txt``.
1501
1501
1502 The --close-branch flag can be used to mark the current branch
1502 The --close-branch flag can be used to mark the current branch
1503 head closed. When all heads of a branch are closed, the branch
1503 head closed. When all heads of a branch are closed, the branch
1504 will be considered closed and no longer listed.
1504 will be considered closed and no longer listed.
1505
1505
1506 The --amend flag can be used to amend the parent of the
1506 The --amend flag can be used to amend the parent of the
1507 working directory with a new commit that contains the changes
1507 working directory with a new commit that contains the changes
1508 in the parent in addition to those currently reported by :hg:`status`,
1508 in the parent in addition to those currently reported by :hg:`status`,
1509 if there are any. The old commit is stored in a backup bundle in
1509 if there are any. The old commit is stored in a backup bundle in
1510 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1510 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1511 on how to restore it).
1511 on how to restore it).
1512
1512
1513 Message, user and date are taken from the amended commit unless
1513 Message, user and date are taken from the amended commit unless
1514 specified. When a message isn't specified on the command line,
1514 specified. When a message isn't specified on the command line,
1515 the editor will open with the message of the amended commit.
1515 the editor will open with the message of the amended commit.
1516
1516
1517 It is not possible to amend public changesets (see :hg:`help phases`)
1517 It is not possible to amend public changesets (see :hg:`help phases`)
1518 or changesets that have children.
1518 or changesets that have children.
1519
1519
1520 See :hg:`help dates` for a list of formats valid for -d/--date.
1520 See :hg:`help dates` for a list of formats valid for -d/--date.
1521
1521
1522 Returns 0 on success, 1 if nothing changed.
1522 Returns 0 on success, 1 if nothing changed.
1523
1523
1524 .. container:: verbose
1524 .. container:: verbose
1525
1525
1526 Examples:
1526 Examples:
1527
1527
1528 - commit all files ending in .py::
1528 - commit all files ending in .py::
1529
1529
1530 hg commit --include "set:**.py"
1530 hg commit --include "set:**.py"
1531
1531
1532 - commit all non-binary files::
1532 - commit all non-binary files::
1533
1533
1534 hg commit --exclude "set:binary()"
1534 hg commit --exclude "set:binary()"
1535
1535
1536 - amend the current commit and set the date to now::
1536 - amend the current commit and set the date to now::
1537
1537
1538 hg commit --amend --date now
1538 hg commit --amend --date now
1539 """
1539 """
1540 wlock = lock = None
1540 wlock = lock = None
1541 try:
1541 try:
1542 wlock = repo.wlock()
1542 wlock = repo.wlock()
1543 lock = repo.lock()
1543 lock = repo.lock()
1544 return _docommit(ui, repo, *pats, **opts)
1544 return _docommit(ui, repo, *pats, **opts)
1545 finally:
1545 finally:
1546 release(lock, wlock)
1546 release(lock, wlock)
1547
1547
1548 def _docommit(ui, repo, *pats, **opts):
1548 def _docommit(ui, repo, *pats, **opts):
1549 if opts.get(r'interactive'):
1549 if opts.get(r'interactive'):
1550 opts.pop(r'interactive')
1550 opts.pop(r'interactive')
1551 ret = cmdutil.dorecord(ui, repo, commit, None, False,
1551 ret = cmdutil.dorecord(ui, repo, commit, None, False,
1552 cmdutil.recordfilter, *pats,
1552 cmdutil.recordfilter, *pats,
1553 **opts)
1553 **opts)
1554 # ret can be 0 (no changes to record) or the value returned by
1554 # ret can be 0 (no changes to record) or the value returned by
1555 # commit(), 1 if nothing changed or None on success.
1555 # commit(), 1 if nothing changed or None on success.
1556 return 1 if ret == 0 else ret
1556 return 1 if ret == 0 else ret
1557
1557
1558 opts = pycompat.byteskwargs(opts)
1558 opts = pycompat.byteskwargs(opts)
1559 if opts.get('subrepos'):
1559 if opts.get('subrepos'):
1560 if opts.get('amend'):
1560 if opts.get('amend'):
1561 raise error.Abort(_('cannot amend with --subrepos'))
1561 raise error.Abort(_('cannot amend with --subrepos'))
1562 # Let --subrepos on the command line override config setting.
1562 # Let --subrepos on the command line override config setting.
1563 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1563 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1564
1564
1565 cmdutil.checkunfinished(repo, commit=True)
1565 cmdutil.checkunfinished(repo, commit=True)
1566
1566
1567 branch = repo[None].branch()
1567 branch = repo[None].branch()
1568 bheads = repo.branchheads(branch)
1568 bheads = repo.branchheads(branch)
1569
1569
1570 extra = {}
1570 extra = {}
1571 if opts.get('close_branch'):
1571 if opts.get('close_branch'):
1572 extra['close'] = '1'
1572 extra['close'] = '1'
1573
1573
1574 if not bheads:
1574 if not bheads:
1575 raise error.Abort(_('can only close branch heads'))
1575 raise error.Abort(_('can only close branch heads'))
1576 elif opts.get('amend'):
1576 elif opts.get('amend'):
1577 if repo[None].parents()[0].p1().branch() != branch and \
1577 if repo[None].parents()[0].p1().branch() != branch and \
1578 repo[None].parents()[0].p2().branch() != branch:
1578 repo[None].parents()[0].p2().branch() != branch:
1579 raise error.Abort(_('can only close branch heads'))
1579 raise error.Abort(_('can only close branch heads'))
1580
1580
1581 if opts.get('amend'):
1581 if opts.get('amend'):
1582 if ui.configbool('ui', 'commitsubrepos'):
1582 if ui.configbool('ui', 'commitsubrepos'):
1583 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1583 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1584
1584
1585 old = repo['.']
1585 old = repo['.']
1586 rewriteutil.precheck(repo, [old.rev()], 'amend')
1586 rewriteutil.precheck(repo, [old.rev()], 'amend')
1587
1587
1588 # Currently histedit gets confused if an amend happens while histedit
1588 # Currently histedit gets confused if an amend happens while histedit
1589 # is in progress. Since we have a checkunfinished command, we are
1589 # is in progress. Since we have a checkunfinished command, we are
1590 # temporarily honoring it.
1590 # temporarily honoring it.
1591 #
1591 #
1592 # Note: eventually this guard will be removed. Please do not expect
1592 # Note: eventually this guard will be removed. Please do not expect
1593 # this behavior to remain.
1593 # this behavior to remain.
1594 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
1594 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
1595 cmdutil.checkunfinished(repo)
1595 cmdutil.checkunfinished(repo)
1596
1596
1597 node = cmdutil.amend(ui, repo, old, extra, pats, opts)
1597 node = cmdutil.amend(ui, repo, old, extra, pats, opts)
1598 if node == old.node():
1598 if node == old.node():
1599 ui.status(_("nothing changed\n"))
1599 ui.status(_("nothing changed\n"))
1600 return 1
1600 return 1
1601 else:
1601 else:
1602 def commitfunc(ui, repo, message, match, opts):
1602 def commitfunc(ui, repo, message, match, opts):
1603 overrides = {}
1603 overrides = {}
1604 if opts.get('secret'):
1604 if opts.get('secret'):
1605 overrides[('phases', 'new-commit')] = 'secret'
1605 overrides[('phases', 'new-commit')] = 'secret'
1606
1606
1607 baseui = repo.baseui
1607 baseui = repo.baseui
1608 with baseui.configoverride(overrides, 'commit'):
1608 with baseui.configoverride(overrides, 'commit'):
1609 with ui.configoverride(overrides, 'commit'):
1609 with ui.configoverride(overrides, 'commit'):
1610 editform = cmdutil.mergeeditform(repo[None],
1610 editform = cmdutil.mergeeditform(repo[None],
1611 'commit.normal')
1611 'commit.normal')
1612 editor = cmdutil.getcommiteditor(
1612 editor = cmdutil.getcommiteditor(
1613 editform=editform, **pycompat.strkwargs(opts))
1613 editform=editform, **pycompat.strkwargs(opts))
1614 return repo.commit(message,
1614 return repo.commit(message,
1615 opts.get('user'),
1615 opts.get('user'),
1616 opts.get('date'),
1616 opts.get('date'),
1617 match,
1617 match,
1618 editor=editor,
1618 editor=editor,
1619 extra=extra)
1619 extra=extra)
1620
1620
1621 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1621 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1622
1622
1623 if not node:
1623 if not node:
1624 stat = cmdutil.postcommitstatus(repo, pats, opts)
1624 stat = cmdutil.postcommitstatus(repo, pats, opts)
1625 if stat[3]:
1625 if stat[3]:
1626 ui.status(_("nothing changed (%d missing files, see "
1626 ui.status(_("nothing changed (%d missing files, see "
1627 "'hg status')\n") % len(stat[3]))
1627 "'hg status')\n") % len(stat[3]))
1628 else:
1628 else:
1629 ui.status(_("nothing changed\n"))
1629 ui.status(_("nothing changed\n"))
1630 return 1
1630 return 1
1631
1631
1632 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1632 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1633
1633
1634 @command('config|showconfig|debugconfig',
1634 @command('config|showconfig|debugconfig',
1635 [('u', 'untrusted', None, _('show untrusted configuration options')),
1635 [('u', 'untrusted', None, _('show untrusted configuration options')),
1636 ('e', 'edit', None, _('edit user config')),
1636 ('e', 'edit', None, _('edit user config')),
1637 ('l', 'local', None, _('edit repository config')),
1637 ('l', 'local', None, _('edit repository config')),
1638 ('g', 'global', None, _('edit global config'))] + formatteropts,
1638 ('g', 'global', None, _('edit global config'))] + formatteropts,
1639 _('[-u] [NAME]...'),
1639 _('[-u] [NAME]...'),
1640 optionalrepo=True,
1640 optionalrepo=True,
1641 intents={INTENT_READONLY})
1641 intents={INTENT_READONLY})
1642 def config(ui, repo, *values, **opts):
1642 def config(ui, repo, *values, **opts):
1643 """show combined config settings from all hgrc files
1643 """show combined config settings from all hgrc files
1644
1644
1645 With no arguments, print names and values of all config items.
1645 With no arguments, print names and values of all config items.
1646
1646
1647 With one argument of the form section.name, print just the value
1647 With one argument of the form section.name, print just the value
1648 of that config item.
1648 of that config item.
1649
1649
1650 With multiple arguments, print names and values of all config
1650 With multiple arguments, print names and values of all config
1651 items with matching section names or section.names.
1651 items with matching section names or section.names.
1652
1652
1653 With --edit, start an editor on the user-level config file. With
1653 With --edit, start an editor on the user-level config file. With
1654 --global, edit the system-wide config file. With --local, edit the
1654 --global, edit the system-wide config file. With --local, edit the
1655 repository-level config file.
1655 repository-level config file.
1656
1656
1657 With --debug, the source (filename and line number) is printed
1657 With --debug, the source (filename and line number) is printed
1658 for each config item.
1658 for each config item.
1659
1659
1660 See :hg:`help config` for more information about config files.
1660 See :hg:`help config` for more information about config files.
1661
1661
1662 Returns 0 on success, 1 if NAME does not exist.
1662 Returns 0 on success, 1 if NAME does not exist.
1663
1663
1664 """
1664 """
1665
1665
1666 opts = pycompat.byteskwargs(opts)
1666 opts = pycompat.byteskwargs(opts)
1667 if opts.get('edit') or opts.get('local') or opts.get('global'):
1667 if opts.get('edit') or opts.get('local') or opts.get('global'):
1668 if opts.get('local') and opts.get('global'):
1668 if opts.get('local') and opts.get('global'):
1669 raise error.Abort(_("can't use --local and --global together"))
1669 raise error.Abort(_("can't use --local and --global together"))
1670
1670
1671 if opts.get('local'):
1671 if opts.get('local'):
1672 if not repo:
1672 if not repo:
1673 raise error.Abort(_("can't use --local outside a repository"))
1673 raise error.Abort(_("can't use --local outside a repository"))
1674 paths = [repo.vfs.join('hgrc')]
1674 paths = [repo.vfs.join('hgrc')]
1675 elif opts.get('global'):
1675 elif opts.get('global'):
1676 paths = rcutil.systemrcpath()
1676 paths = rcutil.systemrcpath()
1677 else:
1677 else:
1678 paths = rcutil.userrcpath()
1678 paths = rcutil.userrcpath()
1679
1679
1680 for f in paths:
1680 for f in paths:
1681 if os.path.exists(f):
1681 if os.path.exists(f):
1682 break
1682 break
1683 else:
1683 else:
1684 if opts.get('global'):
1684 if opts.get('global'):
1685 samplehgrc = uimod.samplehgrcs['global']
1685 samplehgrc = uimod.samplehgrcs['global']
1686 elif opts.get('local'):
1686 elif opts.get('local'):
1687 samplehgrc = uimod.samplehgrcs['local']
1687 samplehgrc = uimod.samplehgrcs['local']
1688 else:
1688 else:
1689 samplehgrc = uimod.samplehgrcs['user']
1689 samplehgrc = uimod.samplehgrcs['user']
1690
1690
1691 f = paths[0]
1691 f = paths[0]
1692 fp = open(f, "wb")
1692 fp = open(f, "wb")
1693 fp.write(util.tonativeeol(samplehgrc))
1693 fp.write(util.tonativeeol(samplehgrc))
1694 fp.close()
1694 fp.close()
1695
1695
1696 editor = ui.geteditor()
1696 editor = ui.geteditor()
1697 ui.system("%s \"%s\"" % (editor, f),
1697 ui.system("%s \"%s\"" % (editor, f),
1698 onerr=error.Abort, errprefix=_("edit failed"),
1698 onerr=error.Abort, errprefix=_("edit failed"),
1699 blockedtag='config_edit')
1699 blockedtag='config_edit')
1700 return
1700 return
1701 ui.pager('config')
1701 ui.pager('config')
1702 fm = ui.formatter('config', opts)
1702 fm = ui.formatter('config', opts)
1703 for t, f in rcutil.rccomponents():
1703 for t, f in rcutil.rccomponents():
1704 if t == 'path':
1704 if t == 'path':
1705 ui.debug('read config from: %s\n' % f)
1705 ui.debug('read config from: %s\n' % f)
1706 elif t == 'items':
1706 elif t == 'items':
1707 for section, name, value, source in f:
1707 for section, name, value, source in f:
1708 ui.debug('set config by: %s\n' % source)
1708 ui.debug('set config by: %s\n' % source)
1709 else:
1709 else:
1710 raise error.ProgrammingError('unknown rctype: %s' % t)
1710 raise error.ProgrammingError('unknown rctype: %s' % t)
1711 untrusted = bool(opts.get('untrusted'))
1711 untrusted = bool(opts.get('untrusted'))
1712
1712
1713 selsections = selentries = []
1713 selsections = selentries = []
1714 if values:
1714 if values:
1715 selsections = [v for v in values if '.' not in v]
1715 selsections = [v for v in values if '.' not in v]
1716 selentries = [v for v in values if '.' in v]
1716 selentries = [v for v in values if '.' in v]
1717 uniquesel = (len(selentries) == 1 and not selsections)
1717 uniquesel = (len(selentries) == 1 and not selsections)
1718 selsections = set(selsections)
1718 selsections = set(selsections)
1719 selentries = set(selentries)
1719 selentries = set(selentries)
1720
1720
1721 matched = False
1721 matched = False
1722 for section, name, value in ui.walkconfig(untrusted=untrusted):
1722 for section, name, value in ui.walkconfig(untrusted=untrusted):
1723 source = ui.configsource(section, name, untrusted)
1723 source = ui.configsource(section, name, untrusted)
1724 value = pycompat.bytestr(value)
1724 value = pycompat.bytestr(value)
1725 if fm.isplain():
1725 if fm.isplain():
1726 source = source or 'none'
1726 source = source or 'none'
1727 value = value.replace('\n', '\\n')
1727 value = value.replace('\n', '\\n')
1728 entryname = section + '.' + name
1728 entryname = section + '.' + name
1729 if values and not (section in selsections or entryname in selentries):
1729 if values and not (section in selsections or entryname in selentries):
1730 continue
1730 continue
1731 fm.startitem()
1731 fm.startitem()
1732 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1732 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1733 if uniquesel:
1733 if uniquesel:
1734 fm.data(name=entryname)
1734 fm.data(name=entryname)
1735 fm.write('value', '%s\n', value)
1735 fm.write('value', '%s\n', value)
1736 else:
1736 else:
1737 fm.write('name value', '%s=%s\n', entryname, value)
1737 fm.write('name value', '%s=%s\n', entryname, value)
1738 matched = True
1738 matched = True
1739 fm.end()
1739 fm.end()
1740 if matched:
1740 if matched:
1741 return 0
1741 return 0
1742 return 1
1742 return 1
1743
1743
1744 @command('copy|cp',
1744 @command('copy|cp',
1745 [('A', 'after', None, _('record a copy that has already occurred')),
1745 [('A', 'after', None, _('record a copy that has already occurred')),
1746 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1746 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1747 ] + walkopts + dryrunopts,
1747 ] + walkopts + dryrunopts,
1748 _('[OPTION]... [SOURCE]... DEST'))
1748 _('[OPTION]... [SOURCE]... DEST'))
1749 def copy(ui, repo, *pats, **opts):
1749 def copy(ui, repo, *pats, **opts):
1750 """mark files as copied for the next commit
1750 """mark files as copied for the next commit
1751
1751
1752 Mark dest as having copies of source files. If dest is a
1752 Mark dest as having copies of source files. If dest is a
1753 directory, copies are put in that directory. If dest is a file,
1753 directory, copies are put in that directory. If dest is a file,
1754 the source must be a single file.
1754 the source must be a single file.
1755
1755
1756 By default, this command copies the contents of files as they
1756 By default, this command copies the contents of files as they
1757 exist in the working directory. If invoked with -A/--after, the
1757 exist in the working directory. If invoked with -A/--after, the
1758 operation is recorded, but no copying is performed.
1758 operation is recorded, but no copying is performed.
1759
1759
1760 This command takes effect with the next commit. To undo a copy
1760 This command takes effect with the next commit. To undo a copy
1761 before that, see :hg:`revert`.
1761 before that, see :hg:`revert`.
1762
1762
1763 Returns 0 on success, 1 if errors are encountered.
1763 Returns 0 on success, 1 if errors are encountered.
1764 """
1764 """
1765 opts = pycompat.byteskwargs(opts)
1765 opts = pycompat.byteskwargs(opts)
1766 with repo.wlock(False):
1766 with repo.wlock(False):
1767 return cmdutil.copy(ui, repo, pats, opts)
1767 return cmdutil.copy(ui, repo, pats, opts)
1768
1768
1769 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1769 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1770 def debugcommands(ui, cmd='', *args):
1770 def debugcommands(ui, cmd='', *args):
1771 """list all available commands and options"""
1771 """list all available commands and options"""
1772 for cmd, vals in sorted(table.iteritems()):
1772 for cmd, vals in sorted(table.iteritems()):
1773 cmd = cmd.split('|')[0].strip('^')
1773 cmd = cmd.split('|')[0].strip('^')
1774 opts = ', '.join([i[1] for i in vals[1]])
1774 opts = ', '.join([i[1] for i in vals[1]])
1775 ui.write('%s: %s\n' % (cmd, opts))
1775 ui.write('%s: %s\n' % (cmd, opts))
1776
1776
1777 @command('debugcomplete',
1777 @command('debugcomplete',
1778 [('o', 'options', None, _('show the command options'))],
1778 [('o', 'options', None, _('show the command options'))],
1779 _('[-o] CMD'),
1779 _('[-o] CMD'),
1780 norepo=True)
1780 norepo=True)
1781 def debugcomplete(ui, cmd='', **opts):
1781 def debugcomplete(ui, cmd='', **opts):
1782 """returns the completion list associated with the given command"""
1782 """returns the completion list associated with the given command"""
1783
1783
1784 if opts.get(r'options'):
1784 if opts.get(r'options'):
1785 options = []
1785 options = []
1786 otables = [globalopts]
1786 otables = [globalopts]
1787 if cmd:
1787 if cmd:
1788 aliases, entry = cmdutil.findcmd(cmd, table, False)
1788 aliases, entry = cmdutil.findcmd(cmd, table, False)
1789 otables.append(entry[1])
1789 otables.append(entry[1])
1790 for t in otables:
1790 for t in otables:
1791 for o in t:
1791 for o in t:
1792 if "(DEPRECATED)" in o[3]:
1792 if "(DEPRECATED)" in o[3]:
1793 continue
1793 continue
1794 if o[0]:
1794 if o[0]:
1795 options.append('-%s' % o[0])
1795 options.append('-%s' % o[0])
1796 options.append('--%s' % o[1])
1796 options.append('--%s' % o[1])
1797 ui.write("%s\n" % "\n".join(options))
1797 ui.write("%s\n" % "\n".join(options))
1798 return
1798 return
1799
1799
1800 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
1800 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
1801 if ui.verbose:
1801 if ui.verbose:
1802 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1802 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1803 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1803 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1804
1804
1805 @command('^diff',
1805 @command('^diff',
1806 [('r', 'rev', [], _('revision'), _('REV')),
1806 [('r', 'rev', [], _('revision'), _('REV')),
1807 ('c', 'change', '', _('change made by revision'), _('REV'))
1807 ('c', 'change', '', _('change made by revision'), _('REV'))
1808 ] + diffopts + diffopts2 + walkopts + subrepoopts,
1808 ] + diffopts + diffopts2 + walkopts + subrepoopts,
1809 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
1809 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
1810 inferrepo=True,
1810 inferrepo=True,
1811 intents={INTENT_READONLY})
1811 intents={INTENT_READONLY})
1812 def diff(ui, repo, *pats, **opts):
1812 def diff(ui, repo, *pats, **opts):
1813 """diff repository (or selected files)
1813 """diff repository (or selected files)
1814
1814
1815 Show differences between revisions for the specified files.
1815 Show differences between revisions for the specified files.
1816
1816
1817 Differences between files are shown using the unified diff format.
1817 Differences between files are shown using the unified diff format.
1818
1818
1819 .. note::
1819 .. note::
1820
1820
1821 :hg:`diff` may generate unexpected results for merges, as it will
1821 :hg:`diff` may generate unexpected results for merges, as it will
1822 default to comparing against the working directory's first
1822 default to comparing against the working directory's first
1823 parent changeset if no revisions are specified.
1823 parent changeset if no revisions are specified.
1824
1824
1825 When two revision arguments are given, then changes are shown
1825 When two revision arguments are given, then changes are shown
1826 between those revisions. If only one revision is specified then
1826 between those revisions. If only one revision is specified then
1827 that revision is compared to the working directory, and, when no
1827 that revision is compared to the working directory, and, when no
1828 revisions are specified, the working directory files are compared
1828 revisions are specified, the working directory files are compared
1829 to its first parent.
1829 to its first parent.
1830
1830
1831 Alternatively you can specify -c/--change with a revision to see
1831 Alternatively you can specify -c/--change with a revision to see
1832 the changes in that changeset relative to its first parent.
1832 the changes in that changeset relative to its first parent.
1833
1833
1834 Without the -a/--text option, diff will avoid generating diffs of
1834 Without the -a/--text option, diff will avoid generating diffs of
1835 files it detects as binary. With -a, diff will generate a diff
1835 files it detects as binary. With -a, diff will generate a diff
1836 anyway, probably with undesirable results.
1836 anyway, probably with undesirable results.
1837
1837
1838 Use the -g/--git option to generate diffs in the git extended diff
1838 Use the -g/--git option to generate diffs in the git extended diff
1839 format. For more information, read :hg:`help diffs`.
1839 format. For more information, read :hg:`help diffs`.
1840
1840
1841 .. container:: verbose
1841 .. container:: verbose
1842
1842
1843 Examples:
1843 Examples:
1844
1844
1845 - compare a file in the current working directory to its parent::
1845 - compare a file in the current working directory to its parent::
1846
1846
1847 hg diff foo.c
1847 hg diff foo.c
1848
1848
1849 - compare two historical versions of a directory, with rename info::
1849 - compare two historical versions of a directory, with rename info::
1850
1850
1851 hg diff --git -r 1.0:1.2 lib/
1851 hg diff --git -r 1.0:1.2 lib/
1852
1852
1853 - get change stats relative to the last change on some date::
1853 - get change stats relative to the last change on some date::
1854
1854
1855 hg diff --stat -r "date('may 2')"
1855 hg diff --stat -r "date('may 2')"
1856
1856
1857 - diff all newly-added files that contain a keyword::
1857 - diff all newly-added files that contain a keyword::
1858
1858
1859 hg diff "set:added() and grep(GNU)"
1859 hg diff "set:added() and grep(GNU)"
1860
1860
1861 - compare a revision and its parents::
1861 - compare a revision and its parents::
1862
1862
1863 hg diff -c 9353 # compare against first parent
1863 hg diff -c 9353 # compare against first parent
1864 hg diff -r 9353^:9353 # same using revset syntax
1864 hg diff -r 9353^:9353 # same using revset syntax
1865 hg diff -r 9353^2:9353 # compare against the second parent
1865 hg diff -r 9353^2:9353 # compare against the second parent
1866
1866
1867 Returns 0 on success.
1867 Returns 0 on success.
1868 """
1868 """
1869
1869
1870 opts = pycompat.byteskwargs(opts)
1870 opts = pycompat.byteskwargs(opts)
1871 revs = opts.get('rev')
1871 revs = opts.get('rev')
1872 change = opts.get('change')
1872 change = opts.get('change')
1873 stat = opts.get('stat')
1873 stat = opts.get('stat')
1874 reverse = opts.get('reverse')
1874 reverse = opts.get('reverse')
1875
1875
1876 if revs and change:
1876 if revs and change:
1877 msg = _('cannot specify --rev and --change at the same time')
1877 msg = _('cannot specify --rev and --change at the same time')
1878 raise error.Abort(msg)
1878 raise error.Abort(msg)
1879 elif change:
1879 elif change:
1880 repo = scmutil.unhidehashlikerevs(repo, [change], 'nowarn')
1880 repo = scmutil.unhidehashlikerevs(repo, [change], 'nowarn')
1881 ctx2 = scmutil.revsingle(repo, change, None)
1881 ctx2 = scmutil.revsingle(repo, change, None)
1882 ctx1 = ctx2.p1()
1882 ctx1 = ctx2.p1()
1883 else:
1883 else:
1884 repo = scmutil.unhidehashlikerevs(repo, revs, 'nowarn')
1884 repo = scmutil.unhidehashlikerevs(repo, revs, 'nowarn')
1885 ctx1, ctx2 = scmutil.revpair(repo, revs)
1885 ctx1, ctx2 = scmutil.revpair(repo, revs)
1886 node1, node2 = ctx1.node(), ctx2.node()
1886 node1, node2 = ctx1.node(), ctx2.node()
1887
1887
1888 if reverse:
1888 if reverse:
1889 node1, node2 = node2, node1
1889 node1, node2 = node2, node1
1890
1890
1891 diffopts = patch.diffallopts(ui, opts)
1891 diffopts = patch.diffallopts(ui, opts)
1892 m = scmutil.match(ctx2, pats, opts)
1892 m = scmutil.match(ctx2, pats, opts)
1893 ui.pager('diff')
1893 ui.pager('diff')
1894 logcmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
1894 logcmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
1895 listsubrepos=opts.get('subrepos'),
1895 listsubrepos=opts.get('subrepos'),
1896 root=opts.get('root'))
1896 root=opts.get('root'))
1897
1897
1898 @command('^export',
1898 @command('^export',
1899 [('o', 'output', '',
1899 [('o', 'output', '',
1900 _('print output to file with formatted name'), _('FORMAT')),
1900 _('print output to file with formatted name'), _('FORMAT')),
1901 ('', 'switch-parent', None, _('diff against the second parent')),
1901 ('', 'switch-parent', None, _('diff against the second parent')),
1902 ('r', 'rev', [], _('revisions to export'), _('REV')),
1902 ('r', 'rev', [], _('revisions to export'), _('REV')),
1903 ] + diffopts + formatteropts,
1903 ] + diffopts + formatteropts,
1904 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'),
1904 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'),
1905 intents={INTENT_READONLY})
1905 intents={INTENT_READONLY})
1906 def export(ui, repo, *changesets, **opts):
1906 def export(ui, repo, *changesets, **opts):
1907 """dump the header and diffs for one or more changesets
1907 """dump the header and diffs for one or more changesets
1908
1908
1909 Print the changeset header and diffs for one or more revisions.
1909 Print the changeset header and diffs for one or more revisions.
1910 If no revision is given, the parent of the working directory is used.
1910 If no revision is given, the parent of the working directory is used.
1911
1911
1912 The information shown in the changeset header is: author, date,
1912 The information shown in the changeset header is: author, date,
1913 branch name (if non-default), changeset hash, parent(s) and commit
1913 branch name (if non-default), changeset hash, parent(s) and commit
1914 comment.
1914 comment.
1915
1915
1916 .. note::
1916 .. note::
1917
1917
1918 :hg:`export` may generate unexpected diff output for merge
1918 :hg:`export` may generate unexpected diff output for merge
1919 changesets, as it will compare the merge changeset against its
1919 changesets, as it will compare the merge changeset against its
1920 first parent only.
1920 first parent only.
1921
1921
1922 Output may be to a file, in which case the name of the file is
1922 Output may be to a file, in which case the name of the file is
1923 given using a template string. See :hg:`help templates`. In addition
1923 given using a template string. See :hg:`help templates`. In addition
1924 to the common template keywords, the following formatting rules are
1924 to the common template keywords, the following formatting rules are
1925 supported:
1925 supported:
1926
1926
1927 :``%%``: literal "%" character
1927 :``%%``: literal "%" character
1928 :``%H``: changeset hash (40 hexadecimal digits)
1928 :``%H``: changeset hash (40 hexadecimal digits)
1929 :``%N``: number of patches being generated
1929 :``%N``: number of patches being generated
1930 :``%R``: changeset revision number
1930 :``%R``: changeset revision number
1931 :``%b``: basename of the exporting repository
1931 :``%b``: basename of the exporting repository
1932 :``%h``: short-form changeset hash (12 hexadecimal digits)
1932 :``%h``: short-form changeset hash (12 hexadecimal digits)
1933 :``%m``: first line of the commit message (only alphanumeric characters)
1933 :``%m``: first line of the commit message (only alphanumeric characters)
1934 :``%n``: zero-padded sequence number, starting at 1
1934 :``%n``: zero-padded sequence number, starting at 1
1935 :``%r``: zero-padded changeset revision number
1935 :``%r``: zero-padded changeset revision number
1936 :``\\``: literal "\\" character
1936 :``\\``: literal "\\" character
1937
1937
1938 Without the -a/--text option, export will avoid generating diffs
1938 Without the -a/--text option, export will avoid generating diffs
1939 of files it detects as binary. With -a, export will generate a
1939 of files it detects as binary. With -a, export will generate a
1940 diff anyway, probably with undesirable results.
1940 diff anyway, probably with undesirable results.
1941
1941
1942 Use the -g/--git option to generate diffs in the git extended diff
1942 Use the -g/--git option to generate diffs in the git extended diff
1943 format. See :hg:`help diffs` for more information.
1943 format. See :hg:`help diffs` for more information.
1944
1944
1945 With the --switch-parent option, the diff will be against the
1945 With the --switch-parent option, the diff will be against the
1946 second parent. It can be useful to review a merge.
1946 second parent. It can be useful to review a merge.
1947
1947
1948 .. container:: verbose
1948 .. container:: verbose
1949
1949
1950 Examples:
1950 Examples:
1951
1951
1952 - use export and import to transplant a bugfix to the current
1952 - use export and import to transplant a bugfix to the current
1953 branch::
1953 branch::
1954
1954
1955 hg export -r 9353 | hg import -
1955 hg export -r 9353 | hg import -
1956
1956
1957 - export all the changesets between two revisions to a file with
1957 - export all the changesets between two revisions to a file with
1958 rename information::
1958 rename information::
1959
1959
1960 hg export --git -r 123:150 > changes.txt
1960 hg export --git -r 123:150 > changes.txt
1961
1961
1962 - split outgoing changes into a series of patches with
1962 - split outgoing changes into a series of patches with
1963 descriptive names::
1963 descriptive names::
1964
1964
1965 hg export -r "outgoing()" -o "%n-%m.patch"
1965 hg export -r "outgoing()" -o "%n-%m.patch"
1966
1966
1967 Returns 0 on success.
1967 Returns 0 on success.
1968 """
1968 """
1969 opts = pycompat.byteskwargs(opts)
1969 opts = pycompat.byteskwargs(opts)
1970 changesets += tuple(opts.get('rev', []))
1970 changesets += tuple(opts.get('rev', []))
1971 if not changesets:
1971 if not changesets:
1972 changesets = ['.']
1972 changesets = ['.']
1973 repo = scmutil.unhidehashlikerevs(repo, changesets, 'nowarn')
1973 repo = scmutil.unhidehashlikerevs(repo, changesets, 'nowarn')
1974 revs = scmutil.revrange(repo, changesets)
1974 revs = scmutil.revrange(repo, changesets)
1975 if not revs:
1975 if not revs:
1976 raise error.Abort(_("export requires at least one changeset"))
1976 raise error.Abort(_("export requires at least one changeset"))
1977 if len(revs) > 1:
1977 if len(revs) > 1:
1978 ui.note(_('exporting patches:\n'))
1978 ui.note(_('exporting patches:\n'))
1979 else:
1979 else:
1980 ui.note(_('exporting patch:\n'))
1980 ui.note(_('exporting patch:\n'))
1981
1981
1982 fntemplate = opts.get('output')
1982 fntemplate = opts.get('output')
1983 if cmdutil.isstdiofilename(fntemplate):
1983 if cmdutil.isstdiofilename(fntemplate):
1984 fntemplate = ''
1984 fntemplate = ''
1985
1985
1986 if fntemplate:
1986 if fntemplate:
1987 fm = formatter.nullformatter(ui, 'export', opts)
1987 fm = formatter.nullformatter(ui, 'export', opts)
1988 else:
1988 else:
1989 ui.pager('export')
1989 ui.pager('export')
1990 fm = ui.formatter('export', opts)
1990 fm = ui.formatter('export', opts)
1991 with fm:
1991 with fm:
1992 cmdutil.export(repo, revs, fm, fntemplate=fntemplate,
1992 cmdutil.export(repo, revs, fm, fntemplate=fntemplate,
1993 switch_parent=opts.get('switch_parent'),
1993 switch_parent=opts.get('switch_parent'),
1994 opts=patch.diffallopts(ui, opts))
1994 opts=patch.diffallopts(ui, opts))
1995
1995
1996 @command('files',
1996 @command('files',
1997 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
1997 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
1998 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
1998 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
1999 ] + walkopts + formatteropts + subrepoopts,
1999 ] + walkopts + formatteropts + subrepoopts,
2000 _('[OPTION]... [FILE]...'),
2000 _('[OPTION]... [FILE]...'),
2001 intents={INTENT_READONLY})
2001 intents={INTENT_READONLY})
2002 def files(ui, repo, *pats, **opts):
2002 def files(ui, repo, *pats, **opts):
2003 """list tracked files
2003 """list tracked files
2004
2004
2005 Print files under Mercurial control in the working directory or
2005 Print files under Mercurial control in the working directory or
2006 specified revision for given files (excluding removed files).
2006 specified revision for given files (excluding removed files).
2007 Files can be specified as filenames or filesets.
2007 Files can be specified as filenames or filesets.
2008
2008
2009 If no files are given to match, this command prints the names
2009 If no files are given to match, this command prints the names
2010 of all files under Mercurial control.
2010 of all files under Mercurial control.
2011
2011
2012 .. container:: verbose
2012 .. container:: verbose
2013
2013
2014 Examples:
2014 Examples:
2015
2015
2016 - list all files under the current directory::
2016 - list all files under the current directory::
2017
2017
2018 hg files .
2018 hg files .
2019
2019
2020 - shows sizes and flags for current revision::
2020 - shows sizes and flags for current revision::
2021
2021
2022 hg files -vr .
2022 hg files -vr .
2023
2023
2024 - list all files named README::
2024 - list all files named README::
2025
2025
2026 hg files -I "**/README"
2026 hg files -I "**/README"
2027
2027
2028 - list all binary files::
2028 - list all binary files::
2029
2029
2030 hg files "set:binary()"
2030 hg files "set:binary()"
2031
2031
2032 - find files containing a regular expression::
2032 - find files containing a regular expression::
2033
2033
2034 hg files "set:grep('bob')"
2034 hg files "set:grep('bob')"
2035
2035
2036 - search tracked file contents with xargs and grep::
2036 - search tracked file contents with xargs and grep::
2037
2037
2038 hg files -0 | xargs -0 grep foo
2038 hg files -0 | xargs -0 grep foo
2039
2039
2040 See :hg:`help patterns` and :hg:`help filesets` for more information
2040 See :hg:`help patterns` and :hg:`help filesets` for more information
2041 on specifying file patterns.
2041 on specifying file patterns.
2042
2042
2043 Returns 0 if a match is found, 1 otherwise.
2043 Returns 0 if a match is found, 1 otherwise.
2044
2044
2045 """
2045 """
2046
2046
2047 opts = pycompat.byteskwargs(opts)
2047 opts = pycompat.byteskwargs(opts)
2048 rev = opts.get('rev')
2048 rev = opts.get('rev')
2049 if rev:
2049 if rev:
2050 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
2050 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
2051 ctx = scmutil.revsingle(repo, rev, None)
2051 ctx = scmutil.revsingle(repo, rev, None)
2052
2052
2053 end = '\n'
2053 end = '\n'
2054 if opts.get('print0'):
2054 if opts.get('print0'):
2055 end = '\0'
2055 end = '\0'
2056 fmt = '%s' + end
2056 fmt = '%s' + end
2057
2057
2058 m = scmutil.match(ctx, pats, opts)
2058 m = scmutil.match(ctx, pats, opts)
2059 ui.pager('files')
2059 ui.pager('files')
2060 with ui.formatter('files', opts) as fm:
2060 with ui.formatter('files', opts) as fm:
2061 return cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
2061 return cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
2062
2062
2063 @command(
2063 @command(
2064 '^forget',
2064 '^forget',
2065 walkopts + dryrunopts + confirmopts,
2065 walkopts + dryrunopts + confirmopts,
2066 _('[OPTION]... FILE...'), inferrepo=True)
2066 _('[OPTION]... FILE...'), inferrepo=True)
2067 def forget(ui, repo, *pats, **opts):
2067 def forget(ui, repo, *pats, **opts):
2068 """forget the specified files on the next commit
2068 """forget the specified files on the next commit
2069
2069
2070 Mark the specified files so they will no longer be tracked
2070 Mark the specified files so they will no longer be tracked
2071 after the next commit.
2071 after the next commit.
2072
2072
2073 This only removes files from the current branch, not from the
2073 This only removes files from the current branch, not from the
2074 entire project history, and it does not delete them from the
2074 entire project history, and it does not delete them from the
2075 working directory.
2075 working directory.
2076
2076
2077 To delete the file from the working directory, see :hg:`remove`.
2077 To delete the file from the working directory, see :hg:`remove`.
2078
2078
2079 To undo a forget before the next commit, see :hg:`add`.
2079 To undo a forget before the next commit, see :hg:`add`.
2080
2080
2081 .. container:: verbose
2081 .. container:: verbose
2082
2082
2083 Examples:
2083 Examples:
2084
2084
2085 - forget newly-added binary files::
2085 - forget newly-added binary files::
2086
2086
2087 hg forget "set:added() and binary()"
2087 hg forget "set:added() and binary()"
2088
2088
2089 - forget files that would be excluded by .hgignore::
2089 - forget files that would be excluded by .hgignore::
2090
2090
2091 hg forget "set:hgignore()"
2091 hg forget "set:hgignore()"
2092
2092
2093 Returns 0 on success.
2093 Returns 0 on success.
2094 """
2094 """
2095
2095
2096 opts = pycompat.byteskwargs(opts)
2096 opts = pycompat.byteskwargs(opts)
2097 if not pats:
2097 if not pats:
2098 raise error.Abort(_('no files specified'))
2098 raise error.Abort(_('no files specified'))
2099
2099
2100 m = scmutil.match(repo[None], pats, opts)
2100 m = scmutil.match(repo[None], pats, opts)
2101 dryrun, confirm = opts.get('dry_run'), opts.get('confirm')
2101 dryrun, confirm = opts.get('dry_run'), opts.get('confirm')
2102 rejected = cmdutil.forget(ui, repo, m, prefix="",
2102 rejected = cmdutil.forget(ui, repo, m, prefix="",
2103 explicitonly=False, dryrun=dryrun,
2103 explicitonly=False, dryrun=dryrun,
2104 confirm=confirm)[0]
2104 confirm=confirm)[0]
2105 return rejected and 1 or 0
2105 return rejected and 1 or 0
2106
2106
2107 @command(
2107 @command(
2108 'graft',
2108 'graft',
2109 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2109 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2110 ('c', 'continue', False, _('resume interrupted graft')),
2110 ('c', 'continue', False, _('resume interrupted graft')),
2111 ('e', 'edit', False, _('invoke editor on commit messages')),
2111 ('e', 'edit', False, _('invoke editor on commit messages')),
2112 ('', 'log', None, _('append graft info to log message')),
2112 ('', 'log', None, _('append graft info to log message')),
2113 ('f', 'force', False, _('force graft')),
2113 ('f', 'force', False, _('force graft')),
2114 ('D', 'currentdate', False,
2114 ('D', 'currentdate', False,
2115 _('record the current date as commit date')),
2115 _('record the current date as commit date')),
2116 ('U', 'currentuser', False,
2116 ('U', 'currentuser', False,
2117 _('record the current user as committer'), _('DATE'))]
2117 _('record the current user as committer'), _('DATE'))]
2118 + commitopts2 + mergetoolopts + dryrunopts,
2118 + commitopts2 + mergetoolopts + dryrunopts,
2119 _('[OPTION]... [-r REV]... REV...'))
2119 _('[OPTION]... [-r REV]... REV...'))
2120 def graft(ui, repo, *revs, **opts):
2120 def graft(ui, repo, *revs, **opts):
2121 '''copy changes from other branches onto the current branch
2121 '''copy changes from other branches onto the current branch
2122
2122
2123 This command uses Mercurial's merge logic to copy individual
2123 This command uses Mercurial's merge logic to copy individual
2124 changes from other branches without merging branches in the
2124 changes from other branches without merging branches in the
2125 history graph. This is sometimes known as 'backporting' or
2125 history graph. This is sometimes known as 'backporting' or
2126 'cherry-picking'. By default, graft will copy user, date, and
2126 'cherry-picking'. By default, graft will copy user, date, and
2127 description from the source changesets.
2127 description from the source changesets.
2128
2128
2129 Changesets that are ancestors of the current revision, that have
2129 Changesets that are ancestors of the current revision, that have
2130 already been grafted, or that are merges will be skipped.
2130 already been grafted, or that are merges will be skipped.
2131
2131
2132 If --log is specified, log messages will have a comment appended
2132 If --log is specified, log messages will have a comment appended
2133 of the form::
2133 of the form::
2134
2134
2135 (grafted from CHANGESETHASH)
2135 (grafted from CHANGESETHASH)
2136
2136
2137 If --force is specified, revisions will be grafted even if they
2137 If --force is specified, revisions will be grafted even if they
2138 are already ancestors of, or have been grafted to, the destination.
2138 are already ancestors of, or have been grafted to, the destination.
2139 This is useful when the revisions have since been backed out.
2139 This is useful when the revisions have since been backed out.
2140
2140
2141 If a graft merge results in conflicts, the graft process is
2141 If a graft merge results in conflicts, the graft process is
2142 interrupted so that the current merge can be manually resolved.
2142 interrupted so that the current merge can be manually resolved.
2143 Once all conflicts are addressed, the graft process can be
2143 Once all conflicts are addressed, the graft process can be
2144 continued with the -c/--continue option.
2144 continued with the -c/--continue option.
2145
2145
2146 .. note::
2146 .. note::
2147
2147
2148 The -c/--continue option does not reapply earlier options, except
2148 The -c/--continue option does not reapply earlier options, except
2149 for --force.
2149 for --force.
2150
2150
2151 .. container:: verbose
2151 .. container:: verbose
2152
2152
2153 Examples:
2153 Examples:
2154
2154
2155 - copy a single change to the stable branch and edit its description::
2155 - copy a single change to the stable branch and edit its description::
2156
2156
2157 hg update stable
2157 hg update stable
2158 hg graft --edit 9393
2158 hg graft --edit 9393
2159
2159
2160 - graft a range of changesets with one exception, updating dates::
2160 - graft a range of changesets with one exception, updating dates::
2161
2161
2162 hg graft -D "2085::2093 and not 2091"
2162 hg graft -D "2085::2093 and not 2091"
2163
2163
2164 - continue a graft after resolving conflicts::
2164 - continue a graft after resolving conflicts::
2165
2165
2166 hg graft -c
2166 hg graft -c
2167
2167
2168 - show the source of a grafted changeset::
2168 - show the source of a grafted changeset::
2169
2169
2170 hg log --debug -r .
2170 hg log --debug -r .
2171
2171
2172 - show revisions sorted by date::
2172 - show revisions sorted by date::
2173
2173
2174 hg log -r "sort(all(), date)"
2174 hg log -r "sort(all(), date)"
2175
2175
2176 See :hg:`help revisions` for more about specifying revisions.
2176 See :hg:`help revisions` for more about specifying revisions.
2177
2177
2178 Returns 0 on successful completion.
2178 Returns 0 on successful completion.
2179 '''
2179 '''
2180 with repo.wlock():
2180 with repo.wlock():
2181 return _dograft(ui, repo, *revs, **opts)
2181 return _dograft(ui, repo, *revs, **opts)
2182
2182
2183 def _dograft(ui, repo, *revs, **opts):
2183 def _dograft(ui, repo, *revs, **opts):
2184 opts = pycompat.byteskwargs(opts)
2184 opts = pycompat.byteskwargs(opts)
2185 if revs and opts.get('rev'):
2185 if revs and opts.get('rev'):
2186 ui.warn(_('warning: inconsistent use of --rev might give unexpected '
2186 ui.warn(_('warning: inconsistent use of --rev might give unexpected '
2187 'revision ordering!\n'))
2187 'revision ordering!\n'))
2188
2188
2189 revs = list(revs)
2189 revs = list(revs)
2190 revs.extend(opts.get('rev'))
2190 revs.extend(opts.get('rev'))
2191
2191
2192 if not opts.get('user') and opts.get('currentuser'):
2192 if not opts.get('user') and opts.get('currentuser'):
2193 opts['user'] = ui.username()
2193 opts['user'] = ui.username()
2194 if not opts.get('date') and opts.get('currentdate'):
2194 if not opts.get('date') and opts.get('currentdate'):
2195 opts['date'] = "%d %d" % dateutil.makedate()
2195 opts['date'] = "%d %d" % dateutil.makedate()
2196
2196
2197 editor = cmdutil.getcommiteditor(editform='graft',
2197 editor = cmdutil.getcommiteditor(editform='graft',
2198 **pycompat.strkwargs(opts))
2198 **pycompat.strkwargs(opts))
2199
2199
2200 cont = False
2200 cont = False
2201 if opts.get('continue'):
2201 if opts.get('continue'):
2202 cont = True
2202 cont = True
2203 if revs:
2203 if revs:
2204 raise error.Abort(_("can't specify --continue and revisions"))
2204 raise error.Abort(_("can't specify --continue and revisions"))
2205 # read in unfinished revisions
2205 # read in unfinished revisions
2206 try:
2206 try:
2207 nodes = repo.vfs.read('graftstate').splitlines()
2207 nodes = repo.vfs.read('graftstate').splitlines()
2208 revs = [repo[node].rev() for node in nodes]
2208 revs = [repo[node].rev() for node in nodes]
2209 except IOError as inst:
2209 except IOError as inst:
2210 if inst.errno != errno.ENOENT:
2210 if inst.errno != errno.ENOENT:
2211 raise
2211 raise
2212 cmdutil.wrongtooltocontinue(repo, _('graft'))
2212 cmdutil.wrongtooltocontinue(repo, _('graft'))
2213 else:
2213 else:
2214 if not revs:
2214 if not revs:
2215 raise error.Abort(_('no revisions specified'))
2215 raise error.Abort(_('no revisions specified'))
2216 cmdutil.checkunfinished(repo)
2216 cmdutil.checkunfinished(repo)
2217 cmdutil.bailifchanged(repo)
2217 cmdutil.bailifchanged(repo)
2218 revs = scmutil.revrange(repo, revs)
2218 revs = scmutil.revrange(repo, revs)
2219
2219
2220 skipped = set()
2220 skipped = set()
2221 # check for merges
2221 # check for merges
2222 for rev in repo.revs('%ld and merge()', revs):
2222 for rev in repo.revs('%ld and merge()', revs):
2223 ui.warn(_('skipping ungraftable merge revision %d\n') % rev)
2223 ui.warn(_('skipping ungraftable merge revision %d\n') % rev)
2224 skipped.add(rev)
2224 skipped.add(rev)
2225 revs = [r for r in revs if r not in skipped]
2225 revs = [r for r in revs if r not in skipped]
2226 if not revs:
2226 if not revs:
2227 return -1
2227 return -1
2228
2228
2229 # Don't check in the --continue case, in effect retaining --force across
2229 # Don't check in the --continue case, in effect retaining --force across
2230 # --continues. That's because without --force, any revisions we decided to
2230 # --continues. That's because without --force, any revisions we decided to
2231 # skip would have been filtered out here, so they wouldn't have made their
2231 # skip would have been filtered out here, so they wouldn't have made their
2232 # way to the graftstate. With --force, any revisions we would have otherwise
2232 # way to the graftstate. With --force, any revisions we would have otherwise
2233 # skipped would not have been filtered out, and if they hadn't been applied
2233 # skipped would not have been filtered out, and if they hadn't been applied
2234 # already, they'd have been in the graftstate.
2234 # already, they'd have been in the graftstate.
2235 if not (cont or opts.get('force')):
2235 if not (cont or opts.get('force')):
2236 # check for ancestors of dest branch
2236 # check for ancestors of dest branch
2237 crev = repo['.'].rev()
2237 crev = repo['.'].rev()
2238 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2238 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2239 # XXX make this lazy in the future
2239 # XXX make this lazy in the future
2240 # don't mutate while iterating, create a copy
2240 # don't mutate while iterating, create a copy
2241 for rev in list(revs):
2241 for rev in list(revs):
2242 if rev in ancestors:
2242 if rev in ancestors:
2243 ui.warn(_('skipping ancestor revision %d:%s\n') %
2243 ui.warn(_('skipping ancestor revision %d:%s\n') %
2244 (rev, repo[rev]))
2244 (rev, repo[rev]))
2245 # XXX remove on list is slow
2245 # XXX remove on list is slow
2246 revs.remove(rev)
2246 revs.remove(rev)
2247 if not revs:
2247 if not revs:
2248 return -1
2248 return -1
2249
2249
2250 # analyze revs for earlier grafts
2250 # analyze revs for earlier grafts
2251 ids = {}
2251 ids = {}
2252 for ctx in repo.set("%ld", revs):
2252 for ctx in repo.set("%ld", revs):
2253 ids[ctx.hex()] = ctx.rev()
2253 ids[ctx.hex()] = ctx.rev()
2254 n = ctx.extra().get('source')
2254 n = ctx.extra().get('source')
2255 if n:
2255 if n:
2256 ids[n] = ctx.rev()
2256 ids[n] = ctx.rev()
2257
2257
2258 # check ancestors for earlier grafts
2258 # check ancestors for earlier grafts
2259 ui.debug('scanning for duplicate grafts\n')
2259 ui.debug('scanning for duplicate grafts\n')
2260
2260
2261 # The only changesets we can be sure doesn't contain grafts of any
2261 # The only changesets we can be sure doesn't contain grafts of any
2262 # revs, are the ones that are common ancestors of *all* revs:
2262 # revs, are the ones that are common ancestors of *all* revs:
2263 for rev in repo.revs('only(%d,ancestor(%ld))', crev, revs):
2263 for rev in repo.revs('only(%d,ancestor(%ld))', crev, revs):
2264 ctx = repo[rev]
2264 ctx = repo[rev]
2265 n = ctx.extra().get('source')
2265 n = ctx.extra().get('source')
2266 if n in ids:
2266 if n in ids:
2267 try:
2267 try:
2268 r = repo[n].rev()
2268 r = repo[n].rev()
2269 except error.RepoLookupError:
2269 except error.RepoLookupError:
2270 r = None
2270 r = None
2271 if r in revs:
2271 if r in revs:
2272 ui.warn(_('skipping revision %d:%s '
2272 ui.warn(_('skipping revision %d:%s '
2273 '(already grafted to %d:%s)\n')
2273 '(already grafted to %d:%s)\n')
2274 % (r, repo[r], rev, ctx))
2274 % (r, repo[r], rev, ctx))
2275 revs.remove(r)
2275 revs.remove(r)
2276 elif ids[n] in revs:
2276 elif ids[n] in revs:
2277 if r is None:
2277 if r is None:
2278 ui.warn(_('skipping already grafted revision %d:%s '
2278 ui.warn(_('skipping already grafted revision %d:%s '
2279 '(%d:%s also has unknown origin %s)\n')
2279 '(%d:%s also has unknown origin %s)\n')
2280 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
2280 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
2281 else:
2281 else:
2282 ui.warn(_('skipping already grafted revision %d:%s '
2282 ui.warn(_('skipping already grafted revision %d:%s '
2283 '(%d:%s also has origin %d:%s)\n')
2283 '(%d:%s also has origin %d:%s)\n')
2284 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
2284 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
2285 revs.remove(ids[n])
2285 revs.remove(ids[n])
2286 elif ctx.hex() in ids:
2286 elif ctx.hex() in ids:
2287 r = ids[ctx.hex()]
2287 r = ids[ctx.hex()]
2288 ui.warn(_('skipping already grafted revision %d:%s '
2288 ui.warn(_('skipping already grafted revision %d:%s '
2289 '(was grafted from %d:%s)\n') %
2289 '(was grafted from %d:%s)\n') %
2290 (r, repo[r], rev, ctx))
2290 (r, repo[r], rev, ctx))
2291 revs.remove(r)
2291 revs.remove(r)
2292 if not revs:
2292 if not revs:
2293 return -1
2293 return -1
2294
2294
2295 for pos, ctx in enumerate(repo.set("%ld", revs)):
2295 for pos, ctx in enumerate(repo.set("%ld", revs)):
2296 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
2296 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
2297 ctx.description().split('\n', 1)[0])
2297 ctx.description().split('\n', 1)[0])
2298 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
2298 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
2299 if names:
2299 if names:
2300 desc += ' (%s)' % ' '.join(names)
2300 desc += ' (%s)' % ' '.join(names)
2301 ui.status(_('grafting %s\n') % desc)
2301 ui.status(_('grafting %s\n') % desc)
2302 if opts.get('dry_run'):
2302 if opts.get('dry_run'):
2303 continue
2303 continue
2304
2304
2305 source = ctx.extra().get('source')
2305 source = ctx.extra().get('source')
2306 extra = {}
2306 extra = {}
2307 if source:
2307 if source:
2308 extra['source'] = source
2308 extra['source'] = source
2309 extra['intermediate-source'] = ctx.hex()
2309 extra['intermediate-source'] = ctx.hex()
2310 else:
2310 else:
2311 extra['source'] = ctx.hex()
2311 extra['source'] = ctx.hex()
2312 user = ctx.user()
2312 user = ctx.user()
2313 if opts.get('user'):
2313 if opts.get('user'):
2314 user = opts['user']
2314 user = opts['user']
2315 date = ctx.date()
2315 date = ctx.date()
2316 if opts.get('date'):
2316 if opts.get('date'):
2317 date = opts['date']
2317 date = opts['date']
2318 message = ctx.description()
2318 message = ctx.description()
2319 if opts.get('log'):
2319 if opts.get('log'):
2320 message += '\n(grafted from %s)' % ctx.hex()
2320 message += '\n(grafted from %s)' % ctx.hex()
2321
2321
2322 # we don't merge the first commit when continuing
2322 # we don't merge the first commit when continuing
2323 if not cont:
2323 if not cont:
2324 # perform the graft merge with p1(rev) as 'ancestor'
2324 # perform the graft merge with p1(rev) as 'ancestor'
2325 try:
2325 try:
2326 # ui.forcemerge is an internal variable, do not document
2326 # ui.forcemerge is an internal variable, do not document
2327 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
2327 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
2328 'graft')
2328 'graft')
2329 stats = mergemod.graft(repo, ctx, ctx.p1(),
2329 stats = mergemod.graft(repo, ctx, ctx.p1(),
2330 ['local', 'graft'])
2330 ['local', 'graft'])
2331 finally:
2331 finally:
2332 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
2332 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
2333 # report any conflicts
2333 # report any conflicts
2334 if stats.unresolvedcount > 0:
2334 if stats.unresolvedcount > 0:
2335 # write out state for --continue
2335 # write out state for --continue
2336 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2336 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2337 repo.vfs.write('graftstate', ''.join(nodelines))
2337 repo.vfs.write('graftstate', ''.join(nodelines))
2338 extra = ''
2338 extra = ''
2339 if opts.get('user'):
2339 if opts.get('user'):
2340 extra += ' --user %s' % procutil.shellquote(opts['user'])
2340 extra += ' --user %s' % procutil.shellquote(opts['user'])
2341 if opts.get('date'):
2341 if opts.get('date'):
2342 extra += ' --date %s' % procutil.shellquote(opts['date'])
2342 extra += ' --date %s' % procutil.shellquote(opts['date'])
2343 if opts.get('log'):
2343 if opts.get('log'):
2344 extra += ' --log'
2344 extra += ' --log'
2345 hint=_("use 'hg resolve' and 'hg graft --continue%s'") % extra
2345 hint=_("use 'hg resolve' and 'hg graft --continue%s'") % extra
2346 raise error.Abort(
2346 raise error.Abort(
2347 _("unresolved conflicts, can't continue"),
2347 _("unresolved conflicts, can't continue"),
2348 hint=hint)
2348 hint=hint)
2349 else:
2349 else:
2350 cont = False
2350 cont = False
2351
2351
2352 # commit
2352 # commit
2353 node = repo.commit(text=message, user=user,
2353 node = repo.commit(text=message, user=user,
2354 date=date, extra=extra, editor=editor)
2354 date=date, extra=extra, editor=editor)
2355 if node is None:
2355 if node is None:
2356 ui.warn(
2356 ui.warn(
2357 _('note: graft of %d:%s created no changes to commit\n') %
2357 _('note: graft of %d:%s created no changes to commit\n') %
2358 (ctx.rev(), ctx))
2358 (ctx.rev(), ctx))
2359
2359
2360 # remove state when we complete successfully
2360 # remove state when we complete successfully
2361 if not opts.get('dry_run'):
2361 if not opts.get('dry_run'):
2362 repo.vfs.unlinkpath('graftstate', ignoremissing=True)
2362 repo.vfs.unlinkpath('graftstate', ignoremissing=True)
2363
2363
2364 return 0
2364 return 0
2365
2365
2366 @command('grep',
2366 @command('grep',
2367 [('0', 'print0', None, _('end fields with NUL')),
2367 [('0', 'print0', None, _('end fields with NUL')),
2368 ('', 'all', None, _('print all revisions that match')),
2368 ('', 'all', None, _('print all revisions that match')),
2369 ('a', 'text', None, _('treat all files as text')),
2369 ('a', 'text', None, _('treat all files as text')),
2370 ('f', 'follow', None,
2370 ('f', 'follow', None,
2371 _('follow changeset history,'
2371 _('follow changeset history,'
2372 ' or file history across copies and renames')),
2372 ' or file history across copies and renames')),
2373 ('i', 'ignore-case', None, _('ignore case when matching')),
2373 ('i', 'ignore-case', None, _('ignore case when matching')),
2374 ('l', 'files-with-matches', None,
2374 ('l', 'files-with-matches', None,
2375 _('print only filenames and revisions that match')),
2375 _('print only filenames and revisions that match')),
2376 ('n', 'line-number', None, _('print matching line numbers')),
2376 ('n', 'line-number', None, _('print matching line numbers')),
2377 ('r', 'rev', [],
2377 ('r', 'rev', [],
2378 _('only search files changed within revision range'), _('REV')),
2378 _('only search files changed within revision range'), _('REV')),
2379 ('u', 'user', None, _('list the author (long with -v)')),
2379 ('u', 'user', None, _('list the author (long with -v)')),
2380 ('d', 'date', None, _('list the date (short with -q)')),
2380 ('d', 'date', None, _('list the date (short with -q)')),
2381 ] + formatteropts + walkopts,
2381 ] + formatteropts + walkopts,
2382 _('[OPTION]... PATTERN [FILE]...'),
2382 _('[OPTION]... PATTERN [FILE]...'),
2383 inferrepo=True,
2383 inferrepo=True,
2384 intents={INTENT_READONLY})
2384 intents={INTENT_READONLY})
2385 def grep(ui, repo, pattern, *pats, **opts):
2385 def grep(ui, repo, pattern, *pats, **opts):
2386 """search revision history for a pattern in specified files
2386 """search revision history for a pattern in specified files
2387
2387
2388 Search revision history for a regular expression in the specified
2388 Search revision history for a regular expression in the specified
2389 files or the entire project.
2389 files or the entire project.
2390
2390
2391 By default, grep prints the most recent revision number for each
2391 By default, grep prints the most recent revision number for each
2392 file in which it finds a match. To get it to print every revision
2392 file in which it finds a match. To get it to print every revision
2393 that contains a change in match status ("-" for a match that becomes
2393 that contains a change in match status ("-" for a match that becomes
2394 a non-match, or "+" for a non-match that becomes a match), use the
2394 a non-match, or "+" for a non-match that becomes a match), use the
2395 --all flag.
2395 --all flag.
2396
2396
2397 PATTERN can be any Python (roughly Perl-compatible) regular
2397 PATTERN can be any Python (roughly Perl-compatible) regular
2398 expression.
2398 expression.
2399
2399
2400 If no FILEs are specified (and -f/--follow isn't set), all files in
2400 If no FILEs are specified (and -f/--follow isn't set), all files in
2401 the repository are searched, including those that don't exist in the
2401 the repository are searched, including those that don't exist in the
2402 current branch or have been deleted in a prior changeset.
2402 current branch or have been deleted in a prior changeset.
2403
2403
2404 Returns 0 if a match is found, 1 otherwise.
2404 Returns 0 if a match is found, 1 otherwise.
2405 """
2405 """
2406 opts = pycompat.byteskwargs(opts)
2406 opts = pycompat.byteskwargs(opts)
2407 reflags = re.M
2407 reflags = re.M
2408 if opts.get('ignore_case'):
2408 if opts.get('ignore_case'):
2409 reflags |= re.I
2409 reflags |= re.I
2410 try:
2410 try:
2411 regexp = util.re.compile(pattern, reflags)
2411 regexp = util.re.compile(pattern, reflags)
2412 except re.error as inst:
2412 except re.error as inst:
2413 ui.warn(_("grep: invalid match pattern: %s\n") % pycompat.bytestr(inst))
2413 ui.warn(_("grep: invalid match pattern: %s\n") % pycompat.bytestr(inst))
2414 return 1
2414 return 1
2415 sep, eol = ':', '\n'
2415 sep, eol = ':', '\n'
2416 if opts.get('print0'):
2416 if opts.get('print0'):
2417 sep = eol = '\0'
2417 sep = eol = '\0'
2418
2418
2419 getfile = util.lrucachefunc(repo.file)
2419 getfile = util.lrucachefunc(repo.file)
2420
2420
2421 def matchlines(body):
2421 def matchlines(body):
2422 begin = 0
2422 begin = 0
2423 linenum = 0
2423 linenum = 0
2424 while begin < len(body):
2424 while begin < len(body):
2425 match = regexp.search(body, begin)
2425 match = regexp.search(body, begin)
2426 if not match:
2426 if not match:
2427 break
2427 break
2428 mstart, mend = match.span()
2428 mstart, mend = match.span()
2429 linenum += body.count('\n', begin, mstart) + 1
2429 linenum += body.count('\n', begin, mstart) + 1
2430 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2430 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2431 begin = body.find('\n', mend) + 1 or len(body) + 1
2431 begin = body.find('\n', mend) + 1 or len(body) + 1
2432 lend = begin - 1
2432 lend = begin - 1
2433 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2433 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2434
2434
2435 class linestate(object):
2435 class linestate(object):
2436 def __init__(self, line, linenum, colstart, colend):
2436 def __init__(self, line, linenum, colstart, colend):
2437 self.line = line
2437 self.line = line
2438 self.linenum = linenum
2438 self.linenum = linenum
2439 self.colstart = colstart
2439 self.colstart = colstart
2440 self.colend = colend
2440 self.colend = colend
2441
2441
2442 def __hash__(self):
2442 def __hash__(self):
2443 return hash((self.linenum, self.line))
2443 return hash((self.linenum, self.line))
2444
2444
2445 def __eq__(self, other):
2445 def __eq__(self, other):
2446 return self.line == other.line
2446 return self.line == other.line
2447
2447
2448 def findpos(self):
2448 def findpos(self):
2449 """Iterate all (start, end) indices of matches"""
2449 """Iterate all (start, end) indices of matches"""
2450 yield self.colstart, self.colend
2450 yield self.colstart, self.colend
2451 p = self.colend
2451 p = self.colend
2452 while p < len(self.line):
2452 while p < len(self.line):
2453 m = regexp.search(self.line, p)
2453 m = regexp.search(self.line, p)
2454 if not m:
2454 if not m:
2455 break
2455 break
2456 yield m.span()
2456 yield m.span()
2457 p = m.end()
2457 p = m.end()
2458
2458
2459 matches = {}
2459 matches = {}
2460 copies = {}
2460 copies = {}
2461 def grepbody(fn, rev, body):
2461 def grepbody(fn, rev, body):
2462 matches[rev].setdefault(fn, [])
2462 matches[rev].setdefault(fn, [])
2463 m = matches[rev][fn]
2463 m = matches[rev][fn]
2464 for lnum, cstart, cend, line in matchlines(body):
2464 for lnum, cstart, cend, line in matchlines(body):
2465 s = linestate(line, lnum, cstart, cend)
2465 s = linestate(line, lnum, cstart, cend)
2466 m.append(s)
2466 m.append(s)
2467
2467
2468 def difflinestates(a, b):
2468 def difflinestates(a, b):
2469 sm = difflib.SequenceMatcher(None, a, b)
2469 sm = difflib.SequenceMatcher(None, a, b)
2470 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2470 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2471 if tag == 'insert':
2471 if tag == 'insert':
2472 for i in xrange(blo, bhi):
2472 for i in xrange(blo, bhi):
2473 yield ('+', b[i])
2473 yield ('+', b[i])
2474 elif tag == 'delete':
2474 elif tag == 'delete':
2475 for i in xrange(alo, ahi):
2475 for i in xrange(alo, ahi):
2476 yield ('-', a[i])
2476 yield ('-', a[i])
2477 elif tag == 'replace':
2477 elif tag == 'replace':
2478 for i in xrange(alo, ahi):
2478 for i in xrange(alo, ahi):
2479 yield ('-', a[i])
2479 yield ('-', a[i])
2480 for i in xrange(blo, bhi):
2480 for i in xrange(blo, bhi):
2481 yield ('+', b[i])
2481 yield ('+', b[i])
2482
2482
2483 def display(fm, fn, ctx, pstates, states):
2483 def display(fm, fn, ctx, pstates, states):
2484 rev = ctx.rev()
2484 rev = ctx.rev()
2485 if fm.isplain():
2485 if fm.isplain():
2486 formatuser = ui.shortuser
2486 formatuser = ui.shortuser
2487 else:
2487 else:
2488 formatuser = str
2488 formatuser = str
2489 if ui.quiet:
2489 if ui.quiet:
2490 datefmt = '%Y-%m-%d'
2490 datefmt = '%Y-%m-%d'
2491 else:
2491 else:
2492 datefmt = '%a %b %d %H:%M:%S %Y %1%2'
2492 datefmt = '%a %b %d %H:%M:%S %Y %1%2'
2493 found = False
2493 found = False
2494 @util.cachefunc
2494 @util.cachefunc
2495 def binary():
2495 def binary():
2496 flog = getfile(fn)
2496 flog = getfile(fn)
2497 return stringutil.binary(flog.read(ctx.filenode(fn)))
2497 return stringutil.binary(flog.read(ctx.filenode(fn)))
2498
2498
2499 fieldnamemap = {'filename': 'file', 'linenumber': 'line_number'}
2499 fieldnamemap = {'filename': 'file', 'linenumber': 'line_number'}
2500 if opts.get('all'):
2500 if opts.get('all'):
2501 iter = difflinestates(pstates, states)
2501 iter = difflinestates(pstates, states)
2502 else:
2502 else:
2503 iter = [('', l) for l in states]
2503 iter = [('', l) for l in states]
2504 for change, l in iter:
2504 for change, l in iter:
2505 fm.startitem()
2505 fm.startitem()
2506 fm.data(node=fm.hexfunc(ctx.node()))
2506 fm.data(node=fm.hexfunc(ctx.node()))
2507 cols = [
2507 cols = [
2508 ('filename', fn, True),
2508 ('filename', fn, True),
2509 ('rev', rev, True),
2509 ('rev', rev, True),
2510 ('linenumber', l.linenum, opts.get('line_number')),
2510 ('linenumber', l.linenum, opts.get('line_number')),
2511 ]
2511 ]
2512 if opts.get('all'):
2512 if opts.get('all'):
2513 cols.append(('change', change, True))
2513 cols.append(('change', change, True))
2514 cols.extend([
2514 cols.extend([
2515 ('user', formatuser(ctx.user()), opts.get('user')),
2515 ('user', formatuser(ctx.user()), opts.get('user')),
2516 ('date', fm.formatdate(ctx.date(), datefmt), opts.get('date')),
2516 ('date', fm.formatdate(ctx.date(), datefmt), opts.get('date')),
2517 ])
2517 ])
2518 lastcol = next(name for name, data, cond in reversed(cols) if cond)
2518 lastcol = next(name for name, data, cond in reversed(cols) if cond)
2519 for name, data, cond in cols:
2519 for name, data, cond in cols:
2520 field = fieldnamemap.get(name, name)
2520 field = fieldnamemap.get(name, name)
2521 fm.condwrite(cond, field, '%s', data, label='grep.%s' % name)
2521 fm.condwrite(cond, field, '%s', data, label='grep.%s' % name)
2522 if cond and name != lastcol:
2522 if cond and name != lastcol:
2523 fm.plain(sep, label='grep.sep')
2523 fm.plain(sep, label='grep.sep')
2524 if not opts.get('files_with_matches'):
2524 if not opts.get('files_with_matches'):
2525 fm.plain(sep, label='grep.sep')
2525 fm.plain(sep, label='grep.sep')
2526 if not opts.get('text') and binary():
2526 if not opts.get('text') and binary():
2527 fm.plain(_(" Binary file matches"))
2527 fm.plain(_(" Binary file matches"))
2528 else:
2528 else:
2529 displaymatches(fm.nested('texts', tmpl='{text}'), l)
2529 displaymatches(fm.nested('texts', tmpl='{text}'), l)
2530 fm.plain(eol)
2530 fm.plain(eol)
2531 found = True
2531 found = True
2532 if opts.get('files_with_matches'):
2532 if opts.get('files_with_matches'):
2533 break
2533 break
2534 return found
2534 return found
2535
2535
2536 def displaymatches(fm, l):
2536 def displaymatches(fm, l):
2537 p = 0
2537 p = 0
2538 for s, e in l.findpos():
2538 for s, e in l.findpos():
2539 if p < s:
2539 if p < s:
2540 fm.startitem()
2540 fm.startitem()
2541 fm.write('text', '%s', l.line[p:s])
2541 fm.write('text', '%s', l.line[p:s])
2542 fm.data(matched=False)
2542 fm.data(matched=False)
2543 fm.startitem()
2543 fm.startitem()
2544 fm.write('text', '%s', l.line[s:e], label='grep.match')
2544 fm.write('text', '%s', l.line[s:e], label='grep.match')
2545 fm.data(matched=True)
2545 fm.data(matched=True)
2546 p = e
2546 p = e
2547 if p < len(l.line):
2547 if p < len(l.line):
2548 fm.startitem()
2548 fm.startitem()
2549 fm.write('text', '%s', l.line[p:])
2549 fm.write('text', '%s', l.line[p:])
2550 fm.data(matched=False)
2550 fm.data(matched=False)
2551 fm.end()
2551 fm.end()
2552
2552
2553 skip = {}
2553 skip = {}
2554 revfiles = {}
2554 revfiles = {}
2555 match = scmutil.match(repo[None], pats, opts)
2555 match = scmutil.match(repo[None], pats, opts)
2556 found = False
2556 found = False
2557 follow = opts.get('follow')
2557 follow = opts.get('follow')
2558
2558
2559 def prep(ctx, fns):
2559 def prep(ctx, fns):
2560 rev = ctx.rev()
2560 rev = ctx.rev()
2561 pctx = ctx.p1()
2561 pctx = ctx.p1()
2562 parent = pctx.rev()
2562 parent = pctx.rev()
2563 matches.setdefault(rev, {})
2563 matches.setdefault(rev, {})
2564 matches.setdefault(parent, {})
2564 matches.setdefault(parent, {})
2565 files = revfiles.setdefault(rev, [])
2565 files = revfiles.setdefault(rev, [])
2566 for fn in fns:
2566 for fn in fns:
2567 flog = getfile(fn)
2567 flog = getfile(fn)
2568 try:
2568 try:
2569 fnode = ctx.filenode(fn)
2569 fnode = ctx.filenode(fn)
2570 except error.LookupError:
2570 except error.LookupError:
2571 continue
2571 continue
2572
2572
2573 copied = flog.renamed(fnode)
2573 copied = flog.renamed(fnode)
2574 copy = follow and copied and copied[0]
2574 copy = follow and copied and copied[0]
2575 if copy:
2575 if copy:
2576 copies.setdefault(rev, {})[fn] = copy
2576 copies.setdefault(rev, {})[fn] = copy
2577 if fn in skip:
2577 if fn in skip:
2578 if copy:
2578 if copy:
2579 skip[copy] = True
2579 skip[copy] = True
2580 continue
2580 continue
2581 files.append(fn)
2581 files.append(fn)
2582
2582
2583 if fn not in matches[rev]:
2583 if fn not in matches[rev]:
2584 grepbody(fn, rev, flog.read(fnode))
2584 grepbody(fn, rev, flog.read(fnode))
2585
2585
2586 pfn = copy or fn
2586 pfn = copy or fn
2587 if pfn not in matches[parent]:
2587 if pfn not in matches[parent]:
2588 try:
2588 try:
2589 fnode = pctx.filenode(pfn)
2589 fnode = pctx.filenode(pfn)
2590 grepbody(pfn, parent, flog.read(fnode))
2590 grepbody(pfn, parent, flog.read(fnode))
2591 except error.LookupError:
2591 except error.LookupError:
2592 pass
2592 pass
2593
2593
2594 ui.pager('grep')
2594 ui.pager('grep')
2595 fm = ui.formatter('grep', opts)
2595 fm = ui.formatter('grep', opts)
2596 for ctx in cmdutil.walkchangerevs(repo, match, opts, prep):
2596 for ctx in cmdutil.walkchangerevs(repo, match, opts, prep):
2597 rev = ctx.rev()
2597 rev = ctx.rev()
2598 parent = ctx.p1().rev()
2598 parent = ctx.p1().rev()
2599 for fn in sorted(revfiles.get(rev, [])):
2599 for fn in sorted(revfiles.get(rev, [])):
2600 states = matches[rev][fn]
2600 states = matches[rev][fn]
2601 copy = copies.get(rev, {}).get(fn)
2601 copy = copies.get(rev, {}).get(fn)
2602 if fn in skip:
2602 if fn in skip:
2603 if copy:
2603 if copy:
2604 skip[copy] = True
2604 skip[copy] = True
2605 continue
2605 continue
2606 pstates = matches.get(parent, {}).get(copy or fn, [])
2606 pstates = matches.get(parent, {}).get(copy or fn, [])
2607 if pstates or states:
2607 if pstates or states:
2608 r = display(fm, fn, ctx, pstates, states)
2608 r = display(fm, fn, ctx, pstates, states)
2609 found = found or r
2609 found = found or r
2610 if r and not opts.get('all'):
2610 if r and not opts.get('all'):
2611 skip[fn] = True
2611 skip[fn] = True
2612 if copy:
2612 if copy:
2613 skip[copy] = True
2613 skip[copy] = True
2614 del revfiles[rev]
2614 del revfiles[rev]
2615 # We will keep the matches dict for the duration of the window
2615 # We will keep the matches dict for the duration of the window
2616 # clear the matches dict once the window is over
2616 # clear the matches dict once the window is over
2617 if not revfiles:
2617 if not revfiles:
2618 matches.clear()
2618 matches.clear()
2619 fm.end()
2619 fm.end()
2620
2620
2621 return not found
2621 return not found
2622
2622
2623 @command('heads',
2623 @command('heads',
2624 [('r', 'rev', '',
2624 [('r', 'rev', '',
2625 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2625 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2626 ('t', 'topo', False, _('show topological heads only')),
2626 ('t', 'topo', False, _('show topological heads only')),
2627 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2627 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2628 ('c', 'closed', False, _('show normal and closed branch heads')),
2628 ('c', 'closed', False, _('show normal and closed branch heads')),
2629 ] + templateopts,
2629 ] + templateopts,
2630 _('[-ct] [-r STARTREV] [REV]...'),
2630 _('[-ct] [-r STARTREV] [REV]...'),
2631 intents={INTENT_READONLY})
2631 intents={INTENT_READONLY})
2632 def heads(ui, repo, *branchrevs, **opts):
2632 def heads(ui, repo, *branchrevs, **opts):
2633 """show branch heads
2633 """show branch heads
2634
2634
2635 With no arguments, show all open branch heads in the repository.
2635 With no arguments, show all open branch heads in the repository.
2636 Branch heads are changesets that have no descendants on the
2636 Branch heads are changesets that have no descendants on the
2637 same branch. They are where development generally takes place and
2637 same branch. They are where development generally takes place and
2638 are the usual targets for update and merge operations.
2638 are the usual targets for update and merge operations.
2639
2639
2640 If one or more REVs are given, only open branch heads on the
2640 If one or more REVs are given, only open branch heads on the
2641 branches associated with the specified changesets are shown. This
2641 branches associated with the specified changesets are shown. This
2642 means that you can use :hg:`heads .` to see the heads on the
2642 means that you can use :hg:`heads .` to see the heads on the
2643 currently checked-out branch.
2643 currently checked-out branch.
2644
2644
2645 If -c/--closed is specified, also show branch heads marked closed
2645 If -c/--closed is specified, also show branch heads marked closed
2646 (see :hg:`commit --close-branch`).
2646 (see :hg:`commit --close-branch`).
2647
2647
2648 If STARTREV is specified, only those heads that are descendants of
2648 If STARTREV is specified, only those heads that are descendants of
2649 STARTREV will be displayed.
2649 STARTREV will be displayed.
2650
2650
2651 If -t/--topo is specified, named branch mechanics will be ignored and only
2651 If -t/--topo is specified, named branch mechanics will be ignored and only
2652 topological heads (changesets with no children) will be shown.
2652 topological heads (changesets with no children) will be shown.
2653
2653
2654 Returns 0 if matching heads are found, 1 if not.
2654 Returns 0 if matching heads are found, 1 if not.
2655 """
2655 """
2656
2656
2657 opts = pycompat.byteskwargs(opts)
2657 opts = pycompat.byteskwargs(opts)
2658 start = None
2658 start = None
2659 rev = opts.get('rev')
2659 rev = opts.get('rev')
2660 if rev:
2660 if rev:
2661 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
2661 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
2662 start = scmutil.revsingle(repo, rev, None).node()
2662 start = scmutil.revsingle(repo, rev, None).node()
2663
2663
2664 if opts.get('topo'):
2664 if opts.get('topo'):
2665 heads = [repo[h] for h in repo.heads(start)]
2665 heads = [repo[h] for h in repo.heads(start)]
2666 else:
2666 else:
2667 heads = []
2667 heads = []
2668 for branch in repo.branchmap():
2668 for branch in repo.branchmap():
2669 heads += repo.branchheads(branch, start, opts.get('closed'))
2669 heads += repo.branchheads(branch, start, opts.get('closed'))
2670 heads = [repo[h] for h in heads]
2670 heads = [repo[h] for h in heads]
2671
2671
2672 if branchrevs:
2672 if branchrevs:
2673 branches = set(repo[r].branch()
2673 branches = set(repo[r].branch()
2674 for r in scmutil.revrange(repo, branchrevs))
2674 for r in scmutil.revrange(repo, branchrevs))
2675 heads = [h for h in heads if h.branch() in branches]
2675 heads = [h for h in heads if h.branch() in branches]
2676
2676
2677 if opts.get('active') and branchrevs:
2677 if opts.get('active') and branchrevs:
2678 dagheads = repo.heads(start)
2678 dagheads = repo.heads(start)
2679 heads = [h for h in heads if h.node() in dagheads]
2679 heads = [h for h in heads if h.node() in dagheads]
2680
2680
2681 if branchrevs:
2681 if branchrevs:
2682 haveheads = set(h.branch() for h in heads)
2682 haveheads = set(h.branch() for h in heads)
2683 if branches - haveheads:
2683 if branches - haveheads:
2684 headless = ', '.join(b for b in branches - haveheads)
2684 headless = ', '.join(b for b in branches - haveheads)
2685 msg = _('no open branch heads found on branches %s')
2685 msg = _('no open branch heads found on branches %s')
2686 if opts.get('rev'):
2686 if opts.get('rev'):
2687 msg += _(' (started at %s)') % opts['rev']
2687 msg += _(' (started at %s)') % opts['rev']
2688 ui.warn((msg + '\n') % headless)
2688 ui.warn((msg + '\n') % headless)
2689
2689
2690 if not heads:
2690 if not heads:
2691 return 1
2691 return 1
2692
2692
2693 ui.pager('heads')
2693 ui.pager('heads')
2694 heads = sorted(heads, key=lambda x: -x.rev())
2694 heads = sorted(heads, key=lambda x: -x.rev())
2695 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
2695 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
2696 for ctx in heads:
2696 for ctx in heads:
2697 displayer.show(ctx)
2697 displayer.show(ctx)
2698 displayer.close()
2698 displayer.close()
2699
2699
2700 @command('help',
2700 @command('help',
2701 [('e', 'extension', None, _('show only help for extensions')),
2701 [('e', 'extension', None, _('show only help for extensions')),
2702 ('c', 'command', None, _('show only help for commands')),
2702 ('c', 'command', None, _('show only help for commands')),
2703 ('k', 'keyword', None, _('show topics matching keyword')),
2703 ('k', 'keyword', None, _('show topics matching keyword')),
2704 ('s', 'system', [], _('show help for specific platform(s)')),
2704 ('s', 'system', [], _('show help for specific platform(s)')),
2705 ],
2705 ],
2706 _('[-ecks] [TOPIC]'),
2706 _('[-ecks] [TOPIC]'),
2707 norepo=True,
2707 norepo=True,
2708 intents={INTENT_READONLY})
2708 intents={INTENT_READONLY})
2709 def help_(ui, name=None, **opts):
2709 def help_(ui, name=None, **opts):
2710 """show help for a given topic or a help overview
2710 """show help for a given topic or a help overview
2711
2711
2712 With no arguments, print a list of commands with short help messages.
2712 With no arguments, print a list of commands with short help messages.
2713
2713
2714 Given a topic, extension, or command name, print help for that
2714 Given a topic, extension, or command name, print help for that
2715 topic.
2715 topic.
2716
2716
2717 Returns 0 if successful.
2717 Returns 0 if successful.
2718 """
2718 """
2719
2719
2720 keep = opts.get(r'system') or []
2720 keep = opts.get(r'system') or []
2721 if len(keep) == 0:
2721 if len(keep) == 0:
2722 if pycompat.sysplatform.startswith('win'):
2722 if pycompat.sysplatform.startswith('win'):
2723 keep.append('windows')
2723 keep.append('windows')
2724 elif pycompat.sysplatform == 'OpenVMS':
2724 elif pycompat.sysplatform == 'OpenVMS':
2725 keep.append('vms')
2725 keep.append('vms')
2726 elif pycompat.sysplatform == 'plan9':
2726 elif pycompat.sysplatform == 'plan9':
2727 keep.append('plan9')
2727 keep.append('plan9')
2728 else:
2728 else:
2729 keep.append('unix')
2729 keep.append('unix')
2730 keep.append(pycompat.sysplatform.lower())
2730 keep.append(pycompat.sysplatform.lower())
2731 if ui.verbose:
2731 if ui.verbose:
2732 keep.append('verbose')
2732 keep.append('verbose')
2733
2733
2734 commands = sys.modules[__name__]
2734 commands = sys.modules[__name__]
2735 formatted = help.formattedhelp(ui, commands, name, keep=keep, **opts)
2735 formatted = help.formattedhelp(ui, commands, name, keep=keep, **opts)
2736 ui.pager('help')
2736 ui.pager('help')
2737 ui.write(formatted)
2737 ui.write(formatted)
2738
2738
2739
2739
2740 @command('identify|id',
2740 @command('identify|id',
2741 [('r', 'rev', '',
2741 [('r', 'rev', '',
2742 _('identify the specified revision'), _('REV')),
2742 _('identify the specified revision'), _('REV')),
2743 ('n', 'num', None, _('show local revision number')),
2743 ('n', 'num', None, _('show local revision number')),
2744 ('i', 'id', None, _('show global revision id')),
2744 ('i', 'id', None, _('show global revision id')),
2745 ('b', 'branch', None, _('show branch')),
2745 ('b', 'branch', None, _('show branch')),
2746 ('t', 'tags', None, _('show tags')),
2746 ('t', 'tags', None, _('show tags')),
2747 ('B', 'bookmarks', None, _('show bookmarks')),
2747 ('B', 'bookmarks', None, _('show bookmarks')),
2748 ] + remoteopts + formatteropts,
2748 ] + remoteopts + formatteropts,
2749 _('[-nibtB] [-r REV] [SOURCE]'),
2749 _('[-nibtB] [-r REV] [SOURCE]'),
2750 optionalrepo=True,
2750 optionalrepo=True,
2751 intents={INTENT_READONLY})
2751 intents={INTENT_READONLY})
2752 def identify(ui, repo, source=None, rev=None,
2752 def identify(ui, repo, source=None, rev=None,
2753 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
2753 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
2754 """identify the working directory or specified revision
2754 """identify the working directory or specified revision
2755
2755
2756 Print a summary identifying the repository state at REV using one or
2756 Print a summary identifying the repository state at REV using one or
2757 two parent hash identifiers, followed by a "+" if the working
2757 two parent hash identifiers, followed by a "+" if the working
2758 directory has uncommitted changes, the branch name (if not default),
2758 directory has uncommitted changes, the branch name (if not default),
2759 a list of tags, and a list of bookmarks.
2759 a list of tags, and a list of bookmarks.
2760
2760
2761 When REV is not given, print a summary of the current state of the
2761 When REV is not given, print a summary of the current state of the
2762 repository including the working directory. Specify -r. to get information
2762 repository including the working directory. Specify -r. to get information
2763 of the working directory parent without scanning uncommitted changes.
2763 of the working directory parent without scanning uncommitted changes.
2764
2764
2765 Specifying a path to a repository root or Mercurial bundle will
2765 Specifying a path to a repository root or Mercurial bundle will
2766 cause lookup to operate on that repository/bundle.
2766 cause lookup to operate on that repository/bundle.
2767
2767
2768 .. container:: verbose
2768 .. container:: verbose
2769
2769
2770 Examples:
2770 Examples:
2771
2771
2772 - generate a build identifier for the working directory::
2772 - generate a build identifier for the working directory::
2773
2773
2774 hg id --id > build-id.dat
2774 hg id --id > build-id.dat
2775
2775
2776 - find the revision corresponding to a tag::
2776 - find the revision corresponding to a tag::
2777
2777
2778 hg id -n -r 1.3
2778 hg id -n -r 1.3
2779
2779
2780 - check the most recent revision of a remote repository::
2780 - check the most recent revision of a remote repository::
2781
2781
2782 hg id -r tip https://www.mercurial-scm.org/repo/hg/
2782 hg id -r tip https://www.mercurial-scm.org/repo/hg/
2783
2783
2784 See :hg:`log` for generating more information about specific revisions,
2784 See :hg:`log` for generating more information about specific revisions,
2785 including full hash identifiers.
2785 including full hash identifiers.
2786
2786
2787 Returns 0 if successful.
2787 Returns 0 if successful.
2788 """
2788 """
2789
2789
2790 opts = pycompat.byteskwargs(opts)
2790 opts = pycompat.byteskwargs(opts)
2791 if not repo and not source:
2791 if not repo and not source:
2792 raise error.Abort(_("there is no Mercurial repository here "
2792 raise error.Abort(_("there is no Mercurial repository here "
2793 "(.hg not found)"))
2793 "(.hg not found)"))
2794
2794
2795 if ui.debugflag:
2795 if ui.debugflag:
2796 hexfunc = hex
2796 hexfunc = hex
2797 else:
2797 else:
2798 hexfunc = short
2798 hexfunc = short
2799 default = not (num or id or branch or tags or bookmarks)
2799 default = not (num or id or branch or tags or bookmarks)
2800 output = []
2800 output = []
2801 revs = []
2801 revs = []
2802
2802
2803 if source:
2803 if source:
2804 source, branches = hg.parseurl(ui.expandpath(source))
2804 source, branches = hg.parseurl(ui.expandpath(source))
2805 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
2805 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
2806 repo = peer.local()
2806 repo = peer.local()
2807 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
2807 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
2808
2808
2809 fm = ui.formatter('identify', opts)
2809 fm = ui.formatter('identify', opts)
2810 fm.startitem()
2810 fm.startitem()
2811
2811
2812 if not repo:
2812 if not repo:
2813 if num or branch or tags:
2813 if num or branch or tags:
2814 raise error.Abort(
2814 raise error.Abort(
2815 _("can't query remote revision number, branch, or tags"))
2815 _("can't query remote revision number, branch, or tags"))
2816 if not rev and revs:
2816 if not rev and revs:
2817 rev = revs[0]
2817 rev = revs[0]
2818 if not rev:
2818 if not rev:
2819 rev = "tip"
2819 rev = "tip"
2820
2820
2821 remoterev = peer.lookup(rev)
2821 remoterev = peer.lookup(rev)
2822 hexrev = hexfunc(remoterev)
2822 hexrev = hexfunc(remoterev)
2823 if default or id:
2823 if default or id:
2824 output = [hexrev]
2824 output = [hexrev]
2825 fm.data(id=hexrev)
2825 fm.data(id=hexrev)
2826
2826
2827 def getbms():
2827 def getbms():
2828 bms = []
2828 bms = []
2829
2829
2830 if 'bookmarks' in peer.listkeys('namespaces'):
2830 if 'bookmarks' in peer.listkeys('namespaces'):
2831 hexremoterev = hex(remoterev)
2831 hexremoterev = hex(remoterev)
2832 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
2832 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
2833 if bmr == hexremoterev]
2833 if bmr == hexremoterev]
2834
2834
2835 return sorted(bms)
2835 return sorted(bms)
2836
2836
2837 bms = getbms()
2837 bms = getbms()
2838 if bookmarks:
2838 if bookmarks:
2839 output.extend(bms)
2839 output.extend(bms)
2840 elif default and not ui.quiet:
2840 elif default and not ui.quiet:
2841 # multiple bookmarks for a single parent separated by '/'
2841 # multiple bookmarks for a single parent separated by '/'
2842 bm = '/'.join(bms)
2842 bm = '/'.join(bms)
2843 if bm:
2843 if bm:
2844 output.append(bm)
2844 output.append(bm)
2845
2845
2846 fm.data(node=hex(remoterev))
2846 fm.data(node=hex(remoterev))
2847 fm.data(bookmarks=fm.formatlist(bms, name='bookmark'))
2847 fm.data(bookmarks=fm.formatlist(bms, name='bookmark'))
2848 else:
2848 else:
2849 if rev:
2849 if rev:
2850 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
2850 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
2851 ctx = scmutil.revsingle(repo, rev, None)
2851 ctx = scmutil.revsingle(repo, rev, None)
2852
2852
2853 if ctx.rev() is None:
2853 if ctx.rev() is None:
2854 ctx = repo[None]
2854 ctx = repo[None]
2855 parents = ctx.parents()
2855 parents = ctx.parents()
2856 taglist = []
2856 taglist = []
2857 for p in parents:
2857 for p in parents:
2858 taglist.extend(p.tags())
2858 taglist.extend(p.tags())
2859
2859
2860 dirty = ""
2860 dirty = ""
2861 if ctx.dirty(missing=True, merge=False, branch=False):
2861 if ctx.dirty(missing=True, merge=False, branch=False):
2862 dirty = '+'
2862 dirty = '+'
2863 fm.data(dirty=dirty)
2863 fm.data(dirty=dirty)
2864
2864
2865 hexoutput = [hexfunc(p.node()) for p in parents]
2865 hexoutput = [hexfunc(p.node()) for p in parents]
2866 if default or id:
2866 if default or id:
2867 output = ["%s%s" % ('+'.join(hexoutput), dirty)]
2867 output = ["%s%s" % ('+'.join(hexoutput), dirty)]
2868 fm.data(id="%s%s" % ('+'.join(hexoutput), dirty))
2868 fm.data(id="%s%s" % ('+'.join(hexoutput), dirty))
2869
2869
2870 if num:
2870 if num:
2871 numoutput = ["%d" % p.rev() for p in parents]
2871 numoutput = ["%d" % p.rev() for p in parents]
2872 output.append("%s%s" % ('+'.join(numoutput), dirty))
2872 output.append("%s%s" % ('+'.join(numoutput), dirty))
2873
2873
2874 fn = fm.nested('parents', tmpl='{rev}:{node|formatnode}', sep=' ')
2874 fn = fm.nested('parents', tmpl='{rev}:{node|formatnode}', sep=' ')
2875 for p in parents:
2875 for p in parents:
2876 fn.startitem()
2876 fn.startitem()
2877 fn.data(rev=p.rev())
2877 fn.data(rev=p.rev())
2878 fn.data(node=p.hex())
2878 fn.data(node=p.hex())
2879 fn.context(ctx=p)
2879 fn.context(ctx=p)
2880 fn.end()
2880 fn.end()
2881 else:
2881 else:
2882 hexoutput = hexfunc(ctx.node())
2882 hexoutput = hexfunc(ctx.node())
2883 if default or id:
2883 if default or id:
2884 output = [hexoutput]
2884 output = [hexoutput]
2885 fm.data(id=hexoutput)
2885 fm.data(id=hexoutput)
2886
2886
2887 if num:
2887 if num:
2888 output.append(pycompat.bytestr(ctx.rev()))
2888 output.append(pycompat.bytestr(ctx.rev()))
2889 taglist = ctx.tags()
2889 taglist = ctx.tags()
2890
2890
2891 if default and not ui.quiet:
2891 if default and not ui.quiet:
2892 b = ctx.branch()
2892 b = ctx.branch()
2893 if b != 'default':
2893 if b != 'default':
2894 output.append("(%s)" % b)
2894 output.append("(%s)" % b)
2895
2895
2896 # multiple tags for a single parent separated by '/'
2896 # multiple tags for a single parent separated by '/'
2897 t = '/'.join(taglist)
2897 t = '/'.join(taglist)
2898 if t:
2898 if t:
2899 output.append(t)
2899 output.append(t)
2900
2900
2901 # multiple bookmarks for a single parent separated by '/'
2901 # multiple bookmarks for a single parent separated by '/'
2902 bm = '/'.join(ctx.bookmarks())
2902 bm = '/'.join(ctx.bookmarks())
2903 if bm:
2903 if bm:
2904 output.append(bm)
2904 output.append(bm)
2905 else:
2905 else:
2906 if branch:
2906 if branch:
2907 output.append(ctx.branch())
2907 output.append(ctx.branch())
2908
2908
2909 if tags:
2909 if tags:
2910 output.extend(taglist)
2910 output.extend(taglist)
2911
2911
2912 if bookmarks:
2912 if bookmarks:
2913 output.extend(ctx.bookmarks())
2913 output.extend(ctx.bookmarks())
2914
2914
2915 fm.data(node=ctx.hex())
2915 fm.data(node=ctx.hex())
2916 fm.data(branch=ctx.branch())
2916 fm.data(branch=ctx.branch())
2917 fm.data(tags=fm.formatlist(taglist, name='tag', sep=':'))
2917 fm.data(tags=fm.formatlist(taglist, name='tag', sep=':'))
2918 fm.data(bookmarks=fm.formatlist(ctx.bookmarks(), name='bookmark'))
2918 fm.data(bookmarks=fm.formatlist(ctx.bookmarks(), name='bookmark'))
2919 fm.context(ctx=ctx)
2919 fm.context(ctx=ctx)
2920
2920
2921 fm.plain("%s\n" % ' '.join(output))
2921 fm.plain("%s\n" % ' '.join(output))
2922 fm.end()
2922 fm.end()
2923
2923
2924 @command('import|patch',
2924 @command('import|patch',
2925 [('p', 'strip', 1,
2925 [('p', 'strip', 1,
2926 _('directory strip option for patch. This has the same '
2926 _('directory strip option for patch. This has the same '
2927 'meaning as the corresponding patch option'), _('NUM')),
2927 'meaning as the corresponding patch option'), _('NUM')),
2928 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
2928 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
2929 ('e', 'edit', False, _('invoke editor on commit messages')),
2929 ('e', 'edit', False, _('invoke editor on commit messages')),
2930 ('f', 'force', None,
2930 ('f', 'force', None,
2931 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
2931 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
2932 ('', 'no-commit', None,
2932 ('', 'no-commit', None,
2933 _("don't commit, just update the working directory")),
2933 _("don't commit, just update the working directory")),
2934 ('', 'bypass', None,
2934 ('', 'bypass', None,
2935 _("apply patch without touching the working directory")),
2935 _("apply patch without touching the working directory")),
2936 ('', 'partial', None,
2936 ('', 'partial', None,
2937 _('commit even if some hunks fail')),
2937 _('commit even if some hunks fail')),
2938 ('', 'exact', None,
2938 ('', 'exact', None,
2939 _('abort if patch would apply lossily')),
2939 _('abort if patch would apply lossily')),
2940 ('', 'prefix', '',
2940 ('', 'prefix', '',
2941 _('apply patch to subdirectory'), _('DIR')),
2941 _('apply patch to subdirectory'), _('DIR')),
2942 ('', 'import-branch', None,
2942 ('', 'import-branch', None,
2943 _('use any branch information in patch (implied by --exact)'))] +
2943 _('use any branch information in patch (implied by --exact)'))] +
2944 commitopts + commitopts2 + similarityopts,
2944 commitopts + commitopts2 + similarityopts,
2945 _('[OPTION]... PATCH...'))
2945 _('[OPTION]... PATCH...'))
2946 def import_(ui, repo, patch1=None, *patches, **opts):
2946 def import_(ui, repo, patch1=None, *patches, **opts):
2947 """import an ordered set of patches
2947 """import an ordered set of patches
2948
2948
2949 Import a list of patches and commit them individually (unless
2949 Import a list of patches and commit them individually (unless
2950 --no-commit is specified).
2950 --no-commit is specified).
2951
2951
2952 To read a patch from standard input (stdin), use "-" as the patch
2952 To read a patch from standard input (stdin), use "-" as the patch
2953 name. If a URL is specified, the patch will be downloaded from
2953 name. If a URL is specified, the patch will be downloaded from
2954 there.
2954 there.
2955
2955
2956 Import first applies changes to the working directory (unless
2956 Import first applies changes to the working directory (unless
2957 --bypass is specified), import will abort if there are outstanding
2957 --bypass is specified), import will abort if there are outstanding
2958 changes.
2958 changes.
2959
2959
2960 Use --bypass to apply and commit patches directly to the
2960 Use --bypass to apply and commit patches directly to the
2961 repository, without affecting the working directory. Without
2961 repository, without affecting the working directory. Without
2962 --exact, patches will be applied on top of the working directory
2962 --exact, patches will be applied on top of the working directory
2963 parent revision.
2963 parent revision.
2964
2964
2965 You can import a patch straight from a mail message. Even patches
2965 You can import a patch straight from a mail message. Even patches
2966 as attachments work (to use the body part, it must have type
2966 as attachments work (to use the body part, it must have type
2967 text/plain or text/x-patch). From and Subject headers of email
2967 text/plain or text/x-patch). From and Subject headers of email
2968 message are used as default committer and commit message. All
2968 message are used as default committer and commit message. All
2969 text/plain body parts before first diff are added to the commit
2969 text/plain body parts before first diff are added to the commit
2970 message.
2970 message.
2971
2971
2972 If the imported patch was generated by :hg:`export`, user and
2972 If the imported patch was generated by :hg:`export`, user and
2973 description from patch override values from message headers and
2973 description from patch override values from message headers and
2974 body. Values given on command line with -m/--message and -u/--user
2974 body. Values given on command line with -m/--message and -u/--user
2975 override these.
2975 override these.
2976
2976
2977 If --exact is specified, import will set the working directory to
2977 If --exact is specified, import will set the working directory to
2978 the parent of each patch before applying it, and will abort if the
2978 the parent of each patch before applying it, and will abort if the
2979 resulting changeset has a different ID than the one recorded in
2979 resulting changeset has a different ID than the one recorded in
2980 the patch. This will guard against various ways that portable
2980 the patch. This will guard against various ways that portable
2981 patch formats and mail systems might fail to transfer Mercurial
2981 patch formats and mail systems might fail to transfer Mercurial
2982 data or metadata. See :hg:`bundle` for lossless transmission.
2982 data or metadata. See :hg:`bundle` for lossless transmission.
2983
2983
2984 Use --partial to ensure a changeset will be created from the patch
2984 Use --partial to ensure a changeset will be created from the patch
2985 even if some hunks fail to apply. Hunks that fail to apply will be
2985 even if some hunks fail to apply. Hunks that fail to apply will be
2986 written to a <target-file>.rej file. Conflicts can then be resolved
2986 written to a <target-file>.rej file. Conflicts can then be resolved
2987 by hand before :hg:`commit --amend` is run to update the created
2987 by hand before :hg:`commit --amend` is run to update the created
2988 changeset. This flag exists to let people import patches that
2988 changeset. This flag exists to let people import patches that
2989 partially apply without losing the associated metadata (author,
2989 partially apply without losing the associated metadata (author,
2990 date, description, ...).
2990 date, description, ...).
2991
2991
2992 .. note::
2992 .. note::
2993
2993
2994 When no hunks apply cleanly, :hg:`import --partial` will create
2994 When no hunks apply cleanly, :hg:`import --partial` will create
2995 an empty changeset, importing only the patch metadata.
2995 an empty changeset, importing only the patch metadata.
2996
2996
2997 With -s/--similarity, hg will attempt to discover renames and
2997 With -s/--similarity, hg will attempt to discover renames and
2998 copies in the patch in the same way as :hg:`addremove`.
2998 copies in the patch in the same way as :hg:`addremove`.
2999
2999
3000 It is possible to use external patch programs to perform the patch
3000 It is possible to use external patch programs to perform the patch
3001 by setting the ``ui.patch`` configuration option. For the default
3001 by setting the ``ui.patch`` configuration option. For the default
3002 internal tool, the fuzz can also be configured via ``patch.fuzz``.
3002 internal tool, the fuzz can also be configured via ``patch.fuzz``.
3003 See :hg:`help config` for more information about configuration
3003 See :hg:`help config` for more information about configuration
3004 files and how to use these options.
3004 files and how to use these options.
3005
3005
3006 See :hg:`help dates` for a list of formats valid for -d/--date.
3006 See :hg:`help dates` for a list of formats valid for -d/--date.
3007
3007
3008 .. container:: verbose
3008 .. container:: verbose
3009
3009
3010 Examples:
3010 Examples:
3011
3011
3012 - import a traditional patch from a website and detect renames::
3012 - import a traditional patch from a website and detect renames::
3013
3013
3014 hg import -s 80 http://example.com/bugfix.patch
3014 hg import -s 80 http://example.com/bugfix.patch
3015
3015
3016 - import a changeset from an hgweb server::
3016 - import a changeset from an hgweb server::
3017
3017
3018 hg import https://www.mercurial-scm.org/repo/hg/rev/5ca8c111e9aa
3018 hg import https://www.mercurial-scm.org/repo/hg/rev/5ca8c111e9aa
3019
3019
3020 - import all the patches in an Unix-style mbox::
3020 - import all the patches in an Unix-style mbox::
3021
3021
3022 hg import incoming-patches.mbox
3022 hg import incoming-patches.mbox
3023
3023
3024 - import patches from stdin::
3024 - import patches from stdin::
3025
3025
3026 hg import -
3026 hg import -
3027
3027
3028 - attempt to exactly restore an exported changeset (not always
3028 - attempt to exactly restore an exported changeset (not always
3029 possible)::
3029 possible)::
3030
3030
3031 hg import --exact proposed-fix.patch
3031 hg import --exact proposed-fix.patch
3032
3032
3033 - use an external tool to apply a patch which is too fuzzy for
3033 - use an external tool to apply a patch which is too fuzzy for
3034 the default internal tool.
3034 the default internal tool.
3035
3035
3036 hg import --config ui.patch="patch --merge" fuzzy.patch
3036 hg import --config ui.patch="patch --merge" fuzzy.patch
3037
3037
3038 - change the default fuzzing from 2 to a less strict 7
3038 - change the default fuzzing from 2 to a less strict 7
3039
3039
3040 hg import --config ui.fuzz=7 fuzz.patch
3040 hg import --config ui.fuzz=7 fuzz.patch
3041
3041
3042 Returns 0 on success, 1 on partial success (see --partial).
3042 Returns 0 on success, 1 on partial success (see --partial).
3043 """
3043 """
3044
3044
3045 opts = pycompat.byteskwargs(opts)
3045 opts = pycompat.byteskwargs(opts)
3046 if not patch1:
3046 if not patch1:
3047 raise error.Abort(_('need at least one patch to import'))
3047 raise error.Abort(_('need at least one patch to import'))
3048
3048
3049 patches = (patch1,) + patches
3049 patches = (patch1,) + patches
3050
3050
3051 date = opts.get('date')
3051 date = opts.get('date')
3052 if date:
3052 if date:
3053 opts['date'] = dateutil.parsedate(date)
3053 opts['date'] = dateutil.parsedate(date)
3054
3054
3055 exact = opts.get('exact')
3055 exact = opts.get('exact')
3056 update = not opts.get('bypass')
3056 update = not opts.get('bypass')
3057 if not update and opts.get('no_commit'):
3057 if not update and opts.get('no_commit'):
3058 raise error.Abort(_('cannot use --no-commit with --bypass'))
3058 raise error.Abort(_('cannot use --no-commit with --bypass'))
3059 try:
3059 try:
3060 sim = float(opts.get('similarity') or 0)
3060 sim = float(opts.get('similarity') or 0)
3061 except ValueError:
3061 except ValueError:
3062 raise error.Abort(_('similarity must be a number'))
3062 raise error.Abort(_('similarity must be a number'))
3063 if sim < 0 or sim > 100:
3063 if sim < 0 or sim > 100:
3064 raise error.Abort(_('similarity must be between 0 and 100'))
3064 raise error.Abort(_('similarity must be between 0 and 100'))
3065 if sim and not update:
3065 if sim and not update:
3066 raise error.Abort(_('cannot use --similarity with --bypass'))
3066 raise error.Abort(_('cannot use --similarity with --bypass'))
3067 if exact:
3067 if exact:
3068 if opts.get('edit'):
3068 if opts.get('edit'):
3069 raise error.Abort(_('cannot use --exact with --edit'))
3069 raise error.Abort(_('cannot use --exact with --edit'))
3070 if opts.get('prefix'):
3070 if opts.get('prefix'):
3071 raise error.Abort(_('cannot use --exact with --prefix'))
3071 raise error.Abort(_('cannot use --exact with --prefix'))
3072
3072
3073 base = opts["base"]
3073 base = opts["base"]
3074 wlock = dsguard = lock = tr = None
3074 wlock = dsguard = lock = tr = None
3075 msgs = []
3075 msgs = []
3076 ret = 0
3076 ret = 0
3077
3077
3078
3078
3079 try:
3079 try:
3080 wlock = repo.wlock()
3080 wlock = repo.wlock()
3081
3081
3082 if update:
3082 if update:
3083 cmdutil.checkunfinished(repo)
3083 cmdutil.checkunfinished(repo)
3084 if (exact or not opts.get('force')):
3084 if (exact or not opts.get('force')):
3085 cmdutil.bailifchanged(repo)
3085 cmdutil.bailifchanged(repo)
3086
3086
3087 if not opts.get('no_commit'):
3087 if not opts.get('no_commit'):
3088 lock = repo.lock()
3088 lock = repo.lock()
3089 tr = repo.transaction('import')
3089 tr = repo.transaction('import')
3090 else:
3090 else:
3091 dsguard = dirstateguard.dirstateguard(repo, 'import')
3091 dsguard = dirstateguard.dirstateguard(repo, 'import')
3092 parents = repo[None].parents()
3092 parents = repo[None].parents()
3093 for patchurl in patches:
3093 for patchurl in patches:
3094 if patchurl == '-':
3094 if patchurl == '-':
3095 ui.status(_('applying patch from stdin\n'))
3095 ui.status(_('applying patch from stdin\n'))
3096 patchfile = ui.fin
3096 patchfile = ui.fin
3097 patchurl = 'stdin' # for error message
3097 patchurl = 'stdin' # for error message
3098 else:
3098 else:
3099 patchurl = os.path.join(base, patchurl)
3099 patchurl = os.path.join(base, patchurl)
3100 ui.status(_('applying %s\n') % patchurl)
3100 ui.status(_('applying %s\n') % patchurl)
3101 patchfile = hg.openpath(ui, patchurl)
3101 patchfile = hg.openpath(ui, patchurl)
3102
3102
3103 haspatch = False
3103 haspatch = False
3104 for hunk in patch.split(patchfile):
3104 for hunk in patch.split(patchfile):
3105 with patch.extract(ui, hunk) as patchdata:
3105 with patch.extract(ui, hunk) as patchdata:
3106 msg, node, rej = cmdutil.tryimportone(ui, repo, patchdata,
3106 msg, node, rej = cmdutil.tryimportone(ui, repo, patchdata,
3107 parents, opts,
3107 parents, opts,
3108 msgs, hg.clean)
3108 msgs, hg.clean)
3109 if msg:
3109 if msg:
3110 haspatch = True
3110 haspatch = True
3111 ui.note(msg + '\n')
3111 ui.note(msg + '\n')
3112 if update or exact:
3112 if update or exact:
3113 parents = repo[None].parents()
3113 parents = repo[None].parents()
3114 else:
3114 else:
3115 parents = [repo[node]]
3115 parents = [repo[node]]
3116 if rej:
3116 if rej:
3117 ui.write_err(_("patch applied partially\n"))
3117 ui.write_err(_("patch applied partially\n"))
3118 ui.write_err(_("(fix the .rej files and run "
3118 ui.write_err(_("(fix the .rej files and run "
3119 "`hg commit --amend`)\n"))
3119 "`hg commit --amend`)\n"))
3120 ret = 1
3120 ret = 1
3121 break
3121 break
3122
3122
3123 if not haspatch:
3123 if not haspatch:
3124 raise error.Abort(_('%s: no diffs found') % patchurl)
3124 raise error.Abort(_('%s: no diffs found') % patchurl)
3125
3125
3126 if tr:
3126 if tr:
3127 tr.close()
3127 tr.close()
3128 if msgs:
3128 if msgs:
3129 repo.savecommitmessage('\n* * *\n'.join(msgs))
3129 repo.savecommitmessage('\n* * *\n'.join(msgs))
3130 if dsguard:
3130 if dsguard:
3131 dsguard.close()
3131 dsguard.close()
3132 return ret
3132 return ret
3133 finally:
3133 finally:
3134 if tr:
3134 if tr:
3135 tr.release()
3135 tr.release()
3136 release(lock, dsguard, wlock)
3136 release(lock, dsguard, wlock)
3137
3137
3138 @command('incoming|in',
3138 @command('incoming|in',
3139 [('f', 'force', None,
3139 [('f', 'force', None,
3140 _('run even if remote repository is unrelated')),
3140 _('run even if remote repository is unrelated')),
3141 ('n', 'newest-first', None, _('show newest record first')),
3141 ('n', 'newest-first', None, _('show newest record first')),
3142 ('', 'bundle', '',
3142 ('', 'bundle', '',
3143 _('file to store the bundles into'), _('FILE')),
3143 _('file to store the bundles into'), _('FILE')),
3144 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3144 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3145 ('B', 'bookmarks', False, _("compare bookmarks")),
3145 ('B', 'bookmarks', False, _("compare bookmarks")),
3146 ('b', 'branch', [],
3146 ('b', 'branch', [],
3147 _('a specific branch you would like to pull'), _('BRANCH')),
3147 _('a specific branch you would like to pull'), _('BRANCH')),
3148 ] + logopts + remoteopts + subrepoopts,
3148 ] + logopts + remoteopts + subrepoopts,
3149 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3149 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3150 def incoming(ui, repo, source="default", **opts):
3150 def incoming(ui, repo, source="default", **opts):
3151 """show new changesets found in source
3151 """show new changesets found in source
3152
3152
3153 Show new changesets found in the specified path/URL or the default
3153 Show new changesets found in the specified path/URL or the default
3154 pull location. These are the changesets that would have been pulled
3154 pull location. These are the changesets that would have been pulled
3155 by :hg:`pull` at the time you issued this command.
3155 by :hg:`pull` at the time you issued this command.
3156
3156
3157 See pull for valid source format details.
3157 See pull for valid source format details.
3158
3158
3159 .. container:: verbose
3159 .. container:: verbose
3160
3160
3161 With -B/--bookmarks, the result of bookmark comparison between
3161 With -B/--bookmarks, the result of bookmark comparison between
3162 local and remote repositories is displayed. With -v/--verbose,
3162 local and remote repositories is displayed. With -v/--verbose,
3163 status is also displayed for each bookmark like below::
3163 status is also displayed for each bookmark like below::
3164
3164
3165 BM1 01234567890a added
3165 BM1 01234567890a added
3166 BM2 1234567890ab advanced
3166 BM2 1234567890ab advanced
3167 BM3 234567890abc diverged
3167 BM3 234567890abc diverged
3168 BM4 34567890abcd changed
3168 BM4 34567890abcd changed
3169
3169
3170 The action taken locally when pulling depends on the
3170 The action taken locally when pulling depends on the
3171 status of each bookmark:
3171 status of each bookmark:
3172
3172
3173 :``added``: pull will create it
3173 :``added``: pull will create it
3174 :``advanced``: pull will update it
3174 :``advanced``: pull will update it
3175 :``diverged``: pull will create a divergent bookmark
3175 :``diverged``: pull will create a divergent bookmark
3176 :``changed``: result depends on remote changesets
3176 :``changed``: result depends on remote changesets
3177
3177
3178 From the point of view of pulling behavior, bookmark
3178 From the point of view of pulling behavior, bookmark
3179 existing only in the remote repository are treated as ``added``,
3179 existing only in the remote repository are treated as ``added``,
3180 even if it is in fact locally deleted.
3180 even if it is in fact locally deleted.
3181
3181
3182 .. container:: verbose
3182 .. container:: verbose
3183
3183
3184 For remote repository, using --bundle avoids downloading the
3184 For remote repository, using --bundle avoids downloading the
3185 changesets twice if the incoming is followed by a pull.
3185 changesets twice if the incoming is followed by a pull.
3186
3186
3187 Examples:
3187 Examples:
3188
3188
3189 - show incoming changes with patches and full description::
3189 - show incoming changes with patches and full description::
3190
3190
3191 hg incoming -vp
3191 hg incoming -vp
3192
3192
3193 - show incoming changes excluding merges, store a bundle::
3193 - show incoming changes excluding merges, store a bundle::
3194
3194
3195 hg in -vpM --bundle incoming.hg
3195 hg in -vpM --bundle incoming.hg
3196 hg pull incoming.hg
3196 hg pull incoming.hg
3197
3197
3198 - briefly list changes inside a bundle::
3198 - briefly list changes inside a bundle::
3199
3199
3200 hg in changes.hg -T "{desc|firstline}\\n"
3200 hg in changes.hg -T "{desc|firstline}\\n"
3201
3201
3202 Returns 0 if there are incoming changes, 1 otherwise.
3202 Returns 0 if there are incoming changes, 1 otherwise.
3203 """
3203 """
3204 opts = pycompat.byteskwargs(opts)
3204 opts = pycompat.byteskwargs(opts)
3205 if opts.get('graph'):
3205 if opts.get('graph'):
3206 logcmdutil.checkunsupportedgraphflags([], opts)
3206 logcmdutil.checkunsupportedgraphflags([], opts)
3207 def display(other, chlist, displayer):
3207 def display(other, chlist, displayer):
3208 revdag = logcmdutil.graphrevs(other, chlist, opts)
3208 revdag = logcmdutil.graphrevs(other, chlist, opts)
3209 logcmdutil.displaygraph(ui, repo, revdag, displayer,
3209 logcmdutil.displaygraph(ui, repo, revdag, displayer,
3210 graphmod.asciiedges)
3210 graphmod.asciiedges)
3211
3211
3212 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3212 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3213 return 0
3213 return 0
3214
3214
3215 if opts.get('bundle') and opts.get('subrepos'):
3215 if opts.get('bundle') and opts.get('subrepos'):
3216 raise error.Abort(_('cannot combine --bundle and --subrepos'))
3216 raise error.Abort(_('cannot combine --bundle and --subrepos'))
3217
3217
3218 if opts.get('bookmarks'):
3218 if opts.get('bookmarks'):
3219 source, branches = hg.parseurl(ui.expandpath(source),
3219 source, branches = hg.parseurl(ui.expandpath(source),
3220 opts.get('branch'))
3220 opts.get('branch'))
3221 other = hg.peer(repo, opts, source)
3221 other = hg.peer(repo, opts, source)
3222 if 'bookmarks' not in other.listkeys('namespaces'):
3222 if 'bookmarks' not in other.listkeys('namespaces'):
3223 ui.warn(_("remote doesn't support bookmarks\n"))
3223 ui.warn(_("remote doesn't support bookmarks\n"))
3224 return 0
3224 return 0
3225 ui.pager('incoming')
3225 ui.pager('incoming')
3226 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3226 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3227 return bookmarks.incoming(ui, repo, other)
3227 return bookmarks.incoming(ui, repo, other)
3228
3228
3229 repo._subtoppath = ui.expandpath(source)
3229 repo._subtoppath = ui.expandpath(source)
3230 try:
3230 try:
3231 return hg.incoming(ui, repo, source, opts)
3231 return hg.incoming(ui, repo, source, opts)
3232 finally:
3232 finally:
3233 del repo._subtoppath
3233 del repo._subtoppath
3234
3234
3235
3235
3236 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
3236 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
3237 norepo=True)
3237 norepo=True)
3238 def init(ui, dest=".", **opts):
3238 def init(ui, dest=".", **opts):
3239 """create a new repository in the given directory
3239 """create a new repository in the given directory
3240
3240
3241 Initialize a new repository in the given directory. If the given
3241 Initialize a new repository in the given directory. If the given
3242 directory does not exist, it will be created.
3242 directory does not exist, it will be created.
3243
3243
3244 If no directory is given, the current directory is used.
3244 If no directory is given, the current directory is used.
3245
3245
3246 It is possible to specify an ``ssh://`` URL as the destination.
3246 It is possible to specify an ``ssh://`` URL as the destination.
3247 See :hg:`help urls` for more information.
3247 See :hg:`help urls` for more information.
3248
3248
3249 Returns 0 on success.
3249 Returns 0 on success.
3250 """
3250 """
3251 opts = pycompat.byteskwargs(opts)
3251 opts = pycompat.byteskwargs(opts)
3252 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3252 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3253
3253
3254 @command('locate',
3254 @command('locate',
3255 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3255 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3256 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3256 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3257 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3257 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3258 ] + walkopts,
3258 ] + walkopts,
3259 _('[OPTION]... [PATTERN]...'))
3259 _('[OPTION]... [PATTERN]...'))
3260 def locate(ui, repo, *pats, **opts):
3260 def locate(ui, repo, *pats, **opts):
3261 """locate files matching specific patterns (DEPRECATED)
3261 """locate files matching specific patterns (DEPRECATED)
3262
3262
3263 Print files under Mercurial control in the working directory whose
3263 Print files under Mercurial control in the working directory whose
3264 names match the given patterns.
3264 names match the given patterns.
3265
3265
3266 By default, this command searches all directories in the working
3266 By default, this command searches all directories in the working
3267 directory. To search just the current directory and its
3267 directory. To search just the current directory and its
3268 subdirectories, use "--include .".
3268 subdirectories, use "--include .".
3269
3269
3270 If no patterns are given to match, this command prints the names
3270 If no patterns are given to match, this command prints the names
3271 of all files under Mercurial control in the working directory.
3271 of all files under Mercurial control in the working directory.
3272
3272
3273 If you want to feed the output of this command into the "xargs"
3273 If you want to feed the output of this command into the "xargs"
3274 command, use the -0 option to both this command and "xargs". This
3274 command, use the -0 option to both this command and "xargs". This
3275 will avoid the problem of "xargs" treating single filenames that
3275 will avoid the problem of "xargs" treating single filenames that
3276 contain whitespace as multiple filenames.
3276 contain whitespace as multiple filenames.
3277
3277
3278 See :hg:`help files` for a more versatile command.
3278 See :hg:`help files` for a more versatile command.
3279
3279
3280 Returns 0 if a match is found, 1 otherwise.
3280 Returns 0 if a match is found, 1 otherwise.
3281 """
3281 """
3282 opts = pycompat.byteskwargs(opts)
3282 opts = pycompat.byteskwargs(opts)
3283 if opts.get('print0'):
3283 if opts.get('print0'):
3284 end = '\0'
3284 end = '\0'
3285 else:
3285 else:
3286 end = '\n'
3286 end = '\n'
3287 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3287 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3288
3288
3289 ret = 1
3289 ret = 1
3290 m = scmutil.match(ctx, pats, opts, default='relglob',
3290 m = scmutil.match(ctx, pats, opts, default='relglob',
3291 badfn=lambda x, y: False)
3291 badfn=lambda x, y: False)
3292
3292
3293 ui.pager('locate')
3293 ui.pager('locate')
3294 for abs in ctx.matches(m):
3294 for abs in ctx.matches(m):
3295 if opts.get('fullpath'):
3295 if opts.get('fullpath'):
3296 ui.write(repo.wjoin(abs), end)
3296 ui.write(repo.wjoin(abs), end)
3297 else:
3297 else:
3298 ui.write(((pats and m.rel(abs)) or abs), end)
3298 ui.write(((pats and m.rel(abs)) or abs), end)
3299 ret = 0
3299 ret = 0
3300
3300
3301 return ret
3301 return ret
3302
3302
3303 @command('^log|history',
3303 @command('^log|history',
3304 [('f', 'follow', None,
3304 [('f', 'follow', None,
3305 _('follow changeset history, or file history across copies and renames')),
3305 _('follow changeset history, or file history across copies and renames')),
3306 ('', 'follow-first', None,
3306 ('', 'follow-first', None,
3307 _('only follow the first parent of merge changesets (DEPRECATED)')),
3307 _('only follow the first parent of merge changesets (DEPRECATED)')),
3308 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3308 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3309 ('C', 'copies', None, _('show copied files')),
3309 ('C', 'copies', None, _('show copied files')),
3310 ('k', 'keyword', [],
3310 ('k', 'keyword', [],
3311 _('do case-insensitive search for a given text'), _('TEXT')),
3311 _('do case-insensitive search for a given text'), _('TEXT')),
3312 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
3312 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
3313 ('L', 'line-range', [],
3313 ('L', 'line-range', [],
3314 _('follow line range of specified file (EXPERIMENTAL)'),
3314 _('follow line range of specified file (EXPERIMENTAL)'),
3315 _('FILE,RANGE')),
3315 _('FILE,RANGE')),
3316 ('', 'removed', None, _('include revisions where files were removed')),
3316 ('', 'removed', None, _('include revisions where files were removed')),
3317 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3317 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3318 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3318 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3319 ('', 'only-branch', [],
3319 ('', 'only-branch', [],
3320 _('show only changesets within the given named branch (DEPRECATED)'),
3320 _('show only changesets within the given named branch (DEPRECATED)'),
3321 _('BRANCH')),
3321 _('BRANCH')),
3322 ('b', 'branch', [],
3322 ('b', 'branch', [],
3323 _('show changesets within the given named branch'), _('BRANCH')),
3323 _('show changesets within the given named branch'), _('BRANCH')),
3324 ('P', 'prune', [],
3324 ('P', 'prune', [],
3325 _('do not display revision or any of its ancestors'), _('REV')),
3325 _('do not display revision or any of its ancestors'), _('REV')),
3326 ] + logopts + walkopts,
3326 ] + logopts + walkopts,
3327 _('[OPTION]... [FILE]'),
3327 _('[OPTION]... [FILE]'),
3328 inferrepo=True,
3328 inferrepo=True,
3329 intents={INTENT_READONLY})
3329 intents={INTENT_READONLY})
3330 def log(ui, repo, *pats, **opts):
3330 def log(ui, repo, *pats, **opts):
3331 """show revision history of entire repository or files
3331 """show revision history of entire repository or files
3332
3332
3333 Print the revision history of the specified files or the entire
3333 Print the revision history of the specified files or the entire
3334 project.
3334 project.
3335
3335
3336 If no revision range is specified, the default is ``tip:0`` unless
3336 If no revision range is specified, the default is ``tip:0`` unless
3337 --follow is set, in which case the working directory parent is
3337 --follow is set, in which case the working directory parent is
3338 used as the starting revision.
3338 used as the starting revision.
3339
3339
3340 File history is shown without following rename or copy history of
3340 File history is shown without following rename or copy history of
3341 files. Use -f/--follow with a filename to follow history across
3341 files. Use -f/--follow with a filename to follow history across
3342 renames and copies. --follow without a filename will only show
3342 renames and copies. --follow without a filename will only show
3343 ancestors of the starting revision.
3343 ancestors of the starting revision.
3344
3344
3345 By default this command prints revision number and changeset id,
3345 By default this command prints revision number and changeset id,
3346 tags, non-trivial parents, user, date and time, and a summary for
3346 tags, non-trivial parents, user, date and time, and a summary for
3347 each commit. When the -v/--verbose switch is used, the list of
3347 each commit. When the -v/--verbose switch is used, the list of
3348 changed files and full commit message are shown.
3348 changed files and full commit message are shown.
3349
3349
3350 With --graph the revisions are shown as an ASCII art DAG with the most
3350 With --graph the revisions are shown as an ASCII art DAG with the most
3351 recent changeset at the top.
3351 recent changeset at the top.
3352 'o' is a changeset, '@' is a working directory parent, '_' closes a branch,
3352 'o' is a changeset, '@' is a working directory parent, '_' closes a branch,
3353 'x' is obsolete, '*' is unstable, and '+' represents a fork where the
3353 'x' is obsolete, '*' is unstable, and '+' represents a fork where the
3354 changeset from the lines below is a parent of the 'o' merge on the same
3354 changeset from the lines below is a parent of the 'o' merge on the same
3355 line.
3355 line.
3356 Paths in the DAG are represented with '|', '/' and so forth. ':' in place
3356 Paths in the DAG are represented with '|', '/' and so forth. ':' in place
3357 of a '|' indicates one or more revisions in a path are omitted.
3357 of a '|' indicates one or more revisions in a path are omitted.
3358
3358
3359 .. container:: verbose
3359 .. container:: verbose
3360
3360
3361 Use -L/--line-range FILE,M:N options to follow the history of lines
3361 Use -L/--line-range FILE,M:N options to follow the history of lines
3362 from M to N in FILE. With -p/--patch only diff hunks affecting
3362 from M to N in FILE. With -p/--patch only diff hunks affecting
3363 specified line range will be shown. This option requires --follow;
3363 specified line range will be shown. This option requires --follow;
3364 it can be specified multiple times. Currently, this option is not
3364 it can be specified multiple times. Currently, this option is not
3365 compatible with --graph. This option is experimental.
3365 compatible with --graph. This option is experimental.
3366
3366
3367 .. note::
3367 .. note::
3368
3368
3369 :hg:`log --patch` may generate unexpected diff output for merge
3369 :hg:`log --patch` may generate unexpected diff output for merge
3370 changesets, as it will only compare the merge changeset against
3370 changesets, as it will only compare the merge changeset against
3371 its first parent. Also, only files different from BOTH parents
3371 its first parent. Also, only files different from BOTH parents
3372 will appear in files:.
3372 will appear in files:.
3373
3373
3374 .. note::
3374 .. note::
3375
3375
3376 For performance reasons, :hg:`log FILE` may omit duplicate changes
3376 For performance reasons, :hg:`log FILE` may omit duplicate changes
3377 made on branches and will not show removals or mode changes. To
3377 made on branches and will not show removals or mode changes. To
3378 see all such changes, use the --removed switch.
3378 see all such changes, use the --removed switch.
3379
3379
3380 .. container:: verbose
3380 .. container:: verbose
3381
3381
3382 .. note::
3382 .. note::
3383
3383
3384 The history resulting from -L/--line-range options depends on diff
3384 The history resulting from -L/--line-range options depends on diff
3385 options; for instance if white-spaces are ignored, respective changes
3385 options; for instance if white-spaces are ignored, respective changes
3386 with only white-spaces in specified line range will not be listed.
3386 with only white-spaces in specified line range will not be listed.
3387
3387
3388 .. container:: verbose
3388 .. container:: verbose
3389
3389
3390 Some examples:
3390 Some examples:
3391
3391
3392 - changesets with full descriptions and file lists::
3392 - changesets with full descriptions and file lists::
3393
3393
3394 hg log -v
3394 hg log -v
3395
3395
3396 - changesets ancestral to the working directory::
3396 - changesets ancestral to the working directory::
3397
3397
3398 hg log -f
3398 hg log -f
3399
3399
3400 - last 10 commits on the current branch::
3400 - last 10 commits on the current branch::
3401
3401
3402 hg log -l 10 -b .
3402 hg log -l 10 -b .
3403
3403
3404 - changesets showing all modifications of a file, including removals::
3404 - changesets showing all modifications of a file, including removals::
3405
3405
3406 hg log --removed file.c
3406 hg log --removed file.c
3407
3407
3408 - all changesets that touch a directory, with diffs, excluding merges::
3408 - all changesets that touch a directory, with diffs, excluding merges::
3409
3409
3410 hg log -Mp lib/
3410 hg log -Mp lib/
3411
3411
3412 - all revision numbers that match a keyword::
3412 - all revision numbers that match a keyword::
3413
3413
3414 hg log -k bug --template "{rev}\\n"
3414 hg log -k bug --template "{rev}\\n"
3415
3415
3416 - the full hash identifier of the working directory parent::
3416 - the full hash identifier of the working directory parent::
3417
3417
3418 hg log -r . --template "{node}\\n"
3418 hg log -r . --template "{node}\\n"
3419
3419
3420 - list available log templates::
3420 - list available log templates::
3421
3421
3422 hg log -T list
3422 hg log -T list
3423
3423
3424 - check if a given changeset is included in a tagged release::
3424 - check if a given changeset is included in a tagged release::
3425
3425
3426 hg log -r "a21ccf and ancestor(1.9)"
3426 hg log -r "a21ccf and ancestor(1.9)"
3427
3427
3428 - find all changesets by some user in a date range::
3428 - find all changesets by some user in a date range::
3429
3429
3430 hg log -k alice -d "may 2008 to jul 2008"
3430 hg log -k alice -d "may 2008 to jul 2008"
3431
3431
3432 - summary of all changesets after the last tag::
3432 - summary of all changesets after the last tag::
3433
3433
3434 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3434 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3435
3435
3436 - changesets touching lines 13 to 23 for file.c::
3436 - changesets touching lines 13 to 23 for file.c::
3437
3437
3438 hg log -L file.c,13:23
3438 hg log -L file.c,13:23
3439
3439
3440 - changesets touching lines 13 to 23 for file.c and lines 2 to 6 of
3440 - changesets touching lines 13 to 23 for file.c and lines 2 to 6 of
3441 main.c with patch::
3441 main.c with patch::
3442
3442
3443 hg log -L file.c,13:23 -L main.c,2:6 -p
3443 hg log -L file.c,13:23 -L main.c,2:6 -p
3444
3444
3445 See :hg:`help dates` for a list of formats valid for -d/--date.
3445 See :hg:`help dates` for a list of formats valid for -d/--date.
3446
3446
3447 See :hg:`help revisions` for more about specifying and ordering
3447 See :hg:`help revisions` for more about specifying and ordering
3448 revisions.
3448 revisions.
3449
3449
3450 See :hg:`help templates` for more about pre-packaged styles and
3450 See :hg:`help templates` for more about pre-packaged styles and
3451 specifying custom templates. The default template used by the log
3451 specifying custom templates. The default template used by the log
3452 command can be customized via the ``ui.logtemplate`` configuration
3452 command can be customized via the ``ui.logtemplate`` configuration
3453 setting.
3453 setting.
3454
3454
3455 Returns 0 on success.
3455 Returns 0 on success.
3456
3456
3457 """
3457 """
3458 opts = pycompat.byteskwargs(opts)
3458 opts = pycompat.byteskwargs(opts)
3459 linerange = opts.get('line_range')
3459 linerange = opts.get('line_range')
3460
3460
3461 if linerange and not opts.get('follow'):
3461 if linerange and not opts.get('follow'):
3462 raise error.Abort(_('--line-range requires --follow'))
3462 raise error.Abort(_('--line-range requires --follow'))
3463
3463
3464 if linerange and pats:
3464 if linerange and pats:
3465 # TODO: take pats as patterns with no line-range filter
3465 # TODO: take pats as patterns with no line-range filter
3466 raise error.Abort(
3466 raise error.Abort(
3467 _('FILE arguments are not compatible with --line-range option')
3467 _('FILE arguments are not compatible with --line-range option')
3468 )
3468 )
3469
3469
3470 repo = scmutil.unhidehashlikerevs(repo, opts.get('rev'), 'nowarn')
3470 repo = scmutil.unhidehashlikerevs(repo, opts.get('rev'), 'nowarn')
3471 revs, differ = logcmdutil.getrevs(repo, pats, opts)
3471 revs, differ = logcmdutil.getrevs(repo, pats, opts)
3472 if linerange:
3472 if linerange:
3473 # TODO: should follow file history from logcmdutil._initialrevs(),
3473 # TODO: should follow file history from logcmdutil._initialrevs(),
3474 # then filter the result by logcmdutil._makerevset() and --limit
3474 # then filter the result by logcmdutil._makerevset() and --limit
3475 revs, differ = logcmdutil.getlinerangerevs(repo, revs, opts)
3475 revs, differ = logcmdutil.getlinerangerevs(repo, revs, opts)
3476
3476
3477 getrenamed = None
3477 getrenamed = None
3478 if opts.get('copies'):
3478 if opts.get('copies'):
3479 endrev = None
3479 endrev = None
3480 if opts.get('rev'):
3480 if revs:
3481 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
3481 endrev = revs.max() + 1
3482 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3482 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3483
3483
3484 ui.pager('log')
3484 ui.pager('log')
3485 displayer = logcmdutil.changesetdisplayer(ui, repo, opts, differ,
3485 displayer = logcmdutil.changesetdisplayer(ui, repo, opts, differ,
3486 buffered=True)
3486 buffered=True)
3487 if opts.get('graph'):
3487 if opts.get('graph'):
3488 displayfn = logcmdutil.displaygraphrevs
3488 displayfn = logcmdutil.displaygraphrevs
3489 else:
3489 else:
3490 displayfn = logcmdutil.displayrevs
3490 displayfn = logcmdutil.displayrevs
3491 displayfn(ui, repo, revs, displayer, getrenamed)
3491 displayfn(ui, repo, revs, displayer, getrenamed)
3492
3492
3493 @command('manifest',
3493 @command('manifest',
3494 [('r', 'rev', '', _('revision to display'), _('REV')),
3494 [('r', 'rev', '', _('revision to display'), _('REV')),
3495 ('', 'all', False, _("list files from all revisions"))]
3495 ('', 'all', False, _("list files from all revisions"))]
3496 + formatteropts,
3496 + formatteropts,
3497 _('[-r REV]'),
3497 _('[-r REV]'),
3498 intents={INTENT_READONLY})
3498 intents={INTENT_READONLY})
3499 def manifest(ui, repo, node=None, rev=None, **opts):
3499 def manifest(ui, repo, node=None, rev=None, **opts):
3500 """output the current or given revision of the project manifest
3500 """output the current or given revision of the project manifest
3501
3501
3502 Print a list of version controlled files for the given revision.
3502 Print a list of version controlled files for the given revision.
3503 If no revision is given, the first parent of the working directory
3503 If no revision is given, the first parent of the working directory
3504 is used, or the null revision if no revision is checked out.
3504 is used, or the null revision if no revision is checked out.
3505
3505
3506 With -v, print file permissions, symlink and executable bits.
3506 With -v, print file permissions, symlink and executable bits.
3507 With --debug, print file revision hashes.
3507 With --debug, print file revision hashes.
3508
3508
3509 If option --all is specified, the list of all files from all revisions
3509 If option --all is specified, the list of all files from all revisions
3510 is printed. This includes deleted and renamed files.
3510 is printed. This includes deleted and renamed files.
3511
3511
3512 Returns 0 on success.
3512 Returns 0 on success.
3513 """
3513 """
3514 opts = pycompat.byteskwargs(opts)
3514 opts = pycompat.byteskwargs(opts)
3515 fm = ui.formatter('manifest', opts)
3515 fm = ui.formatter('manifest', opts)
3516
3516
3517 if opts.get('all'):
3517 if opts.get('all'):
3518 if rev or node:
3518 if rev or node:
3519 raise error.Abort(_("can't specify a revision with --all"))
3519 raise error.Abort(_("can't specify a revision with --all"))
3520
3520
3521 res = set()
3521 res = set()
3522 for rev in repo:
3522 for rev in repo:
3523 ctx = repo[rev]
3523 ctx = repo[rev]
3524 res |= set(ctx.files())
3524 res |= set(ctx.files())
3525
3525
3526 ui.pager('manifest')
3526 ui.pager('manifest')
3527 for f in sorted(res):
3527 for f in sorted(res):
3528 fm.startitem()
3528 fm.startitem()
3529 fm.write("path", '%s\n', f)
3529 fm.write("path", '%s\n', f)
3530 fm.end()
3530 fm.end()
3531 return
3531 return
3532
3532
3533 if rev and node:
3533 if rev and node:
3534 raise error.Abort(_("please specify just one revision"))
3534 raise error.Abort(_("please specify just one revision"))
3535
3535
3536 if not node:
3536 if not node:
3537 node = rev
3537 node = rev
3538
3538
3539 char = {'l': '@', 'x': '*', '': '', 't': 'd'}
3539 char = {'l': '@', 'x': '*', '': '', 't': 'd'}
3540 mode = {'l': '644', 'x': '755', '': '644', 't': '755'}
3540 mode = {'l': '644', 'x': '755', '': '644', 't': '755'}
3541 if node:
3541 if node:
3542 repo = scmutil.unhidehashlikerevs(repo, [node], 'nowarn')
3542 repo = scmutil.unhidehashlikerevs(repo, [node], 'nowarn')
3543 ctx = scmutil.revsingle(repo, node)
3543 ctx = scmutil.revsingle(repo, node)
3544 mf = ctx.manifest()
3544 mf = ctx.manifest()
3545 ui.pager('manifest')
3545 ui.pager('manifest')
3546 for f in ctx:
3546 for f in ctx:
3547 fm.startitem()
3547 fm.startitem()
3548 fl = ctx[f].flags()
3548 fl = ctx[f].flags()
3549 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
3549 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
3550 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
3550 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
3551 fm.write('path', '%s\n', f)
3551 fm.write('path', '%s\n', f)
3552 fm.end()
3552 fm.end()
3553
3553
3554 @command('^merge',
3554 @command('^merge',
3555 [('f', 'force', None,
3555 [('f', 'force', None,
3556 _('force a merge including outstanding changes (DEPRECATED)')),
3556 _('force a merge including outstanding changes (DEPRECATED)')),
3557 ('r', 'rev', '', _('revision to merge'), _('REV')),
3557 ('r', 'rev', '', _('revision to merge'), _('REV')),
3558 ('P', 'preview', None,
3558 ('P', 'preview', None,
3559 _('review revisions to merge (no merge is performed)')),
3559 _('review revisions to merge (no merge is performed)')),
3560 ('', 'abort', None, _('abort the ongoing merge')),
3560 ('', 'abort', None, _('abort the ongoing merge')),
3561 ] + mergetoolopts,
3561 ] + mergetoolopts,
3562 _('[-P] [[-r] REV]'))
3562 _('[-P] [[-r] REV]'))
3563 def merge(ui, repo, node=None, **opts):
3563 def merge(ui, repo, node=None, **opts):
3564 """merge another revision into working directory
3564 """merge another revision into working directory
3565
3565
3566 The current working directory is updated with all changes made in
3566 The current working directory is updated with all changes made in
3567 the requested revision since the last common predecessor revision.
3567 the requested revision since the last common predecessor revision.
3568
3568
3569 Files that changed between either parent are marked as changed for
3569 Files that changed between either parent are marked as changed for
3570 the next commit and a commit must be performed before any further
3570 the next commit and a commit must be performed before any further
3571 updates to the repository are allowed. The next commit will have
3571 updates to the repository are allowed. The next commit will have
3572 two parents.
3572 two parents.
3573
3573
3574 ``--tool`` can be used to specify the merge tool used for file
3574 ``--tool`` can be used to specify the merge tool used for file
3575 merges. It overrides the HGMERGE environment variable and your
3575 merges. It overrides the HGMERGE environment variable and your
3576 configuration files. See :hg:`help merge-tools` for options.
3576 configuration files. See :hg:`help merge-tools` for options.
3577
3577
3578 If no revision is specified, the working directory's parent is a
3578 If no revision is specified, the working directory's parent is a
3579 head revision, and the current branch contains exactly one other
3579 head revision, and the current branch contains exactly one other
3580 head, the other head is merged with by default. Otherwise, an
3580 head, the other head is merged with by default. Otherwise, an
3581 explicit revision with which to merge with must be provided.
3581 explicit revision with which to merge with must be provided.
3582
3582
3583 See :hg:`help resolve` for information on handling file conflicts.
3583 See :hg:`help resolve` for information on handling file conflicts.
3584
3584
3585 To undo an uncommitted merge, use :hg:`merge --abort` which
3585 To undo an uncommitted merge, use :hg:`merge --abort` which
3586 will check out a clean copy of the original merge parent, losing
3586 will check out a clean copy of the original merge parent, losing
3587 all changes.
3587 all changes.
3588
3588
3589 Returns 0 on success, 1 if there are unresolved files.
3589 Returns 0 on success, 1 if there are unresolved files.
3590 """
3590 """
3591
3591
3592 opts = pycompat.byteskwargs(opts)
3592 opts = pycompat.byteskwargs(opts)
3593 abort = opts.get('abort')
3593 abort = opts.get('abort')
3594 if abort and repo.dirstate.p2() == nullid:
3594 if abort and repo.dirstate.p2() == nullid:
3595 cmdutil.wrongtooltocontinue(repo, _('merge'))
3595 cmdutil.wrongtooltocontinue(repo, _('merge'))
3596 if abort:
3596 if abort:
3597 if node:
3597 if node:
3598 raise error.Abort(_("cannot specify a node with --abort"))
3598 raise error.Abort(_("cannot specify a node with --abort"))
3599 if opts.get('rev'):
3599 if opts.get('rev'):
3600 raise error.Abort(_("cannot specify both --rev and --abort"))
3600 raise error.Abort(_("cannot specify both --rev and --abort"))
3601 if opts.get('preview'):
3601 if opts.get('preview'):
3602 raise error.Abort(_("cannot specify --preview with --abort"))
3602 raise error.Abort(_("cannot specify --preview with --abort"))
3603 if opts.get('rev') and node:
3603 if opts.get('rev') and node:
3604 raise error.Abort(_("please specify just one revision"))
3604 raise error.Abort(_("please specify just one revision"))
3605 if not node:
3605 if not node:
3606 node = opts.get('rev')
3606 node = opts.get('rev')
3607
3607
3608 if node:
3608 if node:
3609 node = scmutil.revsingle(repo, node).node()
3609 node = scmutil.revsingle(repo, node).node()
3610
3610
3611 if not node and not abort:
3611 if not node and not abort:
3612 node = repo[destutil.destmerge(repo)].node()
3612 node = repo[destutil.destmerge(repo)].node()
3613
3613
3614 if opts.get('preview'):
3614 if opts.get('preview'):
3615 # find nodes that are ancestors of p2 but not of p1
3615 # find nodes that are ancestors of p2 but not of p1
3616 p1 = repo.lookup('.')
3616 p1 = repo.lookup('.')
3617 p2 = node
3617 p2 = node
3618 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
3618 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
3619
3619
3620 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
3620 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
3621 for node in nodes:
3621 for node in nodes:
3622 displayer.show(repo[node])
3622 displayer.show(repo[node])
3623 displayer.close()
3623 displayer.close()
3624 return 0
3624 return 0
3625
3625
3626 try:
3626 try:
3627 # ui.forcemerge is an internal variable, do not document
3627 # ui.forcemerge is an internal variable, do not document
3628 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
3628 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
3629 force = opts.get('force')
3629 force = opts.get('force')
3630 labels = ['working copy', 'merge rev']
3630 labels = ['working copy', 'merge rev']
3631 return hg.merge(repo, node, force=force, mergeforce=force,
3631 return hg.merge(repo, node, force=force, mergeforce=force,
3632 labels=labels, abort=abort)
3632 labels=labels, abort=abort)
3633 finally:
3633 finally:
3634 ui.setconfig('ui', 'forcemerge', '', 'merge')
3634 ui.setconfig('ui', 'forcemerge', '', 'merge')
3635
3635
3636 @command('outgoing|out',
3636 @command('outgoing|out',
3637 [('f', 'force', None, _('run even when the destination is unrelated')),
3637 [('f', 'force', None, _('run even when the destination is unrelated')),
3638 ('r', 'rev', [],
3638 ('r', 'rev', [],
3639 _('a changeset intended to be included in the destination'), _('REV')),
3639 _('a changeset intended to be included in the destination'), _('REV')),
3640 ('n', 'newest-first', None, _('show newest record first')),
3640 ('n', 'newest-first', None, _('show newest record first')),
3641 ('B', 'bookmarks', False, _('compare bookmarks')),
3641 ('B', 'bookmarks', False, _('compare bookmarks')),
3642 ('b', 'branch', [], _('a specific branch you would like to push'),
3642 ('b', 'branch', [], _('a specific branch you would like to push'),
3643 _('BRANCH')),
3643 _('BRANCH')),
3644 ] + logopts + remoteopts + subrepoopts,
3644 ] + logopts + remoteopts + subrepoopts,
3645 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
3645 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
3646 def outgoing(ui, repo, dest=None, **opts):
3646 def outgoing(ui, repo, dest=None, **opts):
3647 """show changesets not found in the destination
3647 """show changesets not found in the destination
3648
3648
3649 Show changesets not found in the specified destination repository
3649 Show changesets not found in the specified destination repository
3650 or the default push location. These are the changesets that would
3650 or the default push location. These are the changesets that would
3651 be pushed if a push was requested.
3651 be pushed if a push was requested.
3652
3652
3653 See pull for details of valid destination formats.
3653 See pull for details of valid destination formats.
3654
3654
3655 .. container:: verbose
3655 .. container:: verbose
3656
3656
3657 With -B/--bookmarks, the result of bookmark comparison between
3657 With -B/--bookmarks, the result of bookmark comparison between
3658 local and remote repositories is displayed. With -v/--verbose,
3658 local and remote repositories is displayed. With -v/--verbose,
3659 status is also displayed for each bookmark like below::
3659 status is also displayed for each bookmark like below::
3660
3660
3661 BM1 01234567890a added
3661 BM1 01234567890a added
3662 BM2 deleted
3662 BM2 deleted
3663 BM3 234567890abc advanced
3663 BM3 234567890abc advanced
3664 BM4 34567890abcd diverged
3664 BM4 34567890abcd diverged
3665 BM5 4567890abcde changed
3665 BM5 4567890abcde changed
3666
3666
3667 The action taken when pushing depends on the
3667 The action taken when pushing depends on the
3668 status of each bookmark:
3668 status of each bookmark:
3669
3669
3670 :``added``: push with ``-B`` will create it
3670 :``added``: push with ``-B`` will create it
3671 :``deleted``: push with ``-B`` will delete it
3671 :``deleted``: push with ``-B`` will delete it
3672 :``advanced``: push will update it
3672 :``advanced``: push will update it
3673 :``diverged``: push with ``-B`` will update it
3673 :``diverged``: push with ``-B`` will update it
3674 :``changed``: push with ``-B`` will update it
3674 :``changed``: push with ``-B`` will update it
3675
3675
3676 From the point of view of pushing behavior, bookmarks
3676 From the point of view of pushing behavior, bookmarks
3677 existing only in the remote repository are treated as
3677 existing only in the remote repository are treated as
3678 ``deleted``, even if it is in fact added remotely.
3678 ``deleted``, even if it is in fact added remotely.
3679
3679
3680 Returns 0 if there are outgoing changes, 1 otherwise.
3680 Returns 0 if there are outgoing changes, 1 otherwise.
3681 """
3681 """
3682 opts = pycompat.byteskwargs(opts)
3682 opts = pycompat.byteskwargs(opts)
3683 if opts.get('graph'):
3683 if opts.get('graph'):
3684 logcmdutil.checkunsupportedgraphflags([], opts)
3684 logcmdutil.checkunsupportedgraphflags([], opts)
3685 o, other = hg._outgoing(ui, repo, dest, opts)
3685 o, other = hg._outgoing(ui, repo, dest, opts)
3686 if not o:
3686 if not o:
3687 cmdutil.outgoinghooks(ui, repo, other, opts, o)
3687 cmdutil.outgoinghooks(ui, repo, other, opts, o)
3688 return
3688 return
3689
3689
3690 revdag = logcmdutil.graphrevs(repo, o, opts)
3690 revdag = logcmdutil.graphrevs(repo, o, opts)
3691 ui.pager('outgoing')
3691 ui.pager('outgoing')
3692 displayer = logcmdutil.changesetdisplayer(ui, repo, opts, buffered=True)
3692 displayer = logcmdutil.changesetdisplayer(ui, repo, opts, buffered=True)
3693 logcmdutil.displaygraph(ui, repo, revdag, displayer,
3693 logcmdutil.displaygraph(ui, repo, revdag, displayer,
3694 graphmod.asciiedges)
3694 graphmod.asciiedges)
3695 cmdutil.outgoinghooks(ui, repo, other, opts, o)
3695 cmdutil.outgoinghooks(ui, repo, other, opts, o)
3696 return 0
3696 return 0
3697
3697
3698 if opts.get('bookmarks'):
3698 if opts.get('bookmarks'):
3699 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3699 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3700 dest, branches = hg.parseurl(dest, opts.get('branch'))
3700 dest, branches = hg.parseurl(dest, opts.get('branch'))
3701 other = hg.peer(repo, opts, dest)
3701 other = hg.peer(repo, opts, dest)
3702 if 'bookmarks' not in other.listkeys('namespaces'):
3702 if 'bookmarks' not in other.listkeys('namespaces'):
3703 ui.warn(_("remote doesn't support bookmarks\n"))
3703 ui.warn(_("remote doesn't support bookmarks\n"))
3704 return 0
3704 return 0
3705 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
3705 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
3706 ui.pager('outgoing')
3706 ui.pager('outgoing')
3707 return bookmarks.outgoing(ui, repo, other)
3707 return bookmarks.outgoing(ui, repo, other)
3708
3708
3709 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
3709 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
3710 try:
3710 try:
3711 return hg.outgoing(ui, repo, dest, opts)
3711 return hg.outgoing(ui, repo, dest, opts)
3712 finally:
3712 finally:
3713 del repo._subtoppath
3713 del repo._subtoppath
3714
3714
3715 @command('parents',
3715 @command('parents',
3716 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
3716 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
3717 ] + templateopts,
3717 ] + templateopts,
3718 _('[-r REV] [FILE]'),
3718 _('[-r REV] [FILE]'),
3719 inferrepo=True)
3719 inferrepo=True)
3720 def parents(ui, repo, file_=None, **opts):
3720 def parents(ui, repo, file_=None, **opts):
3721 """show the parents of the working directory or revision (DEPRECATED)
3721 """show the parents of the working directory or revision (DEPRECATED)
3722
3722
3723 Print the working directory's parent revisions. If a revision is
3723 Print the working directory's parent revisions. If a revision is
3724 given via -r/--rev, the parent of that revision will be printed.
3724 given via -r/--rev, the parent of that revision will be printed.
3725 If a file argument is given, the revision in which the file was
3725 If a file argument is given, the revision in which the file was
3726 last changed (before the working directory revision or the
3726 last changed (before the working directory revision or the
3727 argument to --rev if given) is printed.
3727 argument to --rev if given) is printed.
3728
3728
3729 This command is equivalent to::
3729 This command is equivalent to::
3730
3730
3731 hg log -r "p1()+p2()" or
3731 hg log -r "p1()+p2()" or
3732 hg log -r "p1(REV)+p2(REV)" or
3732 hg log -r "p1(REV)+p2(REV)" or
3733 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
3733 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
3734 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
3734 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
3735
3735
3736 See :hg:`summary` and :hg:`help revsets` for related information.
3736 See :hg:`summary` and :hg:`help revsets` for related information.
3737
3737
3738 Returns 0 on success.
3738 Returns 0 on success.
3739 """
3739 """
3740
3740
3741 opts = pycompat.byteskwargs(opts)
3741 opts = pycompat.byteskwargs(opts)
3742 rev = opts.get('rev')
3742 rev = opts.get('rev')
3743 if rev:
3743 if rev:
3744 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
3744 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
3745 ctx = scmutil.revsingle(repo, rev, None)
3745 ctx = scmutil.revsingle(repo, rev, None)
3746
3746
3747 if file_:
3747 if file_:
3748 m = scmutil.match(ctx, (file_,), opts)
3748 m = scmutil.match(ctx, (file_,), opts)
3749 if m.anypats() or len(m.files()) != 1:
3749 if m.anypats() or len(m.files()) != 1:
3750 raise error.Abort(_('can only specify an explicit filename'))
3750 raise error.Abort(_('can only specify an explicit filename'))
3751 file_ = m.files()[0]
3751 file_ = m.files()[0]
3752 filenodes = []
3752 filenodes = []
3753 for cp in ctx.parents():
3753 for cp in ctx.parents():
3754 if not cp:
3754 if not cp:
3755 continue
3755 continue
3756 try:
3756 try:
3757 filenodes.append(cp.filenode(file_))
3757 filenodes.append(cp.filenode(file_))
3758 except error.LookupError:
3758 except error.LookupError:
3759 pass
3759 pass
3760 if not filenodes:
3760 if not filenodes:
3761 raise error.Abort(_("'%s' not found in manifest!") % file_)
3761 raise error.Abort(_("'%s' not found in manifest!") % file_)
3762 p = []
3762 p = []
3763 for fn in filenodes:
3763 for fn in filenodes:
3764 fctx = repo.filectx(file_, fileid=fn)
3764 fctx = repo.filectx(file_, fileid=fn)
3765 p.append(fctx.node())
3765 p.append(fctx.node())
3766 else:
3766 else:
3767 p = [cp.node() for cp in ctx.parents()]
3767 p = [cp.node() for cp in ctx.parents()]
3768
3768
3769 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
3769 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
3770 for n in p:
3770 for n in p:
3771 if n != nullid:
3771 if n != nullid:
3772 displayer.show(repo[n])
3772 displayer.show(repo[n])
3773 displayer.close()
3773 displayer.close()
3774
3774
3775 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True,
3775 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True,
3776 intents={INTENT_READONLY})
3776 intents={INTENT_READONLY})
3777 def paths(ui, repo, search=None, **opts):
3777 def paths(ui, repo, search=None, **opts):
3778 """show aliases for remote repositories
3778 """show aliases for remote repositories
3779
3779
3780 Show definition of symbolic path name NAME. If no name is given,
3780 Show definition of symbolic path name NAME. If no name is given,
3781 show definition of all available names.
3781 show definition of all available names.
3782
3782
3783 Option -q/--quiet suppresses all output when searching for NAME
3783 Option -q/--quiet suppresses all output when searching for NAME
3784 and shows only the path names when listing all definitions.
3784 and shows only the path names when listing all definitions.
3785
3785
3786 Path names are defined in the [paths] section of your
3786 Path names are defined in the [paths] section of your
3787 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
3787 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
3788 repository, ``.hg/hgrc`` is used, too.
3788 repository, ``.hg/hgrc`` is used, too.
3789
3789
3790 The path names ``default`` and ``default-push`` have a special
3790 The path names ``default`` and ``default-push`` have a special
3791 meaning. When performing a push or pull operation, they are used
3791 meaning. When performing a push or pull operation, they are used
3792 as fallbacks if no location is specified on the command-line.
3792 as fallbacks if no location is specified on the command-line.
3793 When ``default-push`` is set, it will be used for push and
3793 When ``default-push`` is set, it will be used for push and
3794 ``default`` will be used for pull; otherwise ``default`` is used
3794 ``default`` will be used for pull; otherwise ``default`` is used
3795 as the fallback for both. When cloning a repository, the clone
3795 as the fallback for both. When cloning a repository, the clone
3796 source is written as ``default`` in ``.hg/hgrc``.
3796 source is written as ``default`` in ``.hg/hgrc``.
3797
3797
3798 .. note::
3798 .. note::
3799
3799
3800 ``default`` and ``default-push`` apply to all inbound (e.g.
3800 ``default`` and ``default-push`` apply to all inbound (e.g.
3801 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
3801 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
3802 and :hg:`bundle`) operations.
3802 and :hg:`bundle`) operations.
3803
3803
3804 See :hg:`help urls` for more information.
3804 See :hg:`help urls` for more information.
3805
3805
3806 Returns 0 on success.
3806 Returns 0 on success.
3807 """
3807 """
3808
3808
3809 opts = pycompat.byteskwargs(opts)
3809 opts = pycompat.byteskwargs(opts)
3810 ui.pager('paths')
3810 ui.pager('paths')
3811 if search:
3811 if search:
3812 pathitems = [(name, path) for name, path in ui.paths.iteritems()
3812 pathitems = [(name, path) for name, path in ui.paths.iteritems()
3813 if name == search]
3813 if name == search]
3814 else:
3814 else:
3815 pathitems = sorted(ui.paths.iteritems())
3815 pathitems = sorted(ui.paths.iteritems())
3816
3816
3817 fm = ui.formatter('paths', opts)
3817 fm = ui.formatter('paths', opts)
3818 if fm.isplain():
3818 if fm.isplain():
3819 hidepassword = util.hidepassword
3819 hidepassword = util.hidepassword
3820 else:
3820 else:
3821 hidepassword = bytes
3821 hidepassword = bytes
3822 if ui.quiet:
3822 if ui.quiet:
3823 namefmt = '%s\n'
3823 namefmt = '%s\n'
3824 else:
3824 else:
3825 namefmt = '%s = '
3825 namefmt = '%s = '
3826 showsubopts = not search and not ui.quiet
3826 showsubopts = not search and not ui.quiet
3827
3827
3828 for name, path in pathitems:
3828 for name, path in pathitems:
3829 fm.startitem()
3829 fm.startitem()
3830 fm.condwrite(not search, 'name', namefmt, name)
3830 fm.condwrite(not search, 'name', namefmt, name)
3831 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
3831 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
3832 for subopt, value in sorted(path.suboptions.items()):
3832 for subopt, value in sorted(path.suboptions.items()):
3833 assert subopt not in ('name', 'url')
3833 assert subopt not in ('name', 'url')
3834 if showsubopts:
3834 if showsubopts:
3835 fm.plain('%s:%s = ' % (name, subopt))
3835 fm.plain('%s:%s = ' % (name, subopt))
3836 fm.condwrite(showsubopts, subopt, '%s\n', value)
3836 fm.condwrite(showsubopts, subopt, '%s\n', value)
3837
3837
3838 fm.end()
3838 fm.end()
3839
3839
3840 if search and not pathitems:
3840 if search and not pathitems:
3841 if not ui.quiet:
3841 if not ui.quiet:
3842 ui.warn(_("not found!\n"))
3842 ui.warn(_("not found!\n"))
3843 return 1
3843 return 1
3844 else:
3844 else:
3845 return 0
3845 return 0
3846
3846
3847 @command('phase',
3847 @command('phase',
3848 [('p', 'public', False, _('set changeset phase to public')),
3848 [('p', 'public', False, _('set changeset phase to public')),
3849 ('d', 'draft', False, _('set changeset phase to draft')),
3849 ('d', 'draft', False, _('set changeset phase to draft')),
3850 ('s', 'secret', False, _('set changeset phase to secret')),
3850 ('s', 'secret', False, _('set changeset phase to secret')),
3851 ('f', 'force', False, _('allow to move boundary backward')),
3851 ('f', 'force', False, _('allow to move boundary backward')),
3852 ('r', 'rev', [], _('target revision'), _('REV')),
3852 ('r', 'rev', [], _('target revision'), _('REV')),
3853 ],
3853 ],
3854 _('[-p|-d|-s] [-f] [-r] [REV...]'))
3854 _('[-p|-d|-s] [-f] [-r] [REV...]'))
3855 def phase(ui, repo, *revs, **opts):
3855 def phase(ui, repo, *revs, **opts):
3856 """set or show the current phase name
3856 """set or show the current phase name
3857
3857
3858 With no argument, show the phase name of the current revision(s).
3858 With no argument, show the phase name of the current revision(s).
3859
3859
3860 With one of -p/--public, -d/--draft or -s/--secret, change the
3860 With one of -p/--public, -d/--draft or -s/--secret, change the
3861 phase value of the specified revisions.
3861 phase value of the specified revisions.
3862
3862
3863 Unless -f/--force is specified, :hg:`phase` won't move changesets from a
3863 Unless -f/--force is specified, :hg:`phase` won't move changesets from a
3864 lower phase to a higher phase. Phases are ordered as follows::
3864 lower phase to a higher phase. Phases are ordered as follows::
3865
3865
3866 public < draft < secret
3866 public < draft < secret
3867
3867
3868 Returns 0 on success, 1 if some phases could not be changed.
3868 Returns 0 on success, 1 if some phases could not be changed.
3869
3869
3870 (For more information about the phases concept, see :hg:`help phases`.)
3870 (For more information about the phases concept, see :hg:`help phases`.)
3871 """
3871 """
3872 opts = pycompat.byteskwargs(opts)
3872 opts = pycompat.byteskwargs(opts)
3873 # search for a unique phase argument
3873 # search for a unique phase argument
3874 targetphase = None
3874 targetphase = None
3875 for idx, name in enumerate(phases.phasenames):
3875 for idx, name in enumerate(phases.phasenames):
3876 if opts[name]:
3876 if opts[name]:
3877 if targetphase is not None:
3877 if targetphase is not None:
3878 raise error.Abort(_('only one phase can be specified'))
3878 raise error.Abort(_('only one phase can be specified'))
3879 targetphase = idx
3879 targetphase = idx
3880
3880
3881 # look for specified revision
3881 # look for specified revision
3882 revs = list(revs)
3882 revs = list(revs)
3883 revs.extend(opts['rev'])
3883 revs.extend(opts['rev'])
3884 if not revs:
3884 if not revs:
3885 # display both parents as the second parent phase can influence
3885 # display both parents as the second parent phase can influence
3886 # the phase of a merge commit
3886 # the phase of a merge commit
3887 revs = [c.rev() for c in repo[None].parents()]
3887 revs = [c.rev() for c in repo[None].parents()]
3888
3888
3889 revs = scmutil.revrange(repo, revs)
3889 revs = scmutil.revrange(repo, revs)
3890
3890
3891 ret = 0
3891 ret = 0
3892 if targetphase is None:
3892 if targetphase is None:
3893 # display
3893 # display
3894 for r in revs:
3894 for r in revs:
3895 ctx = repo[r]
3895 ctx = repo[r]
3896 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
3896 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
3897 else:
3897 else:
3898 with repo.lock(), repo.transaction("phase") as tr:
3898 with repo.lock(), repo.transaction("phase") as tr:
3899 # set phase
3899 # set phase
3900 if not revs:
3900 if not revs:
3901 raise error.Abort(_('empty revision set'))
3901 raise error.Abort(_('empty revision set'))
3902 nodes = [repo[r].node() for r in revs]
3902 nodes = [repo[r].node() for r in revs]
3903 # moving revision from public to draft may hide them
3903 # moving revision from public to draft may hide them
3904 # We have to check result on an unfiltered repository
3904 # We have to check result on an unfiltered repository
3905 unfi = repo.unfiltered()
3905 unfi = repo.unfiltered()
3906 getphase = unfi._phasecache.phase
3906 getphase = unfi._phasecache.phase
3907 olddata = [getphase(unfi, r) for r in unfi]
3907 olddata = [getphase(unfi, r) for r in unfi]
3908 phases.advanceboundary(repo, tr, targetphase, nodes)
3908 phases.advanceboundary(repo, tr, targetphase, nodes)
3909 if opts['force']:
3909 if opts['force']:
3910 phases.retractboundary(repo, tr, targetphase, nodes)
3910 phases.retractboundary(repo, tr, targetphase, nodes)
3911 getphase = unfi._phasecache.phase
3911 getphase = unfi._phasecache.phase
3912 newdata = [getphase(unfi, r) for r in unfi]
3912 newdata = [getphase(unfi, r) for r in unfi]
3913 changes = sum(newdata[r] != olddata[r] for r in unfi)
3913 changes = sum(newdata[r] != olddata[r] for r in unfi)
3914 cl = unfi.changelog
3914 cl = unfi.changelog
3915 rejected = [n for n in nodes
3915 rejected = [n for n in nodes
3916 if newdata[cl.rev(n)] < targetphase]
3916 if newdata[cl.rev(n)] < targetphase]
3917 if rejected:
3917 if rejected:
3918 ui.warn(_('cannot move %i changesets to a higher '
3918 ui.warn(_('cannot move %i changesets to a higher '
3919 'phase, use --force\n') % len(rejected))
3919 'phase, use --force\n') % len(rejected))
3920 ret = 1
3920 ret = 1
3921 if changes:
3921 if changes:
3922 msg = _('phase changed for %i changesets\n') % changes
3922 msg = _('phase changed for %i changesets\n') % changes
3923 if ret:
3923 if ret:
3924 ui.status(msg)
3924 ui.status(msg)
3925 else:
3925 else:
3926 ui.note(msg)
3926 ui.note(msg)
3927 else:
3927 else:
3928 ui.warn(_('no phases changed\n'))
3928 ui.warn(_('no phases changed\n'))
3929 return ret
3929 return ret
3930
3930
3931 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
3931 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
3932 """Run after a changegroup has been added via pull/unbundle
3932 """Run after a changegroup has been added via pull/unbundle
3933
3933
3934 This takes arguments below:
3934 This takes arguments below:
3935
3935
3936 :modheads: change of heads by pull/unbundle
3936 :modheads: change of heads by pull/unbundle
3937 :optupdate: updating working directory is needed or not
3937 :optupdate: updating working directory is needed or not
3938 :checkout: update destination revision (or None to default destination)
3938 :checkout: update destination revision (or None to default destination)
3939 :brev: a name, which might be a bookmark to be activated after updating
3939 :brev: a name, which might be a bookmark to be activated after updating
3940 """
3940 """
3941 if modheads == 0:
3941 if modheads == 0:
3942 return
3942 return
3943 if optupdate:
3943 if optupdate:
3944 try:
3944 try:
3945 return hg.updatetotally(ui, repo, checkout, brev)
3945 return hg.updatetotally(ui, repo, checkout, brev)
3946 except error.UpdateAbort as inst:
3946 except error.UpdateAbort as inst:
3947 msg = _("not updating: %s") % stringutil.forcebytestr(inst)
3947 msg = _("not updating: %s") % stringutil.forcebytestr(inst)
3948 hint = inst.hint
3948 hint = inst.hint
3949 raise error.UpdateAbort(msg, hint=hint)
3949 raise error.UpdateAbort(msg, hint=hint)
3950 if modheads > 1:
3950 if modheads > 1:
3951 currentbranchheads = len(repo.branchheads())
3951 currentbranchheads = len(repo.branchheads())
3952 if currentbranchheads == modheads:
3952 if currentbranchheads == modheads:
3953 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
3953 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
3954 elif currentbranchheads > 1:
3954 elif currentbranchheads > 1:
3955 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
3955 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
3956 "merge)\n"))
3956 "merge)\n"))
3957 else:
3957 else:
3958 ui.status(_("(run 'hg heads' to see heads)\n"))
3958 ui.status(_("(run 'hg heads' to see heads)\n"))
3959 elif not ui.configbool('commands', 'update.requiredest'):
3959 elif not ui.configbool('commands', 'update.requiredest'):
3960 ui.status(_("(run 'hg update' to get a working copy)\n"))
3960 ui.status(_("(run 'hg update' to get a working copy)\n"))
3961
3961
3962 @command('^pull',
3962 @command('^pull',
3963 [('u', 'update', None,
3963 [('u', 'update', None,
3964 _('update to new branch head if new descendants were pulled')),
3964 _('update to new branch head if new descendants were pulled')),
3965 ('f', 'force', None, _('run even when remote repository is unrelated')),
3965 ('f', 'force', None, _('run even when remote repository is unrelated')),
3966 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3966 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3967 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
3967 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
3968 ('b', 'branch', [], _('a specific branch you would like to pull'),
3968 ('b', 'branch', [], _('a specific branch you would like to pull'),
3969 _('BRANCH')),
3969 _('BRANCH')),
3970 ] + remoteopts,
3970 ] + remoteopts,
3971 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
3971 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
3972 def pull(ui, repo, source="default", **opts):
3972 def pull(ui, repo, source="default", **opts):
3973 """pull changes from the specified source
3973 """pull changes from the specified source
3974
3974
3975 Pull changes from a remote repository to a local one.
3975 Pull changes from a remote repository to a local one.
3976
3976
3977 This finds all changes from the repository at the specified path
3977 This finds all changes from the repository at the specified path
3978 or URL and adds them to a local repository (the current one unless
3978 or URL and adds them to a local repository (the current one unless
3979 -R is specified). By default, this does not update the copy of the
3979 -R is specified). By default, this does not update the copy of the
3980 project in the working directory.
3980 project in the working directory.
3981
3981
3982 When cloning from servers that support it, Mercurial may fetch
3982 When cloning from servers that support it, Mercurial may fetch
3983 pre-generated data. When this is done, hooks operating on incoming
3983 pre-generated data. When this is done, hooks operating on incoming
3984 changesets and changegroups may fire more than once, once for each
3984 changesets and changegroups may fire more than once, once for each
3985 pre-generated bundle and as well as for any additional remaining
3985 pre-generated bundle and as well as for any additional remaining
3986 data. See :hg:`help -e clonebundles` for more.
3986 data. See :hg:`help -e clonebundles` for more.
3987
3987
3988 Use :hg:`incoming` if you want to see what would have been added
3988 Use :hg:`incoming` if you want to see what would have been added
3989 by a pull at the time you issued this command. If you then decide
3989 by a pull at the time you issued this command. If you then decide
3990 to add those changes to the repository, you should use :hg:`pull
3990 to add those changes to the repository, you should use :hg:`pull
3991 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
3991 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
3992
3992
3993 If SOURCE is omitted, the 'default' path will be used.
3993 If SOURCE is omitted, the 'default' path will be used.
3994 See :hg:`help urls` for more information.
3994 See :hg:`help urls` for more information.
3995
3995
3996 Specifying bookmark as ``.`` is equivalent to specifying the active
3996 Specifying bookmark as ``.`` is equivalent to specifying the active
3997 bookmark's name.
3997 bookmark's name.
3998
3998
3999 Returns 0 on success, 1 if an update had unresolved files.
3999 Returns 0 on success, 1 if an update had unresolved files.
4000 """
4000 """
4001
4001
4002 opts = pycompat.byteskwargs(opts)
4002 opts = pycompat.byteskwargs(opts)
4003 if ui.configbool('commands', 'update.requiredest') and opts.get('update'):
4003 if ui.configbool('commands', 'update.requiredest') and opts.get('update'):
4004 msg = _('update destination required by configuration')
4004 msg = _('update destination required by configuration')
4005 hint = _('use hg pull followed by hg update DEST')
4005 hint = _('use hg pull followed by hg update DEST')
4006 raise error.Abort(msg, hint=hint)
4006 raise error.Abort(msg, hint=hint)
4007
4007
4008 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4008 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4009 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4009 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4010 other = hg.peer(repo, opts, source)
4010 other = hg.peer(repo, opts, source)
4011 try:
4011 try:
4012 revs, checkout = hg.addbranchrevs(repo, other, branches,
4012 revs, checkout = hg.addbranchrevs(repo, other, branches,
4013 opts.get('rev'))
4013 opts.get('rev'))
4014
4014
4015
4015
4016 pullopargs = {}
4016 pullopargs = {}
4017 if opts.get('bookmark'):
4017 if opts.get('bookmark'):
4018 if not revs:
4018 if not revs:
4019 revs = []
4019 revs = []
4020 # The list of bookmark used here is not the one used to actually
4020 # The list of bookmark used here is not the one used to actually
4021 # update the bookmark name. This can result in the revision pulled
4021 # update the bookmark name. This can result in the revision pulled
4022 # not ending up with the name of the bookmark because of a race
4022 # not ending up with the name of the bookmark because of a race
4023 # condition on the server. (See issue 4689 for details)
4023 # condition on the server. (See issue 4689 for details)
4024 remotebookmarks = other.listkeys('bookmarks')
4024 remotebookmarks = other.listkeys('bookmarks')
4025 remotebookmarks = bookmarks.unhexlifybookmarks(remotebookmarks)
4025 remotebookmarks = bookmarks.unhexlifybookmarks(remotebookmarks)
4026 pullopargs['remotebookmarks'] = remotebookmarks
4026 pullopargs['remotebookmarks'] = remotebookmarks
4027 for b in opts['bookmark']:
4027 for b in opts['bookmark']:
4028 b = repo._bookmarks.expandname(b)
4028 b = repo._bookmarks.expandname(b)
4029 if b not in remotebookmarks:
4029 if b not in remotebookmarks:
4030 raise error.Abort(_('remote bookmark %s not found!') % b)
4030 raise error.Abort(_('remote bookmark %s not found!') % b)
4031 revs.append(hex(remotebookmarks[b]))
4031 revs.append(hex(remotebookmarks[b]))
4032
4032
4033 if revs:
4033 if revs:
4034 try:
4034 try:
4035 # When 'rev' is a bookmark name, we cannot guarantee that it
4035 # When 'rev' is a bookmark name, we cannot guarantee that it
4036 # will be updated with that name because of a race condition
4036 # will be updated with that name because of a race condition
4037 # server side. (See issue 4689 for details)
4037 # server side. (See issue 4689 for details)
4038 oldrevs = revs
4038 oldrevs = revs
4039 revs = [] # actually, nodes
4039 revs = [] # actually, nodes
4040 for r in oldrevs:
4040 for r in oldrevs:
4041 with other.commandexecutor() as e:
4041 with other.commandexecutor() as e:
4042 node = e.callcommand('lookup', {'key': r}).result()
4042 node = e.callcommand('lookup', {'key': r}).result()
4043
4043
4044 revs.append(node)
4044 revs.append(node)
4045 if r == checkout:
4045 if r == checkout:
4046 checkout = node
4046 checkout = node
4047 except error.CapabilityError:
4047 except error.CapabilityError:
4048 err = _("other repository doesn't support revision lookup, "
4048 err = _("other repository doesn't support revision lookup, "
4049 "so a rev cannot be specified.")
4049 "so a rev cannot be specified.")
4050 raise error.Abort(err)
4050 raise error.Abort(err)
4051
4051
4052 wlock = util.nullcontextmanager()
4052 wlock = util.nullcontextmanager()
4053 if opts.get('update'):
4053 if opts.get('update'):
4054 wlock = repo.wlock()
4054 wlock = repo.wlock()
4055 with wlock:
4055 with wlock:
4056 pullopargs.update(opts.get('opargs', {}))
4056 pullopargs.update(opts.get('opargs', {}))
4057 modheads = exchange.pull(repo, other, heads=revs,
4057 modheads = exchange.pull(repo, other, heads=revs,
4058 force=opts.get('force'),
4058 force=opts.get('force'),
4059 bookmarks=opts.get('bookmark', ()),
4059 bookmarks=opts.get('bookmark', ()),
4060 opargs=pullopargs).cgresult
4060 opargs=pullopargs).cgresult
4061
4061
4062 # brev is a name, which might be a bookmark to be activated at
4062 # brev is a name, which might be a bookmark to be activated at
4063 # the end of the update. In other words, it is an explicit
4063 # the end of the update. In other words, it is an explicit
4064 # destination of the update
4064 # destination of the update
4065 brev = None
4065 brev = None
4066
4066
4067 if checkout:
4067 if checkout:
4068 checkout = repo.changelog.rev(checkout)
4068 checkout = repo.changelog.rev(checkout)
4069
4069
4070 # order below depends on implementation of
4070 # order below depends on implementation of
4071 # hg.addbranchrevs(). opts['bookmark'] is ignored,
4071 # hg.addbranchrevs(). opts['bookmark'] is ignored,
4072 # because 'checkout' is determined without it.
4072 # because 'checkout' is determined without it.
4073 if opts.get('rev'):
4073 if opts.get('rev'):
4074 brev = opts['rev'][0]
4074 brev = opts['rev'][0]
4075 elif opts.get('branch'):
4075 elif opts.get('branch'):
4076 brev = opts['branch'][0]
4076 brev = opts['branch'][0]
4077 else:
4077 else:
4078 brev = branches[0]
4078 brev = branches[0]
4079 repo._subtoppath = source
4079 repo._subtoppath = source
4080 try:
4080 try:
4081 ret = postincoming(ui, repo, modheads, opts.get('update'),
4081 ret = postincoming(ui, repo, modheads, opts.get('update'),
4082 checkout, brev)
4082 checkout, brev)
4083
4083
4084 finally:
4084 finally:
4085 del repo._subtoppath
4085 del repo._subtoppath
4086
4086
4087 finally:
4087 finally:
4088 other.close()
4088 other.close()
4089 return ret
4089 return ret
4090
4090
4091 @command('^push',
4091 @command('^push',
4092 [('f', 'force', None, _('force push')),
4092 [('f', 'force', None, _('force push')),
4093 ('r', 'rev', [],
4093 ('r', 'rev', [],
4094 _('a changeset intended to be included in the destination'),
4094 _('a changeset intended to be included in the destination'),
4095 _('REV')),
4095 _('REV')),
4096 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4096 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4097 ('b', 'branch', [],
4097 ('b', 'branch', [],
4098 _('a specific branch you would like to push'), _('BRANCH')),
4098 _('a specific branch you would like to push'), _('BRANCH')),
4099 ('', 'new-branch', False, _('allow pushing a new branch')),
4099 ('', 'new-branch', False, _('allow pushing a new branch')),
4100 ('', 'pushvars', [], _('variables that can be sent to server (ADVANCED)')),
4100 ('', 'pushvars', [], _('variables that can be sent to server (ADVANCED)')),
4101 ] + remoteopts,
4101 ] + remoteopts,
4102 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4102 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4103 def push(ui, repo, dest=None, **opts):
4103 def push(ui, repo, dest=None, **opts):
4104 """push changes to the specified destination
4104 """push changes to the specified destination
4105
4105
4106 Push changesets from the local repository to the specified
4106 Push changesets from the local repository to the specified
4107 destination.
4107 destination.
4108
4108
4109 This operation is symmetrical to pull: it is identical to a pull
4109 This operation is symmetrical to pull: it is identical to a pull
4110 in the destination repository from the current one.
4110 in the destination repository from the current one.
4111
4111
4112 By default, push will not allow creation of new heads at the
4112 By default, push will not allow creation of new heads at the
4113 destination, since multiple heads would make it unclear which head
4113 destination, since multiple heads would make it unclear which head
4114 to use. In this situation, it is recommended to pull and merge
4114 to use. In this situation, it is recommended to pull and merge
4115 before pushing.
4115 before pushing.
4116
4116
4117 Use --new-branch if you want to allow push to create a new named
4117 Use --new-branch if you want to allow push to create a new named
4118 branch that is not present at the destination. This allows you to
4118 branch that is not present at the destination. This allows you to
4119 only create a new branch without forcing other changes.
4119 only create a new branch without forcing other changes.
4120
4120
4121 .. note::
4121 .. note::
4122
4122
4123 Extra care should be taken with the -f/--force option,
4123 Extra care should be taken with the -f/--force option,
4124 which will push all new heads on all branches, an action which will
4124 which will push all new heads on all branches, an action which will
4125 almost always cause confusion for collaborators.
4125 almost always cause confusion for collaborators.
4126
4126
4127 If -r/--rev is used, the specified revision and all its ancestors
4127 If -r/--rev is used, the specified revision and all its ancestors
4128 will be pushed to the remote repository.
4128 will be pushed to the remote repository.
4129
4129
4130 If -B/--bookmark is used, the specified bookmarked revision, its
4130 If -B/--bookmark is used, the specified bookmarked revision, its
4131 ancestors, and the bookmark will be pushed to the remote
4131 ancestors, and the bookmark will be pushed to the remote
4132 repository. Specifying ``.`` is equivalent to specifying the active
4132 repository. Specifying ``.`` is equivalent to specifying the active
4133 bookmark's name.
4133 bookmark's name.
4134
4134
4135 Please see :hg:`help urls` for important details about ``ssh://``
4135 Please see :hg:`help urls` for important details about ``ssh://``
4136 URLs. If DESTINATION is omitted, a default path will be used.
4136 URLs. If DESTINATION is omitted, a default path will be used.
4137
4137
4138 .. container:: verbose
4138 .. container:: verbose
4139
4139
4140 The --pushvars option sends strings to the server that become
4140 The --pushvars option sends strings to the server that become
4141 environment variables prepended with ``HG_USERVAR_``. For example,
4141 environment variables prepended with ``HG_USERVAR_``. For example,
4142 ``--pushvars ENABLE_FEATURE=true``, provides the server side hooks with
4142 ``--pushvars ENABLE_FEATURE=true``, provides the server side hooks with
4143 ``HG_USERVAR_ENABLE_FEATURE=true`` as part of their environment.
4143 ``HG_USERVAR_ENABLE_FEATURE=true`` as part of their environment.
4144
4144
4145 pushvars can provide for user-overridable hooks as well as set debug
4145 pushvars can provide for user-overridable hooks as well as set debug
4146 levels. One example is having a hook that blocks commits containing
4146 levels. One example is having a hook that blocks commits containing
4147 conflict markers, but enables the user to override the hook if the file
4147 conflict markers, but enables the user to override the hook if the file
4148 is using conflict markers for testing purposes or the file format has
4148 is using conflict markers for testing purposes or the file format has
4149 strings that look like conflict markers.
4149 strings that look like conflict markers.
4150
4150
4151 By default, servers will ignore `--pushvars`. To enable it add the
4151 By default, servers will ignore `--pushvars`. To enable it add the
4152 following to your configuration file::
4152 following to your configuration file::
4153
4153
4154 [push]
4154 [push]
4155 pushvars.server = true
4155 pushvars.server = true
4156
4156
4157 Returns 0 if push was successful, 1 if nothing to push.
4157 Returns 0 if push was successful, 1 if nothing to push.
4158 """
4158 """
4159
4159
4160 opts = pycompat.byteskwargs(opts)
4160 opts = pycompat.byteskwargs(opts)
4161 if opts.get('bookmark'):
4161 if opts.get('bookmark'):
4162 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
4162 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
4163 for b in opts['bookmark']:
4163 for b in opts['bookmark']:
4164 # translate -B options to -r so changesets get pushed
4164 # translate -B options to -r so changesets get pushed
4165 b = repo._bookmarks.expandname(b)
4165 b = repo._bookmarks.expandname(b)
4166 if b in repo._bookmarks:
4166 if b in repo._bookmarks:
4167 opts.setdefault('rev', []).append(b)
4167 opts.setdefault('rev', []).append(b)
4168 else:
4168 else:
4169 # if we try to push a deleted bookmark, translate it to null
4169 # if we try to push a deleted bookmark, translate it to null
4170 # this lets simultaneous -r, -b options continue working
4170 # this lets simultaneous -r, -b options continue working
4171 opts.setdefault('rev', []).append("null")
4171 opts.setdefault('rev', []).append("null")
4172
4172
4173 path = ui.paths.getpath(dest, default=('default-push', 'default'))
4173 path = ui.paths.getpath(dest, default=('default-push', 'default'))
4174 if not path:
4174 if not path:
4175 raise error.Abort(_('default repository not configured!'),
4175 raise error.Abort(_('default repository not configured!'),
4176 hint=_("see 'hg help config.paths'"))
4176 hint=_("see 'hg help config.paths'"))
4177 dest = path.pushloc or path.loc
4177 dest = path.pushloc or path.loc
4178 branches = (path.branch, opts.get('branch') or [])
4178 branches = (path.branch, opts.get('branch') or [])
4179 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4179 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4180 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4180 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4181 other = hg.peer(repo, opts, dest)
4181 other = hg.peer(repo, opts, dest)
4182
4182
4183 if revs:
4183 if revs:
4184 revs = [repo[r].node() for r in scmutil.revrange(repo, revs)]
4184 revs = [repo[r].node() for r in scmutil.revrange(repo, revs)]
4185 if not revs:
4185 if not revs:
4186 raise error.Abort(_("specified revisions evaluate to an empty set"),
4186 raise error.Abort(_("specified revisions evaluate to an empty set"),
4187 hint=_("use different revision arguments"))
4187 hint=_("use different revision arguments"))
4188 elif path.pushrev:
4188 elif path.pushrev:
4189 # It doesn't make any sense to specify ancestor revisions. So limit
4189 # It doesn't make any sense to specify ancestor revisions. So limit
4190 # to DAG heads to make discovery simpler.
4190 # to DAG heads to make discovery simpler.
4191 expr = revsetlang.formatspec('heads(%r)', path.pushrev)
4191 expr = revsetlang.formatspec('heads(%r)', path.pushrev)
4192 revs = scmutil.revrange(repo, [expr])
4192 revs = scmutil.revrange(repo, [expr])
4193 revs = [repo[rev].node() for rev in revs]
4193 revs = [repo[rev].node() for rev in revs]
4194 if not revs:
4194 if not revs:
4195 raise error.Abort(_('default push revset for path evaluates to an '
4195 raise error.Abort(_('default push revset for path evaluates to an '
4196 'empty set'))
4196 'empty set'))
4197
4197
4198 repo._subtoppath = dest
4198 repo._subtoppath = dest
4199 try:
4199 try:
4200 # push subrepos depth-first for coherent ordering
4200 # push subrepos depth-first for coherent ordering
4201 c = repo['.']
4201 c = repo['.']
4202 subs = c.substate # only repos that are committed
4202 subs = c.substate # only repos that are committed
4203 for s in sorted(subs):
4203 for s in sorted(subs):
4204 result = c.sub(s).push(opts)
4204 result = c.sub(s).push(opts)
4205 if result == 0:
4205 if result == 0:
4206 return not result
4206 return not result
4207 finally:
4207 finally:
4208 del repo._subtoppath
4208 del repo._subtoppath
4209
4209
4210 opargs = dict(opts.get('opargs', {})) # copy opargs since we may mutate it
4210 opargs = dict(opts.get('opargs', {})) # copy opargs since we may mutate it
4211 opargs.setdefault('pushvars', []).extend(opts.get('pushvars', []))
4211 opargs.setdefault('pushvars', []).extend(opts.get('pushvars', []))
4212
4212
4213 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
4213 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
4214 newbranch=opts.get('new_branch'),
4214 newbranch=opts.get('new_branch'),
4215 bookmarks=opts.get('bookmark', ()),
4215 bookmarks=opts.get('bookmark', ()),
4216 opargs=opargs)
4216 opargs=opargs)
4217
4217
4218 result = not pushop.cgresult
4218 result = not pushop.cgresult
4219
4219
4220 if pushop.bkresult is not None:
4220 if pushop.bkresult is not None:
4221 if pushop.bkresult == 2:
4221 if pushop.bkresult == 2:
4222 result = 2
4222 result = 2
4223 elif not result and pushop.bkresult:
4223 elif not result and pushop.bkresult:
4224 result = 2
4224 result = 2
4225
4225
4226 return result
4226 return result
4227
4227
4228 @command('recover', [])
4228 @command('recover', [])
4229 def recover(ui, repo):
4229 def recover(ui, repo):
4230 """roll back an interrupted transaction
4230 """roll back an interrupted transaction
4231
4231
4232 Recover from an interrupted commit or pull.
4232 Recover from an interrupted commit or pull.
4233
4233
4234 This command tries to fix the repository status after an
4234 This command tries to fix the repository status after an
4235 interrupted operation. It should only be necessary when Mercurial
4235 interrupted operation. It should only be necessary when Mercurial
4236 suggests it.
4236 suggests it.
4237
4237
4238 Returns 0 if successful, 1 if nothing to recover or verify fails.
4238 Returns 0 if successful, 1 if nothing to recover or verify fails.
4239 """
4239 """
4240 if repo.recover():
4240 if repo.recover():
4241 return hg.verify(repo)
4241 return hg.verify(repo)
4242 return 1
4242 return 1
4243
4243
4244 @command('^remove|rm',
4244 @command('^remove|rm',
4245 [('A', 'after', None, _('record delete for missing files')),
4245 [('A', 'after', None, _('record delete for missing files')),
4246 ('f', 'force', None,
4246 ('f', 'force', None,
4247 _('forget added files, delete modified files')),
4247 _('forget added files, delete modified files')),
4248 ] + subrepoopts + walkopts + dryrunopts,
4248 ] + subrepoopts + walkopts + dryrunopts,
4249 _('[OPTION]... FILE...'),
4249 _('[OPTION]... FILE...'),
4250 inferrepo=True)
4250 inferrepo=True)
4251 def remove(ui, repo, *pats, **opts):
4251 def remove(ui, repo, *pats, **opts):
4252 """remove the specified files on the next commit
4252 """remove the specified files on the next commit
4253
4253
4254 Schedule the indicated files for removal from the current branch.
4254 Schedule the indicated files for removal from the current branch.
4255
4255
4256 This command schedules the files to be removed at the next commit.
4256 This command schedules the files to be removed at the next commit.
4257 To undo a remove before that, see :hg:`revert`. To undo added
4257 To undo a remove before that, see :hg:`revert`. To undo added
4258 files, see :hg:`forget`.
4258 files, see :hg:`forget`.
4259
4259
4260 .. container:: verbose
4260 .. container:: verbose
4261
4261
4262 -A/--after can be used to remove only files that have already
4262 -A/--after can be used to remove only files that have already
4263 been deleted, -f/--force can be used to force deletion, and -Af
4263 been deleted, -f/--force can be used to force deletion, and -Af
4264 can be used to remove files from the next revision without
4264 can be used to remove files from the next revision without
4265 deleting them from the working directory.
4265 deleting them from the working directory.
4266
4266
4267 The following table details the behavior of remove for different
4267 The following table details the behavior of remove for different
4268 file states (columns) and option combinations (rows). The file
4268 file states (columns) and option combinations (rows). The file
4269 states are Added [A], Clean [C], Modified [M] and Missing [!]
4269 states are Added [A], Clean [C], Modified [M] and Missing [!]
4270 (as reported by :hg:`status`). The actions are Warn, Remove
4270 (as reported by :hg:`status`). The actions are Warn, Remove
4271 (from branch) and Delete (from disk):
4271 (from branch) and Delete (from disk):
4272
4272
4273 ========= == == == ==
4273 ========= == == == ==
4274 opt/state A C M !
4274 opt/state A C M !
4275 ========= == == == ==
4275 ========= == == == ==
4276 none W RD W R
4276 none W RD W R
4277 -f R RD RD R
4277 -f R RD RD R
4278 -A W W W R
4278 -A W W W R
4279 -Af R R R R
4279 -Af R R R R
4280 ========= == == == ==
4280 ========= == == == ==
4281
4281
4282 .. note::
4282 .. note::
4283
4283
4284 :hg:`remove` never deletes files in Added [A] state from the
4284 :hg:`remove` never deletes files in Added [A] state from the
4285 working directory, not even if ``--force`` is specified.
4285 working directory, not even if ``--force`` is specified.
4286
4286
4287 Returns 0 on success, 1 if any warnings encountered.
4287 Returns 0 on success, 1 if any warnings encountered.
4288 """
4288 """
4289
4289
4290 opts = pycompat.byteskwargs(opts)
4290 opts = pycompat.byteskwargs(opts)
4291 after, force = opts.get('after'), opts.get('force')
4291 after, force = opts.get('after'), opts.get('force')
4292 dryrun = opts.get('dry_run')
4292 dryrun = opts.get('dry_run')
4293 if not pats and not after:
4293 if not pats and not after:
4294 raise error.Abort(_('no files specified'))
4294 raise error.Abort(_('no files specified'))
4295
4295
4296 m = scmutil.match(repo[None], pats, opts)
4296 m = scmutil.match(repo[None], pats, opts)
4297 subrepos = opts.get('subrepos')
4297 subrepos = opts.get('subrepos')
4298 return cmdutil.remove(ui, repo, m, "", after, force, subrepos,
4298 return cmdutil.remove(ui, repo, m, "", after, force, subrepos,
4299 dryrun=dryrun)
4299 dryrun=dryrun)
4300
4300
4301 @command('rename|move|mv',
4301 @command('rename|move|mv',
4302 [('A', 'after', None, _('record a rename that has already occurred')),
4302 [('A', 'after', None, _('record a rename that has already occurred')),
4303 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4303 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4304 ] + walkopts + dryrunopts,
4304 ] + walkopts + dryrunopts,
4305 _('[OPTION]... SOURCE... DEST'))
4305 _('[OPTION]... SOURCE... DEST'))
4306 def rename(ui, repo, *pats, **opts):
4306 def rename(ui, repo, *pats, **opts):
4307 """rename files; equivalent of copy + remove
4307 """rename files; equivalent of copy + remove
4308
4308
4309 Mark dest as copies of sources; mark sources for deletion. If dest
4309 Mark dest as copies of sources; mark sources for deletion. If dest
4310 is a directory, copies are put in that directory. If dest is a
4310 is a directory, copies are put in that directory. If dest is a
4311 file, there can only be one source.
4311 file, there can only be one source.
4312
4312
4313 By default, this command copies the contents of files as they
4313 By default, this command copies the contents of files as they
4314 exist in the working directory. If invoked with -A/--after, the
4314 exist in the working directory. If invoked with -A/--after, the
4315 operation is recorded, but no copying is performed.
4315 operation is recorded, but no copying is performed.
4316
4316
4317 This command takes effect at the next commit. To undo a rename
4317 This command takes effect at the next commit. To undo a rename
4318 before that, see :hg:`revert`.
4318 before that, see :hg:`revert`.
4319
4319
4320 Returns 0 on success, 1 if errors are encountered.
4320 Returns 0 on success, 1 if errors are encountered.
4321 """
4321 """
4322 opts = pycompat.byteskwargs(opts)
4322 opts = pycompat.byteskwargs(opts)
4323 with repo.wlock(False):
4323 with repo.wlock(False):
4324 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4324 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4325
4325
4326 @command('resolve',
4326 @command('resolve',
4327 [('a', 'all', None, _('select all unresolved files')),
4327 [('a', 'all', None, _('select all unresolved files')),
4328 ('l', 'list', None, _('list state of files needing merge')),
4328 ('l', 'list', None, _('list state of files needing merge')),
4329 ('m', 'mark', None, _('mark files as resolved')),
4329 ('m', 'mark', None, _('mark files as resolved')),
4330 ('u', 'unmark', None, _('mark files as unresolved')),
4330 ('u', 'unmark', None, _('mark files as unresolved')),
4331 ('n', 'no-status', None, _('hide status prefix'))]
4331 ('n', 'no-status', None, _('hide status prefix'))]
4332 + mergetoolopts + walkopts + formatteropts,
4332 + mergetoolopts + walkopts + formatteropts,
4333 _('[OPTION]... [FILE]...'),
4333 _('[OPTION]... [FILE]...'),
4334 inferrepo=True)
4334 inferrepo=True)
4335 def resolve(ui, repo, *pats, **opts):
4335 def resolve(ui, repo, *pats, **opts):
4336 """redo merges or set/view the merge status of files
4336 """redo merges or set/view the merge status of files
4337
4337
4338 Merges with unresolved conflicts are often the result of
4338 Merges with unresolved conflicts are often the result of
4339 non-interactive merging using the ``internal:merge`` configuration
4339 non-interactive merging using the ``internal:merge`` configuration
4340 setting, or a command-line merge tool like ``diff3``. The resolve
4340 setting, or a command-line merge tool like ``diff3``. The resolve
4341 command is used to manage the files involved in a merge, after
4341 command is used to manage the files involved in a merge, after
4342 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4342 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4343 working directory must have two parents). See :hg:`help
4343 working directory must have two parents). See :hg:`help
4344 merge-tools` for information on configuring merge tools.
4344 merge-tools` for information on configuring merge tools.
4345
4345
4346 The resolve command can be used in the following ways:
4346 The resolve command can be used in the following ways:
4347
4347
4348 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4348 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4349 files, discarding any previous merge attempts. Re-merging is not
4349 files, discarding any previous merge attempts. Re-merging is not
4350 performed for files already marked as resolved. Use ``--all/-a``
4350 performed for files already marked as resolved. Use ``--all/-a``
4351 to select all unresolved files. ``--tool`` can be used to specify
4351 to select all unresolved files. ``--tool`` can be used to specify
4352 the merge tool used for the given files. It overrides the HGMERGE
4352 the merge tool used for the given files. It overrides the HGMERGE
4353 environment variable and your configuration files. Previous file
4353 environment variable and your configuration files. Previous file
4354 contents are saved with a ``.orig`` suffix.
4354 contents are saved with a ``.orig`` suffix.
4355
4355
4356 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4356 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4357 (e.g. after having manually fixed-up the files). The default is
4357 (e.g. after having manually fixed-up the files). The default is
4358 to mark all unresolved files.
4358 to mark all unresolved files.
4359
4359
4360 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4360 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4361 default is to mark all resolved files.
4361 default is to mark all resolved files.
4362
4362
4363 - :hg:`resolve -l`: list files which had or still have conflicts.
4363 - :hg:`resolve -l`: list files which had or still have conflicts.
4364 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4364 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4365 You can use ``set:unresolved()`` or ``set:resolved()`` to filter
4365 You can use ``set:unresolved()`` or ``set:resolved()`` to filter
4366 the list. See :hg:`help filesets` for details.
4366 the list. See :hg:`help filesets` for details.
4367
4367
4368 .. note::
4368 .. note::
4369
4369
4370 Mercurial will not let you commit files with unresolved merge
4370 Mercurial will not let you commit files with unresolved merge
4371 conflicts. You must use :hg:`resolve -m ...` before you can
4371 conflicts. You must use :hg:`resolve -m ...` before you can
4372 commit after a conflicting merge.
4372 commit after a conflicting merge.
4373
4373
4374 Returns 0 on success, 1 if any files fail a resolve attempt.
4374 Returns 0 on success, 1 if any files fail a resolve attempt.
4375 """
4375 """
4376
4376
4377 opts = pycompat.byteskwargs(opts)
4377 opts = pycompat.byteskwargs(opts)
4378 flaglist = 'all mark unmark list no_status'.split()
4378 flaglist = 'all mark unmark list no_status'.split()
4379 all, mark, unmark, show, nostatus = \
4379 all, mark, unmark, show, nostatus = \
4380 [opts.get(o) for o in flaglist]
4380 [opts.get(o) for o in flaglist]
4381
4381
4382 if (show and (mark or unmark)) or (mark and unmark):
4382 if (show and (mark or unmark)) or (mark and unmark):
4383 raise error.Abort(_("too many options specified"))
4383 raise error.Abort(_("too many options specified"))
4384 if pats and all:
4384 if pats and all:
4385 raise error.Abort(_("can't specify --all and patterns"))
4385 raise error.Abort(_("can't specify --all and patterns"))
4386 if not (all or pats or show or mark or unmark):
4386 if not (all or pats or show or mark or unmark):
4387 raise error.Abort(_('no files or directories specified'),
4387 raise error.Abort(_('no files or directories specified'),
4388 hint=('use --all to re-merge all unresolved files'))
4388 hint=('use --all to re-merge all unresolved files'))
4389
4389
4390 if show:
4390 if show:
4391 ui.pager('resolve')
4391 ui.pager('resolve')
4392 fm = ui.formatter('resolve', opts)
4392 fm = ui.formatter('resolve', opts)
4393 ms = mergemod.mergestate.read(repo)
4393 ms = mergemod.mergestate.read(repo)
4394 m = scmutil.match(repo[None], pats, opts)
4394 m = scmutil.match(repo[None], pats, opts)
4395
4395
4396 # Labels and keys based on merge state. Unresolved path conflicts show
4396 # Labels and keys based on merge state. Unresolved path conflicts show
4397 # as 'P'. Resolved path conflicts show as 'R', the same as normal
4397 # as 'P'. Resolved path conflicts show as 'R', the same as normal
4398 # resolved conflicts.
4398 # resolved conflicts.
4399 mergestateinfo = {
4399 mergestateinfo = {
4400 mergemod.MERGE_RECORD_UNRESOLVED: ('resolve.unresolved', 'U'),
4400 mergemod.MERGE_RECORD_UNRESOLVED: ('resolve.unresolved', 'U'),
4401 mergemod.MERGE_RECORD_RESOLVED: ('resolve.resolved', 'R'),
4401 mergemod.MERGE_RECORD_RESOLVED: ('resolve.resolved', 'R'),
4402 mergemod.MERGE_RECORD_UNRESOLVED_PATH: ('resolve.unresolved', 'P'),
4402 mergemod.MERGE_RECORD_UNRESOLVED_PATH: ('resolve.unresolved', 'P'),
4403 mergemod.MERGE_RECORD_RESOLVED_PATH: ('resolve.resolved', 'R'),
4403 mergemod.MERGE_RECORD_RESOLVED_PATH: ('resolve.resolved', 'R'),
4404 mergemod.MERGE_RECORD_DRIVER_RESOLVED: ('resolve.driverresolved',
4404 mergemod.MERGE_RECORD_DRIVER_RESOLVED: ('resolve.driverresolved',
4405 'D'),
4405 'D'),
4406 }
4406 }
4407
4407
4408 for f in ms:
4408 for f in ms:
4409 if not m(f):
4409 if not m(f):
4410 continue
4410 continue
4411
4411
4412 label, key = mergestateinfo[ms[f]]
4412 label, key = mergestateinfo[ms[f]]
4413 fm.startitem()
4413 fm.startitem()
4414 fm.condwrite(not nostatus, 'status', '%s ', key, label=label)
4414 fm.condwrite(not nostatus, 'status', '%s ', key, label=label)
4415 fm.write('path', '%s\n', f, label=label)
4415 fm.write('path', '%s\n', f, label=label)
4416 fm.end()
4416 fm.end()
4417 return 0
4417 return 0
4418
4418
4419 with repo.wlock():
4419 with repo.wlock():
4420 ms = mergemod.mergestate.read(repo)
4420 ms = mergemod.mergestate.read(repo)
4421
4421
4422 if not (ms.active() or repo.dirstate.p2() != nullid):
4422 if not (ms.active() or repo.dirstate.p2() != nullid):
4423 raise error.Abort(
4423 raise error.Abort(
4424 _('resolve command not applicable when not merging'))
4424 _('resolve command not applicable when not merging'))
4425
4425
4426 wctx = repo[None]
4426 wctx = repo[None]
4427
4427
4428 if (ms.mergedriver
4428 if (ms.mergedriver
4429 and ms.mdstate() == mergemod.MERGE_DRIVER_STATE_UNMARKED):
4429 and ms.mdstate() == mergemod.MERGE_DRIVER_STATE_UNMARKED):
4430 proceed = mergemod.driverpreprocess(repo, ms, wctx)
4430 proceed = mergemod.driverpreprocess(repo, ms, wctx)
4431 ms.commit()
4431 ms.commit()
4432 # allow mark and unmark to go through
4432 # allow mark and unmark to go through
4433 if not mark and not unmark and not proceed:
4433 if not mark and not unmark and not proceed:
4434 return 1
4434 return 1
4435
4435
4436 m = scmutil.match(wctx, pats, opts)
4436 m = scmutil.match(wctx, pats, opts)
4437 ret = 0
4437 ret = 0
4438 didwork = False
4438 didwork = False
4439 runconclude = False
4439 runconclude = False
4440
4440
4441 tocomplete = []
4441 tocomplete = []
4442 for f in ms:
4442 for f in ms:
4443 if not m(f):
4443 if not m(f):
4444 continue
4444 continue
4445
4445
4446 didwork = True
4446 didwork = True
4447
4447
4448 # don't let driver-resolved files be marked, and run the conclude
4448 # don't let driver-resolved files be marked, and run the conclude
4449 # step if asked to resolve
4449 # step if asked to resolve
4450 if ms[f] == mergemod.MERGE_RECORD_DRIVER_RESOLVED:
4450 if ms[f] == mergemod.MERGE_RECORD_DRIVER_RESOLVED:
4451 exact = m.exact(f)
4451 exact = m.exact(f)
4452 if mark:
4452 if mark:
4453 if exact:
4453 if exact:
4454 ui.warn(_('not marking %s as it is driver-resolved\n')
4454 ui.warn(_('not marking %s as it is driver-resolved\n')
4455 % f)
4455 % f)
4456 elif unmark:
4456 elif unmark:
4457 if exact:
4457 if exact:
4458 ui.warn(_('not unmarking %s as it is driver-resolved\n')
4458 ui.warn(_('not unmarking %s as it is driver-resolved\n')
4459 % f)
4459 % f)
4460 else:
4460 else:
4461 runconclude = True
4461 runconclude = True
4462 continue
4462 continue
4463
4463
4464 # path conflicts must be resolved manually
4464 # path conflicts must be resolved manually
4465 if ms[f] in (mergemod.MERGE_RECORD_UNRESOLVED_PATH,
4465 if ms[f] in (mergemod.MERGE_RECORD_UNRESOLVED_PATH,
4466 mergemod.MERGE_RECORD_RESOLVED_PATH):
4466 mergemod.MERGE_RECORD_RESOLVED_PATH):
4467 if mark:
4467 if mark:
4468 ms.mark(f, mergemod.MERGE_RECORD_RESOLVED_PATH)
4468 ms.mark(f, mergemod.MERGE_RECORD_RESOLVED_PATH)
4469 elif unmark:
4469 elif unmark:
4470 ms.mark(f, mergemod.MERGE_RECORD_UNRESOLVED_PATH)
4470 ms.mark(f, mergemod.MERGE_RECORD_UNRESOLVED_PATH)
4471 elif ms[f] == mergemod.MERGE_RECORD_UNRESOLVED_PATH:
4471 elif ms[f] == mergemod.MERGE_RECORD_UNRESOLVED_PATH:
4472 ui.warn(_('%s: path conflict must be resolved manually\n')
4472 ui.warn(_('%s: path conflict must be resolved manually\n')
4473 % f)
4473 % f)
4474 continue
4474 continue
4475
4475
4476 if mark:
4476 if mark:
4477 ms.mark(f, mergemod.MERGE_RECORD_RESOLVED)
4477 ms.mark(f, mergemod.MERGE_RECORD_RESOLVED)
4478 elif unmark:
4478 elif unmark:
4479 ms.mark(f, mergemod.MERGE_RECORD_UNRESOLVED)
4479 ms.mark(f, mergemod.MERGE_RECORD_UNRESOLVED)
4480 else:
4480 else:
4481 # backup pre-resolve (merge uses .orig for its own purposes)
4481 # backup pre-resolve (merge uses .orig for its own purposes)
4482 a = repo.wjoin(f)
4482 a = repo.wjoin(f)
4483 try:
4483 try:
4484 util.copyfile(a, a + ".resolve")
4484 util.copyfile(a, a + ".resolve")
4485 except (IOError, OSError) as inst:
4485 except (IOError, OSError) as inst:
4486 if inst.errno != errno.ENOENT:
4486 if inst.errno != errno.ENOENT:
4487 raise
4487 raise
4488
4488
4489 try:
4489 try:
4490 # preresolve file
4490 # preresolve file
4491 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4491 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4492 'resolve')
4492 'resolve')
4493 complete, r = ms.preresolve(f, wctx)
4493 complete, r = ms.preresolve(f, wctx)
4494 if not complete:
4494 if not complete:
4495 tocomplete.append(f)
4495 tocomplete.append(f)
4496 elif r:
4496 elif r:
4497 ret = 1
4497 ret = 1
4498 finally:
4498 finally:
4499 ui.setconfig('ui', 'forcemerge', '', 'resolve')
4499 ui.setconfig('ui', 'forcemerge', '', 'resolve')
4500 ms.commit()
4500 ms.commit()
4501
4501
4502 # replace filemerge's .orig file with our resolve file, but only
4502 # replace filemerge's .orig file with our resolve file, but only
4503 # for merges that are complete
4503 # for merges that are complete
4504 if complete:
4504 if complete:
4505 try:
4505 try:
4506 util.rename(a + ".resolve",
4506 util.rename(a + ".resolve",
4507 scmutil.origpath(ui, repo, a))
4507 scmutil.origpath(ui, repo, a))
4508 except OSError as inst:
4508 except OSError as inst:
4509 if inst.errno != errno.ENOENT:
4509 if inst.errno != errno.ENOENT:
4510 raise
4510 raise
4511
4511
4512 for f in tocomplete:
4512 for f in tocomplete:
4513 try:
4513 try:
4514 # resolve file
4514 # resolve file
4515 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4515 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4516 'resolve')
4516 'resolve')
4517 r = ms.resolve(f, wctx)
4517 r = ms.resolve(f, wctx)
4518 if r:
4518 if r:
4519 ret = 1
4519 ret = 1
4520 finally:
4520 finally:
4521 ui.setconfig('ui', 'forcemerge', '', 'resolve')
4521 ui.setconfig('ui', 'forcemerge', '', 'resolve')
4522 ms.commit()
4522 ms.commit()
4523
4523
4524 # replace filemerge's .orig file with our resolve file
4524 # replace filemerge's .orig file with our resolve file
4525 a = repo.wjoin(f)
4525 a = repo.wjoin(f)
4526 try:
4526 try:
4527 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
4527 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
4528 except OSError as inst:
4528 except OSError as inst:
4529 if inst.errno != errno.ENOENT:
4529 if inst.errno != errno.ENOENT:
4530 raise
4530 raise
4531
4531
4532 ms.commit()
4532 ms.commit()
4533 ms.recordactions()
4533 ms.recordactions()
4534
4534
4535 if not didwork and pats:
4535 if not didwork and pats:
4536 hint = None
4536 hint = None
4537 if not any([p for p in pats if p.find(':') >= 0]):
4537 if not any([p for p in pats if p.find(':') >= 0]):
4538 pats = ['path:%s' % p for p in pats]
4538 pats = ['path:%s' % p for p in pats]
4539 m = scmutil.match(wctx, pats, opts)
4539 m = scmutil.match(wctx, pats, opts)
4540 for f in ms:
4540 for f in ms:
4541 if not m(f):
4541 if not m(f):
4542 continue
4542 continue
4543 flags = ''.join(['-%s ' % o[0:1] for o in flaglist
4543 flags = ''.join(['-%s ' % o[0:1] for o in flaglist
4544 if opts.get(o)])
4544 if opts.get(o)])
4545 hint = _("(try: hg resolve %s%s)\n") % (
4545 hint = _("(try: hg resolve %s%s)\n") % (
4546 flags,
4546 flags,
4547 ' '.join(pats))
4547 ' '.join(pats))
4548 break
4548 break
4549 ui.warn(_("arguments do not match paths that need resolving\n"))
4549 ui.warn(_("arguments do not match paths that need resolving\n"))
4550 if hint:
4550 if hint:
4551 ui.warn(hint)
4551 ui.warn(hint)
4552 elif ms.mergedriver and ms.mdstate() != 's':
4552 elif ms.mergedriver and ms.mdstate() != 's':
4553 # run conclude step when either a driver-resolved file is requested
4553 # run conclude step when either a driver-resolved file is requested
4554 # or there are no driver-resolved files
4554 # or there are no driver-resolved files
4555 # we can't use 'ret' to determine whether any files are unresolved
4555 # we can't use 'ret' to determine whether any files are unresolved
4556 # because we might not have tried to resolve some
4556 # because we might not have tried to resolve some
4557 if ((runconclude or not list(ms.driverresolved()))
4557 if ((runconclude or not list(ms.driverresolved()))
4558 and not list(ms.unresolved())):
4558 and not list(ms.unresolved())):
4559 proceed = mergemod.driverconclude(repo, ms, wctx)
4559 proceed = mergemod.driverconclude(repo, ms, wctx)
4560 ms.commit()
4560 ms.commit()
4561 if not proceed:
4561 if not proceed:
4562 return 1
4562 return 1
4563
4563
4564 # Nudge users into finishing an unfinished operation
4564 # Nudge users into finishing an unfinished operation
4565 unresolvedf = list(ms.unresolved())
4565 unresolvedf = list(ms.unresolved())
4566 driverresolvedf = list(ms.driverresolved())
4566 driverresolvedf = list(ms.driverresolved())
4567 if not unresolvedf and not driverresolvedf:
4567 if not unresolvedf and not driverresolvedf:
4568 ui.status(_('(no more unresolved files)\n'))
4568 ui.status(_('(no more unresolved files)\n'))
4569 cmdutil.checkafterresolved(repo)
4569 cmdutil.checkafterresolved(repo)
4570 elif not unresolvedf:
4570 elif not unresolvedf:
4571 ui.status(_('(no more unresolved files -- '
4571 ui.status(_('(no more unresolved files -- '
4572 'run "hg resolve --all" to conclude)\n'))
4572 'run "hg resolve --all" to conclude)\n'))
4573
4573
4574 return ret
4574 return ret
4575
4575
4576 @command('revert',
4576 @command('revert',
4577 [('a', 'all', None, _('revert all changes when no arguments given')),
4577 [('a', 'all', None, _('revert all changes when no arguments given')),
4578 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4578 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4579 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4579 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4580 ('C', 'no-backup', None, _('do not save backup copies of files')),
4580 ('C', 'no-backup', None, _('do not save backup copies of files')),
4581 ('i', 'interactive', None, _('interactively select the changes')),
4581 ('i', 'interactive', None, _('interactively select the changes')),
4582 ] + walkopts + dryrunopts,
4582 ] + walkopts + dryrunopts,
4583 _('[OPTION]... [-r REV] [NAME]...'))
4583 _('[OPTION]... [-r REV] [NAME]...'))
4584 def revert(ui, repo, *pats, **opts):
4584 def revert(ui, repo, *pats, **opts):
4585 """restore files to their checkout state
4585 """restore files to their checkout state
4586
4586
4587 .. note::
4587 .. note::
4588
4588
4589 To check out earlier revisions, you should use :hg:`update REV`.
4589 To check out earlier revisions, you should use :hg:`update REV`.
4590 To cancel an uncommitted merge (and lose your changes),
4590 To cancel an uncommitted merge (and lose your changes),
4591 use :hg:`merge --abort`.
4591 use :hg:`merge --abort`.
4592
4592
4593 With no revision specified, revert the specified files or directories
4593 With no revision specified, revert the specified files or directories
4594 to the contents they had in the parent of the working directory.
4594 to the contents they had in the parent of the working directory.
4595 This restores the contents of files to an unmodified
4595 This restores the contents of files to an unmodified
4596 state and unschedules adds, removes, copies, and renames. If the
4596 state and unschedules adds, removes, copies, and renames. If the
4597 working directory has two parents, you must explicitly specify a
4597 working directory has two parents, you must explicitly specify a
4598 revision.
4598 revision.
4599
4599
4600 Using the -r/--rev or -d/--date options, revert the given files or
4600 Using the -r/--rev or -d/--date options, revert the given files or
4601 directories to their states as of a specific revision. Because
4601 directories to their states as of a specific revision. Because
4602 revert does not change the working directory parents, this will
4602 revert does not change the working directory parents, this will
4603 cause these files to appear modified. This can be helpful to "back
4603 cause these files to appear modified. This can be helpful to "back
4604 out" some or all of an earlier change. See :hg:`backout` for a
4604 out" some or all of an earlier change. See :hg:`backout` for a
4605 related method.
4605 related method.
4606
4606
4607 Modified files are saved with a .orig suffix before reverting.
4607 Modified files are saved with a .orig suffix before reverting.
4608 To disable these backups, use --no-backup. It is possible to store
4608 To disable these backups, use --no-backup. It is possible to store
4609 the backup files in a custom directory relative to the root of the
4609 the backup files in a custom directory relative to the root of the
4610 repository by setting the ``ui.origbackuppath`` configuration
4610 repository by setting the ``ui.origbackuppath`` configuration
4611 option.
4611 option.
4612
4612
4613 See :hg:`help dates` for a list of formats valid for -d/--date.
4613 See :hg:`help dates` for a list of formats valid for -d/--date.
4614
4614
4615 See :hg:`help backout` for a way to reverse the effect of an
4615 See :hg:`help backout` for a way to reverse the effect of an
4616 earlier changeset.
4616 earlier changeset.
4617
4617
4618 Returns 0 on success.
4618 Returns 0 on success.
4619 """
4619 """
4620
4620
4621 opts = pycompat.byteskwargs(opts)
4621 opts = pycompat.byteskwargs(opts)
4622 if opts.get("date"):
4622 if opts.get("date"):
4623 if opts.get("rev"):
4623 if opts.get("rev"):
4624 raise error.Abort(_("you can't specify a revision and a date"))
4624 raise error.Abort(_("you can't specify a revision and a date"))
4625 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4625 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4626
4626
4627 parent, p2 = repo.dirstate.parents()
4627 parent, p2 = repo.dirstate.parents()
4628 if not opts.get('rev') and p2 != nullid:
4628 if not opts.get('rev') and p2 != nullid:
4629 # revert after merge is a trap for new users (issue2915)
4629 # revert after merge is a trap for new users (issue2915)
4630 raise error.Abort(_('uncommitted merge with no revision specified'),
4630 raise error.Abort(_('uncommitted merge with no revision specified'),
4631 hint=_("use 'hg update' or see 'hg help revert'"))
4631 hint=_("use 'hg update' or see 'hg help revert'"))
4632
4632
4633 rev = opts.get('rev')
4633 rev = opts.get('rev')
4634 if rev:
4634 if rev:
4635 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
4635 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
4636 ctx = scmutil.revsingle(repo, rev)
4636 ctx = scmutil.revsingle(repo, rev)
4637
4637
4638 if (not (pats or opts.get('include') or opts.get('exclude') or
4638 if (not (pats or opts.get('include') or opts.get('exclude') or
4639 opts.get('all') or opts.get('interactive'))):
4639 opts.get('all') or opts.get('interactive'))):
4640 msg = _("no files or directories specified")
4640 msg = _("no files or directories specified")
4641 if p2 != nullid:
4641 if p2 != nullid:
4642 hint = _("uncommitted merge, use --all to discard all changes,"
4642 hint = _("uncommitted merge, use --all to discard all changes,"
4643 " or 'hg update -C .' to abort the merge")
4643 " or 'hg update -C .' to abort the merge")
4644 raise error.Abort(msg, hint=hint)
4644 raise error.Abort(msg, hint=hint)
4645 dirty = any(repo.status())
4645 dirty = any(repo.status())
4646 node = ctx.node()
4646 node = ctx.node()
4647 if node != parent:
4647 if node != parent:
4648 if dirty:
4648 if dirty:
4649 hint = _("uncommitted changes, use --all to discard all"
4649 hint = _("uncommitted changes, use --all to discard all"
4650 " changes, or 'hg update %s' to update") % ctx.rev()
4650 " changes, or 'hg update %s' to update") % ctx.rev()
4651 else:
4651 else:
4652 hint = _("use --all to revert all files,"
4652 hint = _("use --all to revert all files,"
4653 " or 'hg update %s' to update") % ctx.rev()
4653 " or 'hg update %s' to update") % ctx.rev()
4654 elif dirty:
4654 elif dirty:
4655 hint = _("uncommitted changes, use --all to discard all changes")
4655 hint = _("uncommitted changes, use --all to discard all changes")
4656 else:
4656 else:
4657 hint = _("use --all to revert all files")
4657 hint = _("use --all to revert all files")
4658 raise error.Abort(msg, hint=hint)
4658 raise error.Abort(msg, hint=hint)
4659
4659
4660 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats,
4660 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats,
4661 **pycompat.strkwargs(opts))
4661 **pycompat.strkwargs(opts))
4662
4662
4663 @command('rollback', dryrunopts +
4663 @command('rollback', dryrunopts +
4664 [('f', 'force', False, _('ignore safety measures'))])
4664 [('f', 'force', False, _('ignore safety measures'))])
4665 def rollback(ui, repo, **opts):
4665 def rollback(ui, repo, **opts):
4666 """roll back the last transaction (DANGEROUS) (DEPRECATED)
4666 """roll back the last transaction (DANGEROUS) (DEPRECATED)
4667
4667
4668 Please use :hg:`commit --amend` instead of rollback to correct
4668 Please use :hg:`commit --amend` instead of rollback to correct
4669 mistakes in the last commit.
4669 mistakes in the last commit.
4670
4670
4671 This command should be used with care. There is only one level of
4671 This command should be used with care. There is only one level of
4672 rollback, and there is no way to undo a rollback. It will also
4672 rollback, and there is no way to undo a rollback. It will also
4673 restore the dirstate at the time of the last transaction, losing
4673 restore the dirstate at the time of the last transaction, losing
4674 any dirstate changes since that time. This command does not alter
4674 any dirstate changes since that time. This command does not alter
4675 the working directory.
4675 the working directory.
4676
4676
4677 Transactions are used to encapsulate the effects of all commands
4677 Transactions are used to encapsulate the effects of all commands
4678 that create new changesets or propagate existing changesets into a
4678 that create new changesets or propagate existing changesets into a
4679 repository.
4679 repository.
4680
4680
4681 .. container:: verbose
4681 .. container:: verbose
4682
4682
4683 For example, the following commands are transactional, and their
4683 For example, the following commands are transactional, and their
4684 effects can be rolled back:
4684 effects can be rolled back:
4685
4685
4686 - commit
4686 - commit
4687 - import
4687 - import
4688 - pull
4688 - pull
4689 - push (with this repository as the destination)
4689 - push (with this repository as the destination)
4690 - unbundle
4690 - unbundle
4691
4691
4692 To avoid permanent data loss, rollback will refuse to rollback a
4692 To avoid permanent data loss, rollback will refuse to rollback a
4693 commit transaction if it isn't checked out. Use --force to
4693 commit transaction if it isn't checked out. Use --force to
4694 override this protection.
4694 override this protection.
4695
4695
4696 The rollback command can be entirely disabled by setting the
4696 The rollback command can be entirely disabled by setting the
4697 ``ui.rollback`` configuration setting to false. If you're here
4697 ``ui.rollback`` configuration setting to false. If you're here
4698 because you want to use rollback and it's disabled, you can
4698 because you want to use rollback and it's disabled, you can
4699 re-enable the command by setting ``ui.rollback`` to true.
4699 re-enable the command by setting ``ui.rollback`` to true.
4700
4700
4701 This command is not intended for use on public repositories. Once
4701 This command is not intended for use on public repositories. Once
4702 changes are visible for pull by other users, rolling a transaction
4702 changes are visible for pull by other users, rolling a transaction
4703 back locally is ineffective (someone else may already have pulled
4703 back locally is ineffective (someone else may already have pulled
4704 the changes). Furthermore, a race is possible with readers of the
4704 the changes). Furthermore, a race is possible with readers of the
4705 repository; for example an in-progress pull from the repository
4705 repository; for example an in-progress pull from the repository
4706 may fail if a rollback is performed.
4706 may fail if a rollback is performed.
4707
4707
4708 Returns 0 on success, 1 if no rollback data is available.
4708 Returns 0 on success, 1 if no rollback data is available.
4709 """
4709 """
4710 if not ui.configbool('ui', 'rollback'):
4710 if not ui.configbool('ui', 'rollback'):
4711 raise error.Abort(_('rollback is disabled because it is unsafe'),
4711 raise error.Abort(_('rollback is disabled because it is unsafe'),
4712 hint=('see `hg help -v rollback` for information'))
4712 hint=('see `hg help -v rollback` for information'))
4713 return repo.rollback(dryrun=opts.get(r'dry_run'),
4713 return repo.rollback(dryrun=opts.get(r'dry_run'),
4714 force=opts.get(r'force'))
4714 force=opts.get(r'force'))
4715
4715
4716 @command('root', [], intents={INTENT_READONLY})
4716 @command('root', [], intents={INTENT_READONLY})
4717 def root(ui, repo):
4717 def root(ui, repo):
4718 """print the root (top) of the current working directory
4718 """print the root (top) of the current working directory
4719
4719
4720 Print the root directory of the current repository.
4720 Print the root directory of the current repository.
4721
4721
4722 Returns 0 on success.
4722 Returns 0 on success.
4723 """
4723 """
4724 ui.write(repo.root + "\n")
4724 ui.write(repo.root + "\n")
4725
4725
4726 @command('^serve',
4726 @command('^serve',
4727 [('A', 'accesslog', '', _('name of access log file to write to'),
4727 [('A', 'accesslog', '', _('name of access log file to write to'),
4728 _('FILE')),
4728 _('FILE')),
4729 ('d', 'daemon', None, _('run server in background')),
4729 ('d', 'daemon', None, _('run server in background')),
4730 ('', 'daemon-postexec', [], _('used internally by daemon mode')),
4730 ('', 'daemon-postexec', [], _('used internally by daemon mode')),
4731 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4731 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4732 # use string type, then we can check if something was passed
4732 # use string type, then we can check if something was passed
4733 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4733 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4734 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4734 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4735 _('ADDR')),
4735 _('ADDR')),
4736 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4736 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4737 _('PREFIX')),
4737 _('PREFIX')),
4738 ('n', 'name', '',
4738 ('n', 'name', '',
4739 _('name to show in web pages (default: working directory)'), _('NAME')),
4739 _('name to show in web pages (default: working directory)'), _('NAME')),
4740 ('', 'web-conf', '',
4740 ('', 'web-conf', '',
4741 _("name of the hgweb config file (see 'hg help hgweb')"), _('FILE')),
4741 _("name of the hgweb config file (see 'hg help hgweb')"), _('FILE')),
4742 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4742 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4743 _('FILE')),
4743 _('FILE')),
4744 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4744 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4745 ('', 'stdio', None, _('for remote clients (ADVANCED)')),
4745 ('', 'stdio', None, _('for remote clients (ADVANCED)')),
4746 ('', 'cmdserver', '', _('for remote clients (ADVANCED)'), _('MODE')),
4746 ('', 'cmdserver', '', _('for remote clients (ADVANCED)'), _('MODE')),
4747 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4747 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4748 ('', 'style', '', _('template style to use'), _('STYLE')),
4748 ('', 'style', '', _('template style to use'), _('STYLE')),
4749 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4749 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4750 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))]
4750 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))]
4751 + subrepoopts,
4751 + subrepoopts,
4752 _('[OPTION]...'),
4752 _('[OPTION]...'),
4753 optionalrepo=True)
4753 optionalrepo=True)
4754 def serve(ui, repo, **opts):
4754 def serve(ui, repo, **opts):
4755 """start stand-alone webserver
4755 """start stand-alone webserver
4756
4756
4757 Start a local HTTP repository browser and pull server. You can use
4757 Start a local HTTP repository browser and pull server. You can use
4758 this for ad-hoc sharing and browsing of repositories. It is
4758 this for ad-hoc sharing and browsing of repositories. It is
4759 recommended to use a real web server to serve a repository for
4759 recommended to use a real web server to serve a repository for
4760 longer periods of time.
4760 longer periods of time.
4761
4761
4762 Please note that the server does not implement access control.
4762 Please note that the server does not implement access control.
4763 This means that, by default, anybody can read from the server and
4763 This means that, by default, anybody can read from the server and
4764 nobody can write to it by default. Set the ``web.allow-push``
4764 nobody can write to it by default. Set the ``web.allow-push``
4765 option to ``*`` to allow everybody to push to the server. You
4765 option to ``*`` to allow everybody to push to the server. You
4766 should use a real web server if you need to authenticate users.
4766 should use a real web server if you need to authenticate users.
4767
4767
4768 By default, the server logs accesses to stdout and errors to
4768 By default, the server logs accesses to stdout and errors to
4769 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
4769 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
4770 files.
4770 files.
4771
4771
4772 To have the server choose a free port number to listen on, specify
4772 To have the server choose a free port number to listen on, specify
4773 a port number of 0; in this case, the server will print the port
4773 a port number of 0; in this case, the server will print the port
4774 number it uses.
4774 number it uses.
4775
4775
4776 Returns 0 on success.
4776 Returns 0 on success.
4777 """
4777 """
4778
4778
4779 opts = pycompat.byteskwargs(opts)
4779 opts = pycompat.byteskwargs(opts)
4780 if opts["stdio"] and opts["cmdserver"]:
4780 if opts["stdio"] and opts["cmdserver"]:
4781 raise error.Abort(_("cannot use --stdio with --cmdserver"))
4781 raise error.Abort(_("cannot use --stdio with --cmdserver"))
4782
4782
4783 if opts["stdio"]:
4783 if opts["stdio"]:
4784 if repo is None:
4784 if repo is None:
4785 raise error.RepoError(_("there is no Mercurial repository here"
4785 raise error.RepoError(_("there is no Mercurial repository here"
4786 " (.hg not found)"))
4786 " (.hg not found)"))
4787 s = wireprotoserver.sshserver(ui, repo)
4787 s = wireprotoserver.sshserver(ui, repo)
4788 s.serve_forever()
4788 s.serve_forever()
4789
4789
4790 service = server.createservice(ui, repo, opts)
4790 service = server.createservice(ui, repo, opts)
4791 return server.runservice(opts, initfn=service.init, runfn=service.run)
4791 return server.runservice(opts, initfn=service.init, runfn=service.run)
4792
4792
4793 @command('^status|st',
4793 @command('^status|st',
4794 [('A', 'all', None, _('show status of all files')),
4794 [('A', 'all', None, _('show status of all files')),
4795 ('m', 'modified', None, _('show only modified files')),
4795 ('m', 'modified', None, _('show only modified files')),
4796 ('a', 'added', None, _('show only added files')),
4796 ('a', 'added', None, _('show only added files')),
4797 ('r', 'removed', None, _('show only removed files')),
4797 ('r', 'removed', None, _('show only removed files')),
4798 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4798 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4799 ('c', 'clean', None, _('show only files without changes')),
4799 ('c', 'clean', None, _('show only files without changes')),
4800 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4800 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4801 ('i', 'ignored', None, _('show only ignored files')),
4801 ('i', 'ignored', None, _('show only ignored files')),
4802 ('n', 'no-status', None, _('hide status prefix')),
4802 ('n', 'no-status', None, _('hide status prefix')),
4803 ('t', 'terse', '', _('show the terse output (EXPERIMENTAL)')),
4803 ('t', 'terse', '', _('show the terse output (EXPERIMENTAL)')),
4804 ('C', 'copies', None, _('show source of copied files')),
4804 ('C', 'copies', None, _('show source of copied files')),
4805 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4805 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4806 ('', 'rev', [], _('show difference from revision'), _('REV')),
4806 ('', 'rev', [], _('show difference from revision'), _('REV')),
4807 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
4807 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
4808 ] + walkopts + subrepoopts + formatteropts,
4808 ] + walkopts + subrepoopts + formatteropts,
4809 _('[OPTION]... [FILE]...'),
4809 _('[OPTION]... [FILE]...'),
4810 inferrepo=True,
4810 inferrepo=True,
4811 intents={INTENT_READONLY})
4811 intents={INTENT_READONLY})
4812 def status(ui, repo, *pats, **opts):
4812 def status(ui, repo, *pats, **opts):
4813 """show changed files in the working directory
4813 """show changed files in the working directory
4814
4814
4815 Show status of files in the repository. If names are given, only
4815 Show status of files in the repository. If names are given, only
4816 files that match are shown. Files that are clean or ignored or
4816 files that match are shown. Files that are clean or ignored or
4817 the source of a copy/move operation, are not listed unless
4817 the source of a copy/move operation, are not listed unless
4818 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
4818 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
4819 Unless options described with "show only ..." are given, the
4819 Unless options described with "show only ..." are given, the
4820 options -mardu are used.
4820 options -mardu are used.
4821
4821
4822 Option -q/--quiet hides untracked (unknown and ignored) files
4822 Option -q/--quiet hides untracked (unknown and ignored) files
4823 unless explicitly requested with -u/--unknown or -i/--ignored.
4823 unless explicitly requested with -u/--unknown or -i/--ignored.
4824
4824
4825 .. note::
4825 .. note::
4826
4826
4827 :hg:`status` may appear to disagree with diff if permissions have
4827 :hg:`status` may appear to disagree with diff if permissions have
4828 changed or a merge has occurred. The standard diff format does
4828 changed or a merge has occurred. The standard diff format does
4829 not report permission changes and diff only reports changes
4829 not report permission changes and diff only reports changes
4830 relative to one merge parent.
4830 relative to one merge parent.
4831
4831
4832 If one revision is given, it is used as the base revision.
4832 If one revision is given, it is used as the base revision.
4833 If two revisions are given, the differences between them are
4833 If two revisions are given, the differences between them are
4834 shown. The --change option can also be used as a shortcut to list
4834 shown. The --change option can also be used as a shortcut to list
4835 the changed files of a revision from its first parent.
4835 the changed files of a revision from its first parent.
4836
4836
4837 The codes used to show the status of files are::
4837 The codes used to show the status of files are::
4838
4838
4839 M = modified
4839 M = modified
4840 A = added
4840 A = added
4841 R = removed
4841 R = removed
4842 C = clean
4842 C = clean
4843 ! = missing (deleted by non-hg command, but still tracked)
4843 ! = missing (deleted by non-hg command, but still tracked)
4844 ? = not tracked
4844 ? = not tracked
4845 I = ignored
4845 I = ignored
4846 = origin of the previous file (with --copies)
4846 = origin of the previous file (with --copies)
4847
4847
4848 .. container:: verbose
4848 .. container:: verbose
4849
4849
4850 The -t/--terse option abbreviates the output by showing only the directory
4850 The -t/--terse option abbreviates the output by showing only the directory
4851 name if all the files in it share the same status. The option takes an
4851 name if all the files in it share the same status. The option takes an
4852 argument indicating the statuses to abbreviate: 'm' for 'modified', 'a'
4852 argument indicating the statuses to abbreviate: 'm' for 'modified', 'a'
4853 for 'added', 'r' for 'removed', 'd' for 'deleted', 'u' for 'unknown', 'i'
4853 for 'added', 'r' for 'removed', 'd' for 'deleted', 'u' for 'unknown', 'i'
4854 for 'ignored' and 'c' for clean.
4854 for 'ignored' and 'c' for clean.
4855
4855
4856 It abbreviates only those statuses which are passed. Note that clean and
4856 It abbreviates only those statuses which are passed. Note that clean and
4857 ignored files are not displayed with '--terse ic' unless the -c/--clean
4857 ignored files are not displayed with '--terse ic' unless the -c/--clean
4858 and -i/--ignored options are also used.
4858 and -i/--ignored options are also used.
4859
4859
4860 The -v/--verbose option shows information when the repository is in an
4860 The -v/--verbose option shows information when the repository is in an
4861 unfinished merge, shelve, rebase state etc. You can have this behavior
4861 unfinished merge, shelve, rebase state etc. You can have this behavior
4862 turned on by default by enabling the ``commands.status.verbose`` option.
4862 turned on by default by enabling the ``commands.status.verbose`` option.
4863
4863
4864 You can skip displaying some of these states by setting
4864 You can skip displaying some of these states by setting
4865 ``commands.status.skipstates`` to one or more of: 'bisect', 'graft',
4865 ``commands.status.skipstates`` to one or more of: 'bisect', 'graft',
4866 'histedit', 'merge', 'rebase', or 'unshelve'.
4866 'histedit', 'merge', 'rebase', or 'unshelve'.
4867
4867
4868 Examples:
4868 Examples:
4869
4869
4870 - show changes in the working directory relative to a
4870 - show changes in the working directory relative to a
4871 changeset::
4871 changeset::
4872
4872
4873 hg status --rev 9353
4873 hg status --rev 9353
4874
4874
4875 - show changes in the working directory relative to the
4875 - show changes in the working directory relative to the
4876 current directory (see :hg:`help patterns` for more information)::
4876 current directory (see :hg:`help patterns` for more information)::
4877
4877
4878 hg status re:
4878 hg status re:
4879
4879
4880 - show all changes including copies in an existing changeset::
4880 - show all changes including copies in an existing changeset::
4881
4881
4882 hg status --copies --change 9353
4882 hg status --copies --change 9353
4883
4883
4884 - get a NUL separated list of added files, suitable for xargs::
4884 - get a NUL separated list of added files, suitable for xargs::
4885
4885
4886 hg status -an0
4886 hg status -an0
4887
4887
4888 - show more information about the repository status, abbreviating
4888 - show more information about the repository status, abbreviating
4889 added, removed, modified, deleted, and untracked paths::
4889 added, removed, modified, deleted, and untracked paths::
4890
4890
4891 hg status -v -t mardu
4891 hg status -v -t mardu
4892
4892
4893 Returns 0 on success.
4893 Returns 0 on success.
4894
4894
4895 """
4895 """
4896
4896
4897 opts = pycompat.byteskwargs(opts)
4897 opts = pycompat.byteskwargs(opts)
4898 revs = opts.get('rev')
4898 revs = opts.get('rev')
4899 change = opts.get('change')
4899 change = opts.get('change')
4900 terse = opts.get('terse')
4900 terse = opts.get('terse')
4901
4901
4902 if revs and change:
4902 if revs and change:
4903 msg = _('cannot specify --rev and --change at the same time')
4903 msg = _('cannot specify --rev and --change at the same time')
4904 raise error.Abort(msg)
4904 raise error.Abort(msg)
4905 elif revs and terse:
4905 elif revs and terse:
4906 msg = _('cannot use --terse with --rev')
4906 msg = _('cannot use --terse with --rev')
4907 raise error.Abort(msg)
4907 raise error.Abort(msg)
4908 elif change:
4908 elif change:
4909 repo = scmutil.unhidehashlikerevs(repo, [change], 'nowarn')
4909 repo = scmutil.unhidehashlikerevs(repo, [change], 'nowarn')
4910 ctx2 = scmutil.revsingle(repo, change, None)
4910 ctx2 = scmutil.revsingle(repo, change, None)
4911 ctx1 = ctx2.p1()
4911 ctx1 = ctx2.p1()
4912 else:
4912 else:
4913 repo = scmutil.unhidehashlikerevs(repo, revs, 'nowarn')
4913 repo = scmutil.unhidehashlikerevs(repo, revs, 'nowarn')
4914 ctx1, ctx2 = scmutil.revpair(repo, revs)
4914 ctx1, ctx2 = scmutil.revpair(repo, revs)
4915
4915
4916 if pats or ui.configbool('commands', 'status.relative'):
4916 if pats or ui.configbool('commands', 'status.relative'):
4917 cwd = repo.getcwd()
4917 cwd = repo.getcwd()
4918 else:
4918 else:
4919 cwd = ''
4919 cwd = ''
4920
4920
4921 if opts.get('print0'):
4921 if opts.get('print0'):
4922 end = '\0'
4922 end = '\0'
4923 else:
4923 else:
4924 end = '\n'
4924 end = '\n'
4925 copy = {}
4925 copy = {}
4926 states = 'modified added removed deleted unknown ignored clean'.split()
4926 states = 'modified added removed deleted unknown ignored clean'.split()
4927 show = [k for k in states if opts.get(k)]
4927 show = [k for k in states if opts.get(k)]
4928 if opts.get('all'):
4928 if opts.get('all'):
4929 show += ui.quiet and (states[:4] + ['clean']) or states
4929 show += ui.quiet and (states[:4] + ['clean']) or states
4930
4930
4931 if not show:
4931 if not show:
4932 if ui.quiet:
4932 if ui.quiet:
4933 show = states[:4]
4933 show = states[:4]
4934 else:
4934 else:
4935 show = states[:5]
4935 show = states[:5]
4936
4936
4937 m = scmutil.match(ctx2, pats, opts)
4937 m = scmutil.match(ctx2, pats, opts)
4938 if terse:
4938 if terse:
4939 # we need to compute clean and unknown to terse
4939 # we need to compute clean and unknown to terse
4940 stat = repo.status(ctx1.node(), ctx2.node(), m,
4940 stat = repo.status(ctx1.node(), ctx2.node(), m,
4941 'ignored' in show or 'i' in terse,
4941 'ignored' in show or 'i' in terse,
4942 True, True, opts.get('subrepos'))
4942 True, True, opts.get('subrepos'))
4943
4943
4944 stat = cmdutil.tersedir(stat, terse)
4944 stat = cmdutil.tersedir(stat, terse)
4945 else:
4945 else:
4946 stat = repo.status(ctx1.node(), ctx2.node(), m,
4946 stat = repo.status(ctx1.node(), ctx2.node(), m,
4947 'ignored' in show, 'clean' in show,
4947 'ignored' in show, 'clean' in show,
4948 'unknown' in show, opts.get('subrepos'))
4948 'unknown' in show, opts.get('subrepos'))
4949
4949
4950 changestates = zip(states, pycompat.iterbytestr('MAR!?IC'), stat)
4950 changestates = zip(states, pycompat.iterbytestr('MAR!?IC'), stat)
4951
4951
4952 if (opts.get('all') or opts.get('copies')
4952 if (opts.get('all') or opts.get('copies')
4953 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
4953 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
4954 copy = copies.pathcopies(ctx1, ctx2, m)
4954 copy = copies.pathcopies(ctx1, ctx2, m)
4955
4955
4956 ui.pager('status')
4956 ui.pager('status')
4957 fm = ui.formatter('status', opts)
4957 fm = ui.formatter('status', opts)
4958 fmt = '%s' + end
4958 fmt = '%s' + end
4959 showchar = not opts.get('no_status')
4959 showchar = not opts.get('no_status')
4960
4960
4961 for state, char, files in changestates:
4961 for state, char, files in changestates:
4962 if state in show:
4962 if state in show:
4963 label = 'status.' + state
4963 label = 'status.' + state
4964 for f in files:
4964 for f in files:
4965 fm.startitem()
4965 fm.startitem()
4966 fm.condwrite(showchar, 'status', '%s ', char, label=label)
4966 fm.condwrite(showchar, 'status', '%s ', char, label=label)
4967 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
4967 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
4968 if f in copy:
4968 if f in copy:
4969 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
4969 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
4970 label='status.copied')
4970 label='status.copied')
4971
4971
4972 if ((ui.verbose or ui.configbool('commands', 'status.verbose'))
4972 if ((ui.verbose or ui.configbool('commands', 'status.verbose'))
4973 and not ui.plain()):
4973 and not ui.plain()):
4974 cmdutil.morestatus(repo, fm)
4974 cmdutil.morestatus(repo, fm)
4975 fm.end()
4975 fm.end()
4976
4976
4977 @command('^summary|sum',
4977 @command('^summary|sum',
4978 [('', 'remote', None, _('check for push and pull'))],
4978 [('', 'remote', None, _('check for push and pull'))],
4979 '[--remote]',
4979 '[--remote]',
4980 intents={INTENT_READONLY})
4980 intents={INTENT_READONLY})
4981 def summary(ui, repo, **opts):
4981 def summary(ui, repo, **opts):
4982 """summarize working directory state
4982 """summarize working directory state
4983
4983
4984 This generates a brief summary of the working directory state,
4984 This generates a brief summary of the working directory state,
4985 including parents, branch, commit status, phase and available updates.
4985 including parents, branch, commit status, phase and available updates.
4986
4986
4987 With the --remote option, this will check the default paths for
4987 With the --remote option, this will check the default paths for
4988 incoming and outgoing changes. This can be time-consuming.
4988 incoming and outgoing changes. This can be time-consuming.
4989
4989
4990 Returns 0 on success.
4990 Returns 0 on success.
4991 """
4991 """
4992
4992
4993 opts = pycompat.byteskwargs(opts)
4993 opts = pycompat.byteskwargs(opts)
4994 ui.pager('summary')
4994 ui.pager('summary')
4995 ctx = repo[None]
4995 ctx = repo[None]
4996 parents = ctx.parents()
4996 parents = ctx.parents()
4997 pnode = parents[0].node()
4997 pnode = parents[0].node()
4998 marks = []
4998 marks = []
4999
4999
5000 ms = None
5000 ms = None
5001 try:
5001 try:
5002 ms = mergemod.mergestate.read(repo)
5002 ms = mergemod.mergestate.read(repo)
5003 except error.UnsupportedMergeRecords as e:
5003 except error.UnsupportedMergeRecords as e:
5004 s = ' '.join(e.recordtypes)
5004 s = ' '.join(e.recordtypes)
5005 ui.warn(
5005 ui.warn(
5006 _('warning: merge state has unsupported record types: %s\n') % s)
5006 _('warning: merge state has unsupported record types: %s\n') % s)
5007 unresolved = []
5007 unresolved = []
5008 else:
5008 else:
5009 unresolved = list(ms.unresolved())
5009 unresolved = list(ms.unresolved())
5010
5010
5011 for p in parents:
5011 for p in parents:
5012 # label with log.changeset (instead of log.parent) since this
5012 # label with log.changeset (instead of log.parent) since this
5013 # shows a working directory parent *changeset*:
5013 # shows a working directory parent *changeset*:
5014 # i18n: column positioning for "hg summary"
5014 # i18n: column positioning for "hg summary"
5015 ui.write(_('parent: %d:%s ') % (p.rev(), p),
5015 ui.write(_('parent: %d:%s ') % (p.rev(), p),
5016 label=logcmdutil.changesetlabels(p))
5016 label=logcmdutil.changesetlabels(p))
5017 ui.write(' '.join(p.tags()), label='log.tag')
5017 ui.write(' '.join(p.tags()), label='log.tag')
5018 if p.bookmarks():
5018 if p.bookmarks():
5019 marks.extend(p.bookmarks())
5019 marks.extend(p.bookmarks())
5020 if p.rev() == -1:
5020 if p.rev() == -1:
5021 if not len(repo):
5021 if not len(repo):
5022 ui.write(_(' (empty repository)'))
5022 ui.write(_(' (empty repository)'))
5023 else:
5023 else:
5024 ui.write(_(' (no revision checked out)'))
5024 ui.write(_(' (no revision checked out)'))
5025 if p.obsolete():
5025 if p.obsolete():
5026 ui.write(_(' (obsolete)'))
5026 ui.write(_(' (obsolete)'))
5027 if p.isunstable():
5027 if p.isunstable():
5028 instabilities = (ui.label(instability, 'trouble.%s' % instability)
5028 instabilities = (ui.label(instability, 'trouble.%s' % instability)
5029 for instability in p.instabilities())
5029 for instability in p.instabilities())
5030 ui.write(' ('
5030 ui.write(' ('
5031 + ', '.join(instabilities)
5031 + ', '.join(instabilities)
5032 + ')')
5032 + ')')
5033 ui.write('\n')
5033 ui.write('\n')
5034 if p.description():
5034 if p.description():
5035 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5035 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5036 label='log.summary')
5036 label='log.summary')
5037
5037
5038 branch = ctx.branch()
5038 branch = ctx.branch()
5039 bheads = repo.branchheads(branch)
5039 bheads = repo.branchheads(branch)
5040 # i18n: column positioning for "hg summary"
5040 # i18n: column positioning for "hg summary"
5041 m = _('branch: %s\n') % branch
5041 m = _('branch: %s\n') % branch
5042 if branch != 'default':
5042 if branch != 'default':
5043 ui.write(m, label='log.branch')
5043 ui.write(m, label='log.branch')
5044 else:
5044 else:
5045 ui.status(m, label='log.branch')
5045 ui.status(m, label='log.branch')
5046
5046
5047 if marks:
5047 if marks:
5048 active = repo._activebookmark
5048 active = repo._activebookmark
5049 # i18n: column positioning for "hg summary"
5049 # i18n: column positioning for "hg summary"
5050 ui.write(_('bookmarks:'), label='log.bookmark')
5050 ui.write(_('bookmarks:'), label='log.bookmark')
5051 if active is not None:
5051 if active is not None:
5052 if active in marks:
5052 if active in marks:
5053 ui.write(' *' + active, label=bookmarks.activebookmarklabel)
5053 ui.write(' *' + active, label=bookmarks.activebookmarklabel)
5054 marks.remove(active)
5054 marks.remove(active)
5055 else:
5055 else:
5056 ui.write(' [%s]' % active, label=bookmarks.activebookmarklabel)
5056 ui.write(' [%s]' % active, label=bookmarks.activebookmarklabel)
5057 for m in marks:
5057 for m in marks:
5058 ui.write(' ' + m, label='log.bookmark')
5058 ui.write(' ' + m, label='log.bookmark')
5059 ui.write('\n', label='log.bookmark')
5059 ui.write('\n', label='log.bookmark')
5060
5060
5061 status = repo.status(unknown=True)
5061 status = repo.status(unknown=True)
5062
5062
5063 c = repo.dirstate.copies()
5063 c = repo.dirstate.copies()
5064 copied, renamed = [], []
5064 copied, renamed = [], []
5065 for d, s in c.iteritems():
5065 for d, s in c.iteritems():
5066 if s in status.removed:
5066 if s in status.removed:
5067 status.removed.remove(s)
5067 status.removed.remove(s)
5068 renamed.append(d)
5068 renamed.append(d)
5069 else:
5069 else:
5070 copied.append(d)
5070 copied.append(d)
5071 if d in status.added:
5071 if d in status.added:
5072 status.added.remove(d)
5072 status.added.remove(d)
5073
5073
5074 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5074 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5075
5075
5076 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
5076 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
5077 (ui.label(_('%d added'), 'status.added'), status.added),
5077 (ui.label(_('%d added'), 'status.added'), status.added),
5078 (ui.label(_('%d removed'), 'status.removed'), status.removed),
5078 (ui.label(_('%d removed'), 'status.removed'), status.removed),
5079 (ui.label(_('%d renamed'), 'status.copied'), renamed),
5079 (ui.label(_('%d renamed'), 'status.copied'), renamed),
5080 (ui.label(_('%d copied'), 'status.copied'), copied),
5080 (ui.label(_('%d copied'), 'status.copied'), copied),
5081 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
5081 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
5082 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
5082 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
5083 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
5083 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
5084 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
5084 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
5085 t = []
5085 t = []
5086 for l, s in labels:
5086 for l, s in labels:
5087 if s:
5087 if s:
5088 t.append(l % len(s))
5088 t.append(l % len(s))
5089
5089
5090 t = ', '.join(t)
5090 t = ', '.join(t)
5091 cleanworkdir = False
5091 cleanworkdir = False
5092
5092
5093 if repo.vfs.exists('graftstate'):
5093 if repo.vfs.exists('graftstate'):
5094 t += _(' (graft in progress)')
5094 t += _(' (graft in progress)')
5095 if repo.vfs.exists('updatestate'):
5095 if repo.vfs.exists('updatestate'):
5096 t += _(' (interrupted update)')
5096 t += _(' (interrupted update)')
5097 elif len(parents) > 1:
5097 elif len(parents) > 1:
5098 t += _(' (merge)')
5098 t += _(' (merge)')
5099 elif branch != parents[0].branch():
5099 elif branch != parents[0].branch():
5100 t += _(' (new branch)')
5100 t += _(' (new branch)')
5101 elif (parents[0].closesbranch() and
5101 elif (parents[0].closesbranch() and
5102 pnode in repo.branchheads(branch, closed=True)):
5102 pnode in repo.branchheads(branch, closed=True)):
5103 t += _(' (head closed)')
5103 t += _(' (head closed)')
5104 elif not (status.modified or status.added or status.removed or renamed or
5104 elif not (status.modified or status.added or status.removed or renamed or
5105 copied or subs):
5105 copied or subs):
5106 t += _(' (clean)')
5106 t += _(' (clean)')
5107 cleanworkdir = True
5107 cleanworkdir = True
5108 elif pnode not in bheads:
5108 elif pnode not in bheads:
5109 t += _(' (new branch head)')
5109 t += _(' (new branch head)')
5110
5110
5111 if parents:
5111 if parents:
5112 pendingphase = max(p.phase() for p in parents)
5112 pendingphase = max(p.phase() for p in parents)
5113 else:
5113 else:
5114 pendingphase = phases.public
5114 pendingphase = phases.public
5115
5115
5116 if pendingphase > phases.newcommitphase(ui):
5116 if pendingphase > phases.newcommitphase(ui):
5117 t += ' (%s)' % phases.phasenames[pendingphase]
5117 t += ' (%s)' % phases.phasenames[pendingphase]
5118
5118
5119 if cleanworkdir:
5119 if cleanworkdir:
5120 # i18n: column positioning for "hg summary"
5120 # i18n: column positioning for "hg summary"
5121 ui.status(_('commit: %s\n') % t.strip())
5121 ui.status(_('commit: %s\n') % t.strip())
5122 else:
5122 else:
5123 # i18n: column positioning for "hg summary"
5123 # i18n: column positioning for "hg summary"
5124 ui.write(_('commit: %s\n') % t.strip())
5124 ui.write(_('commit: %s\n') % t.strip())
5125
5125
5126 # all ancestors of branch heads - all ancestors of parent = new csets
5126 # all ancestors of branch heads - all ancestors of parent = new csets
5127 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
5127 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
5128 bheads))
5128 bheads))
5129
5129
5130 if new == 0:
5130 if new == 0:
5131 # i18n: column positioning for "hg summary"
5131 # i18n: column positioning for "hg summary"
5132 ui.status(_('update: (current)\n'))
5132 ui.status(_('update: (current)\n'))
5133 elif pnode not in bheads:
5133 elif pnode not in bheads:
5134 # i18n: column positioning for "hg summary"
5134 # i18n: column positioning for "hg summary"
5135 ui.write(_('update: %d new changesets (update)\n') % new)
5135 ui.write(_('update: %d new changesets (update)\n') % new)
5136 else:
5136 else:
5137 # i18n: column positioning for "hg summary"
5137 # i18n: column positioning for "hg summary"
5138 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5138 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5139 (new, len(bheads)))
5139 (new, len(bheads)))
5140
5140
5141 t = []
5141 t = []
5142 draft = len(repo.revs('draft()'))
5142 draft = len(repo.revs('draft()'))
5143 if draft:
5143 if draft:
5144 t.append(_('%d draft') % draft)
5144 t.append(_('%d draft') % draft)
5145 secret = len(repo.revs('secret()'))
5145 secret = len(repo.revs('secret()'))
5146 if secret:
5146 if secret:
5147 t.append(_('%d secret') % secret)
5147 t.append(_('%d secret') % secret)
5148
5148
5149 if draft or secret:
5149 if draft or secret:
5150 ui.status(_('phases: %s\n') % ', '.join(t))
5150 ui.status(_('phases: %s\n') % ', '.join(t))
5151
5151
5152 if obsolete.isenabled(repo, obsolete.createmarkersopt):
5152 if obsolete.isenabled(repo, obsolete.createmarkersopt):
5153 for trouble in ("orphan", "contentdivergent", "phasedivergent"):
5153 for trouble in ("orphan", "contentdivergent", "phasedivergent"):
5154 numtrouble = len(repo.revs(trouble + "()"))
5154 numtrouble = len(repo.revs(trouble + "()"))
5155 # We write all the possibilities to ease translation
5155 # We write all the possibilities to ease translation
5156 troublemsg = {
5156 troublemsg = {
5157 "orphan": _("orphan: %d changesets"),
5157 "orphan": _("orphan: %d changesets"),
5158 "contentdivergent": _("content-divergent: %d changesets"),
5158 "contentdivergent": _("content-divergent: %d changesets"),
5159 "phasedivergent": _("phase-divergent: %d changesets"),
5159 "phasedivergent": _("phase-divergent: %d changesets"),
5160 }
5160 }
5161 if numtrouble > 0:
5161 if numtrouble > 0:
5162 ui.status(troublemsg[trouble] % numtrouble + "\n")
5162 ui.status(troublemsg[trouble] % numtrouble + "\n")
5163
5163
5164 cmdutil.summaryhooks(ui, repo)
5164 cmdutil.summaryhooks(ui, repo)
5165
5165
5166 if opts.get('remote'):
5166 if opts.get('remote'):
5167 needsincoming, needsoutgoing = True, True
5167 needsincoming, needsoutgoing = True, True
5168 else:
5168 else:
5169 needsincoming, needsoutgoing = False, False
5169 needsincoming, needsoutgoing = False, False
5170 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5170 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5171 if i:
5171 if i:
5172 needsincoming = True
5172 needsincoming = True
5173 if o:
5173 if o:
5174 needsoutgoing = True
5174 needsoutgoing = True
5175 if not needsincoming and not needsoutgoing:
5175 if not needsincoming and not needsoutgoing:
5176 return
5176 return
5177
5177
5178 def getincoming():
5178 def getincoming():
5179 source, branches = hg.parseurl(ui.expandpath('default'))
5179 source, branches = hg.parseurl(ui.expandpath('default'))
5180 sbranch = branches[0]
5180 sbranch = branches[0]
5181 try:
5181 try:
5182 other = hg.peer(repo, {}, source)
5182 other = hg.peer(repo, {}, source)
5183 except error.RepoError:
5183 except error.RepoError:
5184 if opts.get('remote'):
5184 if opts.get('remote'):
5185 raise
5185 raise
5186 return source, sbranch, None, None, None
5186 return source, sbranch, None, None, None
5187 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5187 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5188 if revs:
5188 if revs:
5189 revs = [other.lookup(rev) for rev in revs]
5189 revs = [other.lookup(rev) for rev in revs]
5190 ui.debug('comparing with %s\n' % util.hidepassword(source))
5190 ui.debug('comparing with %s\n' % util.hidepassword(source))
5191 repo.ui.pushbuffer()
5191 repo.ui.pushbuffer()
5192 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5192 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5193 repo.ui.popbuffer()
5193 repo.ui.popbuffer()
5194 return source, sbranch, other, commoninc, commoninc[1]
5194 return source, sbranch, other, commoninc, commoninc[1]
5195
5195
5196 if needsincoming:
5196 if needsincoming:
5197 source, sbranch, sother, commoninc, incoming = getincoming()
5197 source, sbranch, sother, commoninc, incoming = getincoming()
5198 else:
5198 else:
5199 source = sbranch = sother = commoninc = incoming = None
5199 source = sbranch = sother = commoninc = incoming = None
5200
5200
5201 def getoutgoing():
5201 def getoutgoing():
5202 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5202 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5203 dbranch = branches[0]
5203 dbranch = branches[0]
5204 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5204 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5205 if source != dest:
5205 if source != dest:
5206 try:
5206 try:
5207 dother = hg.peer(repo, {}, dest)
5207 dother = hg.peer(repo, {}, dest)
5208 except error.RepoError:
5208 except error.RepoError:
5209 if opts.get('remote'):
5209 if opts.get('remote'):
5210 raise
5210 raise
5211 return dest, dbranch, None, None
5211 return dest, dbranch, None, None
5212 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5212 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5213 elif sother is None:
5213 elif sother is None:
5214 # there is no explicit destination peer, but source one is invalid
5214 # there is no explicit destination peer, but source one is invalid
5215 return dest, dbranch, None, None
5215 return dest, dbranch, None, None
5216 else:
5216 else:
5217 dother = sother
5217 dother = sother
5218 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5218 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5219 common = None
5219 common = None
5220 else:
5220 else:
5221 common = commoninc
5221 common = commoninc
5222 if revs:
5222 if revs:
5223 revs = [repo.lookup(rev) for rev in revs]
5223 revs = [repo.lookup(rev) for rev in revs]
5224 repo.ui.pushbuffer()
5224 repo.ui.pushbuffer()
5225 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5225 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5226 commoninc=common)
5226 commoninc=common)
5227 repo.ui.popbuffer()
5227 repo.ui.popbuffer()
5228 return dest, dbranch, dother, outgoing
5228 return dest, dbranch, dother, outgoing
5229
5229
5230 if needsoutgoing:
5230 if needsoutgoing:
5231 dest, dbranch, dother, outgoing = getoutgoing()
5231 dest, dbranch, dother, outgoing = getoutgoing()
5232 else:
5232 else:
5233 dest = dbranch = dother = outgoing = None
5233 dest = dbranch = dother = outgoing = None
5234
5234
5235 if opts.get('remote'):
5235 if opts.get('remote'):
5236 t = []
5236 t = []
5237 if incoming:
5237 if incoming:
5238 t.append(_('1 or more incoming'))
5238 t.append(_('1 or more incoming'))
5239 o = outgoing.missing
5239 o = outgoing.missing
5240 if o:
5240 if o:
5241 t.append(_('%d outgoing') % len(o))
5241 t.append(_('%d outgoing') % len(o))
5242 other = dother or sother
5242 other = dother or sother
5243 if 'bookmarks' in other.listkeys('namespaces'):
5243 if 'bookmarks' in other.listkeys('namespaces'):
5244 counts = bookmarks.summary(repo, other)
5244 counts = bookmarks.summary(repo, other)
5245 if counts[0] > 0:
5245 if counts[0] > 0:
5246 t.append(_('%d incoming bookmarks') % counts[0])
5246 t.append(_('%d incoming bookmarks') % counts[0])
5247 if counts[1] > 0:
5247 if counts[1] > 0:
5248 t.append(_('%d outgoing bookmarks') % counts[1])
5248 t.append(_('%d outgoing bookmarks') % counts[1])
5249
5249
5250 if t:
5250 if t:
5251 # i18n: column positioning for "hg summary"
5251 # i18n: column positioning for "hg summary"
5252 ui.write(_('remote: %s\n') % (', '.join(t)))
5252 ui.write(_('remote: %s\n') % (', '.join(t)))
5253 else:
5253 else:
5254 # i18n: column positioning for "hg summary"
5254 # i18n: column positioning for "hg summary"
5255 ui.status(_('remote: (synced)\n'))
5255 ui.status(_('remote: (synced)\n'))
5256
5256
5257 cmdutil.summaryremotehooks(ui, repo, opts,
5257 cmdutil.summaryremotehooks(ui, repo, opts,
5258 ((source, sbranch, sother, commoninc),
5258 ((source, sbranch, sother, commoninc),
5259 (dest, dbranch, dother, outgoing)))
5259 (dest, dbranch, dother, outgoing)))
5260
5260
5261 @command('tag',
5261 @command('tag',
5262 [('f', 'force', None, _('force tag')),
5262 [('f', 'force', None, _('force tag')),
5263 ('l', 'local', None, _('make the tag local')),
5263 ('l', 'local', None, _('make the tag local')),
5264 ('r', 'rev', '', _('revision to tag'), _('REV')),
5264 ('r', 'rev', '', _('revision to tag'), _('REV')),
5265 ('', 'remove', None, _('remove a tag')),
5265 ('', 'remove', None, _('remove a tag')),
5266 # -l/--local is already there, commitopts cannot be used
5266 # -l/--local is already there, commitopts cannot be used
5267 ('e', 'edit', None, _('invoke editor on commit messages')),
5267 ('e', 'edit', None, _('invoke editor on commit messages')),
5268 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5268 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5269 ] + commitopts2,
5269 ] + commitopts2,
5270 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5270 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5271 def tag(ui, repo, name1, *names, **opts):
5271 def tag(ui, repo, name1, *names, **opts):
5272 """add one or more tags for the current or given revision
5272 """add one or more tags for the current or given revision
5273
5273
5274 Name a particular revision using <name>.
5274 Name a particular revision using <name>.
5275
5275
5276 Tags are used to name particular revisions of the repository and are
5276 Tags are used to name particular revisions of the repository and are
5277 very useful to compare different revisions, to go back to significant
5277 very useful to compare different revisions, to go back to significant
5278 earlier versions or to mark branch points as releases, etc. Changing
5278 earlier versions or to mark branch points as releases, etc. Changing
5279 an existing tag is normally disallowed; use -f/--force to override.
5279 an existing tag is normally disallowed; use -f/--force to override.
5280
5280
5281 If no revision is given, the parent of the working directory is
5281 If no revision is given, the parent of the working directory is
5282 used.
5282 used.
5283
5283
5284 To facilitate version control, distribution, and merging of tags,
5284 To facilitate version control, distribution, and merging of tags,
5285 they are stored as a file named ".hgtags" which is managed similarly
5285 they are stored as a file named ".hgtags" which is managed similarly
5286 to other project files and can be hand-edited if necessary. This
5286 to other project files and can be hand-edited if necessary. This
5287 also means that tagging creates a new commit. The file
5287 also means that tagging creates a new commit. The file
5288 ".hg/localtags" is used for local tags (not shared among
5288 ".hg/localtags" is used for local tags (not shared among
5289 repositories).
5289 repositories).
5290
5290
5291 Tag commits are usually made at the head of a branch. If the parent
5291 Tag commits are usually made at the head of a branch. If the parent
5292 of the working directory is not a branch head, :hg:`tag` aborts; use
5292 of the working directory is not a branch head, :hg:`tag` aborts; use
5293 -f/--force to force the tag commit to be based on a non-head
5293 -f/--force to force the tag commit to be based on a non-head
5294 changeset.
5294 changeset.
5295
5295
5296 See :hg:`help dates` for a list of formats valid for -d/--date.
5296 See :hg:`help dates` for a list of formats valid for -d/--date.
5297
5297
5298 Since tag names have priority over branch names during revision
5298 Since tag names have priority over branch names during revision
5299 lookup, using an existing branch name as a tag name is discouraged.
5299 lookup, using an existing branch name as a tag name is discouraged.
5300
5300
5301 Returns 0 on success.
5301 Returns 0 on success.
5302 """
5302 """
5303 opts = pycompat.byteskwargs(opts)
5303 opts = pycompat.byteskwargs(opts)
5304 wlock = lock = None
5304 wlock = lock = None
5305 try:
5305 try:
5306 wlock = repo.wlock()
5306 wlock = repo.wlock()
5307 lock = repo.lock()
5307 lock = repo.lock()
5308 rev_ = "."
5308 rev_ = "."
5309 names = [t.strip() for t in (name1,) + names]
5309 names = [t.strip() for t in (name1,) + names]
5310 if len(names) != len(set(names)):
5310 if len(names) != len(set(names)):
5311 raise error.Abort(_('tag names must be unique'))
5311 raise error.Abort(_('tag names must be unique'))
5312 for n in names:
5312 for n in names:
5313 scmutil.checknewlabel(repo, n, 'tag')
5313 scmutil.checknewlabel(repo, n, 'tag')
5314 if not n:
5314 if not n:
5315 raise error.Abort(_('tag names cannot consist entirely of '
5315 raise error.Abort(_('tag names cannot consist entirely of '
5316 'whitespace'))
5316 'whitespace'))
5317 if opts.get('rev') and opts.get('remove'):
5317 if opts.get('rev') and opts.get('remove'):
5318 raise error.Abort(_("--rev and --remove are incompatible"))
5318 raise error.Abort(_("--rev and --remove are incompatible"))
5319 if opts.get('rev'):
5319 if opts.get('rev'):
5320 rev_ = opts['rev']
5320 rev_ = opts['rev']
5321 message = opts.get('message')
5321 message = opts.get('message')
5322 if opts.get('remove'):
5322 if opts.get('remove'):
5323 if opts.get('local'):
5323 if opts.get('local'):
5324 expectedtype = 'local'
5324 expectedtype = 'local'
5325 else:
5325 else:
5326 expectedtype = 'global'
5326 expectedtype = 'global'
5327
5327
5328 for n in names:
5328 for n in names:
5329 if not repo.tagtype(n):
5329 if not repo.tagtype(n):
5330 raise error.Abort(_("tag '%s' does not exist") % n)
5330 raise error.Abort(_("tag '%s' does not exist") % n)
5331 if repo.tagtype(n) != expectedtype:
5331 if repo.tagtype(n) != expectedtype:
5332 if expectedtype == 'global':
5332 if expectedtype == 'global':
5333 raise error.Abort(_("tag '%s' is not a global tag") % n)
5333 raise error.Abort(_("tag '%s' is not a global tag") % n)
5334 else:
5334 else:
5335 raise error.Abort(_("tag '%s' is not a local tag") % n)
5335 raise error.Abort(_("tag '%s' is not a local tag") % n)
5336 rev_ = 'null'
5336 rev_ = 'null'
5337 if not message:
5337 if not message:
5338 # we don't translate commit messages
5338 # we don't translate commit messages
5339 message = 'Removed tag %s' % ', '.join(names)
5339 message = 'Removed tag %s' % ', '.join(names)
5340 elif not opts.get('force'):
5340 elif not opts.get('force'):
5341 for n in names:
5341 for n in names:
5342 if n in repo.tags():
5342 if n in repo.tags():
5343 raise error.Abort(_("tag '%s' already exists "
5343 raise error.Abort(_("tag '%s' already exists "
5344 "(use -f to force)") % n)
5344 "(use -f to force)") % n)
5345 if not opts.get('local'):
5345 if not opts.get('local'):
5346 p1, p2 = repo.dirstate.parents()
5346 p1, p2 = repo.dirstate.parents()
5347 if p2 != nullid:
5347 if p2 != nullid:
5348 raise error.Abort(_('uncommitted merge'))
5348 raise error.Abort(_('uncommitted merge'))
5349 bheads = repo.branchheads()
5349 bheads = repo.branchheads()
5350 if not opts.get('force') and bheads and p1 not in bheads:
5350 if not opts.get('force') and bheads and p1 not in bheads:
5351 raise error.Abort(_('working directory is not at a branch head '
5351 raise error.Abort(_('working directory is not at a branch head '
5352 '(use -f to force)'))
5352 '(use -f to force)'))
5353 node = scmutil.revsingle(repo, rev_).node()
5353 node = scmutil.revsingle(repo, rev_).node()
5354
5354
5355 if not message:
5355 if not message:
5356 # we don't translate commit messages
5356 # we don't translate commit messages
5357 message = ('Added tag %s for changeset %s' %
5357 message = ('Added tag %s for changeset %s' %
5358 (', '.join(names), short(node)))
5358 (', '.join(names), short(node)))
5359
5359
5360 date = opts.get('date')
5360 date = opts.get('date')
5361 if date:
5361 if date:
5362 date = dateutil.parsedate(date)
5362 date = dateutil.parsedate(date)
5363
5363
5364 if opts.get('remove'):
5364 if opts.get('remove'):
5365 editform = 'tag.remove'
5365 editform = 'tag.remove'
5366 else:
5366 else:
5367 editform = 'tag.add'
5367 editform = 'tag.add'
5368 editor = cmdutil.getcommiteditor(editform=editform,
5368 editor = cmdutil.getcommiteditor(editform=editform,
5369 **pycompat.strkwargs(opts))
5369 **pycompat.strkwargs(opts))
5370
5370
5371 # don't allow tagging the null rev
5371 # don't allow tagging the null rev
5372 if (not opts.get('remove') and
5372 if (not opts.get('remove') and
5373 scmutil.revsingle(repo, rev_).rev() == nullrev):
5373 scmutil.revsingle(repo, rev_).rev() == nullrev):
5374 raise error.Abort(_("cannot tag null revision"))
5374 raise error.Abort(_("cannot tag null revision"))
5375
5375
5376 tagsmod.tag(repo, names, node, message, opts.get('local'),
5376 tagsmod.tag(repo, names, node, message, opts.get('local'),
5377 opts.get('user'), date, editor=editor)
5377 opts.get('user'), date, editor=editor)
5378 finally:
5378 finally:
5379 release(lock, wlock)
5379 release(lock, wlock)
5380
5380
5381 @command('tags', formatteropts, '', intents={INTENT_READONLY})
5381 @command('tags', formatteropts, '', intents={INTENT_READONLY})
5382 def tags(ui, repo, **opts):
5382 def tags(ui, repo, **opts):
5383 """list repository tags
5383 """list repository tags
5384
5384
5385 This lists both regular and local tags. When the -v/--verbose
5385 This lists both regular and local tags. When the -v/--verbose
5386 switch is used, a third column "local" is printed for local tags.
5386 switch is used, a third column "local" is printed for local tags.
5387 When the -q/--quiet switch is used, only the tag name is printed.
5387 When the -q/--quiet switch is used, only the tag name is printed.
5388
5388
5389 Returns 0 on success.
5389 Returns 0 on success.
5390 """
5390 """
5391
5391
5392 opts = pycompat.byteskwargs(opts)
5392 opts = pycompat.byteskwargs(opts)
5393 ui.pager('tags')
5393 ui.pager('tags')
5394 fm = ui.formatter('tags', opts)
5394 fm = ui.formatter('tags', opts)
5395 hexfunc = fm.hexfunc
5395 hexfunc = fm.hexfunc
5396 tagtype = ""
5396 tagtype = ""
5397
5397
5398 for t, n in reversed(repo.tagslist()):
5398 for t, n in reversed(repo.tagslist()):
5399 hn = hexfunc(n)
5399 hn = hexfunc(n)
5400 label = 'tags.normal'
5400 label = 'tags.normal'
5401 tagtype = ''
5401 tagtype = ''
5402 if repo.tagtype(t) == 'local':
5402 if repo.tagtype(t) == 'local':
5403 label = 'tags.local'
5403 label = 'tags.local'
5404 tagtype = 'local'
5404 tagtype = 'local'
5405
5405
5406 fm.startitem()
5406 fm.startitem()
5407 fm.write('tag', '%s', t, label=label)
5407 fm.write('tag', '%s', t, label=label)
5408 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5408 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5409 fm.condwrite(not ui.quiet, 'rev node', fmt,
5409 fm.condwrite(not ui.quiet, 'rev node', fmt,
5410 repo.changelog.rev(n), hn, label=label)
5410 repo.changelog.rev(n), hn, label=label)
5411 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5411 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5412 tagtype, label=label)
5412 tagtype, label=label)
5413 fm.plain('\n')
5413 fm.plain('\n')
5414 fm.end()
5414 fm.end()
5415
5415
5416 @command('tip',
5416 @command('tip',
5417 [('p', 'patch', None, _('show patch')),
5417 [('p', 'patch', None, _('show patch')),
5418 ('g', 'git', None, _('use git extended diff format')),
5418 ('g', 'git', None, _('use git extended diff format')),
5419 ] + templateopts,
5419 ] + templateopts,
5420 _('[-p] [-g]'))
5420 _('[-p] [-g]'))
5421 def tip(ui, repo, **opts):
5421 def tip(ui, repo, **opts):
5422 """show the tip revision (DEPRECATED)
5422 """show the tip revision (DEPRECATED)
5423
5423
5424 The tip revision (usually just called the tip) is the changeset
5424 The tip revision (usually just called the tip) is the changeset
5425 most recently added to the repository (and therefore the most
5425 most recently added to the repository (and therefore the most
5426 recently changed head).
5426 recently changed head).
5427
5427
5428 If you have just made a commit, that commit will be the tip. If
5428 If you have just made a commit, that commit will be the tip. If
5429 you have just pulled changes from another repository, the tip of
5429 you have just pulled changes from another repository, the tip of
5430 that repository becomes the current tip. The "tip" tag is special
5430 that repository becomes the current tip. The "tip" tag is special
5431 and cannot be renamed or assigned to a different changeset.
5431 and cannot be renamed or assigned to a different changeset.
5432
5432
5433 This command is deprecated, please use :hg:`heads` instead.
5433 This command is deprecated, please use :hg:`heads` instead.
5434
5434
5435 Returns 0 on success.
5435 Returns 0 on success.
5436 """
5436 """
5437 opts = pycompat.byteskwargs(opts)
5437 opts = pycompat.byteskwargs(opts)
5438 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
5438 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
5439 displayer.show(repo['tip'])
5439 displayer.show(repo['tip'])
5440 displayer.close()
5440 displayer.close()
5441
5441
5442 @command('unbundle',
5442 @command('unbundle',
5443 [('u', 'update', None,
5443 [('u', 'update', None,
5444 _('update to new branch head if changesets were unbundled'))],
5444 _('update to new branch head if changesets were unbundled'))],
5445 _('[-u] FILE...'))
5445 _('[-u] FILE...'))
5446 def unbundle(ui, repo, fname1, *fnames, **opts):
5446 def unbundle(ui, repo, fname1, *fnames, **opts):
5447 """apply one or more bundle files
5447 """apply one or more bundle files
5448
5448
5449 Apply one or more bundle files generated by :hg:`bundle`.
5449 Apply one or more bundle files generated by :hg:`bundle`.
5450
5450
5451 Returns 0 on success, 1 if an update has unresolved files.
5451 Returns 0 on success, 1 if an update has unresolved files.
5452 """
5452 """
5453 fnames = (fname1,) + fnames
5453 fnames = (fname1,) + fnames
5454
5454
5455 with repo.lock():
5455 with repo.lock():
5456 for fname in fnames:
5456 for fname in fnames:
5457 f = hg.openpath(ui, fname)
5457 f = hg.openpath(ui, fname)
5458 gen = exchange.readbundle(ui, f, fname)
5458 gen = exchange.readbundle(ui, f, fname)
5459 if isinstance(gen, streamclone.streamcloneapplier):
5459 if isinstance(gen, streamclone.streamcloneapplier):
5460 raise error.Abort(
5460 raise error.Abort(
5461 _('packed bundles cannot be applied with '
5461 _('packed bundles cannot be applied with '
5462 '"hg unbundle"'),
5462 '"hg unbundle"'),
5463 hint=_('use "hg debugapplystreamclonebundle"'))
5463 hint=_('use "hg debugapplystreamclonebundle"'))
5464 url = 'bundle:' + fname
5464 url = 'bundle:' + fname
5465 try:
5465 try:
5466 txnname = 'unbundle'
5466 txnname = 'unbundle'
5467 if not isinstance(gen, bundle2.unbundle20):
5467 if not isinstance(gen, bundle2.unbundle20):
5468 txnname = 'unbundle\n%s' % util.hidepassword(url)
5468 txnname = 'unbundle\n%s' % util.hidepassword(url)
5469 with repo.transaction(txnname) as tr:
5469 with repo.transaction(txnname) as tr:
5470 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
5470 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
5471 url=url)
5471 url=url)
5472 except error.BundleUnknownFeatureError as exc:
5472 except error.BundleUnknownFeatureError as exc:
5473 raise error.Abort(
5473 raise error.Abort(
5474 _('%s: unknown bundle feature, %s') % (fname, exc),
5474 _('%s: unknown bundle feature, %s') % (fname, exc),
5475 hint=_("see https://mercurial-scm.org/"
5475 hint=_("see https://mercurial-scm.org/"
5476 "wiki/BundleFeature for more "
5476 "wiki/BundleFeature for more "
5477 "information"))
5477 "information"))
5478 modheads = bundle2.combinechangegroupresults(op)
5478 modheads = bundle2.combinechangegroupresults(op)
5479
5479
5480 return postincoming(ui, repo, modheads, opts.get(r'update'), None, None)
5480 return postincoming(ui, repo, modheads, opts.get(r'update'), None, None)
5481
5481
5482 @command('^update|up|checkout|co',
5482 @command('^update|up|checkout|co',
5483 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5483 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5484 ('c', 'check', None, _('require clean working directory')),
5484 ('c', 'check', None, _('require clean working directory')),
5485 ('m', 'merge', None, _('merge uncommitted changes')),
5485 ('m', 'merge', None, _('merge uncommitted changes')),
5486 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5486 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5487 ('r', 'rev', '', _('revision'), _('REV'))
5487 ('r', 'rev', '', _('revision'), _('REV'))
5488 ] + mergetoolopts,
5488 ] + mergetoolopts,
5489 _('[-C|-c|-m] [-d DATE] [[-r] REV]'))
5489 _('[-C|-c|-m] [-d DATE] [[-r] REV]'))
5490 def update(ui, repo, node=None, **opts):
5490 def update(ui, repo, node=None, **opts):
5491 """update working directory (or switch revisions)
5491 """update working directory (or switch revisions)
5492
5492
5493 Update the repository's working directory to the specified
5493 Update the repository's working directory to the specified
5494 changeset. If no changeset is specified, update to the tip of the
5494 changeset. If no changeset is specified, update to the tip of the
5495 current named branch and move the active bookmark (see :hg:`help
5495 current named branch and move the active bookmark (see :hg:`help
5496 bookmarks`).
5496 bookmarks`).
5497
5497
5498 Update sets the working directory's parent revision to the specified
5498 Update sets the working directory's parent revision to the specified
5499 changeset (see :hg:`help parents`).
5499 changeset (see :hg:`help parents`).
5500
5500
5501 If the changeset is not a descendant or ancestor of the working
5501 If the changeset is not a descendant or ancestor of the working
5502 directory's parent and there are uncommitted changes, the update is
5502 directory's parent and there are uncommitted changes, the update is
5503 aborted. With the -c/--check option, the working directory is checked
5503 aborted. With the -c/--check option, the working directory is checked
5504 for uncommitted changes; if none are found, the working directory is
5504 for uncommitted changes; if none are found, the working directory is
5505 updated to the specified changeset.
5505 updated to the specified changeset.
5506
5506
5507 .. container:: verbose
5507 .. container:: verbose
5508
5508
5509 The -C/--clean, -c/--check, and -m/--merge options control what
5509 The -C/--clean, -c/--check, and -m/--merge options control what
5510 happens if the working directory contains uncommitted changes.
5510 happens if the working directory contains uncommitted changes.
5511 At most of one of them can be specified.
5511 At most of one of them can be specified.
5512
5512
5513 1. If no option is specified, and if
5513 1. If no option is specified, and if
5514 the requested changeset is an ancestor or descendant of
5514 the requested changeset is an ancestor or descendant of
5515 the working directory's parent, the uncommitted changes
5515 the working directory's parent, the uncommitted changes
5516 are merged into the requested changeset and the merged
5516 are merged into the requested changeset and the merged
5517 result is left uncommitted. If the requested changeset is
5517 result is left uncommitted. If the requested changeset is
5518 not an ancestor or descendant (that is, it is on another
5518 not an ancestor or descendant (that is, it is on another
5519 branch), the update is aborted and the uncommitted changes
5519 branch), the update is aborted and the uncommitted changes
5520 are preserved.
5520 are preserved.
5521
5521
5522 2. With the -m/--merge option, the update is allowed even if the
5522 2. With the -m/--merge option, the update is allowed even if the
5523 requested changeset is not an ancestor or descendant of
5523 requested changeset is not an ancestor or descendant of
5524 the working directory's parent.
5524 the working directory's parent.
5525
5525
5526 3. With the -c/--check option, the update is aborted and the
5526 3. With the -c/--check option, the update is aborted and the
5527 uncommitted changes are preserved.
5527 uncommitted changes are preserved.
5528
5528
5529 4. With the -C/--clean option, uncommitted changes are discarded and
5529 4. With the -C/--clean option, uncommitted changes are discarded and
5530 the working directory is updated to the requested changeset.
5530 the working directory is updated to the requested changeset.
5531
5531
5532 To cancel an uncommitted merge (and lose your changes), use
5532 To cancel an uncommitted merge (and lose your changes), use
5533 :hg:`merge --abort`.
5533 :hg:`merge --abort`.
5534
5534
5535 Use null as the changeset to remove the working directory (like
5535 Use null as the changeset to remove the working directory (like
5536 :hg:`clone -U`).
5536 :hg:`clone -U`).
5537
5537
5538 If you want to revert just one file to an older revision, use
5538 If you want to revert just one file to an older revision, use
5539 :hg:`revert [-r REV] NAME`.
5539 :hg:`revert [-r REV] NAME`.
5540
5540
5541 See :hg:`help dates` for a list of formats valid for -d/--date.
5541 See :hg:`help dates` for a list of formats valid for -d/--date.
5542
5542
5543 Returns 0 on success, 1 if there are unresolved files.
5543 Returns 0 on success, 1 if there are unresolved files.
5544 """
5544 """
5545 rev = opts.get(r'rev')
5545 rev = opts.get(r'rev')
5546 date = opts.get(r'date')
5546 date = opts.get(r'date')
5547 clean = opts.get(r'clean')
5547 clean = opts.get(r'clean')
5548 check = opts.get(r'check')
5548 check = opts.get(r'check')
5549 merge = opts.get(r'merge')
5549 merge = opts.get(r'merge')
5550 if rev and node:
5550 if rev and node:
5551 raise error.Abort(_("please specify just one revision"))
5551 raise error.Abort(_("please specify just one revision"))
5552
5552
5553 if ui.configbool('commands', 'update.requiredest'):
5553 if ui.configbool('commands', 'update.requiredest'):
5554 if not node and not rev and not date:
5554 if not node and not rev and not date:
5555 raise error.Abort(_('you must specify a destination'),
5555 raise error.Abort(_('you must specify a destination'),
5556 hint=_('for example: hg update ".::"'))
5556 hint=_('for example: hg update ".::"'))
5557
5557
5558 if rev is None or rev == '':
5558 if rev is None or rev == '':
5559 rev = node
5559 rev = node
5560
5560
5561 if date and rev is not None:
5561 if date and rev is not None:
5562 raise error.Abort(_("you can't specify a revision and a date"))
5562 raise error.Abort(_("you can't specify a revision and a date"))
5563
5563
5564 if len([x for x in (clean, check, merge) if x]) > 1:
5564 if len([x for x in (clean, check, merge) if x]) > 1:
5565 raise error.Abort(_("can only specify one of -C/--clean, -c/--check, "
5565 raise error.Abort(_("can only specify one of -C/--clean, -c/--check, "
5566 "or -m/--merge"))
5566 "or -m/--merge"))
5567
5567
5568 updatecheck = None
5568 updatecheck = None
5569 if check:
5569 if check:
5570 updatecheck = 'abort'
5570 updatecheck = 'abort'
5571 elif merge:
5571 elif merge:
5572 updatecheck = 'none'
5572 updatecheck = 'none'
5573
5573
5574 with repo.wlock():
5574 with repo.wlock():
5575 cmdutil.clearunfinished(repo)
5575 cmdutil.clearunfinished(repo)
5576
5576
5577 if date:
5577 if date:
5578 rev = cmdutil.finddate(ui, repo, date)
5578 rev = cmdutil.finddate(ui, repo, date)
5579
5579
5580 # if we defined a bookmark, we have to remember the original name
5580 # if we defined a bookmark, we have to remember the original name
5581 brev = rev
5581 brev = rev
5582 if rev:
5582 if rev:
5583 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
5583 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
5584 ctx = scmutil.revsingle(repo, rev, rev)
5584 ctx = scmutil.revsingle(repo, rev, rev)
5585 rev = ctx.rev()
5585 rev = ctx.rev()
5586 if ctx.hidden():
5586 if ctx.hidden():
5587 ctxstr = ctx.hex()[:12]
5587 ctxstr = ctx.hex()[:12]
5588 ui.warn(_("updating to a hidden changeset %s\n") % ctxstr)
5588 ui.warn(_("updating to a hidden changeset %s\n") % ctxstr)
5589
5589
5590 if ctx.obsolete():
5590 if ctx.obsolete():
5591 obsfatemsg = obsutil._getfilteredreason(repo, ctxstr, ctx)
5591 obsfatemsg = obsutil._getfilteredreason(repo, ctxstr, ctx)
5592 ui.warn("(%s)\n" % obsfatemsg)
5592 ui.warn("(%s)\n" % obsfatemsg)
5593
5593
5594 repo.ui.setconfig('ui', 'forcemerge', opts.get(r'tool'), 'update')
5594 repo.ui.setconfig('ui', 'forcemerge', opts.get(r'tool'), 'update')
5595
5595
5596 return hg.updatetotally(ui, repo, rev, brev, clean=clean,
5596 return hg.updatetotally(ui, repo, rev, brev, clean=clean,
5597 updatecheck=updatecheck)
5597 updatecheck=updatecheck)
5598
5598
5599 @command('verify', [])
5599 @command('verify', [])
5600 def verify(ui, repo):
5600 def verify(ui, repo):
5601 """verify the integrity of the repository
5601 """verify the integrity of the repository
5602
5602
5603 Verify the integrity of the current repository.
5603 Verify the integrity of the current repository.
5604
5604
5605 This will perform an extensive check of the repository's
5605 This will perform an extensive check of the repository's
5606 integrity, validating the hashes and checksums of each entry in
5606 integrity, validating the hashes and checksums of each entry in
5607 the changelog, manifest, and tracked files, as well as the
5607 the changelog, manifest, and tracked files, as well as the
5608 integrity of their crosslinks and indices.
5608 integrity of their crosslinks and indices.
5609
5609
5610 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
5610 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
5611 for more information about recovery from corruption of the
5611 for more information about recovery from corruption of the
5612 repository.
5612 repository.
5613
5613
5614 Returns 0 on success, 1 if errors are encountered.
5614 Returns 0 on success, 1 if errors are encountered.
5615 """
5615 """
5616 return hg.verify(repo)
5616 return hg.verify(repo)
5617
5617
5618 @command('version', [] + formatteropts, norepo=True,
5618 @command('version', [] + formatteropts, norepo=True,
5619 intents={INTENT_READONLY})
5619 intents={INTENT_READONLY})
5620 def version_(ui, **opts):
5620 def version_(ui, **opts):
5621 """output version and copyright information"""
5621 """output version and copyright information"""
5622 opts = pycompat.byteskwargs(opts)
5622 opts = pycompat.byteskwargs(opts)
5623 if ui.verbose:
5623 if ui.verbose:
5624 ui.pager('version')
5624 ui.pager('version')
5625 fm = ui.formatter("version", opts)
5625 fm = ui.formatter("version", opts)
5626 fm.startitem()
5626 fm.startitem()
5627 fm.write("ver", _("Mercurial Distributed SCM (version %s)\n"),
5627 fm.write("ver", _("Mercurial Distributed SCM (version %s)\n"),
5628 util.version())
5628 util.version())
5629 license = _(
5629 license = _(
5630 "(see https://mercurial-scm.org for more information)\n"
5630 "(see https://mercurial-scm.org for more information)\n"
5631 "\nCopyright (C) 2005-2018 Matt Mackall and others\n"
5631 "\nCopyright (C) 2005-2018 Matt Mackall and others\n"
5632 "This is free software; see the source for copying conditions. "
5632 "This is free software; see the source for copying conditions. "
5633 "There is NO\nwarranty; "
5633 "There is NO\nwarranty; "
5634 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5634 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5635 )
5635 )
5636 if not ui.quiet:
5636 if not ui.quiet:
5637 fm.plain(license)
5637 fm.plain(license)
5638
5638
5639 if ui.verbose:
5639 if ui.verbose:
5640 fm.plain(_("\nEnabled extensions:\n\n"))
5640 fm.plain(_("\nEnabled extensions:\n\n"))
5641 # format names and versions into columns
5641 # format names and versions into columns
5642 names = []
5642 names = []
5643 vers = []
5643 vers = []
5644 isinternals = []
5644 isinternals = []
5645 for name, module in extensions.extensions():
5645 for name, module in extensions.extensions():
5646 names.append(name)
5646 names.append(name)
5647 vers.append(extensions.moduleversion(module) or None)
5647 vers.append(extensions.moduleversion(module) or None)
5648 isinternals.append(extensions.ismoduleinternal(module))
5648 isinternals.append(extensions.ismoduleinternal(module))
5649 fn = fm.nested("extensions", tmpl='{name}\n')
5649 fn = fm.nested("extensions", tmpl='{name}\n')
5650 if names:
5650 if names:
5651 namefmt = " %%-%ds " % max(len(n) for n in names)
5651 namefmt = " %%-%ds " % max(len(n) for n in names)
5652 places = [_("external"), _("internal")]
5652 places = [_("external"), _("internal")]
5653 for n, v, p in zip(names, vers, isinternals):
5653 for n, v, p in zip(names, vers, isinternals):
5654 fn.startitem()
5654 fn.startitem()
5655 fn.condwrite(ui.verbose, "name", namefmt, n)
5655 fn.condwrite(ui.verbose, "name", namefmt, n)
5656 if ui.verbose:
5656 if ui.verbose:
5657 fn.plain("%s " % places[p])
5657 fn.plain("%s " % places[p])
5658 fn.data(bundled=p)
5658 fn.data(bundled=p)
5659 fn.condwrite(ui.verbose and v, "ver", "%s", v)
5659 fn.condwrite(ui.verbose and v, "ver", "%s", v)
5660 if ui.verbose:
5660 if ui.verbose:
5661 fn.plain("\n")
5661 fn.plain("\n")
5662 fn.end()
5662 fn.end()
5663 fm.end()
5663 fm.end()
5664
5664
5665 def loadcmdtable(ui, name, cmdtable):
5665 def loadcmdtable(ui, name, cmdtable):
5666 """Load command functions from specified cmdtable
5666 """Load command functions from specified cmdtable
5667 """
5667 """
5668 overrides = [cmd for cmd in cmdtable if cmd in table]
5668 overrides = [cmd for cmd in cmdtable if cmd in table]
5669 if overrides:
5669 if overrides:
5670 ui.warn(_("extension '%s' overrides commands: %s\n")
5670 ui.warn(_("extension '%s' overrides commands: %s\n")
5671 % (name, " ".join(overrides)))
5671 % (name, " ".join(overrides)))
5672 table.update(cmdtable)
5672 table.update(cmdtable)
@@ -1,2634 +1,2637 b''
1 Log on empty repository: checking consistency
1 Log on empty repository: checking consistency
2
2
3 $ hg init empty
3 $ hg init empty
4 $ cd empty
4 $ cd empty
5 $ hg log
5 $ hg log
6 $ hg log -r 1
6 $ hg log -r 1
7 abort: unknown revision '1'!
7 abort: unknown revision '1'!
8 [255]
8 [255]
9 $ hg log -r -1:0
9 $ hg log -r -1:0
10 abort: unknown revision '-1'!
10 abort: unknown revision '-1'!
11 [255]
11 [255]
12 $ hg log -r 'branch(name)'
12 $ hg log -r 'branch(name)'
13 abort: unknown revision 'name'!
13 abort: unknown revision 'name'!
14 [255]
14 [255]
15 $ hg log -r null -q
15 $ hg log -r null -q
16 -1:000000000000
16 -1:000000000000
17
17
18 $ cd ..
18 $ cd ..
19
19
20 The g is crafted to have 2 filelog topological heads in a linear
20 The g is crafted to have 2 filelog topological heads in a linear
21 changeset graph
21 changeset graph
22
22
23 $ hg init a
23 $ hg init a
24 $ cd a
24 $ cd a
25 $ echo a > a
25 $ echo a > a
26 $ echo f > f
26 $ echo f > f
27 $ hg ci -Ama -d '1 0'
27 $ hg ci -Ama -d '1 0'
28 adding a
28 adding a
29 adding f
29 adding f
30
30
31 $ hg cp a b
31 $ hg cp a b
32 $ hg cp f g
32 $ hg cp f g
33 $ hg ci -mb -d '2 0'
33 $ hg ci -mb -d '2 0'
34
34
35 $ mkdir dir
35 $ mkdir dir
36 $ hg mv b dir
36 $ hg mv b dir
37 $ echo g >> g
37 $ echo g >> g
38 $ echo f >> f
38 $ echo f >> f
39 $ hg ci -mc -d '3 0'
39 $ hg ci -mc -d '3 0'
40
40
41 $ hg mv a b
41 $ hg mv a b
42 $ hg cp -f f g
42 $ hg cp -f f g
43 $ echo a > d
43 $ echo a > d
44 $ hg add d
44 $ hg add d
45 $ hg ci -md -d '4 0'
45 $ hg ci -md -d '4 0'
46
46
47 $ hg mv dir/b e
47 $ hg mv dir/b e
48 $ hg ci -me -d '5 0'
48 $ hg ci -me -d '5 0'
49
49
50 Make sure largefiles doesn't interfere with logging a regular file
50 Make sure largefiles doesn't interfere with logging a regular file
51 $ hg --debug log a -T '{rev}: {desc}\n' --config extensions.largefiles=
51 $ hg --debug log a -T '{rev}: {desc}\n' --config extensions.largefiles=
52 The fsmonitor extension is incompatible with the largefiles extension and has been disabled. (fsmonitor !)
52 The fsmonitor extension is incompatible with the largefiles extension and has been disabled. (fsmonitor !)
53 updated patterns: .hglf/a, a
53 updated patterns: .hglf/a, a
54 0: a
54 0: a
55 $ hg log a
55 $ hg log a
56 changeset: 0:9161b9aeaf16
56 changeset: 0:9161b9aeaf16
57 user: test
57 user: test
58 date: Thu Jan 01 00:00:01 1970 +0000
58 date: Thu Jan 01 00:00:01 1970 +0000
59 summary: a
59 summary: a
60
60
61 $ hg log glob:a*
61 $ hg log glob:a*
62 changeset: 3:2ca5ba701980
62 changeset: 3:2ca5ba701980
63 user: test
63 user: test
64 date: Thu Jan 01 00:00:04 1970 +0000
64 date: Thu Jan 01 00:00:04 1970 +0000
65 summary: d
65 summary: d
66
66
67 changeset: 0:9161b9aeaf16
67 changeset: 0:9161b9aeaf16
68 user: test
68 user: test
69 date: Thu Jan 01 00:00:01 1970 +0000
69 date: Thu Jan 01 00:00:01 1970 +0000
70 summary: a
70 summary: a
71
71
72 $ hg --debug log glob:a* -T '{rev}: {desc}\n' --config extensions.largefiles=
72 $ hg --debug log glob:a* -T '{rev}: {desc}\n' --config extensions.largefiles=
73 The fsmonitor extension is incompatible with the largefiles extension and has been disabled. (fsmonitor !)
73 The fsmonitor extension is incompatible with the largefiles extension and has been disabled. (fsmonitor !)
74 updated patterns: glob:.hglf/a*, glob:a*
74 updated patterns: glob:.hglf/a*, glob:a*
75 3: d
75 3: d
76 0: a
76 0: a
77
77
78 log on directory
78 log on directory
79
79
80 $ hg log dir
80 $ hg log dir
81 changeset: 4:7e4639b4691b
81 changeset: 4:7e4639b4691b
82 tag: tip
82 tag: tip
83 user: test
83 user: test
84 date: Thu Jan 01 00:00:05 1970 +0000
84 date: Thu Jan 01 00:00:05 1970 +0000
85 summary: e
85 summary: e
86
86
87 changeset: 2:f8954cd4dc1f
87 changeset: 2:f8954cd4dc1f
88 user: test
88 user: test
89 date: Thu Jan 01 00:00:03 1970 +0000
89 date: Thu Jan 01 00:00:03 1970 +0000
90 summary: c
90 summary: c
91
91
92 $ hg log somethingthatdoesntexist dir
92 $ hg log somethingthatdoesntexist dir
93 changeset: 4:7e4639b4691b
93 changeset: 4:7e4639b4691b
94 tag: tip
94 tag: tip
95 user: test
95 user: test
96 date: Thu Jan 01 00:00:05 1970 +0000
96 date: Thu Jan 01 00:00:05 1970 +0000
97 summary: e
97 summary: e
98
98
99 changeset: 2:f8954cd4dc1f
99 changeset: 2:f8954cd4dc1f
100 user: test
100 user: test
101 date: Thu Jan 01 00:00:03 1970 +0000
101 date: Thu Jan 01 00:00:03 1970 +0000
102 summary: c
102 summary: c
103
103
104
104
105 -X, with explicit path
105 -X, with explicit path
106
106
107 $ hg log a -X a
107 $ hg log a -X a
108
108
109 -f, non-existent directory
109 -f, non-existent directory
110
110
111 $ hg log -f dir
111 $ hg log -f dir
112 abort: cannot follow file not in parent revision: "dir"
112 abort: cannot follow file not in parent revision: "dir"
113 [255]
113 [255]
114
114
115 -f, directory
115 -f, directory
116
116
117 $ hg up -q 3
117 $ hg up -q 3
118 $ hg log -f dir
118 $ hg log -f dir
119 changeset: 2:f8954cd4dc1f
119 changeset: 2:f8954cd4dc1f
120 user: test
120 user: test
121 date: Thu Jan 01 00:00:03 1970 +0000
121 date: Thu Jan 01 00:00:03 1970 +0000
122 summary: c
122 summary: c
123
123
124 -f, directory with --patch
124 -f, directory with --patch
125
125
126 $ hg log -f dir -p
126 $ hg log -f dir -p
127 changeset: 2:f8954cd4dc1f
127 changeset: 2:f8954cd4dc1f
128 user: test
128 user: test
129 date: Thu Jan 01 00:00:03 1970 +0000
129 date: Thu Jan 01 00:00:03 1970 +0000
130 summary: c
130 summary: c
131
131
132 diff -r d89b0a12d229 -r f8954cd4dc1f dir/b
132 diff -r d89b0a12d229 -r f8954cd4dc1f dir/b
133 --- /dev/null* (glob)
133 --- /dev/null* (glob)
134 +++ b/dir/b* (glob)
134 +++ b/dir/b* (glob)
135 @@ -0,0 +1,1 @@
135 @@ -0,0 +1,1 @@
136 +a
136 +a
137
137
138
138
139 -f, pattern
139 -f, pattern
140
140
141 $ hg log -f -I 'dir**' -p
141 $ hg log -f -I 'dir**' -p
142 changeset: 2:f8954cd4dc1f
142 changeset: 2:f8954cd4dc1f
143 user: test
143 user: test
144 date: Thu Jan 01 00:00:03 1970 +0000
144 date: Thu Jan 01 00:00:03 1970 +0000
145 summary: c
145 summary: c
146
146
147 diff -r d89b0a12d229 -r f8954cd4dc1f dir/b
147 diff -r d89b0a12d229 -r f8954cd4dc1f dir/b
148 --- /dev/null* (glob)
148 --- /dev/null* (glob)
149 +++ b/dir/b* (glob)
149 +++ b/dir/b* (glob)
150 @@ -0,0 +1,1 @@
150 @@ -0,0 +1,1 @@
151 +a
151 +a
152
152
153 $ hg up -q 4
153 $ hg up -q 4
154
154
155 -f, a wrong style
155 -f, a wrong style
156
156
157 $ hg log -f -l1 --style something
157 $ hg log -f -l1 --style something
158 abort: style 'something' not found
158 abort: style 'something' not found
159 (available styles: bisect, changelog, compact, default, phases, show, status, xml)
159 (available styles: bisect, changelog, compact, default, phases, show, status, xml)
160 [255]
160 [255]
161
161
162 -f, phases style
162 -f, phases style
163
163
164
164
165 $ hg log -f -l1 --style phases
165 $ hg log -f -l1 --style phases
166 changeset: 4:7e4639b4691b
166 changeset: 4:7e4639b4691b
167 tag: tip
167 tag: tip
168 phase: draft
168 phase: draft
169 user: test
169 user: test
170 date: Thu Jan 01 00:00:05 1970 +0000
170 date: Thu Jan 01 00:00:05 1970 +0000
171 summary: e
171 summary: e
172
172
173
173
174 $ hg log -f -l1 --style phases -q
174 $ hg log -f -l1 --style phases -q
175 4:7e4639b4691b
175 4:7e4639b4691b
176
176
177 -f, but no args
177 -f, but no args
178
178
179 $ hg log -f
179 $ hg log -f
180 changeset: 4:7e4639b4691b
180 changeset: 4:7e4639b4691b
181 tag: tip
181 tag: tip
182 user: test
182 user: test
183 date: Thu Jan 01 00:00:05 1970 +0000
183 date: Thu Jan 01 00:00:05 1970 +0000
184 summary: e
184 summary: e
185
185
186 changeset: 3:2ca5ba701980
186 changeset: 3:2ca5ba701980
187 user: test
187 user: test
188 date: Thu Jan 01 00:00:04 1970 +0000
188 date: Thu Jan 01 00:00:04 1970 +0000
189 summary: d
189 summary: d
190
190
191 changeset: 2:f8954cd4dc1f
191 changeset: 2:f8954cd4dc1f
192 user: test
192 user: test
193 date: Thu Jan 01 00:00:03 1970 +0000
193 date: Thu Jan 01 00:00:03 1970 +0000
194 summary: c
194 summary: c
195
195
196 changeset: 1:d89b0a12d229
196 changeset: 1:d89b0a12d229
197 user: test
197 user: test
198 date: Thu Jan 01 00:00:02 1970 +0000
198 date: Thu Jan 01 00:00:02 1970 +0000
199 summary: b
199 summary: b
200
200
201 changeset: 0:9161b9aeaf16
201 changeset: 0:9161b9aeaf16
202 user: test
202 user: test
203 date: Thu Jan 01 00:00:01 1970 +0000
203 date: Thu Jan 01 00:00:01 1970 +0000
204 summary: a
204 summary: a
205
205
206
206
207 one rename
207 one rename
208
208
209 $ hg up -q 2
209 $ hg up -q 2
210 $ hg log -vf a
210 $ hg log -vf a
211 changeset: 0:9161b9aeaf16
211 changeset: 0:9161b9aeaf16
212 user: test
212 user: test
213 date: Thu Jan 01 00:00:01 1970 +0000
213 date: Thu Jan 01 00:00:01 1970 +0000
214 files: a f
214 files: a f
215 description:
215 description:
216 a
216 a
217
217
218
218
219
219
220 many renames
220 many renames
221
221
222 $ hg up -q tip
222 $ hg up -q tip
223 $ hg log -vf e
223 $ hg log -vf e
224 changeset: 4:7e4639b4691b
224 changeset: 4:7e4639b4691b
225 tag: tip
225 tag: tip
226 user: test
226 user: test
227 date: Thu Jan 01 00:00:05 1970 +0000
227 date: Thu Jan 01 00:00:05 1970 +0000
228 files: dir/b e
228 files: dir/b e
229 description:
229 description:
230 e
230 e
231
231
232
232
233 changeset: 2:f8954cd4dc1f
233 changeset: 2:f8954cd4dc1f
234 user: test
234 user: test
235 date: Thu Jan 01 00:00:03 1970 +0000
235 date: Thu Jan 01 00:00:03 1970 +0000
236 files: b dir/b f g
236 files: b dir/b f g
237 description:
237 description:
238 c
238 c
239
239
240
240
241 changeset: 1:d89b0a12d229
241 changeset: 1:d89b0a12d229
242 user: test
242 user: test
243 date: Thu Jan 01 00:00:02 1970 +0000
243 date: Thu Jan 01 00:00:02 1970 +0000
244 files: b g
244 files: b g
245 description:
245 description:
246 b
246 b
247
247
248
248
249 changeset: 0:9161b9aeaf16
249 changeset: 0:9161b9aeaf16
250 user: test
250 user: test
251 date: Thu Jan 01 00:00:01 1970 +0000
251 date: Thu Jan 01 00:00:01 1970 +0000
252 files: a f
252 files: a f
253 description:
253 description:
254 a
254 a
255
255
256
256
257
257
258
258
259 log -pf dir/b
259 log -pf dir/b
260
260
261 $ hg up -q 3
261 $ hg up -q 3
262 $ hg log -pf dir/b
262 $ hg log -pf dir/b
263 changeset: 2:f8954cd4dc1f
263 changeset: 2:f8954cd4dc1f
264 user: test
264 user: test
265 date: Thu Jan 01 00:00:03 1970 +0000
265 date: Thu Jan 01 00:00:03 1970 +0000
266 summary: c
266 summary: c
267
267
268 diff -r d89b0a12d229 -r f8954cd4dc1f dir/b
268 diff -r d89b0a12d229 -r f8954cd4dc1f dir/b
269 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
269 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
270 +++ b/dir/b Thu Jan 01 00:00:03 1970 +0000
270 +++ b/dir/b Thu Jan 01 00:00:03 1970 +0000
271 @@ -0,0 +1,1 @@
271 @@ -0,0 +1,1 @@
272 +a
272 +a
273
273
274 changeset: 1:d89b0a12d229
274 changeset: 1:d89b0a12d229
275 user: test
275 user: test
276 date: Thu Jan 01 00:00:02 1970 +0000
276 date: Thu Jan 01 00:00:02 1970 +0000
277 summary: b
277 summary: b
278
278
279 diff -r 9161b9aeaf16 -r d89b0a12d229 b
279 diff -r 9161b9aeaf16 -r d89b0a12d229 b
280 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
280 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
281 +++ b/b Thu Jan 01 00:00:02 1970 +0000
281 +++ b/b Thu Jan 01 00:00:02 1970 +0000
282 @@ -0,0 +1,1 @@
282 @@ -0,0 +1,1 @@
283 +a
283 +a
284
284
285 changeset: 0:9161b9aeaf16
285 changeset: 0:9161b9aeaf16
286 user: test
286 user: test
287 date: Thu Jan 01 00:00:01 1970 +0000
287 date: Thu Jan 01 00:00:01 1970 +0000
288 summary: a
288 summary: a
289
289
290 diff -r 000000000000 -r 9161b9aeaf16 a
290 diff -r 000000000000 -r 9161b9aeaf16 a
291 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
291 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
292 +++ b/a Thu Jan 01 00:00:01 1970 +0000
292 +++ b/a Thu Jan 01 00:00:01 1970 +0000
293 @@ -0,0 +1,1 @@
293 @@ -0,0 +1,1 @@
294 +a
294 +a
295
295
296
296
297 log -pf b inside dir
297 log -pf b inside dir
298
298
299 $ hg --cwd=dir log -pf b
299 $ hg --cwd=dir log -pf b
300 changeset: 2:f8954cd4dc1f
300 changeset: 2:f8954cd4dc1f
301 user: test
301 user: test
302 date: Thu Jan 01 00:00:03 1970 +0000
302 date: Thu Jan 01 00:00:03 1970 +0000
303 summary: c
303 summary: c
304
304
305 diff -r d89b0a12d229 -r f8954cd4dc1f dir/b
305 diff -r d89b0a12d229 -r f8954cd4dc1f dir/b
306 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
306 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
307 +++ b/dir/b Thu Jan 01 00:00:03 1970 +0000
307 +++ b/dir/b Thu Jan 01 00:00:03 1970 +0000
308 @@ -0,0 +1,1 @@
308 @@ -0,0 +1,1 @@
309 +a
309 +a
310
310
311 changeset: 1:d89b0a12d229
311 changeset: 1:d89b0a12d229
312 user: test
312 user: test
313 date: Thu Jan 01 00:00:02 1970 +0000
313 date: Thu Jan 01 00:00:02 1970 +0000
314 summary: b
314 summary: b
315
315
316 diff -r 9161b9aeaf16 -r d89b0a12d229 b
316 diff -r 9161b9aeaf16 -r d89b0a12d229 b
317 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
317 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
318 +++ b/b Thu Jan 01 00:00:02 1970 +0000
318 +++ b/b Thu Jan 01 00:00:02 1970 +0000
319 @@ -0,0 +1,1 @@
319 @@ -0,0 +1,1 @@
320 +a
320 +a
321
321
322 changeset: 0:9161b9aeaf16
322 changeset: 0:9161b9aeaf16
323 user: test
323 user: test
324 date: Thu Jan 01 00:00:01 1970 +0000
324 date: Thu Jan 01 00:00:01 1970 +0000
325 summary: a
325 summary: a
326
326
327 diff -r 000000000000 -r 9161b9aeaf16 a
327 diff -r 000000000000 -r 9161b9aeaf16 a
328 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
328 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
329 +++ b/a Thu Jan 01 00:00:01 1970 +0000
329 +++ b/a Thu Jan 01 00:00:01 1970 +0000
330 @@ -0,0 +1,1 @@
330 @@ -0,0 +1,1 @@
331 +a
331 +a
332
332
333
333
334 log -pf, but no args
334 log -pf, but no args
335
335
336 $ hg log -pf
336 $ hg log -pf
337 changeset: 3:2ca5ba701980
337 changeset: 3:2ca5ba701980
338 user: test
338 user: test
339 date: Thu Jan 01 00:00:04 1970 +0000
339 date: Thu Jan 01 00:00:04 1970 +0000
340 summary: d
340 summary: d
341
341
342 diff -r f8954cd4dc1f -r 2ca5ba701980 a
342 diff -r f8954cd4dc1f -r 2ca5ba701980 a
343 --- a/a Thu Jan 01 00:00:03 1970 +0000
343 --- a/a Thu Jan 01 00:00:03 1970 +0000
344 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
344 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
345 @@ -1,1 +0,0 @@
345 @@ -1,1 +0,0 @@
346 -a
346 -a
347 diff -r f8954cd4dc1f -r 2ca5ba701980 b
347 diff -r f8954cd4dc1f -r 2ca5ba701980 b
348 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
348 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
349 +++ b/b Thu Jan 01 00:00:04 1970 +0000
349 +++ b/b Thu Jan 01 00:00:04 1970 +0000
350 @@ -0,0 +1,1 @@
350 @@ -0,0 +1,1 @@
351 +a
351 +a
352 diff -r f8954cd4dc1f -r 2ca5ba701980 d
352 diff -r f8954cd4dc1f -r 2ca5ba701980 d
353 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
353 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
354 +++ b/d Thu Jan 01 00:00:04 1970 +0000
354 +++ b/d Thu Jan 01 00:00:04 1970 +0000
355 @@ -0,0 +1,1 @@
355 @@ -0,0 +1,1 @@
356 +a
356 +a
357 diff -r f8954cd4dc1f -r 2ca5ba701980 g
357 diff -r f8954cd4dc1f -r 2ca5ba701980 g
358 --- a/g Thu Jan 01 00:00:03 1970 +0000
358 --- a/g Thu Jan 01 00:00:03 1970 +0000
359 +++ b/g Thu Jan 01 00:00:04 1970 +0000
359 +++ b/g Thu Jan 01 00:00:04 1970 +0000
360 @@ -1,2 +1,2 @@
360 @@ -1,2 +1,2 @@
361 f
361 f
362 -g
362 -g
363 +f
363 +f
364
364
365 changeset: 2:f8954cd4dc1f
365 changeset: 2:f8954cd4dc1f
366 user: test
366 user: test
367 date: Thu Jan 01 00:00:03 1970 +0000
367 date: Thu Jan 01 00:00:03 1970 +0000
368 summary: c
368 summary: c
369
369
370 diff -r d89b0a12d229 -r f8954cd4dc1f b
370 diff -r d89b0a12d229 -r f8954cd4dc1f b
371 --- a/b Thu Jan 01 00:00:02 1970 +0000
371 --- a/b Thu Jan 01 00:00:02 1970 +0000
372 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
372 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
373 @@ -1,1 +0,0 @@
373 @@ -1,1 +0,0 @@
374 -a
374 -a
375 diff -r d89b0a12d229 -r f8954cd4dc1f dir/b
375 diff -r d89b0a12d229 -r f8954cd4dc1f dir/b
376 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
376 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
377 +++ b/dir/b Thu Jan 01 00:00:03 1970 +0000
377 +++ b/dir/b Thu Jan 01 00:00:03 1970 +0000
378 @@ -0,0 +1,1 @@
378 @@ -0,0 +1,1 @@
379 +a
379 +a
380 diff -r d89b0a12d229 -r f8954cd4dc1f f
380 diff -r d89b0a12d229 -r f8954cd4dc1f f
381 --- a/f Thu Jan 01 00:00:02 1970 +0000
381 --- a/f Thu Jan 01 00:00:02 1970 +0000
382 +++ b/f Thu Jan 01 00:00:03 1970 +0000
382 +++ b/f Thu Jan 01 00:00:03 1970 +0000
383 @@ -1,1 +1,2 @@
383 @@ -1,1 +1,2 @@
384 f
384 f
385 +f
385 +f
386 diff -r d89b0a12d229 -r f8954cd4dc1f g
386 diff -r d89b0a12d229 -r f8954cd4dc1f g
387 --- a/g Thu Jan 01 00:00:02 1970 +0000
387 --- a/g Thu Jan 01 00:00:02 1970 +0000
388 +++ b/g Thu Jan 01 00:00:03 1970 +0000
388 +++ b/g Thu Jan 01 00:00:03 1970 +0000
389 @@ -1,1 +1,2 @@
389 @@ -1,1 +1,2 @@
390 f
390 f
391 +g
391 +g
392
392
393 changeset: 1:d89b0a12d229
393 changeset: 1:d89b0a12d229
394 user: test
394 user: test
395 date: Thu Jan 01 00:00:02 1970 +0000
395 date: Thu Jan 01 00:00:02 1970 +0000
396 summary: b
396 summary: b
397
397
398 diff -r 9161b9aeaf16 -r d89b0a12d229 b
398 diff -r 9161b9aeaf16 -r d89b0a12d229 b
399 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
399 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
400 +++ b/b Thu Jan 01 00:00:02 1970 +0000
400 +++ b/b Thu Jan 01 00:00:02 1970 +0000
401 @@ -0,0 +1,1 @@
401 @@ -0,0 +1,1 @@
402 +a
402 +a
403 diff -r 9161b9aeaf16 -r d89b0a12d229 g
403 diff -r 9161b9aeaf16 -r d89b0a12d229 g
404 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
404 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
405 +++ b/g Thu Jan 01 00:00:02 1970 +0000
405 +++ b/g Thu Jan 01 00:00:02 1970 +0000
406 @@ -0,0 +1,1 @@
406 @@ -0,0 +1,1 @@
407 +f
407 +f
408
408
409 changeset: 0:9161b9aeaf16
409 changeset: 0:9161b9aeaf16
410 user: test
410 user: test
411 date: Thu Jan 01 00:00:01 1970 +0000
411 date: Thu Jan 01 00:00:01 1970 +0000
412 summary: a
412 summary: a
413
413
414 diff -r 000000000000 -r 9161b9aeaf16 a
414 diff -r 000000000000 -r 9161b9aeaf16 a
415 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
415 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
416 +++ b/a Thu Jan 01 00:00:01 1970 +0000
416 +++ b/a Thu Jan 01 00:00:01 1970 +0000
417 @@ -0,0 +1,1 @@
417 @@ -0,0 +1,1 @@
418 +a
418 +a
419 diff -r 000000000000 -r 9161b9aeaf16 f
419 diff -r 000000000000 -r 9161b9aeaf16 f
420 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
420 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
421 +++ b/f Thu Jan 01 00:00:01 1970 +0000
421 +++ b/f Thu Jan 01 00:00:01 1970 +0000
422 @@ -0,0 +1,1 @@
422 @@ -0,0 +1,1 @@
423 +f
423 +f
424
424
425
425
426 log -vf dir/b
426 log -vf dir/b
427
427
428 $ hg log -vf dir/b
428 $ hg log -vf dir/b
429 changeset: 2:f8954cd4dc1f
429 changeset: 2:f8954cd4dc1f
430 user: test
430 user: test
431 date: Thu Jan 01 00:00:03 1970 +0000
431 date: Thu Jan 01 00:00:03 1970 +0000
432 files: b dir/b f g
432 files: b dir/b f g
433 description:
433 description:
434 c
434 c
435
435
436
436
437 changeset: 1:d89b0a12d229
437 changeset: 1:d89b0a12d229
438 user: test
438 user: test
439 date: Thu Jan 01 00:00:02 1970 +0000
439 date: Thu Jan 01 00:00:02 1970 +0000
440 files: b g
440 files: b g
441 description:
441 description:
442 b
442 b
443
443
444
444
445 changeset: 0:9161b9aeaf16
445 changeset: 0:9161b9aeaf16
446 user: test
446 user: test
447 date: Thu Jan 01 00:00:01 1970 +0000
447 date: Thu Jan 01 00:00:01 1970 +0000
448 files: a f
448 files: a f
449 description:
449 description:
450 a
450 a
451
451
452
452
453
453
454
454
455 -f and multiple filelog heads
455 -f and multiple filelog heads
456
456
457 $ hg up -q 2
457 $ hg up -q 2
458 $ hg log -f g --template '{rev}\n'
458 $ hg log -f g --template '{rev}\n'
459 2
459 2
460 1
460 1
461 0
461 0
462 $ hg up -q tip
462 $ hg up -q tip
463 $ hg log -f g --template '{rev}\n'
463 $ hg log -f g --template '{rev}\n'
464 3
464 3
465 2
465 2
466 0
466 0
467
467
468 follow files from the specified revisions (issue4959)
468 follow files from the specified revisions (issue4959)
469
469
470 $ hg log -G -T '{rev} {files},{file_copies % " {source}->{name}"}\n'
470 $ hg log -G -T '{rev} {files},{file_copies % " {source}->{name}"}\n'
471 @ 4 dir/b e, dir/b->e
471 @ 4 dir/b e, dir/b->e
472 |
472 |
473 o 3 a b d g, a->b f->g
473 o 3 a b d g, a->b f->g
474 |
474 |
475 o 2 b dir/b f g, b->dir/b
475 o 2 b dir/b f g, b->dir/b
476 |
476 |
477 o 1 b g, a->b f->g
477 o 1 b g, a->b f->g
478 |
478 |
479 o 0 a f,
479 o 0 a f,
480
480
481
481
482 $ hg log -T '{rev}\n' -fr 4 e
482 $ hg log -T '{rev}\n' -fr 4 e
483 4
483 4
484 2
484 2
485 1
485 1
486 0
486 0
487 $ hg log -T '{rev}\n' -fr 2 g
487 $ hg log -T '{rev}\n' -fr 2 g
488 2
488 2
489 1
489 1
490 0
490 0
491 $ hg log -T '{rev}\n' -fr '2+3' g
491 $ hg log -T '{rev}\n' -fr '2+3' g
492 3
492 3
493 2
493 2
494 1
494 1
495 0
495 0
496
496
497 follow files from the specified revisions with glob patterns (issue5053)
497 follow files from the specified revisions with glob patterns (issue5053)
498 (BROKEN: should follow copies from e@4)
498 (BROKEN: should follow copies from e@4)
499
499
500 $ hg log -T '{rev}\n' -fr4 e -X '[abcdfg]'
500 $ hg log -T '{rev}\n' -fr4 e -X '[abcdfg]'
501 4
501 4
502 2 (false !)
502 2 (false !)
503 1 (false !)
503 1 (false !)
504 0 (false !)
504 0 (false !)
505
505
506 follow files from the specified revisions with missing patterns
506 follow files from the specified revisions with missing patterns
507 (BROKEN: should follow copies from e@4)
507 (BROKEN: should follow copies from e@4)
508
508
509 $ hg log -T '{rev}\n' -fr4 e x
509 $ hg log -T '{rev}\n' -fr4 e x
510 4
510 4
511 2 (false !)
511 2 (false !)
512 1 (false !)
512 1 (false !)
513 0 (false !)
513 0 (false !)
514
514
515 follow files from the specified revisions across copies with -p/--patch
515 follow files from the specified revisions across copies with -p/--patch
516
516
517 $ hg log -T '== rev: {rev},{file_copies % " {source}->{name}"} ==\n' -fpr 4 e g
517 $ hg log -T '== rev: {rev},{file_copies % " {source}->{name}"} ==\n' -fpr 4 e g
518 == rev: 4, dir/b->e ==
518 == rev: 4, dir/b->e ==
519 diff -r 2ca5ba701980 -r 7e4639b4691b e
519 diff -r 2ca5ba701980 -r 7e4639b4691b e
520 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
520 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
521 +++ b/e Thu Jan 01 00:00:05 1970 +0000
521 +++ b/e Thu Jan 01 00:00:05 1970 +0000
522 @@ -0,0 +1,1 @@
522 @@ -0,0 +1,1 @@
523 +a
523 +a
524
524
525 == rev: 3, a->b f->g ==
525 == rev: 3, a->b f->g ==
526 diff -r f8954cd4dc1f -r 2ca5ba701980 g
526 diff -r f8954cd4dc1f -r 2ca5ba701980 g
527 --- a/g Thu Jan 01 00:00:03 1970 +0000
527 --- a/g Thu Jan 01 00:00:03 1970 +0000
528 +++ b/g Thu Jan 01 00:00:04 1970 +0000
528 +++ b/g Thu Jan 01 00:00:04 1970 +0000
529 @@ -1,2 +1,2 @@
529 @@ -1,2 +1,2 @@
530 f
530 f
531 -g
531 -g
532 +f
532 +f
533
533
534 == rev: 2, b->dir/b ==
534 == rev: 2, b->dir/b ==
535 diff -r d89b0a12d229 -r f8954cd4dc1f dir/b
535 diff -r d89b0a12d229 -r f8954cd4dc1f dir/b
536 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
536 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
537 +++ b/dir/b Thu Jan 01 00:00:03 1970 +0000
537 +++ b/dir/b Thu Jan 01 00:00:03 1970 +0000
538 @@ -0,0 +1,1 @@
538 @@ -0,0 +1,1 @@
539 +a
539 +a
540 diff -r d89b0a12d229 -r f8954cd4dc1f f
540 diff -r d89b0a12d229 -r f8954cd4dc1f f
541 --- a/f Thu Jan 01 00:00:02 1970 +0000
541 --- a/f Thu Jan 01 00:00:02 1970 +0000
542 +++ b/f Thu Jan 01 00:00:03 1970 +0000
542 +++ b/f Thu Jan 01 00:00:03 1970 +0000
543 @@ -1,1 +1,2 @@
543 @@ -1,1 +1,2 @@
544 f
544 f
545 +f
545 +f
546
546
547 == rev: 1, a->b f->g ==
547 == rev: 1, a->b f->g ==
548 diff -r 9161b9aeaf16 -r d89b0a12d229 b
548 diff -r 9161b9aeaf16 -r d89b0a12d229 b
549 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
549 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
550 +++ b/b Thu Jan 01 00:00:02 1970 +0000
550 +++ b/b Thu Jan 01 00:00:02 1970 +0000
551 @@ -0,0 +1,1 @@
551 @@ -0,0 +1,1 @@
552 +a
552 +a
553
553
554 == rev: 0, ==
554 == rev: 0, ==
555 diff -r 000000000000 -r 9161b9aeaf16 a
555 diff -r 000000000000 -r 9161b9aeaf16 a
556 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
556 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
557 +++ b/a Thu Jan 01 00:00:01 1970 +0000
557 +++ b/a Thu Jan 01 00:00:01 1970 +0000
558 @@ -0,0 +1,1 @@
558 @@ -0,0 +1,1 @@
559 +a
559 +a
560 diff -r 000000000000 -r 9161b9aeaf16 f
560 diff -r 000000000000 -r 9161b9aeaf16 f
561 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
561 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
562 +++ b/f Thu Jan 01 00:00:01 1970 +0000
562 +++ b/f Thu Jan 01 00:00:01 1970 +0000
563 @@ -0,0 +1,1 @@
563 @@ -0,0 +1,1 @@
564 +f
564 +f
565
565
566
566
567 log copies with --copies
567 log copies with --copies
568
568
569 $ hg log -vC --template '{rev} {file_copies}\n'
569 $ hg log -vC --template '{rev} {file_copies}\n'
570 4 e (dir/b)
570 4 e (dir/b)
571 3 b (a)g (f)
571 3 b (a)g (f)
572 2 dir/b (b)
572 2 dir/b (b)
573 1 b (a)g (f)
573 1 b (a)g (f)
574 0
574 0
575
575
576 log copies switch without --copies, with old filecopy template
576 log copies switch without --copies, with old filecopy template
577
577
578 $ hg log -v --template '{rev} {file_copies_switch%filecopy}\n'
578 $ hg log -v --template '{rev} {file_copies_switch%filecopy}\n'
579 4
579 4
580 3
580 3
581 2
581 2
582 1
582 1
583 0
583 0
584
584
585 log copies switch with --copies
585 log copies switch with --copies
586
586
587 $ hg log -vC --template '{rev} {file_copies_switch}\n'
587 $ hg log -vC --template '{rev} {file_copies_switch}\n'
588 4 e (dir/b)
588 4 e (dir/b)
589 3 b (a)g (f)
589 3 b (a)g (f)
590 2 dir/b (b)
590 2 dir/b (b)
591 1 b (a)g (f)
591 1 b (a)g (f)
592 0
592 0
593
593
594
594
595 log copies with hardcoded style and with --style=default
595 log copies with hardcoded style and with --style=default
596
596
597 $ hg log -vC -r4
597 $ hg log -vC -r4
598 changeset: 4:7e4639b4691b
598 changeset: 4:7e4639b4691b
599 tag: tip
599 tag: tip
600 user: test
600 user: test
601 date: Thu Jan 01 00:00:05 1970 +0000
601 date: Thu Jan 01 00:00:05 1970 +0000
602 files: dir/b e
602 files: dir/b e
603 copies: e (dir/b)
603 copies: e (dir/b)
604 description:
604 description:
605 e
605 e
606
606
607
607
608 $ hg log -vC -r4 --style=default
608 $ hg log -vC -r4 --style=default
609 changeset: 4:7e4639b4691b
609 changeset: 4:7e4639b4691b
610 tag: tip
610 tag: tip
611 user: test
611 user: test
612 date: Thu Jan 01 00:00:05 1970 +0000
612 date: Thu Jan 01 00:00:05 1970 +0000
613 files: dir/b e
613 files: dir/b e
614 copies: e (dir/b)
614 copies: e (dir/b)
615 description:
615 description:
616 e
616 e
617
617
618
618
619 $ hg log -vC -r4 -Tjson
619 $ hg log -vC -r4 -Tjson
620 [
620 [
621 {
621 {
622 "bookmarks": [],
622 "bookmarks": [],
623 "branch": "default",
623 "branch": "default",
624 "copies": {"e": "dir/b"},
624 "copies": {"e": "dir/b"},
625 "date": [5, 0],
625 "date": [5, 0],
626 "desc": "e",
626 "desc": "e",
627 "files": ["dir/b", "e"],
627 "files": ["dir/b", "e"],
628 "node": "7e4639b4691b9f84b81036a8d4fb218ce3c5e3a3",
628 "node": "7e4639b4691b9f84b81036a8d4fb218ce3c5e3a3",
629 "parents": ["2ca5ba7019804f1f597249caddf22a64d34df0ba"],
629 "parents": ["2ca5ba7019804f1f597249caddf22a64d34df0ba"],
630 "phase": "draft",
630 "phase": "draft",
631 "rev": 4,
631 "rev": 4,
632 "tags": ["tip"],
632 "tags": ["tip"],
633 "user": "test"
633 "user": "test"
634 }
634 }
635 ]
635 ]
636
636
637 log copies, non-linear manifest
637 log copies, non-linear manifest
638
638
639 $ hg up -C 3
639 $ hg up -C 3
640 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
640 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
641 $ hg mv dir/b e
641 $ hg mv dir/b e
642 $ echo foo > foo
642 $ echo foo > foo
643 $ hg ci -Ame2 -d '6 0'
643 $ hg ci -Ame2 -d '6 0'
644 adding foo
644 adding foo
645 created new head
645 created new head
646 $ hg log -v --template '{rev} {file_copies}\n' -r 5
646 $ hg log -v --template '{rev} {file_copies}\n' -r 5
647 5 e (dir/b)
647 5 e (dir/b)
648
648
649
649
650 log copies, execute bit set
650 log copies, execute bit set
651
651
652 #if execbit
652 #if execbit
653 $ chmod +x e
653 $ chmod +x e
654 $ hg ci -me3 -d '7 0'
654 $ hg ci -me3 -d '7 0'
655 $ hg log -v --template '{rev} {file_copies}\n' -r 6
655 $ hg log -v --template '{rev} {file_copies}\n' -r 6
656 6
656 6
657 #endif
657 #endif
658
658
659 log copies, empty set
660
661 $ hg log --copies -r '0 and not 0'
659
662
660 log -p d
663 log -p d
661
664
662 $ hg log -pv d
665 $ hg log -pv d
663 changeset: 3:2ca5ba701980
666 changeset: 3:2ca5ba701980
664 user: test
667 user: test
665 date: Thu Jan 01 00:00:04 1970 +0000
668 date: Thu Jan 01 00:00:04 1970 +0000
666 files: a b d g
669 files: a b d g
667 description:
670 description:
668 d
671 d
669
672
670
673
671 diff -r f8954cd4dc1f -r 2ca5ba701980 d
674 diff -r f8954cd4dc1f -r 2ca5ba701980 d
672 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
675 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
673 +++ b/d Thu Jan 01 00:00:04 1970 +0000
676 +++ b/d Thu Jan 01 00:00:04 1970 +0000
674 @@ -0,0 +1,1 @@
677 @@ -0,0 +1,1 @@
675 +a
678 +a
676
679
677
680
678
681
679 log --removed file
682 log --removed file
680
683
681 $ hg log --removed -v a
684 $ hg log --removed -v a
682 changeset: 3:2ca5ba701980
685 changeset: 3:2ca5ba701980
683 user: test
686 user: test
684 date: Thu Jan 01 00:00:04 1970 +0000
687 date: Thu Jan 01 00:00:04 1970 +0000
685 files: a b d g
688 files: a b d g
686 description:
689 description:
687 d
690 d
688
691
689
692
690 changeset: 0:9161b9aeaf16
693 changeset: 0:9161b9aeaf16
691 user: test
694 user: test
692 date: Thu Jan 01 00:00:01 1970 +0000
695 date: Thu Jan 01 00:00:01 1970 +0000
693 files: a f
696 files: a f
694 description:
697 description:
695 a
698 a
696
699
697
700
698
701
699 log --removed revrange file
702 log --removed revrange file
700
703
701 $ hg log --removed -v -r0:2 a
704 $ hg log --removed -v -r0:2 a
702 changeset: 0:9161b9aeaf16
705 changeset: 0:9161b9aeaf16
703 user: test
706 user: test
704 date: Thu Jan 01 00:00:01 1970 +0000
707 date: Thu Jan 01 00:00:01 1970 +0000
705 files: a f
708 files: a f
706 description:
709 description:
707 a
710 a
708
711
709
712
710 $ cd ..
713 $ cd ..
711
714
712 log --follow tests
715 log --follow tests
713
716
714 $ hg init follow
717 $ hg init follow
715 $ cd follow
718 $ cd follow
716
719
717 $ echo base > base
720 $ echo base > base
718 $ hg ci -Ambase -d '1 0'
721 $ hg ci -Ambase -d '1 0'
719 adding base
722 adding base
720
723
721 $ echo r1 >> base
724 $ echo r1 >> base
722 $ hg ci -Amr1 -d '1 0'
725 $ hg ci -Amr1 -d '1 0'
723 $ echo r2 >> base
726 $ echo r2 >> base
724 $ hg ci -Amr2 -d '1 0'
727 $ hg ci -Amr2 -d '1 0'
725
728
726 $ hg up -C 1
729 $ hg up -C 1
727 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
730 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
728 $ echo b1 > b1
731 $ echo b1 > b1
729
732
730 log -r "follow('set:clean()')"
733 log -r "follow('set:clean()')"
731
734
732 $ hg log -r "follow('set:clean()')"
735 $ hg log -r "follow('set:clean()')"
733 changeset: 0:67e992f2c4f3
736 changeset: 0:67e992f2c4f3
734 user: test
737 user: test
735 date: Thu Jan 01 00:00:01 1970 +0000
738 date: Thu Jan 01 00:00:01 1970 +0000
736 summary: base
739 summary: base
737
740
738 changeset: 1:3d5bf5654eda
741 changeset: 1:3d5bf5654eda
739 user: test
742 user: test
740 date: Thu Jan 01 00:00:01 1970 +0000
743 date: Thu Jan 01 00:00:01 1970 +0000
741 summary: r1
744 summary: r1
742
745
743
746
744 $ hg ci -Amb1 -d '1 0'
747 $ hg ci -Amb1 -d '1 0'
745 adding b1
748 adding b1
746 created new head
749 created new head
747
750
748
751
749 log -f
752 log -f
750
753
751 $ hg log -f
754 $ hg log -f
752 changeset: 3:e62f78d544b4
755 changeset: 3:e62f78d544b4
753 tag: tip
756 tag: tip
754 parent: 1:3d5bf5654eda
757 parent: 1:3d5bf5654eda
755 user: test
758 user: test
756 date: Thu Jan 01 00:00:01 1970 +0000
759 date: Thu Jan 01 00:00:01 1970 +0000
757 summary: b1
760 summary: b1
758
761
759 changeset: 1:3d5bf5654eda
762 changeset: 1:3d5bf5654eda
760 user: test
763 user: test
761 date: Thu Jan 01 00:00:01 1970 +0000
764 date: Thu Jan 01 00:00:01 1970 +0000
762 summary: r1
765 summary: r1
763
766
764 changeset: 0:67e992f2c4f3
767 changeset: 0:67e992f2c4f3
765 user: test
768 user: test
766 date: Thu Jan 01 00:00:01 1970 +0000
769 date: Thu Jan 01 00:00:01 1970 +0000
767 summary: base
770 summary: base
768
771
769
772
770 log -r follow('glob:b*')
773 log -r follow('glob:b*')
771
774
772 $ hg log -r "follow('glob:b*')"
775 $ hg log -r "follow('glob:b*')"
773 changeset: 0:67e992f2c4f3
776 changeset: 0:67e992f2c4f3
774 user: test
777 user: test
775 date: Thu Jan 01 00:00:01 1970 +0000
778 date: Thu Jan 01 00:00:01 1970 +0000
776 summary: base
779 summary: base
777
780
778 changeset: 1:3d5bf5654eda
781 changeset: 1:3d5bf5654eda
779 user: test
782 user: test
780 date: Thu Jan 01 00:00:01 1970 +0000
783 date: Thu Jan 01 00:00:01 1970 +0000
781 summary: r1
784 summary: r1
782
785
783 changeset: 3:e62f78d544b4
786 changeset: 3:e62f78d544b4
784 tag: tip
787 tag: tip
785 parent: 1:3d5bf5654eda
788 parent: 1:3d5bf5654eda
786 user: test
789 user: test
787 date: Thu Jan 01 00:00:01 1970 +0000
790 date: Thu Jan 01 00:00:01 1970 +0000
788 summary: b1
791 summary: b1
789
792
790 log -f -r '1 + 4'
793 log -f -r '1 + 4'
791
794
792 $ hg up -C 0
795 $ hg up -C 0
793 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
796 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
794 $ echo b2 > b2
797 $ echo b2 > b2
795 $ hg ci -Amb2 -d '1 0'
798 $ hg ci -Amb2 -d '1 0'
796 adding b2
799 adding b2
797 created new head
800 created new head
798 $ hg log -f -r '1 + 4'
801 $ hg log -f -r '1 + 4'
799 changeset: 4:ddb82e70d1a1
802 changeset: 4:ddb82e70d1a1
800 tag: tip
803 tag: tip
801 parent: 0:67e992f2c4f3
804 parent: 0:67e992f2c4f3
802 user: test
805 user: test
803 date: Thu Jan 01 00:00:01 1970 +0000
806 date: Thu Jan 01 00:00:01 1970 +0000
804 summary: b2
807 summary: b2
805
808
806 changeset: 1:3d5bf5654eda
809 changeset: 1:3d5bf5654eda
807 user: test
810 user: test
808 date: Thu Jan 01 00:00:01 1970 +0000
811 date: Thu Jan 01 00:00:01 1970 +0000
809 summary: r1
812 summary: r1
810
813
811 changeset: 0:67e992f2c4f3
814 changeset: 0:67e992f2c4f3
812 user: test
815 user: test
813 date: Thu Jan 01 00:00:01 1970 +0000
816 date: Thu Jan 01 00:00:01 1970 +0000
814 summary: base
817 summary: base
815
818
816
819
817 log -fr with aliases: 'A' should be expanded, but 'reverse()' should have no
820 log -fr with aliases: 'A' should be expanded, but 'reverse()' should have no
818 effect
821 effect
819
822
820 $ hg log --config 'revsetalias.reverse(x)=x' --config 'revsetalias.A=1+4' -qfrA
823 $ hg log --config 'revsetalias.reverse(x)=x' --config 'revsetalias.A=1+4' -qfrA
821 4:ddb82e70d1a1
824 4:ddb82e70d1a1
822 1:3d5bf5654eda
825 1:3d5bf5654eda
823 0:67e992f2c4f3
826 0:67e992f2c4f3
824
827
825 log -r "follow('set:grep(b2)')"
828 log -r "follow('set:grep(b2)')"
826
829
827 $ hg log -r "follow('set:grep(b2)')"
830 $ hg log -r "follow('set:grep(b2)')"
828 changeset: 4:ddb82e70d1a1
831 changeset: 4:ddb82e70d1a1
829 tag: tip
832 tag: tip
830 parent: 0:67e992f2c4f3
833 parent: 0:67e992f2c4f3
831 user: test
834 user: test
832 date: Thu Jan 01 00:00:01 1970 +0000
835 date: Thu Jan 01 00:00:01 1970 +0000
833 summary: b2
836 summary: b2
834
837
835 log -r "follow('set:grep(b2)', 4)"
838 log -r "follow('set:grep(b2)', 4)"
836
839
837 $ hg up -qC 0
840 $ hg up -qC 0
838 $ hg log -r "follow('set:grep(b2)', 4)"
841 $ hg log -r "follow('set:grep(b2)', 4)"
839 changeset: 4:ddb82e70d1a1
842 changeset: 4:ddb82e70d1a1
840 tag: tip
843 tag: tip
841 parent: 0:67e992f2c4f3
844 parent: 0:67e992f2c4f3
842 user: test
845 user: test
843 date: Thu Jan 01 00:00:01 1970 +0000
846 date: Thu Jan 01 00:00:01 1970 +0000
844 summary: b2
847 summary: b2
845
848
846
849
847 follow files starting from multiple revisions:
850 follow files starting from multiple revisions:
848
851
849 $ hg log -T '{rev}: {files}\n' -r "follow('glob:b?', startrev=2+3+4)"
852 $ hg log -T '{rev}: {files}\n' -r "follow('glob:b?', startrev=2+3+4)"
850 3: b1
853 3: b1
851 4: b2
854 4: b2
852
855
853 follow files starting from empty revision:
856 follow files starting from empty revision:
854
857
855 $ hg log -T '{rev}: {files}\n' -r "follow('glob:*', startrev=.-.)"
858 $ hg log -T '{rev}: {files}\n' -r "follow('glob:*', startrev=.-.)"
856
859
857 follow starting from revisions:
860 follow starting from revisions:
858
861
859 $ hg log -Gq -r "follow(startrev=2+4)"
862 $ hg log -Gq -r "follow(startrev=2+4)"
860 o 4:ddb82e70d1a1
863 o 4:ddb82e70d1a1
861 |
864 |
862 | o 2:60c670bf5b30
865 | o 2:60c670bf5b30
863 | |
866 | |
864 | o 1:3d5bf5654eda
867 | o 1:3d5bf5654eda
865 |/
868 |/
866 @ 0:67e992f2c4f3
869 @ 0:67e992f2c4f3
867
870
868
871
869 follow the current revision:
872 follow the current revision:
870
873
871 $ hg log -Gq -r "follow()"
874 $ hg log -Gq -r "follow()"
872 @ 0:67e992f2c4f3
875 @ 0:67e992f2c4f3
873
876
874
877
875 $ hg up -qC 4
878 $ hg up -qC 4
876
879
877 log -f -r null
880 log -f -r null
878
881
879 $ hg log -f -r null
882 $ hg log -f -r null
880 changeset: -1:000000000000
883 changeset: -1:000000000000
881 user:
884 user:
882 date: Thu Jan 01 00:00:00 1970 +0000
885 date: Thu Jan 01 00:00:00 1970 +0000
883
886
884 $ hg log -f -r null -G
887 $ hg log -f -r null -G
885 o changeset: -1:000000000000
888 o changeset: -1:000000000000
886 user:
889 user:
887 date: Thu Jan 01 00:00:00 1970 +0000
890 date: Thu Jan 01 00:00:00 1970 +0000
888
891
889
892
890
893
891 log -f with null parent
894 log -f with null parent
892
895
893 $ hg up -C null
896 $ hg up -C null
894 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
897 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
895 $ hg log -f
898 $ hg log -f
896
899
897
900
898 log -r . with two parents
901 log -r . with two parents
899
902
900 $ hg up -C 3
903 $ hg up -C 3
901 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
904 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
902 $ hg merge tip
905 $ hg merge tip
903 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
906 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
904 (branch merge, don't forget to commit)
907 (branch merge, don't forget to commit)
905 $ hg log -r .
908 $ hg log -r .
906 changeset: 3:e62f78d544b4
909 changeset: 3:e62f78d544b4
907 parent: 1:3d5bf5654eda
910 parent: 1:3d5bf5654eda
908 user: test
911 user: test
909 date: Thu Jan 01 00:00:01 1970 +0000
912 date: Thu Jan 01 00:00:01 1970 +0000
910 summary: b1
913 summary: b1
911
914
912
915
913
916
914 log -r . with one parent
917 log -r . with one parent
915
918
916 $ hg ci -mm12 -d '1 0'
919 $ hg ci -mm12 -d '1 0'
917 $ hg log -r .
920 $ hg log -r .
918 changeset: 5:302e9dd6890d
921 changeset: 5:302e9dd6890d
919 tag: tip
922 tag: tip
920 parent: 3:e62f78d544b4
923 parent: 3:e62f78d544b4
921 parent: 4:ddb82e70d1a1
924 parent: 4:ddb82e70d1a1
922 user: test
925 user: test
923 date: Thu Jan 01 00:00:01 1970 +0000
926 date: Thu Jan 01 00:00:01 1970 +0000
924 summary: m12
927 summary: m12
925
928
926
929
927 $ echo postm >> b1
930 $ echo postm >> b1
928 $ hg ci -Amb1.1 -d'1 0'
931 $ hg ci -Amb1.1 -d'1 0'
929
932
930
933
931 log --follow-first
934 log --follow-first
932
935
933 $ hg log --follow-first
936 $ hg log --follow-first
934 changeset: 6:2404bbcab562
937 changeset: 6:2404bbcab562
935 tag: tip
938 tag: tip
936 user: test
939 user: test
937 date: Thu Jan 01 00:00:01 1970 +0000
940 date: Thu Jan 01 00:00:01 1970 +0000
938 summary: b1.1
941 summary: b1.1
939
942
940 changeset: 5:302e9dd6890d
943 changeset: 5:302e9dd6890d
941 parent: 3:e62f78d544b4
944 parent: 3:e62f78d544b4
942 parent: 4:ddb82e70d1a1
945 parent: 4:ddb82e70d1a1
943 user: test
946 user: test
944 date: Thu Jan 01 00:00:01 1970 +0000
947 date: Thu Jan 01 00:00:01 1970 +0000
945 summary: m12
948 summary: m12
946
949
947 changeset: 3:e62f78d544b4
950 changeset: 3:e62f78d544b4
948 parent: 1:3d5bf5654eda
951 parent: 1:3d5bf5654eda
949 user: test
952 user: test
950 date: Thu Jan 01 00:00:01 1970 +0000
953 date: Thu Jan 01 00:00:01 1970 +0000
951 summary: b1
954 summary: b1
952
955
953 changeset: 1:3d5bf5654eda
956 changeset: 1:3d5bf5654eda
954 user: test
957 user: test
955 date: Thu Jan 01 00:00:01 1970 +0000
958 date: Thu Jan 01 00:00:01 1970 +0000
956 summary: r1
959 summary: r1
957
960
958 changeset: 0:67e992f2c4f3
961 changeset: 0:67e992f2c4f3
959 user: test
962 user: test
960 date: Thu Jan 01 00:00:01 1970 +0000
963 date: Thu Jan 01 00:00:01 1970 +0000
961 summary: base
964 summary: base
962
965
963
966
964
967
965 log -P 2
968 log -P 2
966
969
967 $ hg log -P 2
970 $ hg log -P 2
968 changeset: 6:2404bbcab562
971 changeset: 6:2404bbcab562
969 tag: tip
972 tag: tip
970 user: test
973 user: test
971 date: Thu Jan 01 00:00:01 1970 +0000
974 date: Thu Jan 01 00:00:01 1970 +0000
972 summary: b1.1
975 summary: b1.1
973
976
974 changeset: 5:302e9dd6890d
977 changeset: 5:302e9dd6890d
975 parent: 3:e62f78d544b4
978 parent: 3:e62f78d544b4
976 parent: 4:ddb82e70d1a1
979 parent: 4:ddb82e70d1a1
977 user: test
980 user: test
978 date: Thu Jan 01 00:00:01 1970 +0000
981 date: Thu Jan 01 00:00:01 1970 +0000
979 summary: m12
982 summary: m12
980
983
981 changeset: 4:ddb82e70d1a1
984 changeset: 4:ddb82e70d1a1
982 parent: 0:67e992f2c4f3
985 parent: 0:67e992f2c4f3
983 user: test
986 user: test
984 date: Thu Jan 01 00:00:01 1970 +0000
987 date: Thu Jan 01 00:00:01 1970 +0000
985 summary: b2
988 summary: b2
986
989
987 changeset: 3:e62f78d544b4
990 changeset: 3:e62f78d544b4
988 parent: 1:3d5bf5654eda
991 parent: 1:3d5bf5654eda
989 user: test
992 user: test
990 date: Thu Jan 01 00:00:01 1970 +0000
993 date: Thu Jan 01 00:00:01 1970 +0000
991 summary: b1
994 summary: b1
992
995
993
996
994
997
995 log -r tip -p --git
998 log -r tip -p --git
996
999
997 $ hg log -r tip -p --git
1000 $ hg log -r tip -p --git
998 changeset: 6:2404bbcab562
1001 changeset: 6:2404bbcab562
999 tag: tip
1002 tag: tip
1000 user: test
1003 user: test
1001 date: Thu Jan 01 00:00:01 1970 +0000
1004 date: Thu Jan 01 00:00:01 1970 +0000
1002 summary: b1.1
1005 summary: b1.1
1003
1006
1004 diff --git a/b1 b/b1
1007 diff --git a/b1 b/b1
1005 --- a/b1
1008 --- a/b1
1006 +++ b/b1
1009 +++ b/b1
1007 @@ -1,1 +1,2 @@
1010 @@ -1,1 +1,2 @@
1008 b1
1011 b1
1009 +postm
1012 +postm
1010
1013
1011
1014
1012
1015
1013 log -r ""
1016 log -r ""
1014
1017
1015 $ hg log -r ''
1018 $ hg log -r ''
1016 hg: parse error: empty query
1019 hg: parse error: empty query
1017 [255]
1020 [255]
1018
1021
1019 log -r <some unknown node id>
1022 log -r <some unknown node id>
1020
1023
1021 $ hg log -r 1000000000000000000000000000000000000000
1024 $ hg log -r 1000000000000000000000000000000000000000
1022 abort: unknown revision '1000000000000000000000000000000000000000'!
1025 abort: unknown revision '1000000000000000000000000000000000000000'!
1023 [255]
1026 [255]
1024
1027
1025 log -k r1
1028 log -k r1
1026
1029
1027 $ hg log -k r1
1030 $ hg log -k r1
1028 changeset: 1:3d5bf5654eda
1031 changeset: 1:3d5bf5654eda
1029 user: test
1032 user: test
1030 date: Thu Jan 01 00:00:01 1970 +0000
1033 date: Thu Jan 01 00:00:01 1970 +0000
1031 summary: r1
1034 summary: r1
1032
1035
1033 log -p -l2 --color=always
1036 log -p -l2 --color=always
1034
1037
1035 $ hg --config extensions.color= --config color.mode=ansi \
1038 $ hg --config extensions.color= --config color.mode=ansi \
1036 > log -p -l2 --color=always
1039 > log -p -l2 --color=always
1037 \x1b[0;33mchangeset: 6:2404bbcab562\x1b[0m (esc)
1040 \x1b[0;33mchangeset: 6:2404bbcab562\x1b[0m (esc)
1038 tag: tip
1041 tag: tip
1039 user: test
1042 user: test
1040 date: Thu Jan 01 00:00:01 1970 +0000
1043 date: Thu Jan 01 00:00:01 1970 +0000
1041 summary: b1.1
1044 summary: b1.1
1042
1045
1043 \x1b[0;1mdiff -r 302e9dd6890d -r 2404bbcab562 b1\x1b[0m (esc)
1046 \x1b[0;1mdiff -r 302e9dd6890d -r 2404bbcab562 b1\x1b[0m (esc)
1044 \x1b[0;31;1m--- a/b1 Thu Jan 01 00:00:01 1970 +0000\x1b[0m (esc)
1047 \x1b[0;31;1m--- a/b1 Thu Jan 01 00:00:01 1970 +0000\x1b[0m (esc)
1045 \x1b[0;32;1m+++ b/b1 Thu Jan 01 00:00:01 1970 +0000\x1b[0m (esc)
1048 \x1b[0;32;1m+++ b/b1 Thu Jan 01 00:00:01 1970 +0000\x1b[0m (esc)
1046 \x1b[0;35m@@ -1,1 +1,2 @@\x1b[0m (esc)
1049 \x1b[0;35m@@ -1,1 +1,2 @@\x1b[0m (esc)
1047 b1
1050 b1
1048 \x1b[0;32m+postm\x1b[0m (esc)
1051 \x1b[0;32m+postm\x1b[0m (esc)
1049
1052
1050 \x1b[0;33mchangeset: 5:302e9dd6890d\x1b[0m (esc)
1053 \x1b[0;33mchangeset: 5:302e9dd6890d\x1b[0m (esc)
1051 parent: 3:e62f78d544b4
1054 parent: 3:e62f78d544b4
1052 parent: 4:ddb82e70d1a1
1055 parent: 4:ddb82e70d1a1
1053 user: test
1056 user: test
1054 date: Thu Jan 01 00:00:01 1970 +0000
1057 date: Thu Jan 01 00:00:01 1970 +0000
1055 summary: m12
1058 summary: m12
1056
1059
1057 \x1b[0;1mdiff -r e62f78d544b4 -r 302e9dd6890d b2\x1b[0m (esc)
1060 \x1b[0;1mdiff -r e62f78d544b4 -r 302e9dd6890d b2\x1b[0m (esc)
1058 \x1b[0;31;1m--- /dev/null Thu Jan 01 00:00:00 1970 +0000\x1b[0m (esc)
1061 \x1b[0;31;1m--- /dev/null Thu Jan 01 00:00:00 1970 +0000\x1b[0m (esc)
1059 \x1b[0;32;1m+++ b/b2 Thu Jan 01 00:00:01 1970 +0000\x1b[0m (esc)
1062 \x1b[0;32;1m+++ b/b2 Thu Jan 01 00:00:01 1970 +0000\x1b[0m (esc)
1060 \x1b[0;35m@@ -0,0 +1,1 @@\x1b[0m (esc)
1063 \x1b[0;35m@@ -0,0 +1,1 @@\x1b[0m (esc)
1061 \x1b[0;32m+b2\x1b[0m (esc)
1064 \x1b[0;32m+b2\x1b[0m (esc)
1062
1065
1063
1066
1064
1067
1065 log -r tip --stat
1068 log -r tip --stat
1066
1069
1067 $ hg log -r tip --stat
1070 $ hg log -r tip --stat
1068 changeset: 6:2404bbcab562
1071 changeset: 6:2404bbcab562
1069 tag: tip
1072 tag: tip
1070 user: test
1073 user: test
1071 date: Thu Jan 01 00:00:01 1970 +0000
1074 date: Thu Jan 01 00:00:01 1970 +0000
1072 summary: b1.1
1075 summary: b1.1
1073
1076
1074 b1 | 1 +
1077 b1 | 1 +
1075 1 files changed, 1 insertions(+), 0 deletions(-)
1078 1 files changed, 1 insertions(+), 0 deletions(-)
1076
1079
1077
1080
1078 $ cd ..
1081 $ cd ..
1079
1082
1080 log --follow --patch FILE in repository where linkrev isn't trustworthy
1083 log --follow --patch FILE in repository where linkrev isn't trustworthy
1081 (issue5376)
1084 (issue5376)
1082
1085
1083 $ hg init follow-dup
1086 $ hg init follow-dup
1084 $ cd follow-dup
1087 $ cd follow-dup
1085 $ cat <<EOF >> .hg/hgrc
1088 $ cat <<EOF >> .hg/hgrc
1086 > [ui]
1089 > [ui]
1087 > logtemplate = '=== {rev}: {desc}\n'
1090 > logtemplate = '=== {rev}: {desc}\n'
1088 > [diff]
1091 > [diff]
1089 > nodates = True
1092 > nodates = True
1090 > EOF
1093 > EOF
1091 $ echo 0 >> a
1094 $ echo 0 >> a
1092 $ hg ci -qAm 'a0'
1095 $ hg ci -qAm 'a0'
1093 $ echo 1 >> a
1096 $ echo 1 >> a
1094 $ hg ci -m 'a1'
1097 $ hg ci -m 'a1'
1095 $ hg up -q 0
1098 $ hg up -q 0
1096 $ echo 1 >> a
1099 $ echo 1 >> a
1097 $ touch b
1100 $ touch b
1098 $ hg ci -qAm 'a1 with b'
1101 $ hg ci -qAm 'a1 with b'
1099 $ echo 3 >> a
1102 $ echo 3 >> a
1100 $ hg ci -m 'a3'
1103 $ hg ci -m 'a3'
1101
1104
1102 fctx.rev() == 2, but fctx.linkrev() == 1
1105 fctx.rev() == 2, but fctx.linkrev() == 1
1103
1106
1104 $ hg log -pf a
1107 $ hg log -pf a
1105 === 3: a3
1108 === 3: a3
1106 diff -r 4ea02ba94d66 -r e7a6331a34f0 a
1109 diff -r 4ea02ba94d66 -r e7a6331a34f0 a
1107 --- a/a
1110 --- a/a
1108 +++ b/a
1111 +++ b/a
1109 @@ -1,2 +1,3 @@
1112 @@ -1,2 +1,3 @@
1110 0
1113 0
1111 1
1114 1
1112 +3
1115 +3
1113
1116
1114 === 2: a1 with b
1117 === 2: a1 with b
1115 diff -r 49b5e81287e2 -r 4ea02ba94d66 a
1118 diff -r 49b5e81287e2 -r 4ea02ba94d66 a
1116 --- a/a
1119 --- a/a
1117 +++ b/a
1120 +++ b/a
1118 @@ -1,1 +1,2 @@
1121 @@ -1,1 +1,2 @@
1119 0
1122 0
1120 +1
1123 +1
1121
1124
1122 === 0: a0
1125 === 0: a0
1123 diff -r 000000000000 -r 49b5e81287e2 a
1126 diff -r 000000000000 -r 49b5e81287e2 a
1124 --- /dev/null
1127 --- /dev/null
1125 +++ b/a
1128 +++ b/a
1126 @@ -0,0 +1,1 @@
1129 @@ -0,0 +1,1 @@
1127 +0
1130 +0
1128
1131
1129
1132
1130 fctx.introrev() == 2, but fctx.linkrev() == 1
1133 fctx.introrev() == 2, but fctx.linkrev() == 1
1131
1134
1132 $ hg up -q 2
1135 $ hg up -q 2
1133 $ hg log -pf a
1136 $ hg log -pf a
1134 === 2: a1 with b
1137 === 2: a1 with b
1135 diff -r 49b5e81287e2 -r 4ea02ba94d66 a
1138 diff -r 49b5e81287e2 -r 4ea02ba94d66 a
1136 --- a/a
1139 --- a/a
1137 +++ b/a
1140 +++ b/a
1138 @@ -1,1 +1,2 @@
1141 @@ -1,1 +1,2 @@
1139 0
1142 0
1140 +1
1143 +1
1141
1144
1142 === 0: a0
1145 === 0: a0
1143 diff -r 000000000000 -r 49b5e81287e2 a
1146 diff -r 000000000000 -r 49b5e81287e2 a
1144 --- /dev/null
1147 --- /dev/null
1145 +++ b/a
1148 +++ b/a
1146 @@ -0,0 +1,1 @@
1149 @@ -0,0 +1,1 @@
1147 +0
1150 +0
1148
1151
1149
1152
1150 $ cd ..
1153 $ cd ..
1151
1154
1152 Multiple copy sources of a file:
1155 Multiple copy sources of a file:
1153
1156
1154 $ hg init follow-multi
1157 $ hg init follow-multi
1155 $ cd follow-multi
1158 $ cd follow-multi
1156 $ echo 0 >> a
1159 $ echo 0 >> a
1157 $ hg ci -qAm 'a'
1160 $ hg ci -qAm 'a'
1158 $ hg cp a b
1161 $ hg cp a b
1159 $ hg ci -m 'a->b'
1162 $ hg ci -m 'a->b'
1160 $ echo 2 >> a
1163 $ echo 2 >> a
1161 $ hg ci -m 'a'
1164 $ hg ci -m 'a'
1162 $ echo 3 >> b
1165 $ echo 3 >> b
1163 $ hg ci -m 'b'
1166 $ hg ci -m 'b'
1164 $ echo 4 >> a
1167 $ echo 4 >> a
1165 $ echo 4 >> b
1168 $ echo 4 >> b
1166 $ hg ci -m 'a,b'
1169 $ hg ci -m 'a,b'
1167 $ echo 5 >> a
1170 $ echo 5 >> a
1168 $ hg ci -m 'a0'
1171 $ hg ci -m 'a0'
1169 $ echo 6 >> b
1172 $ echo 6 >> b
1170 $ hg ci -m 'b0'
1173 $ hg ci -m 'b0'
1171 $ hg up -q 4
1174 $ hg up -q 4
1172 $ echo 7 >> b
1175 $ echo 7 >> b
1173 $ hg ci -m 'b1'
1176 $ hg ci -m 'b1'
1174 created new head
1177 created new head
1175 $ echo 8 >> a
1178 $ echo 8 >> a
1176 $ hg ci -m 'a1'
1179 $ hg ci -m 'a1'
1177 $ hg rm a
1180 $ hg rm a
1178 $ hg mv b a
1181 $ hg mv b a
1179 $ hg ci -m 'b1->a1'
1182 $ hg ci -m 'b1->a1'
1180 $ hg merge -qt :local
1183 $ hg merge -qt :local
1181 $ hg ci -m '(a0,b1->a1)->a'
1184 $ hg ci -m '(a0,b1->a1)->a'
1182
1185
1183 $ hg log -GT '{rev}: {desc}\n'
1186 $ hg log -GT '{rev}: {desc}\n'
1184 @ 10: (a0,b1->a1)->a
1187 @ 10: (a0,b1->a1)->a
1185 |\
1188 |\
1186 | o 9: b1->a1
1189 | o 9: b1->a1
1187 | |
1190 | |
1188 | o 8: a1
1191 | o 8: a1
1189 | |
1192 | |
1190 | o 7: b1
1193 | o 7: b1
1191 | |
1194 | |
1192 o | 6: b0
1195 o | 6: b0
1193 | |
1196 | |
1194 o | 5: a0
1197 o | 5: a0
1195 |/
1198 |/
1196 o 4: a,b
1199 o 4: a,b
1197 |
1200 |
1198 o 3: b
1201 o 3: b
1199 |
1202 |
1200 o 2: a
1203 o 2: a
1201 |
1204 |
1202 o 1: a->b
1205 o 1: a->b
1203 |
1206 |
1204 o 0: a
1207 o 0: a
1205
1208
1206
1209
1207 since file 'a' has multiple copy sources at the revision 4, ancestors can't
1210 since file 'a' has multiple copy sources at the revision 4, ancestors can't
1208 be indexed solely by fctx.linkrev().
1211 be indexed solely by fctx.linkrev().
1209
1212
1210 $ hg log -T '{rev}: {desc}\n' -f a
1213 $ hg log -T '{rev}: {desc}\n' -f a
1211 10: (a0,b1->a1)->a
1214 10: (a0,b1->a1)->a
1212 9: b1->a1
1215 9: b1->a1
1213 7: b1
1216 7: b1
1214 5: a0
1217 5: a0
1215 4: a,b
1218 4: a,b
1216 3: b
1219 3: b
1217 2: a
1220 2: a
1218 1: a->b
1221 1: a->b
1219 0: a
1222 0: a
1220
1223
1221 $ cd ..
1224 $ cd ..
1222
1225
1223 Test that log should respect the order of -rREV even if multiple OR conditions
1226 Test that log should respect the order of -rREV even if multiple OR conditions
1224 are specified (issue5100):
1227 are specified (issue5100):
1225
1228
1226 $ hg init revorder
1229 $ hg init revorder
1227 $ cd revorder
1230 $ cd revorder
1228
1231
1229 $ hg branch -q b0
1232 $ hg branch -q b0
1230 $ echo 0 >> f0
1233 $ echo 0 >> f0
1231 $ hg ci -qAm k0 -u u0
1234 $ hg ci -qAm k0 -u u0
1232 $ hg branch -q b1
1235 $ hg branch -q b1
1233 $ echo 1 >> f1
1236 $ echo 1 >> f1
1234 $ hg ci -qAm k1 -u u1
1237 $ hg ci -qAm k1 -u u1
1235 $ hg branch -q b2
1238 $ hg branch -q b2
1236 $ echo 2 >> f2
1239 $ echo 2 >> f2
1237 $ hg ci -qAm k2 -u u2
1240 $ hg ci -qAm k2 -u u2
1238
1241
1239 $ hg update -q b2
1242 $ hg update -q b2
1240 $ echo 3 >> f2
1243 $ echo 3 >> f2
1241 $ hg ci -qAm k2 -u u2
1244 $ hg ci -qAm k2 -u u2
1242 $ hg update -q b1
1245 $ hg update -q b1
1243 $ echo 4 >> f1
1246 $ echo 4 >> f1
1244 $ hg ci -qAm k1 -u u1
1247 $ hg ci -qAm k1 -u u1
1245 $ hg update -q b0
1248 $ hg update -q b0
1246 $ echo 5 >> f0
1249 $ echo 5 >> f0
1247 $ hg ci -qAm k0 -u u0
1250 $ hg ci -qAm k0 -u u0
1248
1251
1249 summary of revisions:
1252 summary of revisions:
1250
1253
1251 $ hg log -G -T '{rev} {branch} {author} {desc} {files}\n'
1254 $ hg log -G -T '{rev} {branch} {author} {desc} {files}\n'
1252 @ 5 b0 u0 k0 f0
1255 @ 5 b0 u0 k0 f0
1253 |
1256 |
1254 | o 4 b1 u1 k1 f1
1257 | o 4 b1 u1 k1 f1
1255 | |
1258 | |
1256 | | o 3 b2 u2 k2 f2
1259 | | o 3 b2 u2 k2 f2
1257 | | |
1260 | | |
1258 | | o 2 b2 u2 k2 f2
1261 | | o 2 b2 u2 k2 f2
1259 | |/
1262 | |/
1260 | o 1 b1 u1 k1 f1
1263 | o 1 b1 u1 k1 f1
1261 |/
1264 |/
1262 o 0 b0 u0 k0 f0
1265 o 0 b0 u0 k0 f0
1263
1266
1264
1267
1265 log -b BRANCH in ascending order:
1268 log -b BRANCH in ascending order:
1266
1269
1267 $ hg log -r0:tip -T '{rev} {branch}\n' -b b0 -b b1
1270 $ hg log -r0:tip -T '{rev} {branch}\n' -b b0 -b b1
1268 0 b0
1271 0 b0
1269 1 b1
1272 1 b1
1270 4 b1
1273 4 b1
1271 5 b0
1274 5 b0
1272 $ hg log -r0:tip -T '{rev} {branch}\n' -b b1 -b b0
1275 $ hg log -r0:tip -T '{rev} {branch}\n' -b b1 -b b0
1273 0 b0
1276 0 b0
1274 1 b1
1277 1 b1
1275 4 b1
1278 4 b1
1276 5 b0
1279 5 b0
1277
1280
1278 log --only-branch BRANCH in descending order:
1281 log --only-branch BRANCH in descending order:
1279
1282
1280 $ hg log -rtip:0 -T '{rev} {branch}\n' --only-branch b1 --only-branch b2
1283 $ hg log -rtip:0 -T '{rev} {branch}\n' --only-branch b1 --only-branch b2
1281 4 b1
1284 4 b1
1282 3 b2
1285 3 b2
1283 2 b2
1286 2 b2
1284 1 b1
1287 1 b1
1285 $ hg log -rtip:0 -T '{rev} {branch}\n' --only-branch b2 --only-branch b1
1288 $ hg log -rtip:0 -T '{rev} {branch}\n' --only-branch b2 --only-branch b1
1286 4 b1
1289 4 b1
1287 3 b2
1290 3 b2
1288 2 b2
1291 2 b2
1289 1 b1
1292 1 b1
1290
1293
1291 log -u USER in ascending order, against compound set:
1294 log -u USER in ascending order, against compound set:
1292
1295
1293 $ hg log -r'::head()' -T '{rev} {author}\n' -u u0 -u u2
1296 $ hg log -r'::head()' -T '{rev} {author}\n' -u u0 -u u2
1294 0 u0
1297 0 u0
1295 2 u2
1298 2 u2
1296 3 u2
1299 3 u2
1297 5 u0
1300 5 u0
1298 $ hg log -r'::head()' -T '{rev} {author}\n' -u u2 -u u0
1301 $ hg log -r'::head()' -T '{rev} {author}\n' -u u2 -u u0
1299 0 u0
1302 0 u0
1300 2 u2
1303 2 u2
1301 3 u2
1304 3 u2
1302 5 u0
1305 5 u0
1303
1306
1304 log -k TEXT in descending order, against compound set:
1307 log -k TEXT in descending order, against compound set:
1305
1308
1306 $ hg log -r'5 + reverse(::3)' -T '{rev} {desc}\n' -k k0 -k k1 -k k2
1309 $ hg log -r'5 + reverse(::3)' -T '{rev} {desc}\n' -k k0 -k k1 -k k2
1307 5 k0
1310 5 k0
1308 3 k2
1311 3 k2
1309 2 k2
1312 2 k2
1310 1 k1
1313 1 k1
1311 0 k0
1314 0 k0
1312 $ hg log -r'5 + reverse(::3)' -T '{rev} {desc}\n' -k k2 -k k1 -k k0
1315 $ hg log -r'5 + reverse(::3)' -T '{rev} {desc}\n' -k k2 -k k1 -k k0
1313 5 k0
1316 5 k0
1314 3 k2
1317 3 k2
1315 2 k2
1318 2 k2
1316 1 k1
1319 1 k1
1317 0 k0
1320 0 k0
1318
1321
1319 log FILE in ascending order, against dagrange:
1322 log FILE in ascending order, against dagrange:
1320
1323
1321 $ hg log -r1:: -T '{rev} {files}\n' f1 f2
1324 $ hg log -r1:: -T '{rev} {files}\n' f1 f2
1322 1 f1
1325 1 f1
1323 2 f2
1326 2 f2
1324 3 f2
1327 3 f2
1325 4 f1
1328 4 f1
1326 $ hg log -r1:: -T '{rev} {files}\n' f2 f1
1329 $ hg log -r1:: -T '{rev} {files}\n' f2 f1
1327 1 f1
1330 1 f1
1328 2 f2
1331 2 f2
1329 3 f2
1332 3 f2
1330 4 f1
1333 4 f1
1331
1334
1332 $ cd ..
1335 $ cd ..
1333
1336
1334 User
1337 User
1335
1338
1336 $ hg init usertest
1339 $ hg init usertest
1337 $ cd usertest
1340 $ cd usertest
1338
1341
1339 $ echo a > a
1342 $ echo a > a
1340 $ hg ci -A -m "a" -u "User One <user1@example.org>"
1343 $ hg ci -A -m "a" -u "User One <user1@example.org>"
1341 adding a
1344 adding a
1342 $ echo b > b
1345 $ echo b > b
1343 $ hg ci -A -m "b" -u "User Two <user2@example.org>"
1346 $ hg ci -A -m "b" -u "User Two <user2@example.org>"
1344 adding b
1347 adding b
1345
1348
1346 $ hg log -u "User One <user1@example.org>"
1349 $ hg log -u "User One <user1@example.org>"
1347 changeset: 0:29a4c94f1924
1350 changeset: 0:29a4c94f1924
1348 user: User One <user1@example.org>
1351 user: User One <user1@example.org>
1349 date: Thu Jan 01 00:00:00 1970 +0000
1352 date: Thu Jan 01 00:00:00 1970 +0000
1350 summary: a
1353 summary: a
1351
1354
1352 $ hg log -u "user1" -u "user2"
1355 $ hg log -u "user1" -u "user2"
1353 changeset: 1:e834b5e69c0e
1356 changeset: 1:e834b5e69c0e
1354 tag: tip
1357 tag: tip
1355 user: User Two <user2@example.org>
1358 user: User Two <user2@example.org>
1356 date: Thu Jan 01 00:00:00 1970 +0000
1359 date: Thu Jan 01 00:00:00 1970 +0000
1357 summary: b
1360 summary: b
1358
1361
1359 changeset: 0:29a4c94f1924
1362 changeset: 0:29a4c94f1924
1360 user: User One <user1@example.org>
1363 user: User One <user1@example.org>
1361 date: Thu Jan 01 00:00:00 1970 +0000
1364 date: Thu Jan 01 00:00:00 1970 +0000
1362 summary: a
1365 summary: a
1363
1366
1364 $ hg log -u "user3"
1367 $ hg log -u "user3"
1365
1368
1366 "-u USER" shouldn't be overridden by "user(USER)" alias
1369 "-u USER" shouldn't be overridden by "user(USER)" alias
1367
1370
1368 $ hg log --config 'revsetalias.user(x)=branch(x)' -u default
1371 $ hg log --config 'revsetalias.user(x)=branch(x)' -u default
1369 $ hg log --config 'revsetalias.user(x)=branch(x)' -u user1
1372 $ hg log --config 'revsetalias.user(x)=branch(x)' -u user1
1370 changeset: 0:29a4c94f1924
1373 changeset: 0:29a4c94f1924
1371 user: User One <user1@example.org>
1374 user: User One <user1@example.org>
1372 date: Thu Jan 01 00:00:00 1970 +0000
1375 date: Thu Jan 01 00:00:00 1970 +0000
1373 summary: a
1376 summary: a
1374
1377
1375
1378
1376 $ cd ..
1379 $ cd ..
1377
1380
1378 $ hg init branches
1381 $ hg init branches
1379 $ cd branches
1382 $ cd branches
1380
1383
1381 $ echo a > a
1384 $ echo a > a
1382 $ hg ci -A -m "commit on default"
1385 $ hg ci -A -m "commit on default"
1383 adding a
1386 adding a
1384 $ hg branch test
1387 $ hg branch test
1385 marked working directory as branch test
1388 marked working directory as branch test
1386 (branches are permanent and global, did you want a bookmark?)
1389 (branches are permanent and global, did you want a bookmark?)
1387 $ echo b > b
1390 $ echo b > b
1388 $ hg ci -A -m "commit on test"
1391 $ hg ci -A -m "commit on test"
1389 adding b
1392 adding b
1390
1393
1391 $ hg up default
1394 $ hg up default
1392 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1395 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1393 $ echo c > c
1396 $ echo c > c
1394 $ hg ci -A -m "commit on default"
1397 $ hg ci -A -m "commit on default"
1395 adding c
1398 adding c
1396 $ hg up test
1399 $ hg up test
1397 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
1400 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
1398 $ echo c > c
1401 $ echo c > c
1399 $ hg ci -A -m "commit on test"
1402 $ hg ci -A -m "commit on test"
1400 adding c
1403 adding c
1401
1404
1402
1405
1403 log -b default
1406 log -b default
1404
1407
1405 $ hg log -b default
1408 $ hg log -b default
1406 changeset: 2:c3a4f03cc9a7
1409 changeset: 2:c3a4f03cc9a7
1407 parent: 0:24427303d56f
1410 parent: 0:24427303d56f
1408 user: test
1411 user: test
1409 date: Thu Jan 01 00:00:00 1970 +0000
1412 date: Thu Jan 01 00:00:00 1970 +0000
1410 summary: commit on default
1413 summary: commit on default
1411
1414
1412 changeset: 0:24427303d56f
1415 changeset: 0:24427303d56f
1413 user: test
1416 user: test
1414 date: Thu Jan 01 00:00:00 1970 +0000
1417 date: Thu Jan 01 00:00:00 1970 +0000
1415 summary: commit on default
1418 summary: commit on default
1416
1419
1417
1420
1418
1421
1419 log -b test
1422 log -b test
1420
1423
1421 $ hg log -b test
1424 $ hg log -b test
1422 changeset: 3:f5d8de11c2e2
1425 changeset: 3:f5d8de11c2e2
1423 branch: test
1426 branch: test
1424 tag: tip
1427 tag: tip
1425 parent: 1:d32277701ccb
1428 parent: 1:d32277701ccb
1426 user: test
1429 user: test
1427 date: Thu Jan 01 00:00:00 1970 +0000
1430 date: Thu Jan 01 00:00:00 1970 +0000
1428 summary: commit on test
1431 summary: commit on test
1429
1432
1430 changeset: 1:d32277701ccb
1433 changeset: 1:d32277701ccb
1431 branch: test
1434 branch: test
1432 user: test
1435 user: test
1433 date: Thu Jan 01 00:00:00 1970 +0000
1436 date: Thu Jan 01 00:00:00 1970 +0000
1434 summary: commit on test
1437 summary: commit on test
1435
1438
1436
1439
1437
1440
1438 log -b dummy
1441 log -b dummy
1439
1442
1440 $ hg log -b dummy
1443 $ hg log -b dummy
1441 abort: unknown revision 'dummy'!
1444 abort: unknown revision 'dummy'!
1442 [255]
1445 [255]
1443
1446
1444
1447
1445 log -b .
1448 log -b .
1446
1449
1447 $ hg log -b .
1450 $ hg log -b .
1448 changeset: 3:f5d8de11c2e2
1451 changeset: 3:f5d8de11c2e2
1449 branch: test
1452 branch: test
1450 tag: tip
1453 tag: tip
1451 parent: 1:d32277701ccb
1454 parent: 1:d32277701ccb
1452 user: test
1455 user: test
1453 date: Thu Jan 01 00:00:00 1970 +0000
1456 date: Thu Jan 01 00:00:00 1970 +0000
1454 summary: commit on test
1457 summary: commit on test
1455
1458
1456 changeset: 1:d32277701ccb
1459 changeset: 1:d32277701ccb
1457 branch: test
1460 branch: test
1458 user: test
1461 user: test
1459 date: Thu Jan 01 00:00:00 1970 +0000
1462 date: Thu Jan 01 00:00:00 1970 +0000
1460 summary: commit on test
1463 summary: commit on test
1461
1464
1462
1465
1463
1466
1464 log -b default -b test
1467 log -b default -b test
1465
1468
1466 $ hg log -b default -b test
1469 $ hg log -b default -b test
1467 changeset: 3:f5d8de11c2e2
1470 changeset: 3:f5d8de11c2e2
1468 branch: test
1471 branch: test
1469 tag: tip
1472 tag: tip
1470 parent: 1:d32277701ccb
1473 parent: 1:d32277701ccb
1471 user: test
1474 user: test
1472 date: Thu Jan 01 00:00:00 1970 +0000
1475 date: Thu Jan 01 00:00:00 1970 +0000
1473 summary: commit on test
1476 summary: commit on test
1474
1477
1475 changeset: 2:c3a4f03cc9a7
1478 changeset: 2:c3a4f03cc9a7
1476 parent: 0:24427303d56f
1479 parent: 0:24427303d56f
1477 user: test
1480 user: test
1478 date: Thu Jan 01 00:00:00 1970 +0000
1481 date: Thu Jan 01 00:00:00 1970 +0000
1479 summary: commit on default
1482 summary: commit on default
1480
1483
1481 changeset: 1:d32277701ccb
1484 changeset: 1:d32277701ccb
1482 branch: test
1485 branch: test
1483 user: test
1486 user: test
1484 date: Thu Jan 01 00:00:00 1970 +0000
1487 date: Thu Jan 01 00:00:00 1970 +0000
1485 summary: commit on test
1488 summary: commit on test
1486
1489
1487 changeset: 0:24427303d56f
1490 changeset: 0:24427303d56f
1488 user: test
1491 user: test
1489 date: Thu Jan 01 00:00:00 1970 +0000
1492 date: Thu Jan 01 00:00:00 1970 +0000
1490 summary: commit on default
1493 summary: commit on default
1491
1494
1492
1495
1493
1496
1494 log -b default -b .
1497 log -b default -b .
1495
1498
1496 $ hg log -b default -b .
1499 $ hg log -b default -b .
1497 changeset: 3:f5d8de11c2e2
1500 changeset: 3:f5d8de11c2e2
1498 branch: test
1501 branch: test
1499 tag: tip
1502 tag: tip
1500 parent: 1:d32277701ccb
1503 parent: 1:d32277701ccb
1501 user: test
1504 user: test
1502 date: Thu Jan 01 00:00:00 1970 +0000
1505 date: Thu Jan 01 00:00:00 1970 +0000
1503 summary: commit on test
1506 summary: commit on test
1504
1507
1505 changeset: 2:c3a4f03cc9a7
1508 changeset: 2:c3a4f03cc9a7
1506 parent: 0:24427303d56f
1509 parent: 0:24427303d56f
1507 user: test
1510 user: test
1508 date: Thu Jan 01 00:00:00 1970 +0000
1511 date: Thu Jan 01 00:00:00 1970 +0000
1509 summary: commit on default
1512 summary: commit on default
1510
1513
1511 changeset: 1:d32277701ccb
1514 changeset: 1:d32277701ccb
1512 branch: test
1515 branch: test
1513 user: test
1516 user: test
1514 date: Thu Jan 01 00:00:00 1970 +0000
1517 date: Thu Jan 01 00:00:00 1970 +0000
1515 summary: commit on test
1518 summary: commit on test
1516
1519
1517 changeset: 0:24427303d56f
1520 changeset: 0:24427303d56f
1518 user: test
1521 user: test
1519 date: Thu Jan 01 00:00:00 1970 +0000
1522 date: Thu Jan 01 00:00:00 1970 +0000
1520 summary: commit on default
1523 summary: commit on default
1521
1524
1522
1525
1523
1526
1524 log -b . -b test
1527 log -b . -b test
1525
1528
1526 $ hg log -b . -b test
1529 $ hg log -b . -b test
1527 changeset: 3:f5d8de11c2e2
1530 changeset: 3:f5d8de11c2e2
1528 branch: test
1531 branch: test
1529 tag: tip
1532 tag: tip
1530 parent: 1:d32277701ccb
1533 parent: 1:d32277701ccb
1531 user: test
1534 user: test
1532 date: Thu Jan 01 00:00:00 1970 +0000
1535 date: Thu Jan 01 00:00:00 1970 +0000
1533 summary: commit on test
1536 summary: commit on test
1534
1537
1535 changeset: 1:d32277701ccb
1538 changeset: 1:d32277701ccb
1536 branch: test
1539 branch: test
1537 user: test
1540 user: test
1538 date: Thu Jan 01 00:00:00 1970 +0000
1541 date: Thu Jan 01 00:00:00 1970 +0000
1539 summary: commit on test
1542 summary: commit on test
1540
1543
1541
1544
1542
1545
1543 log -b 2
1546 log -b 2
1544
1547
1545 $ hg log -b 2
1548 $ hg log -b 2
1546 changeset: 2:c3a4f03cc9a7
1549 changeset: 2:c3a4f03cc9a7
1547 parent: 0:24427303d56f
1550 parent: 0:24427303d56f
1548 user: test
1551 user: test
1549 date: Thu Jan 01 00:00:00 1970 +0000
1552 date: Thu Jan 01 00:00:00 1970 +0000
1550 summary: commit on default
1553 summary: commit on default
1551
1554
1552 changeset: 0:24427303d56f
1555 changeset: 0:24427303d56f
1553 user: test
1556 user: test
1554 date: Thu Jan 01 00:00:00 1970 +0000
1557 date: Thu Jan 01 00:00:00 1970 +0000
1555 summary: commit on default
1558 summary: commit on default
1556
1559
1557 #if gettext
1560 #if gettext
1558
1561
1559 Test that all log names are translated (e.g. branches, bookmarks, tags):
1562 Test that all log names are translated (e.g. branches, bookmarks, tags):
1560
1563
1561 $ hg bookmark babar -r tip
1564 $ hg bookmark babar -r tip
1562
1565
1563 $ HGENCODING=UTF-8 LANGUAGE=de hg log -r tip
1566 $ HGENCODING=UTF-8 LANGUAGE=de hg log -r tip
1564 \xc3\x84nderung: 3:f5d8de11c2e2 (esc)
1567 \xc3\x84nderung: 3:f5d8de11c2e2 (esc)
1565 Zweig: test
1568 Zweig: test
1566 Lesezeichen: babar
1569 Lesezeichen: babar
1567 Marke: tip
1570 Marke: tip
1568 Vorg\xc3\xa4nger: 1:d32277701ccb (esc)
1571 Vorg\xc3\xa4nger: 1:d32277701ccb (esc)
1569 Nutzer: test
1572 Nutzer: test
1570 Datum: Thu Jan 01 00:00:00 1970 +0000
1573 Datum: Thu Jan 01 00:00:00 1970 +0000
1571 Zusammenfassung: commit on test
1574 Zusammenfassung: commit on test
1572
1575
1573 $ hg bookmark -d babar
1576 $ hg bookmark -d babar
1574
1577
1575 #endif
1578 #endif
1576
1579
1577 log -p --cwd dir (in subdir)
1580 log -p --cwd dir (in subdir)
1578
1581
1579 $ mkdir dir
1582 $ mkdir dir
1580 $ hg log -p --cwd dir
1583 $ hg log -p --cwd dir
1581 changeset: 3:f5d8de11c2e2
1584 changeset: 3:f5d8de11c2e2
1582 branch: test
1585 branch: test
1583 tag: tip
1586 tag: tip
1584 parent: 1:d32277701ccb
1587 parent: 1:d32277701ccb
1585 user: test
1588 user: test
1586 date: Thu Jan 01 00:00:00 1970 +0000
1589 date: Thu Jan 01 00:00:00 1970 +0000
1587 summary: commit on test
1590 summary: commit on test
1588
1591
1589 diff -r d32277701ccb -r f5d8de11c2e2 c
1592 diff -r d32277701ccb -r f5d8de11c2e2 c
1590 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1593 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1591 +++ b/c Thu Jan 01 00:00:00 1970 +0000
1594 +++ b/c Thu Jan 01 00:00:00 1970 +0000
1592 @@ -0,0 +1,1 @@
1595 @@ -0,0 +1,1 @@
1593 +c
1596 +c
1594
1597
1595 changeset: 2:c3a4f03cc9a7
1598 changeset: 2:c3a4f03cc9a7
1596 parent: 0:24427303d56f
1599 parent: 0:24427303d56f
1597 user: test
1600 user: test
1598 date: Thu Jan 01 00:00:00 1970 +0000
1601 date: Thu Jan 01 00:00:00 1970 +0000
1599 summary: commit on default
1602 summary: commit on default
1600
1603
1601 diff -r 24427303d56f -r c3a4f03cc9a7 c
1604 diff -r 24427303d56f -r c3a4f03cc9a7 c
1602 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1605 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1603 +++ b/c Thu Jan 01 00:00:00 1970 +0000
1606 +++ b/c Thu Jan 01 00:00:00 1970 +0000
1604 @@ -0,0 +1,1 @@
1607 @@ -0,0 +1,1 @@
1605 +c
1608 +c
1606
1609
1607 changeset: 1:d32277701ccb
1610 changeset: 1:d32277701ccb
1608 branch: test
1611 branch: test
1609 user: test
1612 user: test
1610 date: Thu Jan 01 00:00:00 1970 +0000
1613 date: Thu Jan 01 00:00:00 1970 +0000
1611 summary: commit on test
1614 summary: commit on test
1612
1615
1613 diff -r 24427303d56f -r d32277701ccb b
1616 diff -r 24427303d56f -r d32277701ccb b
1614 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1617 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1615 +++ b/b Thu Jan 01 00:00:00 1970 +0000
1618 +++ b/b Thu Jan 01 00:00:00 1970 +0000
1616 @@ -0,0 +1,1 @@
1619 @@ -0,0 +1,1 @@
1617 +b
1620 +b
1618
1621
1619 changeset: 0:24427303d56f
1622 changeset: 0:24427303d56f
1620 user: test
1623 user: test
1621 date: Thu Jan 01 00:00:00 1970 +0000
1624 date: Thu Jan 01 00:00:00 1970 +0000
1622 summary: commit on default
1625 summary: commit on default
1623
1626
1624 diff -r 000000000000 -r 24427303d56f a
1627 diff -r 000000000000 -r 24427303d56f a
1625 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1628 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1626 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1629 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1627 @@ -0,0 +1,1 @@
1630 @@ -0,0 +1,1 @@
1628 +a
1631 +a
1629
1632
1630
1633
1631
1634
1632 log -p -R repo
1635 log -p -R repo
1633
1636
1634 $ cd dir
1637 $ cd dir
1635 $ hg log -p -R .. ../a
1638 $ hg log -p -R .. ../a
1636 changeset: 0:24427303d56f
1639 changeset: 0:24427303d56f
1637 user: test
1640 user: test
1638 date: Thu Jan 01 00:00:00 1970 +0000
1641 date: Thu Jan 01 00:00:00 1970 +0000
1639 summary: commit on default
1642 summary: commit on default
1640
1643
1641 diff -r 000000000000 -r 24427303d56f a
1644 diff -r 000000000000 -r 24427303d56f a
1642 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1645 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1643 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1646 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1644 @@ -0,0 +1,1 @@
1647 @@ -0,0 +1,1 @@
1645 +a
1648 +a
1646
1649
1647
1650
1648 $ cd ../..
1651 $ cd ../..
1649
1652
1650 $ hg init follow2
1653 $ hg init follow2
1651 $ cd follow2
1654 $ cd follow2
1652
1655
1653 # Build the following history:
1656 # Build the following history:
1654 # tip - o - x - o - x - x
1657 # tip - o - x - o - x - x
1655 # \ /
1658 # \ /
1656 # o - o - o - x
1659 # o - o - o - x
1657 # \ /
1660 # \ /
1658 # o
1661 # o
1659 #
1662 #
1660 # Where "o" is a revision containing "foo" and
1663 # Where "o" is a revision containing "foo" and
1661 # "x" is a revision without "foo"
1664 # "x" is a revision without "foo"
1662
1665
1663 $ touch init
1666 $ touch init
1664 $ hg ci -A -m "init, unrelated"
1667 $ hg ci -A -m "init, unrelated"
1665 adding init
1668 adding init
1666 $ echo 'foo' > init
1669 $ echo 'foo' > init
1667 $ hg ci -m "change, unrelated"
1670 $ hg ci -m "change, unrelated"
1668 $ echo 'foo' > foo
1671 $ echo 'foo' > foo
1669 $ hg ci -A -m "add unrelated old foo"
1672 $ hg ci -A -m "add unrelated old foo"
1670 adding foo
1673 adding foo
1671 $ hg rm foo
1674 $ hg rm foo
1672 $ hg ci -m "delete foo, unrelated"
1675 $ hg ci -m "delete foo, unrelated"
1673 $ echo 'related' > foo
1676 $ echo 'related' > foo
1674 $ hg ci -A -m "add foo, related"
1677 $ hg ci -A -m "add foo, related"
1675 adding foo
1678 adding foo
1676
1679
1677 $ hg up 0
1680 $ hg up 0
1678 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
1681 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
1679 $ touch branch
1682 $ touch branch
1680 $ hg ci -A -m "first branch, unrelated"
1683 $ hg ci -A -m "first branch, unrelated"
1681 adding branch
1684 adding branch
1682 created new head
1685 created new head
1683 $ touch foo
1686 $ touch foo
1684 $ hg ci -A -m "create foo, related"
1687 $ hg ci -A -m "create foo, related"
1685 adding foo
1688 adding foo
1686 $ echo 'change' > foo
1689 $ echo 'change' > foo
1687 $ hg ci -m "change foo, related"
1690 $ hg ci -m "change foo, related"
1688
1691
1689 $ hg up 6
1692 $ hg up 6
1690 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1693 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1691 $ echo 'change foo in branch' > foo
1694 $ echo 'change foo in branch' > foo
1692 $ hg ci -m "change foo in branch, related"
1695 $ hg ci -m "change foo in branch, related"
1693 created new head
1696 created new head
1694 $ hg merge 7
1697 $ hg merge 7
1695 merging foo
1698 merging foo
1696 warning: conflicts while merging foo! (edit, then use 'hg resolve --mark')
1699 warning: conflicts while merging foo! (edit, then use 'hg resolve --mark')
1697 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
1700 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
1698 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
1701 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
1699 [1]
1702 [1]
1700 $ echo 'merge 1' > foo
1703 $ echo 'merge 1' > foo
1701 $ hg resolve -m foo
1704 $ hg resolve -m foo
1702 (no more unresolved files)
1705 (no more unresolved files)
1703 $ hg ci -m "First merge, related"
1706 $ hg ci -m "First merge, related"
1704
1707
1705 $ hg merge 4
1708 $ hg merge 4
1706 merging foo
1709 merging foo
1707 warning: conflicts while merging foo! (edit, then use 'hg resolve --mark')
1710 warning: conflicts while merging foo! (edit, then use 'hg resolve --mark')
1708 1 files updated, 0 files merged, 0 files removed, 1 files unresolved
1711 1 files updated, 0 files merged, 0 files removed, 1 files unresolved
1709 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
1712 use 'hg resolve' to retry unresolved file merges or 'hg merge --abort' to abandon
1710 [1]
1713 [1]
1711 $ echo 'merge 2' > foo
1714 $ echo 'merge 2' > foo
1712 $ hg resolve -m foo
1715 $ hg resolve -m foo
1713 (no more unresolved files)
1716 (no more unresolved files)
1714 $ hg ci -m "Last merge, related"
1717 $ hg ci -m "Last merge, related"
1715
1718
1716 $ hg log --graph
1719 $ hg log --graph
1717 @ changeset: 10:4dae8563d2c5
1720 @ changeset: 10:4dae8563d2c5
1718 |\ tag: tip
1721 |\ tag: tip
1719 | | parent: 9:7b35701b003e
1722 | | parent: 9:7b35701b003e
1720 | | parent: 4:88176d361b69
1723 | | parent: 4:88176d361b69
1721 | | user: test
1724 | | user: test
1722 | | date: Thu Jan 01 00:00:00 1970 +0000
1725 | | date: Thu Jan 01 00:00:00 1970 +0000
1723 | | summary: Last merge, related
1726 | | summary: Last merge, related
1724 | |
1727 | |
1725 | o changeset: 9:7b35701b003e
1728 | o changeset: 9:7b35701b003e
1726 | |\ parent: 8:e5416ad8a855
1729 | |\ parent: 8:e5416ad8a855
1727 | | | parent: 7:87fe3144dcfa
1730 | | | parent: 7:87fe3144dcfa
1728 | | | user: test
1731 | | | user: test
1729 | | | date: Thu Jan 01 00:00:00 1970 +0000
1732 | | | date: Thu Jan 01 00:00:00 1970 +0000
1730 | | | summary: First merge, related
1733 | | | summary: First merge, related
1731 | | |
1734 | | |
1732 | | o changeset: 8:e5416ad8a855
1735 | | o changeset: 8:e5416ad8a855
1733 | | | parent: 6:dc6c325fe5ee
1736 | | | parent: 6:dc6c325fe5ee
1734 | | | user: test
1737 | | | user: test
1735 | | | date: Thu Jan 01 00:00:00 1970 +0000
1738 | | | date: Thu Jan 01 00:00:00 1970 +0000
1736 | | | summary: change foo in branch, related
1739 | | | summary: change foo in branch, related
1737 | | |
1740 | | |
1738 | o | changeset: 7:87fe3144dcfa
1741 | o | changeset: 7:87fe3144dcfa
1739 | |/ user: test
1742 | |/ user: test
1740 | | date: Thu Jan 01 00:00:00 1970 +0000
1743 | | date: Thu Jan 01 00:00:00 1970 +0000
1741 | | summary: change foo, related
1744 | | summary: change foo, related
1742 | |
1745 | |
1743 | o changeset: 6:dc6c325fe5ee
1746 | o changeset: 6:dc6c325fe5ee
1744 | | user: test
1747 | | user: test
1745 | | date: Thu Jan 01 00:00:00 1970 +0000
1748 | | date: Thu Jan 01 00:00:00 1970 +0000
1746 | | summary: create foo, related
1749 | | summary: create foo, related
1747 | |
1750 | |
1748 | o changeset: 5:73db34516eb9
1751 | o changeset: 5:73db34516eb9
1749 | | parent: 0:e87515fd044a
1752 | | parent: 0:e87515fd044a
1750 | | user: test
1753 | | user: test
1751 | | date: Thu Jan 01 00:00:00 1970 +0000
1754 | | date: Thu Jan 01 00:00:00 1970 +0000
1752 | | summary: first branch, unrelated
1755 | | summary: first branch, unrelated
1753 | |
1756 | |
1754 o | changeset: 4:88176d361b69
1757 o | changeset: 4:88176d361b69
1755 | | user: test
1758 | | user: test
1756 | | date: Thu Jan 01 00:00:00 1970 +0000
1759 | | date: Thu Jan 01 00:00:00 1970 +0000
1757 | | summary: add foo, related
1760 | | summary: add foo, related
1758 | |
1761 | |
1759 o | changeset: 3:dd78ae4afb56
1762 o | changeset: 3:dd78ae4afb56
1760 | | user: test
1763 | | user: test
1761 | | date: Thu Jan 01 00:00:00 1970 +0000
1764 | | date: Thu Jan 01 00:00:00 1970 +0000
1762 | | summary: delete foo, unrelated
1765 | | summary: delete foo, unrelated
1763 | |
1766 | |
1764 o | changeset: 2:c4c64aedf0f7
1767 o | changeset: 2:c4c64aedf0f7
1765 | | user: test
1768 | | user: test
1766 | | date: Thu Jan 01 00:00:00 1970 +0000
1769 | | date: Thu Jan 01 00:00:00 1970 +0000
1767 | | summary: add unrelated old foo
1770 | | summary: add unrelated old foo
1768 | |
1771 | |
1769 o | changeset: 1:e5faa7440653
1772 o | changeset: 1:e5faa7440653
1770 |/ user: test
1773 |/ user: test
1771 | date: Thu Jan 01 00:00:00 1970 +0000
1774 | date: Thu Jan 01 00:00:00 1970 +0000
1772 | summary: change, unrelated
1775 | summary: change, unrelated
1773 |
1776 |
1774 o changeset: 0:e87515fd044a
1777 o changeset: 0:e87515fd044a
1775 user: test
1778 user: test
1776 date: Thu Jan 01 00:00:00 1970 +0000
1779 date: Thu Jan 01 00:00:00 1970 +0000
1777 summary: init, unrelated
1780 summary: init, unrelated
1778
1781
1779
1782
1780 $ hg --traceback log -f foo
1783 $ hg --traceback log -f foo
1781 changeset: 10:4dae8563d2c5
1784 changeset: 10:4dae8563d2c5
1782 tag: tip
1785 tag: tip
1783 parent: 9:7b35701b003e
1786 parent: 9:7b35701b003e
1784 parent: 4:88176d361b69
1787 parent: 4:88176d361b69
1785 user: test
1788 user: test
1786 date: Thu Jan 01 00:00:00 1970 +0000
1789 date: Thu Jan 01 00:00:00 1970 +0000
1787 summary: Last merge, related
1790 summary: Last merge, related
1788
1791
1789 changeset: 9:7b35701b003e
1792 changeset: 9:7b35701b003e
1790 parent: 8:e5416ad8a855
1793 parent: 8:e5416ad8a855
1791 parent: 7:87fe3144dcfa
1794 parent: 7:87fe3144dcfa
1792 user: test
1795 user: test
1793 date: Thu Jan 01 00:00:00 1970 +0000
1796 date: Thu Jan 01 00:00:00 1970 +0000
1794 summary: First merge, related
1797 summary: First merge, related
1795
1798
1796 changeset: 8:e5416ad8a855
1799 changeset: 8:e5416ad8a855
1797 parent: 6:dc6c325fe5ee
1800 parent: 6:dc6c325fe5ee
1798 user: test
1801 user: test
1799 date: Thu Jan 01 00:00:00 1970 +0000
1802 date: Thu Jan 01 00:00:00 1970 +0000
1800 summary: change foo in branch, related
1803 summary: change foo in branch, related
1801
1804
1802 changeset: 7:87fe3144dcfa
1805 changeset: 7:87fe3144dcfa
1803 user: test
1806 user: test
1804 date: Thu Jan 01 00:00:00 1970 +0000
1807 date: Thu Jan 01 00:00:00 1970 +0000
1805 summary: change foo, related
1808 summary: change foo, related
1806
1809
1807 changeset: 6:dc6c325fe5ee
1810 changeset: 6:dc6c325fe5ee
1808 user: test
1811 user: test
1809 date: Thu Jan 01 00:00:00 1970 +0000
1812 date: Thu Jan 01 00:00:00 1970 +0000
1810 summary: create foo, related
1813 summary: create foo, related
1811
1814
1812 changeset: 4:88176d361b69
1815 changeset: 4:88176d361b69
1813 user: test
1816 user: test
1814 date: Thu Jan 01 00:00:00 1970 +0000
1817 date: Thu Jan 01 00:00:00 1970 +0000
1815 summary: add foo, related
1818 summary: add foo, related
1816
1819
1817
1820
1818 Also check when maxrev < lastrevfilelog
1821 Also check when maxrev < lastrevfilelog
1819
1822
1820 $ hg --traceback log -f -r4 foo
1823 $ hg --traceback log -f -r4 foo
1821 changeset: 4:88176d361b69
1824 changeset: 4:88176d361b69
1822 user: test
1825 user: test
1823 date: Thu Jan 01 00:00:00 1970 +0000
1826 date: Thu Jan 01 00:00:00 1970 +0000
1824 summary: add foo, related
1827 summary: add foo, related
1825
1828
1826 $ cd ..
1829 $ cd ..
1827
1830
1828 Issue2383: hg log showing _less_ differences than hg diff
1831 Issue2383: hg log showing _less_ differences than hg diff
1829
1832
1830 $ hg init issue2383
1833 $ hg init issue2383
1831 $ cd issue2383
1834 $ cd issue2383
1832
1835
1833 Create a test repo:
1836 Create a test repo:
1834
1837
1835 $ echo a > a
1838 $ echo a > a
1836 $ hg ci -Am0
1839 $ hg ci -Am0
1837 adding a
1840 adding a
1838 $ echo b > b
1841 $ echo b > b
1839 $ hg ci -Am1
1842 $ hg ci -Am1
1840 adding b
1843 adding b
1841 $ hg co 0
1844 $ hg co 0
1842 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1845 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
1843 $ echo b > a
1846 $ echo b > a
1844 $ hg ci -m2
1847 $ hg ci -m2
1845 created new head
1848 created new head
1846
1849
1847 Merge:
1850 Merge:
1848
1851
1849 $ hg merge
1852 $ hg merge
1850 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1853 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1851 (branch merge, don't forget to commit)
1854 (branch merge, don't forget to commit)
1852
1855
1853 Make sure there's a file listed in the merge to trigger the bug:
1856 Make sure there's a file listed in the merge to trigger the bug:
1854
1857
1855 $ echo c > a
1858 $ echo c > a
1856 $ hg ci -m3
1859 $ hg ci -m3
1857
1860
1858 Two files shown here in diff:
1861 Two files shown here in diff:
1859
1862
1860 $ hg diff --rev 2:3
1863 $ hg diff --rev 2:3
1861 diff -r b09be438c43a -r 8e07aafe1edc a
1864 diff -r b09be438c43a -r 8e07aafe1edc a
1862 --- a/a Thu Jan 01 00:00:00 1970 +0000
1865 --- a/a Thu Jan 01 00:00:00 1970 +0000
1863 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1866 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1864 @@ -1,1 +1,1 @@
1867 @@ -1,1 +1,1 @@
1865 -b
1868 -b
1866 +c
1869 +c
1867 diff -r b09be438c43a -r 8e07aafe1edc b
1870 diff -r b09be438c43a -r 8e07aafe1edc b
1868 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1871 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1869 +++ b/b Thu Jan 01 00:00:00 1970 +0000
1872 +++ b/b Thu Jan 01 00:00:00 1970 +0000
1870 @@ -0,0 +1,1 @@
1873 @@ -0,0 +1,1 @@
1871 +b
1874 +b
1872
1875
1873 Diff here should be the same:
1876 Diff here should be the same:
1874
1877
1875 $ hg log -vpr 3
1878 $ hg log -vpr 3
1876 changeset: 3:8e07aafe1edc
1879 changeset: 3:8e07aafe1edc
1877 tag: tip
1880 tag: tip
1878 parent: 2:b09be438c43a
1881 parent: 2:b09be438c43a
1879 parent: 1:925d80f479bb
1882 parent: 1:925d80f479bb
1880 user: test
1883 user: test
1881 date: Thu Jan 01 00:00:00 1970 +0000
1884 date: Thu Jan 01 00:00:00 1970 +0000
1882 files: a
1885 files: a
1883 description:
1886 description:
1884 3
1887 3
1885
1888
1886
1889
1887 diff -r b09be438c43a -r 8e07aafe1edc a
1890 diff -r b09be438c43a -r 8e07aafe1edc a
1888 --- a/a Thu Jan 01 00:00:00 1970 +0000
1891 --- a/a Thu Jan 01 00:00:00 1970 +0000
1889 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1892 +++ b/a Thu Jan 01 00:00:00 1970 +0000
1890 @@ -1,1 +1,1 @@
1893 @@ -1,1 +1,1 @@
1891 -b
1894 -b
1892 +c
1895 +c
1893 diff -r b09be438c43a -r 8e07aafe1edc b
1896 diff -r b09be438c43a -r 8e07aafe1edc b
1894 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1897 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1895 +++ b/b Thu Jan 01 00:00:00 1970 +0000
1898 +++ b/b Thu Jan 01 00:00:00 1970 +0000
1896 @@ -0,0 +1,1 @@
1899 @@ -0,0 +1,1 @@
1897 +b
1900 +b
1898
1901
1899 $ cd ..
1902 $ cd ..
1900
1903
1901 'hg log -r rev fn' when last(filelog(fn)) != rev
1904 'hg log -r rev fn' when last(filelog(fn)) != rev
1902
1905
1903 $ hg init simplelog
1906 $ hg init simplelog
1904 $ cd simplelog
1907 $ cd simplelog
1905 $ echo f > a
1908 $ echo f > a
1906 $ hg ci -Am'a' -d '0 0'
1909 $ hg ci -Am'a' -d '0 0'
1907 adding a
1910 adding a
1908 $ echo f >> a
1911 $ echo f >> a
1909 $ hg ci -Am'a bis' -d '1 0'
1912 $ hg ci -Am'a bis' -d '1 0'
1910
1913
1911 $ hg log -r0 a
1914 $ hg log -r0 a
1912 changeset: 0:9f758d63dcde
1915 changeset: 0:9f758d63dcde
1913 user: test
1916 user: test
1914 date: Thu Jan 01 00:00:00 1970 +0000
1917 date: Thu Jan 01 00:00:00 1970 +0000
1915 summary: a
1918 summary: a
1916
1919
1917 enable obsolete to test hidden feature
1920 enable obsolete to test hidden feature
1918
1921
1919 $ cat >> $HGRCPATH << EOF
1922 $ cat >> $HGRCPATH << EOF
1920 > [experimental]
1923 > [experimental]
1921 > evolution.createmarkers=True
1924 > evolution.createmarkers=True
1922 > EOF
1925 > EOF
1923
1926
1924 $ hg log --template='{rev}:{node}\n'
1927 $ hg log --template='{rev}:{node}\n'
1925 1:a765632148dc55d38c35c4f247c618701886cb2f
1928 1:a765632148dc55d38c35c4f247c618701886cb2f
1926 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1929 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1927 $ hg debugobsolete a765632148dc55d38c35c4f247c618701886cb2f
1930 $ hg debugobsolete a765632148dc55d38c35c4f247c618701886cb2f
1928 obsoleted 1 changesets
1931 obsoleted 1 changesets
1929 $ hg up null -q
1932 $ hg up null -q
1930 $ hg log --template='{rev}:{node}\n'
1933 $ hg log --template='{rev}:{node}\n'
1931 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1934 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1932 $ hg log --template='{rev}:{node}\n' --hidden
1935 $ hg log --template='{rev}:{node}\n' --hidden
1933 1:a765632148dc55d38c35c4f247c618701886cb2f
1936 1:a765632148dc55d38c35c4f247c618701886cb2f
1934 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1937 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1935 $ hg log -r a
1938 $ hg log -r a
1936 abort: hidden revision 'a' is pruned!
1939 abort: hidden revision 'a' is pruned!
1937 (use --hidden to access hidden revisions)
1940 (use --hidden to access hidden revisions)
1938 [255]
1941 [255]
1939
1942
1940 test that parent prevent a changeset to be hidden
1943 test that parent prevent a changeset to be hidden
1941
1944
1942 $ hg up 1 -q --hidden
1945 $ hg up 1 -q --hidden
1943 updating to a hidden changeset a765632148dc
1946 updating to a hidden changeset a765632148dc
1944 (hidden revision 'a765632148dc' is pruned)
1947 (hidden revision 'a765632148dc' is pruned)
1945 $ hg log --template='{rev}:{node}\n'
1948 $ hg log --template='{rev}:{node}\n'
1946 1:a765632148dc55d38c35c4f247c618701886cb2f
1949 1:a765632148dc55d38c35c4f247c618701886cb2f
1947 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1950 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1948
1951
1949 test that second parent prevent a changeset to be hidden too
1952 test that second parent prevent a changeset to be hidden too
1950
1953
1951 $ hg debugsetparents 0 1 # nothing suitable to merge here
1954 $ hg debugsetparents 0 1 # nothing suitable to merge here
1952 $ hg log --template='{rev}:{node}\n'
1955 $ hg log --template='{rev}:{node}\n'
1953 1:a765632148dc55d38c35c4f247c618701886cb2f
1956 1:a765632148dc55d38c35c4f247c618701886cb2f
1954 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1957 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1955 $ hg debugsetparents 1
1958 $ hg debugsetparents 1
1956 $ hg up -q null
1959 $ hg up -q null
1957
1960
1958 bookmarks prevent a changeset being hidden
1961 bookmarks prevent a changeset being hidden
1959
1962
1960 $ hg bookmark --hidden -r 1 X
1963 $ hg bookmark --hidden -r 1 X
1961 bookmarking hidden changeset a765632148dc
1964 bookmarking hidden changeset a765632148dc
1962 (hidden revision 'a765632148dc' is pruned)
1965 (hidden revision 'a765632148dc' is pruned)
1963 $ hg log --template '{rev}:{node}\n'
1966 $ hg log --template '{rev}:{node}\n'
1964 1:a765632148dc55d38c35c4f247c618701886cb2f
1967 1:a765632148dc55d38c35c4f247c618701886cb2f
1965 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1968 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1966 $ hg bookmark -d X
1969 $ hg bookmark -d X
1967
1970
1968 divergent bookmarks are not hidden
1971 divergent bookmarks are not hidden
1969
1972
1970 $ hg bookmark --hidden -r 1 X@foo
1973 $ hg bookmark --hidden -r 1 X@foo
1971 bookmarking hidden changeset a765632148dc
1974 bookmarking hidden changeset a765632148dc
1972 (hidden revision 'a765632148dc' is pruned)
1975 (hidden revision 'a765632148dc' is pruned)
1973 $ hg log --template '{rev}:{node}\n'
1976 $ hg log --template '{rev}:{node}\n'
1974 1:a765632148dc55d38c35c4f247c618701886cb2f
1977 1:a765632148dc55d38c35c4f247c618701886cb2f
1975 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1978 0:9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1976
1979
1977 test hidden revision 0 (issue5385)
1980 test hidden revision 0 (issue5385)
1978
1981
1979 $ hg bookmark -d X@foo
1982 $ hg bookmark -d X@foo
1980 $ hg up null -q
1983 $ hg up null -q
1981 $ hg debugobsolete 9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1984 $ hg debugobsolete 9f758d63dcde62d547ebfb08e1e7ee96535f2b05
1982 obsoleted 1 changesets
1985 obsoleted 1 changesets
1983 $ echo f > b
1986 $ echo f > b
1984 $ hg ci -Am'b' -d '2 0'
1987 $ hg ci -Am'b' -d '2 0'
1985 adding b
1988 adding b
1986 $ echo f >> b
1989 $ echo f >> b
1987 $ hg ci -m'b bis' -d '3 0'
1990 $ hg ci -m'b bis' -d '3 0'
1988 $ hg log -T'{rev}:{node}\n'
1991 $ hg log -T'{rev}:{node}\n'
1989 3:d7d28b288a6b83d5d2cf49f10c5974deed3a1d2e
1992 3:d7d28b288a6b83d5d2cf49f10c5974deed3a1d2e
1990 2:94375ec45bddd2a824535fc04855bd058c926ec0
1993 2:94375ec45bddd2a824535fc04855bd058c926ec0
1991
1994
1992 $ hg log -T'{rev}:{node}\n' -r:
1995 $ hg log -T'{rev}:{node}\n' -r:
1993 2:94375ec45bddd2a824535fc04855bd058c926ec0
1996 2:94375ec45bddd2a824535fc04855bd058c926ec0
1994 3:d7d28b288a6b83d5d2cf49f10c5974deed3a1d2e
1997 3:d7d28b288a6b83d5d2cf49f10c5974deed3a1d2e
1995 $ hg log -T'{rev}:{node}\n' -r:tip
1998 $ hg log -T'{rev}:{node}\n' -r:tip
1996 2:94375ec45bddd2a824535fc04855bd058c926ec0
1999 2:94375ec45bddd2a824535fc04855bd058c926ec0
1997 3:d7d28b288a6b83d5d2cf49f10c5974deed3a1d2e
2000 3:d7d28b288a6b83d5d2cf49f10c5974deed3a1d2e
1998 $ hg log -T'{rev}:{node}\n' -r:0
2001 $ hg log -T'{rev}:{node}\n' -r:0
1999 abort: hidden revision '0' is pruned!
2002 abort: hidden revision '0' is pruned!
2000 (use --hidden to access hidden revisions)
2003 (use --hidden to access hidden revisions)
2001 [255]
2004 [255]
2002 $ hg log -T'{rev}:{node}\n' -f
2005 $ hg log -T'{rev}:{node}\n' -f
2003 3:d7d28b288a6b83d5d2cf49f10c5974deed3a1d2e
2006 3:d7d28b288a6b83d5d2cf49f10c5974deed3a1d2e
2004 2:94375ec45bddd2a824535fc04855bd058c926ec0
2007 2:94375ec45bddd2a824535fc04855bd058c926ec0
2005
2008
2006 clear extensions configuration
2009 clear extensions configuration
2007 $ echo '[extensions]' >> $HGRCPATH
2010 $ echo '[extensions]' >> $HGRCPATH
2008 $ echo "obs=!" >> $HGRCPATH
2011 $ echo "obs=!" >> $HGRCPATH
2009 $ cd ..
2012 $ cd ..
2010
2013
2011 test -u/-k for problematic encoding
2014 test -u/-k for problematic encoding
2012 # unicode: cp932:
2015 # unicode: cp932:
2013 # u30A2 0x83 0x41(= 'A')
2016 # u30A2 0x83 0x41(= 'A')
2014 # u30C2 0x83 0x61(= 'a')
2017 # u30C2 0x83 0x61(= 'a')
2015
2018
2016 $ hg init problematicencoding
2019 $ hg init problematicencoding
2017 $ cd problematicencoding
2020 $ cd problematicencoding
2018
2021
2019 >>> with open('setup.sh', 'wb') as f:
2022 >>> with open('setup.sh', 'wb') as f:
2020 ... f.write(u'''
2023 ... f.write(u'''
2021 ... echo a > text
2024 ... echo a > text
2022 ... hg add text
2025 ... hg add text
2023 ... hg --encoding utf-8 commit -u '\u30A2' -m none
2026 ... hg --encoding utf-8 commit -u '\u30A2' -m none
2024 ... echo b > text
2027 ... echo b > text
2025 ... hg --encoding utf-8 commit -u '\u30C2' -m none
2028 ... hg --encoding utf-8 commit -u '\u30C2' -m none
2026 ... echo c > text
2029 ... echo c > text
2027 ... hg --encoding utf-8 commit -u none -m '\u30A2'
2030 ... hg --encoding utf-8 commit -u none -m '\u30A2'
2028 ... echo d > text
2031 ... echo d > text
2029 ... hg --encoding utf-8 commit -u none -m '\u30C2'
2032 ... hg --encoding utf-8 commit -u none -m '\u30C2'
2030 ... '''.encode('utf-8')) and None
2033 ... '''.encode('utf-8')) and None
2031 $ sh < setup.sh
2034 $ sh < setup.sh
2032
2035
2033 test in problematic encoding
2036 test in problematic encoding
2034 >>> with open('test.sh', 'wb') as f:
2037 >>> with open('test.sh', 'wb') as f:
2035 ... f.write(u'''
2038 ... f.write(u'''
2036 ... hg --encoding cp932 log --template '{rev}\\n' -u '\u30A2'
2039 ... hg --encoding cp932 log --template '{rev}\\n' -u '\u30A2'
2037 ... echo ====
2040 ... echo ====
2038 ... hg --encoding cp932 log --template '{rev}\\n' -u '\u30C2'
2041 ... hg --encoding cp932 log --template '{rev}\\n' -u '\u30C2'
2039 ... echo ====
2042 ... echo ====
2040 ... hg --encoding cp932 log --template '{rev}\\n' -k '\u30A2'
2043 ... hg --encoding cp932 log --template '{rev}\\n' -k '\u30A2'
2041 ... echo ====
2044 ... echo ====
2042 ... hg --encoding cp932 log --template '{rev}\\n' -k '\u30C2'
2045 ... hg --encoding cp932 log --template '{rev}\\n' -k '\u30C2'
2043 ... '''.encode('cp932')) and None
2046 ... '''.encode('cp932')) and None
2044 $ sh < test.sh
2047 $ sh < test.sh
2045 0
2048 0
2046 ====
2049 ====
2047 1
2050 1
2048 ====
2051 ====
2049 2
2052 2
2050 0
2053 0
2051 ====
2054 ====
2052 3
2055 3
2053 1
2056 1
2054
2057
2055 $ cd ..
2058 $ cd ..
2056
2059
2057 test hg log on non-existent files and on directories
2060 test hg log on non-existent files and on directories
2058 $ hg init issue1340
2061 $ hg init issue1340
2059 $ cd issue1340
2062 $ cd issue1340
2060 $ mkdir d1; mkdir D2; mkdir D3.i; mkdir d4.hg; mkdir d5.d; mkdir .d6
2063 $ mkdir d1; mkdir D2; mkdir D3.i; mkdir d4.hg; mkdir d5.d; mkdir .d6
2061 $ echo 1 > d1/f1
2064 $ echo 1 > d1/f1
2062 $ echo 1 > D2/f1
2065 $ echo 1 > D2/f1
2063 $ echo 1 > D3.i/f1
2066 $ echo 1 > D3.i/f1
2064 $ echo 1 > d4.hg/f1
2067 $ echo 1 > d4.hg/f1
2065 $ echo 1 > d5.d/f1
2068 $ echo 1 > d5.d/f1
2066 $ echo 1 > .d6/f1
2069 $ echo 1 > .d6/f1
2067 $ hg -q add .
2070 $ hg -q add .
2068 $ hg commit -m "a bunch of weird directories"
2071 $ hg commit -m "a bunch of weird directories"
2069 $ hg log -l1 d1/f1 | grep changeset
2072 $ hg log -l1 d1/f1 | grep changeset
2070 changeset: 0:65624cd9070a
2073 changeset: 0:65624cd9070a
2071 $ hg log -l1 f1
2074 $ hg log -l1 f1
2072 $ hg log -l1 . | grep changeset
2075 $ hg log -l1 . | grep changeset
2073 changeset: 0:65624cd9070a
2076 changeset: 0:65624cd9070a
2074 $ hg log -l1 ./ | grep changeset
2077 $ hg log -l1 ./ | grep changeset
2075 changeset: 0:65624cd9070a
2078 changeset: 0:65624cd9070a
2076 $ hg log -l1 d1 | grep changeset
2079 $ hg log -l1 d1 | grep changeset
2077 changeset: 0:65624cd9070a
2080 changeset: 0:65624cd9070a
2078 $ hg log -l1 D2 | grep changeset
2081 $ hg log -l1 D2 | grep changeset
2079 changeset: 0:65624cd9070a
2082 changeset: 0:65624cd9070a
2080 $ hg log -l1 D2/f1 | grep changeset
2083 $ hg log -l1 D2/f1 | grep changeset
2081 changeset: 0:65624cd9070a
2084 changeset: 0:65624cd9070a
2082 $ hg log -l1 D3.i | grep changeset
2085 $ hg log -l1 D3.i | grep changeset
2083 changeset: 0:65624cd9070a
2086 changeset: 0:65624cd9070a
2084 $ hg log -l1 D3.i/f1 | grep changeset
2087 $ hg log -l1 D3.i/f1 | grep changeset
2085 changeset: 0:65624cd9070a
2088 changeset: 0:65624cd9070a
2086 $ hg log -l1 d4.hg | grep changeset
2089 $ hg log -l1 d4.hg | grep changeset
2087 changeset: 0:65624cd9070a
2090 changeset: 0:65624cd9070a
2088 $ hg log -l1 d4.hg/f1 | grep changeset
2091 $ hg log -l1 d4.hg/f1 | grep changeset
2089 changeset: 0:65624cd9070a
2092 changeset: 0:65624cd9070a
2090 $ hg log -l1 d5.d | grep changeset
2093 $ hg log -l1 d5.d | grep changeset
2091 changeset: 0:65624cd9070a
2094 changeset: 0:65624cd9070a
2092 $ hg log -l1 d5.d/f1 | grep changeset
2095 $ hg log -l1 d5.d/f1 | grep changeset
2093 changeset: 0:65624cd9070a
2096 changeset: 0:65624cd9070a
2094 $ hg log -l1 .d6 | grep changeset
2097 $ hg log -l1 .d6 | grep changeset
2095 changeset: 0:65624cd9070a
2098 changeset: 0:65624cd9070a
2096 $ hg log -l1 .d6/f1 | grep changeset
2099 $ hg log -l1 .d6/f1 | grep changeset
2097 changeset: 0:65624cd9070a
2100 changeset: 0:65624cd9070a
2098
2101
2099 issue3772: hg log -r :null showing revision 0 as well
2102 issue3772: hg log -r :null showing revision 0 as well
2100
2103
2101 $ hg log -r :null
2104 $ hg log -r :null
2102 changeset: 0:65624cd9070a
2105 changeset: 0:65624cd9070a
2103 tag: tip
2106 tag: tip
2104 user: test
2107 user: test
2105 date: Thu Jan 01 00:00:00 1970 +0000
2108 date: Thu Jan 01 00:00:00 1970 +0000
2106 summary: a bunch of weird directories
2109 summary: a bunch of weird directories
2107
2110
2108 changeset: -1:000000000000
2111 changeset: -1:000000000000
2109 user:
2112 user:
2110 date: Thu Jan 01 00:00:00 1970 +0000
2113 date: Thu Jan 01 00:00:00 1970 +0000
2111
2114
2112 $ hg log -r null:null
2115 $ hg log -r null:null
2113 changeset: -1:000000000000
2116 changeset: -1:000000000000
2114 user:
2117 user:
2115 date: Thu Jan 01 00:00:00 1970 +0000
2118 date: Thu Jan 01 00:00:00 1970 +0000
2116
2119
2117 working-directory revision requires special treatment
2120 working-directory revision requires special treatment
2118
2121
2119 clean:
2122 clean:
2120
2123
2121 $ hg log -r 'wdir()' --debug
2124 $ hg log -r 'wdir()' --debug
2122 changeset: 2147483647:ffffffffffffffffffffffffffffffffffffffff
2125 changeset: 2147483647:ffffffffffffffffffffffffffffffffffffffff
2123 phase: draft
2126 phase: draft
2124 parent: 0:65624cd9070a035fa7191a54f2b8af39f16b0c08
2127 parent: 0:65624cd9070a035fa7191a54f2b8af39f16b0c08
2125 parent: -1:0000000000000000000000000000000000000000
2128 parent: -1:0000000000000000000000000000000000000000
2126 user: test
2129 user: test
2127 date: [A-Za-z0-9:+ ]+ (re)
2130 date: [A-Za-z0-9:+ ]+ (re)
2128 extra: branch=default
2131 extra: branch=default
2129
2132
2130 $ hg log -r 'wdir()' -p --stat
2133 $ hg log -r 'wdir()' -p --stat
2131 changeset: 2147483647:ffffffffffff
2134 changeset: 2147483647:ffffffffffff
2132 parent: 0:65624cd9070a
2135 parent: 0:65624cd9070a
2133 user: test
2136 user: test
2134 date: [A-Za-z0-9:+ ]+ (re)
2137 date: [A-Za-z0-9:+ ]+ (re)
2135
2138
2136
2139
2137
2140
2138
2141
2139 dirty:
2142 dirty:
2140
2143
2141 $ echo 2 >> d1/f1
2144 $ echo 2 >> d1/f1
2142 $ echo 2 > d1/f2
2145 $ echo 2 > d1/f2
2143 $ hg add d1/f2
2146 $ hg add d1/f2
2144 $ hg remove .d6/f1
2147 $ hg remove .d6/f1
2145 $ hg status
2148 $ hg status
2146 M d1/f1
2149 M d1/f1
2147 A d1/f2
2150 A d1/f2
2148 R .d6/f1
2151 R .d6/f1
2149
2152
2150 $ hg log -r 'wdir()'
2153 $ hg log -r 'wdir()'
2151 changeset: 2147483647:ffffffffffff
2154 changeset: 2147483647:ffffffffffff
2152 parent: 0:65624cd9070a
2155 parent: 0:65624cd9070a
2153 user: test
2156 user: test
2154 date: [A-Za-z0-9:+ ]+ (re)
2157 date: [A-Za-z0-9:+ ]+ (re)
2155
2158
2156 $ hg log -r 'wdir()' -q
2159 $ hg log -r 'wdir()' -q
2157 2147483647:ffffffffffff
2160 2147483647:ffffffffffff
2158
2161
2159 $ hg log -r 'wdir()' --debug
2162 $ hg log -r 'wdir()' --debug
2160 changeset: 2147483647:ffffffffffffffffffffffffffffffffffffffff
2163 changeset: 2147483647:ffffffffffffffffffffffffffffffffffffffff
2161 phase: draft
2164 phase: draft
2162 parent: 0:65624cd9070a035fa7191a54f2b8af39f16b0c08
2165 parent: 0:65624cd9070a035fa7191a54f2b8af39f16b0c08
2163 parent: -1:0000000000000000000000000000000000000000
2166 parent: -1:0000000000000000000000000000000000000000
2164 user: test
2167 user: test
2165 date: [A-Za-z0-9:+ ]+ (re)
2168 date: [A-Za-z0-9:+ ]+ (re)
2166 files: d1/f1
2169 files: d1/f1
2167 files+: d1/f2
2170 files+: d1/f2
2168 files-: .d6/f1
2171 files-: .d6/f1
2169 extra: branch=default
2172 extra: branch=default
2170
2173
2171 $ hg log -r 'wdir()' -p --stat --git
2174 $ hg log -r 'wdir()' -p --stat --git
2172 changeset: 2147483647:ffffffffffff
2175 changeset: 2147483647:ffffffffffff
2173 parent: 0:65624cd9070a
2176 parent: 0:65624cd9070a
2174 user: test
2177 user: test
2175 date: [A-Za-z0-9:+ ]+ (re)
2178 date: [A-Za-z0-9:+ ]+ (re)
2176
2179
2177 .d6/f1 | 1 -
2180 .d6/f1 | 1 -
2178 d1/f1 | 1 +
2181 d1/f1 | 1 +
2179 d1/f2 | 1 +
2182 d1/f2 | 1 +
2180 3 files changed, 2 insertions(+), 1 deletions(-)
2183 3 files changed, 2 insertions(+), 1 deletions(-)
2181
2184
2182 diff --git a/.d6/f1 b/.d6/f1
2185 diff --git a/.d6/f1 b/.d6/f1
2183 deleted file mode 100644
2186 deleted file mode 100644
2184 --- a/.d6/f1
2187 --- a/.d6/f1
2185 +++ /dev/null
2188 +++ /dev/null
2186 @@ -1,1 +0,0 @@
2189 @@ -1,1 +0,0 @@
2187 -1
2190 -1
2188 diff --git a/d1/f1 b/d1/f1
2191 diff --git a/d1/f1 b/d1/f1
2189 --- a/d1/f1
2192 --- a/d1/f1
2190 +++ b/d1/f1
2193 +++ b/d1/f1
2191 @@ -1,1 +1,2 @@
2194 @@ -1,1 +1,2 @@
2192 1
2195 1
2193 +2
2196 +2
2194 diff --git a/d1/f2 b/d1/f2
2197 diff --git a/d1/f2 b/d1/f2
2195 new file mode 100644
2198 new file mode 100644
2196 --- /dev/null
2199 --- /dev/null
2197 +++ b/d1/f2
2200 +++ b/d1/f2
2198 @@ -0,0 +1,1 @@
2201 @@ -0,0 +1,1 @@
2199 +2
2202 +2
2200
2203
2201 $ hg log -r 'wdir()' -Tjson
2204 $ hg log -r 'wdir()' -Tjson
2202 [
2205 [
2203 {
2206 {
2204 "bookmarks": [],
2207 "bookmarks": [],
2205 "branch": "default",
2208 "branch": "default",
2206 "date": [*, 0], (glob)
2209 "date": [*, 0], (glob)
2207 "desc": "",
2210 "desc": "",
2208 "node": null,
2211 "node": null,
2209 "parents": ["65624cd9070a035fa7191a54f2b8af39f16b0c08"],
2212 "parents": ["65624cd9070a035fa7191a54f2b8af39f16b0c08"],
2210 "phase": "draft",
2213 "phase": "draft",
2211 "rev": null,
2214 "rev": null,
2212 "tags": [],
2215 "tags": [],
2213 "user": "test"
2216 "user": "test"
2214 }
2217 }
2215 ]
2218 ]
2216
2219
2217 $ hg log -r 'wdir()' -Tjson -q
2220 $ hg log -r 'wdir()' -Tjson -q
2218 [
2221 [
2219 {
2222 {
2220 "node": null,
2223 "node": null,
2221 "rev": null
2224 "rev": null
2222 }
2225 }
2223 ]
2226 ]
2224
2227
2225 $ hg log -r 'wdir()' -Tjson --debug
2228 $ hg log -r 'wdir()' -Tjson --debug
2226 [
2229 [
2227 {
2230 {
2228 "added": ["d1/f2"],
2231 "added": ["d1/f2"],
2229 "bookmarks": [],
2232 "bookmarks": [],
2230 "branch": "default",
2233 "branch": "default",
2231 "date": [*, 0], (glob)
2234 "date": [*, 0], (glob)
2232 "desc": "",
2235 "desc": "",
2233 "extra": {"branch": "default"},
2236 "extra": {"branch": "default"},
2234 "manifest": null,
2237 "manifest": null,
2235 "modified": ["d1/f1"],
2238 "modified": ["d1/f1"],
2236 "node": null,
2239 "node": null,
2237 "parents": ["65624cd9070a035fa7191a54f2b8af39f16b0c08"],
2240 "parents": ["65624cd9070a035fa7191a54f2b8af39f16b0c08"],
2238 "phase": "draft",
2241 "phase": "draft",
2239 "removed": [".d6/f1"],
2242 "removed": [".d6/f1"],
2240 "rev": null,
2243 "rev": null,
2241 "tags": [],
2244 "tags": [],
2242 "user": "test"
2245 "user": "test"
2243 }
2246 }
2244 ]
2247 ]
2245
2248
2246 $ hg revert -aqC
2249 $ hg revert -aqC
2247
2250
2248 Check that adding an arbitrary name shows up in log automatically
2251 Check that adding an arbitrary name shows up in log automatically
2249
2252
2250 $ cat > ../names.py <<EOF
2253 $ cat > ../names.py <<EOF
2251 > """A small extension to test adding arbitrary names to a repo"""
2254 > """A small extension to test adding arbitrary names to a repo"""
2252 > from __future__ import absolute_import
2255 > from __future__ import absolute_import
2253 > from mercurial import namespaces
2256 > from mercurial import namespaces
2254 >
2257 >
2255 > def reposetup(ui, repo):
2258 > def reposetup(ui, repo):
2256 > foo = {b'foo': repo[0].node()}
2259 > foo = {b'foo': repo[0].node()}
2257 > names = lambda r: foo.keys()
2260 > names = lambda r: foo.keys()
2258 > namemap = lambda r, name: foo.get(name)
2261 > namemap = lambda r, name: foo.get(name)
2259 > nodemap = lambda r, node: [name for name, n in foo.items()
2262 > nodemap = lambda r, node: [name for name, n in foo.items()
2260 > if n == node]
2263 > if n == node]
2261 > ns = namespaces.namespace(
2264 > ns = namespaces.namespace(
2262 > b"bars", templatename=b"bar", logname=b"barlog",
2265 > b"bars", templatename=b"bar", logname=b"barlog",
2263 > colorname=b"barcolor", listnames=names, namemap=namemap,
2266 > colorname=b"barcolor", listnames=names, namemap=namemap,
2264 > nodemap=nodemap)
2267 > nodemap=nodemap)
2265 >
2268 >
2266 > repo.names.addnamespace(ns)
2269 > repo.names.addnamespace(ns)
2267 > EOF
2270 > EOF
2268
2271
2269 $ hg --config extensions.names=../names.py log -r 0
2272 $ hg --config extensions.names=../names.py log -r 0
2270 changeset: 0:65624cd9070a
2273 changeset: 0:65624cd9070a
2271 tag: tip
2274 tag: tip
2272 barlog: foo
2275 barlog: foo
2273 user: test
2276 user: test
2274 date: Thu Jan 01 00:00:00 1970 +0000
2277 date: Thu Jan 01 00:00:00 1970 +0000
2275 summary: a bunch of weird directories
2278 summary: a bunch of weird directories
2276
2279
2277 $ hg --config extensions.names=../names.py \
2280 $ hg --config extensions.names=../names.py \
2278 > --config extensions.color= --config color.log.barcolor=red \
2281 > --config extensions.color= --config color.log.barcolor=red \
2279 > --color=always log -r 0
2282 > --color=always log -r 0
2280 \x1b[0;33mchangeset: 0:65624cd9070a\x1b[0m (esc)
2283 \x1b[0;33mchangeset: 0:65624cd9070a\x1b[0m (esc)
2281 tag: tip
2284 tag: tip
2282 \x1b[0;31mbarlog: foo\x1b[0m (esc)
2285 \x1b[0;31mbarlog: foo\x1b[0m (esc)
2283 user: test
2286 user: test
2284 date: Thu Jan 01 00:00:00 1970 +0000
2287 date: Thu Jan 01 00:00:00 1970 +0000
2285 summary: a bunch of weird directories
2288 summary: a bunch of weird directories
2286
2289
2287 $ hg --config extensions.names=../names.py log -r 0 --template '{bars}\n'
2290 $ hg --config extensions.names=../names.py log -r 0 --template '{bars}\n'
2288 foo
2291 foo
2289
2292
2290 Templater parse errors:
2293 Templater parse errors:
2291
2294
2292 simple error
2295 simple error
2293 $ hg log -r . -T '{shortest(node}'
2296 $ hg log -r . -T '{shortest(node}'
2294 hg: parse error at 14: unexpected token: end
2297 hg: parse error at 14: unexpected token: end
2295 ({shortest(node}
2298 ({shortest(node}
2296 ^ here)
2299 ^ here)
2297 [255]
2300 [255]
2298
2301
2299 multi-line template with error
2302 multi-line template with error
2300 $ hg log -r . -T 'line 1
2303 $ hg log -r . -T 'line 1
2301 > line2
2304 > line2
2302 > {shortest(node}
2305 > {shortest(node}
2303 > line4\nline5'
2306 > line4\nline5'
2304 hg: parse error at 27: unexpected token: end
2307 hg: parse error at 27: unexpected token: end
2305 (line 1\nline2\n{shortest(node}\nline4\nline5
2308 (line 1\nline2\n{shortest(node}\nline4\nline5
2306 ^ here)
2309 ^ here)
2307 [255]
2310 [255]
2308
2311
2309 $ cd ..
2312 $ cd ..
2310
2313
2311 hg log -f dir across branches
2314 hg log -f dir across branches
2312
2315
2313 $ hg init acrossbranches
2316 $ hg init acrossbranches
2314 $ cd acrossbranches
2317 $ cd acrossbranches
2315 $ mkdir d
2318 $ mkdir d
2316 $ echo a > d/a && hg ci -Aqm a
2319 $ echo a > d/a && hg ci -Aqm a
2317 $ echo b > d/a && hg ci -Aqm b
2320 $ echo b > d/a && hg ci -Aqm b
2318 $ hg up -q 0
2321 $ hg up -q 0
2319 $ echo b > d/a && hg ci -Aqm c
2322 $ echo b > d/a && hg ci -Aqm c
2320 $ hg log -f d -T '{desc}' -G
2323 $ hg log -f d -T '{desc}' -G
2321 @ c
2324 @ c
2322 |
2325 |
2323 o a
2326 o a
2324
2327
2325 Ensure that largefiles doesn't interfere with following a normal file
2328 Ensure that largefiles doesn't interfere with following a normal file
2326 $ hg --config extensions.largefiles= log -f d -T '{desc}' -G
2329 $ hg --config extensions.largefiles= log -f d -T '{desc}' -G
2327 The fsmonitor extension is incompatible with the largefiles extension and has been disabled. (fsmonitor !)
2330 The fsmonitor extension is incompatible with the largefiles extension and has been disabled. (fsmonitor !)
2328 @ c
2331 @ c
2329 |
2332 |
2330 o a
2333 o a
2331
2334
2332 $ hg log -f d/a -T '{desc}' -G
2335 $ hg log -f d/a -T '{desc}' -G
2333 @ c
2336 @ c
2334 |
2337 |
2335 o a
2338 o a
2336
2339
2337 $ cd ..
2340 $ cd ..
2338
2341
2339 hg log -f with linkrev pointing to another branch
2342 hg log -f with linkrev pointing to another branch
2340 -------------------------------------------------
2343 -------------------------------------------------
2341
2344
2342 create history with a filerev whose linkrev points to another branch
2345 create history with a filerev whose linkrev points to another branch
2343
2346
2344 $ hg init branchedlinkrev
2347 $ hg init branchedlinkrev
2345 $ cd branchedlinkrev
2348 $ cd branchedlinkrev
2346 $ echo 1 > a
2349 $ echo 1 > a
2347 $ hg commit -Am 'content1'
2350 $ hg commit -Am 'content1'
2348 adding a
2351 adding a
2349 $ echo 2 > a
2352 $ echo 2 > a
2350 $ hg commit -m 'content2'
2353 $ hg commit -m 'content2'
2351 $ hg up --rev 'desc(content1)'
2354 $ hg up --rev 'desc(content1)'
2352 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
2355 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
2353 $ echo unrelated > unrelated
2356 $ echo unrelated > unrelated
2354 $ hg commit -Am 'unrelated'
2357 $ hg commit -Am 'unrelated'
2355 adding unrelated
2358 adding unrelated
2356 created new head
2359 created new head
2357 $ hg graft -r 'desc(content2)'
2360 $ hg graft -r 'desc(content2)'
2358 grafting 1:2294ae80ad84 "content2"
2361 grafting 1:2294ae80ad84 "content2"
2359 $ echo 3 > a
2362 $ echo 3 > a
2360 $ hg commit -m 'content3'
2363 $ hg commit -m 'content3'
2361 $ hg log -G
2364 $ hg log -G
2362 @ changeset: 4:50b9b36e9c5d
2365 @ changeset: 4:50b9b36e9c5d
2363 | tag: tip
2366 | tag: tip
2364 | user: test
2367 | user: test
2365 | date: Thu Jan 01 00:00:00 1970 +0000
2368 | date: Thu Jan 01 00:00:00 1970 +0000
2366 | summary: content3
2369 | summary: content3
2367 |
2370 |
2368 o changeset: 3:15b2327059e5
2371 o changeset: 3:15b2327059e5
2369 | user: test
2372 | user: test
2370 | date: Thu Jan 01 00:00:00 1970 +0000
2373 | date: Thu Jan 01 00:00:00 1970 +0000
2371 | summary: content2
2374 | summary: content2
2372 |
2375 |
2373 o changeset: 2:2029acd1168c
2376 o changeset: 2:2029acd1168c
2374 | parent: 0:ae0a3c9f9e95
2377 | parent: 0:ae0a3c9f9e95
2375 | user: test
2378 | user: test
2376 | date: Thu Jan 01 00:00:00 1970 +0000
2379 | date: Thu Jan 01 00:00:00 1970 +0000
2377 | summary: unrelated
2380 | summary: unrelated
2378 |
2381 |
2379 | o changeset: 1:2294ae80ad84
2382 | o changeset: 1:2294ae80ad84
2380 |/ user: test
2383 |/ user: test
2381 | date: Thu Jan 01 00:00:00 1970 +0000
2384 | date: Thu Jan 01 00:00:00 1970 +0000
2382 | summary: content2
2385 | summary: content2
2383 |
2386 |
2384 o changeset: 0:ae0a3c9f9e95
2387 o changeset: 0:ae0a3c9f9e95
2385 user: test
2388 user: test
2386 date: Thu Jan 01 00:00:00 1970 +0000
2389 date: Thu Jan 01 00:00:00 1970 +0000
2387 summary: content1
2390 summary: content1
2388
2391
2389
2392
2390 log -f on the file should list the graft result.
2393 log -f on the file should list the graft result.
2391
2394
2392 $ hg log -Gf a
2395 $ hg log -Gf a
2393 @ changeset: 4:50b9b36e9c5d
2396 @ changeset: 4:50b9b36e9c5d
2394 | tag: tip
2397 | tag: tip
2395 | user: test
2398 | user: test
2396 | date: Thu Jan 01 00:00:00 1970 +0000
2399 | date: Thu Jan 01 00:00:00 1970 +0000
2397 | summary: content3
2400 | summary: content3
2398 |
2401 |
2399 o changeset: 3:15b2327059e5
2402 o changeset: 3:15b2327059e5
2400 : user: test
2403 : user: test
2401 : date: Thu Jan 01 00:00:00 1970 +0000
2404 : date: Thu Jan 01 00:00:00 1970 +0000
2402 : summary: content2
2405 : summary: content2
2403 :
2406 :
2404 o changeset: 0:ae0a3c9f9e95
2407 o changeset: 0:ae0a3c9f9e95
2405 user: test
2408 user: test
2406 date: Thu Jan 01 00:00:00 1970 +0000
2409 date: Thu Jan 01 00:00:00 1970 +0000
2407 summary: content1
2410 summary: content1
2408
2411
2409
2412
2410 plain log lists the original version
2413 plain log lists the original version
2411 (XXX we should probably list both)
2414 (XXX we should probably list both)
2412
2415
2413 $ hg log -G a
2416 $ hg log -G a
2414 @ changeset: 4:50b9b36e9c5d
2417 @ changeset: 4:50b9b36e9c5d
2415 : tag: tip
2418 : tag: tip
2416 : user: test
2419 : user: test
2417 : date: Thu Jan 01 00:00:00 1970 +0000
2420 : date: Thu Jan 01 00:00:00 1970 +0000
2418 : summary: content3
2421 : summary: content3
2419 :
2422 :
2420 : o changeset: 1:2294ae80ad84
2423 : o changeset: 1:2294ae80ad84
2421 :/ user: test
2424 :/ user: test
2422 : date: Thu Jan 01 00:00:00 1970 +0000
2425 : date: Thu Jan 01 00:00:00 1970 +0000
2423 : summary: content2
2426 : summary: content2
2424 :
2427 :
2425 o changeset: 0:ae0a3c9f9e95
2428 o changeset: 0:ae0a3c9f9e95
2426 user: test
2429 user: test
2427 date: Thu Jan 01 00:00:00 1970 +0000
2430 date: Thu Jan 01 00:00:00 1970 +0000
2428 summary: content1
2431 summary: content1
2429
2432
2430
2433
2431 hg log -f from the grafted changeset
2434 hg log -f from the grafted changeset
2432 (The bootstrap should properly take the topology in account)
2435 (The bootstrap should properly take the topology in account)
2433
2436
2434 $ hg up 'desc(content3)^'
2437 $ hg up 'desc(content3)^'
2435 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
2438 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
2436 $ hg log -Gf a
2439 $ hg log -Gf a
2437 @ changeset: 3:15b2327059e5
2440 @ changeset: 3:15b2327059e5
2438 : user: test
2441 : user: test
2439 : date: Thu Jan 01 00:00:00 1970 +0000
2442 : date: Thu Jan 01 00:00:00 1970 +0000
2440 : summary: content2
2443 : summary: content2
2441 :
2444 :
2442 o changeset: 0:ae0a3c9f9e95
2445 o changeset: 0:ae0a3c9f9e95
2443 user: test
2446 user: test
2444 date: Thu Jan 01 00:00:00 1970 +0000
2447 date: Thu Jan 01 00:00:00 1970 +0000
2445 summary: content1
2448 summary: content1
2446
2449
2447
2450
2448 Test that we use the first non-hidden changeset in that case.
2451 Test that we use the first non-hidden changeset in that case.
2449
2452
2450 (hide the changeset)
2453 (hide the changeset)
2451
2454
2452 $ hg log -T '{node}\n' -r 1
2455 $ hg log -T '{node}\n' -r 1
2453 2294ae80ad8447bc78383182eeac50cb049df623
2456 2294ae80ad8447bc78383182eeac50cb049df623
2454 $ hg debugobsolete 2294ae80ad8447bc78383182eeac50cb049df623
2457 $ hg debugobsolete 2294ae80ad8447bc78383182eeac50cb049df623
2455 obsoleted 1 changesets
2458 obsoleted 1 changesets
2456 $ hg log -G
2459 $ hg log -G
2457 o changeset: 4:50b9b36e9c5d
2460 o changeset: 4:50b9b36e9c5d
2458 | tag: tip
2461 | tag: tip
2459 | user: test
2462 | user: test
2460 | date: Thu Jan 01 00:00:00 1970 +0000
2463 | date: Thu Jan 01 00:00:00 1970 +0000
2461 | summary: content3
2464 | summary: content3
2462 |
2465 |
2463 @ changeset: 3:15b2327059e5
2466 @ changeset: 3:15b2327059e5
2464 | user: test
2467 | user: test
2465 | date: Thu Jan 01 00:00:00 1970 +0000
2468 | date: Thu Jan 01 00:00:00 1970 +0000
2466 | summary: content2
2469 | summary: content2
2467 |
2470 |
2468 o changeset: 2:2029acd1168c
2471 o changeset: 2:2029acd1168c
2469 | parent: 0:ae0a3c9f9e95
2472 | parent: 0:ae0a3c9f9e95
2470 | user: test
2473 | user: test
2471 | date: Thu Jan 01 00:00:00 1970 +0000
2474 | date: Thu Jan 01 00:00:00 1970 +0000
2472 | summary: unrelated
2475 | summary: unrelated
2473 |
2476 |
2474 o changeset: 0:ae0a3c9f9e95
2477 o changeset: 0:ae0a3c9f9e95
2475 user: test
2478 user: test
2476 date: Thu Jan 01 00:00:00 1970 +0000
2479 date: Thu Jan 01 00:00:00 1970 +0000
2477 summary: content1
2480 summary: content1
2478
2481
2479
2482
2480 Check that log on the file does not drop the file revision.
2483 Check that log on the file does not drop the file revision.
2481
2484
2482 $ hg log -G a
2485 $ hg log -G a
2483 o changeset: 4:50b9b36e9c5d
2486 o changeset: 4:50b9b36e9c5d
2484 | tag: tip
2487 | tag: tip
2485 | user: test
2488 | user: test
2486 | date: Thu Jan 01 00:00:00 1970 +0000
2489 | date: Thu Jan 01 00:00:00 1970 +0000
2487 | summary: content3
2490 | summary: content3
2488 |
2491 |
2489 @ changeset: 3:15b2327059e5
2492 @ changeset: 3:15b2327059e5
2490 : user: test
2493 : user: test
2491 : date: Thu Jan 01 00:00:00 1970 +0000
2494 : date: Thu Jan 01 00:00:00 1970 +0000
2492 : summary: content2
2495 : summary: content2
2493 :
2496 :
2494 o changeset: 0:ae0a3c9f9e95
2497 o changeset: 0:ae0a3c9f9e95
2495 user: test
2498 user: test
2496 date: Thu Jan 01 00:00:00 1970 +0000
2499 date: Thu Jan 01 00:00:00 1970 +0000
2497 summary: content1
2500 summary: content1
2498
2501
2499
2502
2500 Even when a head revision is linkrev-shadowed.
2503 Even when a head revision is linkrev-shadowed.
2501
2504
2502 $ hg log -T '{node}\n' -r 4
2505 $ hg log -T '{node}\n' -r 4
2503 50b9b36e9c5df2c6fc6dcefa8ad0da929e84aed2
2506 50b9b36e9c5df2c6fc6dcefa8ad0da929e84aed2
2504 $ hg debugobsolete 50b9b36e9c5df2c6fc6dcefa8ad0da929e84aed2
2507 $ hg debugobsolete 50b9b36e9c5df2c6fc6dcefa8ad0da929e84aed2
2505 obsoleted 1 changesets
2508 obsoleted 1 changesets
2506 $ hg log -G a
2509 $ hg log -G a
2507 @ changeset: 3:15b2327059e5
2510 @ changeset: 3:15b2327059e5
2508 : tag: tip
2511 : tag: tip
2509 : user: test
2512 : user: test
2510 : date: Thu Jan 01 00:00:00 1970 +0000
2513 : date: Thu Jan 01 00:00:00 1970 +0000
2511 : summary: content2
2514 : summary: content2
2512 :
2515 :
2513 o changeset: 0:ae0a3c9f9e95
2516 o changeset: 0:ae0a3c9f9e95
2514 user: test
2517 user: test
2515 date: Thu Jan 01 00:00:00 1970 +0000
2518 date: Thu Jan 01 00:00:00 1970 +0000
2516 summary: content1
2519 summary: content1
2517
2520
2518
2521
2519 $ cd ..
2522 $ cd ..
2520
2523
2521 Even when the file revision is missing from some head:
2524 Even when the file revision is missing from some head:
2522
2525
2523 $ hg init issue4490
2526 $ hg init issue4490
2524 $ cd issue4490
2527 $ cd issue4490
2525 $ echo '[experimental]' >> .hg/hgrc
2528 $ echo '[experimental]' >> .hg/hgrc
2526 $ echo 'evolution.createmarkers=True' >> .hg/hgrc
2529 $ echo 'evolution.createmarkers=True' >> .hg/hgrc
2527 $ echo a > a
2530 $ echo a > a
2528 $ hg ci -Am0
2531 $ hg ci -Am0
2529 adding a
2532 adding a
2530 $ echo b > b
2533 $ echo b > b
2531 $ hg ci -Am1
2534 $ hg ci -Am1
2532 adding b
2535 adding b
2533 $ echo B > b
2536 $ echo B > b
2534 $ hg ci --amend -m 1
2537 $ hg ci --amend -m 1
2535 $ hg up 0
2538 $ hg up 0
2536 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
2539 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
2537 $ echo c > c
2540 $ echo c > c
2538 $ hg ci -Am2
2541 $ hg ci -Am2
2539 adding c
2542 adding c
2540 created new head
2543 created new head
2541 $ hg up 'head() and not .'
2544 $ hg up 'head() and not .'
2542 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
2545 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
2543 $ hg log -G
2546 $ hg log -G
2544 o changeset: 3:db815d6d32e6
2547 o changeset: 3:db815d6d32e6
2545 | tag: tip
2548 | tag: tip
2546 | parent: 0:f7b1eb17ad24
2549 | parent: 0:f7b1eb17ad24
2547 | user: test
2550 | user: test
2548 | date: Thu Jan 01 00:00:00 1970 +0000
2551 | date: Thu Jan 01 00:00:00 1970 +0000
2549 | summary: 2
2552 | summary: 2
2550 |
2553 |
2551 | @ changeset: 2:9bc8ce7f9356
2554 | @ changeset: 2:9bc8ce7f9356
2552 |/ parent: 0:f7b1eb17ad24
2555 |/ parent: 0:f7b1eb17ad24
2553 | user: test
2556 | user: test
2554 | date: Thu Jan 01 00:00:00 1970 +0000
2557 | date: Thu Jan 01 00:00:00 1970 +0000
2555 | summary: 1
2558 | summary: 1
2556 |
2559 |
2557 o changeset: 0:f7b1eb17ad24
2560 o changeset: 0:f7b1eb17ad24
2558 user: test
2561 user: test
2559 date: Thu Jan 01 00:00:00 1970 +0000
2562 date: Thu Jan 01 00:00:00 1970 +0000
2560 summary: 0
2563 summary: 0
2561
2564
2562 $ hg log -f -G b
2565 $ hg log -f -G b
2563 @ changeset: 2:9bc8ce7f9356
2566 @ changeset: 2:9bc8ce7f9356
2564 | parent: 0:f7b1eb17ad24
2567 | parent: 0:f7b1eb17ad24
2565 ~ user: test
2568 ~ user: test
2566 date: Thu Jan 01 00:00:00 1970 +0000
2569 date: Thu Jan 01 00:00:00 1970 +0000
2567 summary: 1
2570 summary: 1
2568
2571
2569 $ hg log -G b
2572 $ hg log -G b
2570 @ changeset: 2:9bc8ce7f9356
2573 @ changeset: 2:9bc8ce7f9356
2571 | parent: 0:f7b1eb17ad24
2574 | parent: 0:f7b1eb17ad24
2572 ~ user: test
2575 ~ user: test
2573 date: Thu Jan 01 00:00:00 1970 +0000
2576 date: Thu Jan 01 00:00:00 1970 +0000
2574 summary: 1
2577 summary: 1
2575
2578
2576 $ cd ..
2579 $ cd ..
2577
2580
2578 Check proper report when the manifest changes but not the file issue4499
2581 Check proper report when the manifest changes but not the file issue4499
2579 ------------------------------------------------------------------------
2582 ------------------------------------------------------------------------
2580
2583
2581 $ hg init issue4499
2584 $ hg init issue4499
2582 $ cd issue4499
2585 $ cd issue4499
2583 $ for f in A B C D F E G H I J K L M N O P Q R S T U; do
2586 $ for f in A B C D F E G H I J K L M N O P Q R S T U; do
2584 > echo 1 > $f;
2587 > echo 1 > $f;
2585 > hg add $f;
2588 > hg add $f;
2586 > done
2589 > done
2587 $ hg commit -m 'A1B1C1'
2590 $ hg commit -m 'A1B1C1'
2588 $ echo 2 > A
2591 $ echo 2 > A
2589 $ echo 2 > B
2592 $ echo 2 > B
2590 $ echo 2 > C
2593 $ echo 2 > C
2591 $ hg commit -m 'A2B2C2'
2594 $ hg commit -m 'A2B2C2'
2592 $ hg up 0
2595 $ hg up 0
2593 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
2596 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
2594 $ echo 3 > A
2597 $ echo 3 > A
2595 $ echo 2 > B
2598 $ echo 2 > B
2596 $ echo 2 > C
2599 $ echo 2 > C
2597 $ hg commit -m 'A3B2C2'
2600 $ hg commit -m 'A3B2C2'
2598 created new head
2601 created new head
2599
2602
2600 $ hg log -G
2603 $ hg log -G
2601 @ changeset: 2:fe5fc3d0eb17
2604 @ changeset: 2:fe5fc3d0eb17
2602 | tag: tip
2605 | tag: tip
2603 | parent: 0:abf4f0e38563
2606 | parent: 0:abf4f0e38563
2604 | user: test
2607 | user: test
2605 | date: Thu Jan 01 00:00:00 1970 +0000
2608 | date: Thu Jan 01 00:00:00 1970 +0000
2606 | summary: A3B2C2
2609 | summary: A3B2C2
2607 |
2610 |
2608 | o changeset: 1:07dcc6b312c0
2611 | o changeset: 1:07dcc6b312c0
2609 |/ user: test
2612 |/ user: test
2610 | date: Thu Jan 01 00:00:00 1970 +0000
2613 | date: Thu Jan 01 00:00:00 1970 +0000
2611 | summary: A2B2C2
2614 | summary: A2B2C2
2612 |
2615 |
2613 o changeset: 0:abf4f0e38563
2616 o changeset: 0:abf4f0e38563
2614 user: test
2617 user: test
2615 date: Thu Jan 01 00:00:00 1970 +0000
2618 date: Thu Jan 01 00:00:00 1970 +0000
2616 summary: A1B1C1
2619 summary: A1B1C1
2617
2620
2618
2621
2619 Log -f on B should reports current changesets
2622 Log -f on B should reports current changesets
2620
2623
2621 $ hg log -fG B
2624 $ hg log -fG B
2622 @ changeset: 2:fe5fc3d0eb17
2625 @ changeset: 2:fe5fc3d0eb17
2623 | tag: tip
2626 | tag: tip
2624 | parent: 0:abf4f0e38563
2627 | parent: 0:abf4f0e38563
2625 | user: test
2628 | user: test
2626 | date: Thu Jan 01 00:00:00 1970 +0000
2629 | date: Thu Jan 01 00:00:00 1970 +0000
2627 | summary: A3B2C2
2630 | summary: A3B2C2
2628 |
2631 |
2629 o changeset: 0:abf4f0e38563
2632 o changeset: 0:abf4f0e38563
2630 user: test
2633 user: test
2631 date: Thu Jan 01 00:00:00 1970 +0000
2634 date: Thu Jan 01 00:00:00 1970 +0000
2632 summary: A1B1C1
2635 summary: A1B1C1
2633
2636
2634 $ cd ..
2637 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now