##// END OF EJS Templates
archive: add support to specify hidden revs if directaccess config is set...
Pulkit Goyal -
r35553:ffd7b7cd default
parent child Browse files
Show More
@@ -1,5620 +1,5623 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 merge as mergemod,
44 merge as mergemod,
45 obsolete,
45 obsolete,
46 patch,
46 patch,
47 phases,
47 phases,
48 pycompat,
48 pycompat,
49 rcutil,
49 rcutil,
50 registrar,
50 registrar,
51 revsetlang,
51 revsetlang,
52 rewriteutil,
52 rewriteutil,
53 scmutil,
53 scmutil,
54 server,
54 server,
55 sshserver,
55 sshserver,
56 streamclone,
56 streamclone,
57 tags as tagsmod,
57 tags as tagsmod,
58 templatekw,
58 templatekw,
59 ui as uimod,
59 ui as uimod,
60 util,
60 util,
61 )
61 )
62
62
63 release = lockmod.release
63 release = lockmod.release
64
64
65 table = {}
65 table = {}
66 table.update(debugcommandsmod.command._table)
66 table.update(debugcommandsmod.command._table)
67
67
68 command = registrar.command(table)
68 command = registrar.command(table)
69 readonly = registrar.command.readonly
69 readonly = registrar.command.readonly
70
70
71 # common command options
71 # common command options
72
72
73 globalopts = [
73 globalopts = [
74 ('R', 'repository', '',
74 ('R', 'repository', '',
75 _('repository root directory or name of overlay bundle file'),
75 _('repository root directory or name of overlay bundle file'),
76 _('REPO')),
76 _('REPO')),
77 ('', 'cwd', '',
77 ('', 'cwd', '',
78 _('change working directory'), _('DIR')),
78 _('change working directory'), _('DIR')),
79 ('y', 'noninteractive', None,
79 ('y', 'noninteractive', None,
80 _('do not prompt, automatically pick the first choice for all prompts')),
80 _('do not prompt, automatically pick the first choice for all prompts')),
81 ('q', 'quiet', None, _('suppress output')),
81 ('q', 'quiet', None, _('suppress output')),
82 ('v', 'verbose', None, _('enable additional output')),
82 ('v', 'verbose', None, _('enable additional output')),
83 ('', 'color', '',
83 ('', 'color', '',
84 # i18n: 'always', 'auto', 'never', and 'debug' are keywords
84 # i18n: 'always', 'auto', 'never', and 'debug' are keywords
85 # and should not be translated
85 # and should not be translated
86 _("when to colorize (boolean, always, auto, never, or debug)"),
86 _("when to colorize (boolean, always, auto, never, or debug)"),
87 _('TYPE')),
87 _('TYPE')),
88 ('', 'config', [],
88 ('', 'config', [],
89 _('set/override config option (use \'section.name=value\')'),
89 _('set/override config option (use \'section.name=value\')'),
90 _('CONFIG')),
90 _('CONFIG')),
91 ('', 'debug', None, _('enable debugging output')),
91 ('', 'debug', None, _('enable debugging output')),
92 ('', 'debugger', None, _('start debugger')),
92 ('', 'debugger', None, _('start debugger')),
93 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
93 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
94 _('ENCODE')),
94 _('ENCODE')),
95 ('', 'encodingmode', encoding.encodingmode,
95 ('', 'encodingmode', encoding.encodingmode,
96 _('set the charset encoding mode'), _('MODE')),
96 _('set the charset encoding mode'), _('MODE')),
97 ('', 'traceback', None, _('always print a traceback on exception')),
97 ('', 'traceback', None, _('always print a traceback on exception')),
98 ('', 'time', None, _('time how long the command takes')),
98 ('', 'time', None, _('time how long the command takes')),
99 ('', 'profile', None, _('print command execution profile')),
99 ('', 'profile', None, _('print command execution profile')),
100 ('', 'version', None, _('output version information and exit')),
100 ('', 'version', None, _('output version information and exit')),
101 ('h', 'help', None, _('display help and exit')),
101 ('h', 'help', None, _('display help and exit')),
102 ('', 'hidden', False, _('consider hidden changesets')),
102 ('', 'hidden', False, _('consider hidden changesets')),
103 ('', 'pager', 'auto',
103 ('', 'pager', 'auto',
104 _("when to paginate (boolean, always, auto, or never)"), _('TYPE')),
104 _("when to paginate (boolean, always, auto, or never)"), _('TYPE')),
105 ]
105 ]
106
106
107 dryrunopts = cmdutil.dryrunopts
107 dryrunopts = cmdutil.dryrunopts
108 remoteopts = cmdutil.remoteopts
108 remoteopts = cmdutil.remoteopts
109 walkopts = cmdutil.walkopts
109 walkopts = cmdutil.walkopts
110 commitopts = cmdutil.commitopts
110 commitopts = cmdutil.commitopts
111 commitopts2 = cmdutil.commitopts2
111 commitopts2 = cmdutil.commitopts2
112 formatteropts = cmdutil.formatteropts
112 formatteropts = cmdutil.formatteropts
113 templateopts = cmdutil.templateopts
113 templateopts = cmdutil.templateopts
114 logopts = cmdutil.logopts
114 logopts = cmdutil.logopts
115 diffopts = cmdutil.diffopts
115 diffopts = cmdutil.diffopts
116 diffwsopts = cmdutil.diffwsopts
116 diffwsopts = cmdutil.diffwsopts
117 diffopts2 = cmdutil.diffopts2
117 diffopts2 = cmdutil.diffopts2
118 mergetoolopts = cmdutil.mergetoolopts
118 mergetoolopts = cmdutil.mergetoolopts
119 similarityopts = cmdutil.similarityopts
119 similarityopts = cmdutil.similarityopts
120 subrepoopts = cmdutil.subrepoopts
120 subrepoopts = cmdutil.subrepoopts
121 debugrevlogopts = cmdutil.debugrevlogopts
121 debugrevlogopts = cmdutil.debugrevlogopts
122
122
123 # Commands start here, listed alphabetically
123 # Commands start here, listed alphabetically
124
124
125 @command('^add',
125 @command('^add',
126 walkopts + subrepoopts + dryrunopts,
126 walkopts + subrepoopts + dryrunopts,
127 _('[OPTION]... [FILE]...'),
127 _('[OPTION]... [FILE]...'),
128 inferrepo=True)
128 inferrepo=True)
129 def add(ui, repo, *pats, **opts):
129 def add(ui, repo, *pats, **opts):
130 """add the specified files on the next commit
130 """add the specified files on the next commit
131
131
132 Schedule files to be version controlled and added to the
132 Schedule files to be version controlled and added to the
133 repository.
133 repository.
134
134
135 The files will be added to the repository at the next commit. To
135 The files will be added to the repository at the next commit. To
136 undo an add before that, see :hg:`forget`.
136 undo an add before that, see :hg:`forget`.
137
137
138 If no names are given, add all files to the repository (except
138 If no names are given, add all files to the repository (except
139 files matching ``.hgignore``).
139 files matching ``.hgignore``).
140
140
141 .. container:: verbose
141 .. container:: verbose
142
142
143 Examples:
143 Examples:
144
144
145 - New (unknown) files are added
145 - New (unknown) files are added
146 automatically by :hg:`add`::
146 automatically by :hg:`add`::
147
147
148 $ ls
148 $ ls
149 foo.c
149 foo.c
150 $ hg status
150 $ hg status
151 ? foo.c
151 ? foo.c
152 $ hg add
152 $ hg add
153 adding foo.c
153 adding foo.c
154 $ hg status
154 $ hg status
155 A foo.c
155 A foo.c
156
156
157 - Specific files to be added can be specified::
157 - Specific files to be added can be specified::
158
158
159 $ ls
159 $ ls
160 bar.c foo.c
160 bar.c foo.c
161 $ hg status
161 $ hg status
162 ? bar.c
162 ? bar.c
163 ? foo.c
163 ? foo.c
164 $ hg add bar.c
164 $ hg add bar.c
165 $ hg status
165 $ hg status
166 A bar.c
166 A bar.c
167 ? foo.c
167 ? foo.c
168
168
169 Returns 0 if all files are successfully added.
169 Returns 0 if all files are successfully added.
170 """
170 """
171
171
172 m = scmutil.match(repo[None], pats, pycompat.byteskwargs(opts))
172 m = scmutil.match(repo[None], pats, pycompat.byteskwargs(opts))
173 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
173 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
174 return rejected and 1 or 0
174 return rejected and 1 or 0
175
175
176 @command('addremove',
176 @command('addremove',
177 similarityopts + subrepoopts + walkopts + dryrunopts,
177 similarityopts + subrepoopts + walkopts + dryrunopts,
178 _('[OPTION]... [FILE]...'),
178 _('[OPTION]... [FILE]...'),
179 inferrepo=True)
179 inferrepo=True)
180 def addremove(ui, repo, *pats, **opts):
180 def addremove(ui, repo, *pats, **opts):
181 """add all new files, delete all missing files
181 """add all new files, delete all missing files
182
182
183 Add all new files and remove all missing files from the
183 Add all new files and remove all missing files from the
184 repository.
184 repository.
185
185
186 Unless names are given, new files are ignored if they match any of
186 Unless names are given, new files are ignored if they match any of
187 the patterns in ``.hgignore``. As with add, these changes take
187 the patterns in ``.hgignore``. As with add, these changes take
188 effect at the next commit.
188 effect at the next commit.
189
189
190 Use the -s/--similarity option to detect renamed files. This
190 Use the -s/--similarity option to detect renamed files. This
191 option takes a percentage between 0 (disabled) and 100 (files must
191 option takes a percentage between 0 (disabled) and 100 (files must
192 be identical) as its parameter. With a parameter greater than 0,
192 be identical) as its parameter. With a parameter greater than 0,
193 this compares every removed file with every added file and records
193 this compares every removed file with every added file and records
194 those similar enough as renames. Detecting renamed files this way
194 those similar enough as renames. Detecting renamed files this way
195 can be expensive. After using this option, :hg:`status -C` can be
195 can be expensive. After using this option, :hg:`status -C` can be
196 used to check which files were identified as moved or renamed. If
196 used to check which files were identified as moved or renamed. If
197 not specified, -s/--similarity defaults to 100 and only renames of
197 not specified, -s/--similarity defaults to 100 and only renames of
198 identical files are detected.
198 identical files are detected.
199
199
200 .. container:: verbose
200 .. container:: verbose
201
201
202 Examples:
202 Examples:
203
203
204 - A number of files (bar.c and foo.c) are new,
204 - A number of files (bar.c and foo.c) are new,
205 while foobar.c has been removed (without using :hg:`remove`)
205 while foobar.c has been removed (without using :hg:`remove`)
206 from the repository::
206 from the repository::
207
207
208 $ ls
208 $ ls
209 bar.c foo.c
209 bar.c foo.c
210 $ hg status
210 $ hg status
211 ! foobar.c
211 ! foobar.c
212 ? bar.c
212 ? bar.c
213 ? foo.c
213 ? foo.c
214 $ hg addremove
214 $ hg addremove
215 adding bar.c
215 adding bar.c
216 adding foo.c
216 adding foo.c
217 removing foobar.c
217 removing foobar.c
218 $ hg status
218 $ hg status
219 A bar.c
219 A bar.c
220 A foo.c
220 A foo.c
221 R foobar.c
221 R foobar.c
222
222
223 - A file foobar.c was moved to foo.c without using :hg:`rename`.
223 - A file foobar.c was moved to foo.c without using :hg:`rename`.
224 Afterwards, it was edited slightly::
224 Afterwards, it was edited slightly::
225
225
226 $ ls
226 $ ls
227 foo.c
227 foo.c
228 $ hg status
228 $ hg status
229 ! foobar.c
229 ! foobar.c
230 ? foo.c
230 ? foo.c
231 $ hg addremove --similarity 90
231 $ hg addremove --similarity 90
232 removing foobar.c
232 removing foobar.c
233 adding foo.c
233 adding foo.c
234 recording removal of foobar.c as rename to foo.c (94% similar)
234 recording removal of foobar.c as rename to foo.c (94% similar)
235 $ hg status -C
235 $ hg status -C
236 A foo.c
236 A foo.c
237 foobar.c
237 foobar.c
238 R foobar.c
238 R foobar.c
239
239
240 Returns 0 if all files are successfully added.
240 Returns 0 if all files are successfully added.
241 """
241 """
242 opts = pycompat.byteskwargs(opts)
242 opts = pycompat.byteskwargs(opts)
243 try:
243 try:
244 sim = float(opts.get('similarity') or 100)
244 sim = float(opts.get('similarity') or 100)
245 except ValueError:
245 except ValueError:
246 raise error.Abort(_('similarity must be a number'))
246 raise error.Abort(_('similarity must be a number'))
247 if sim < 0 or sim > 100:
247 if sim < 0 or sim > 100:
248 raise error.Abort(_('similarity must be between 0 and 100'))
248 raise error.Abort(_('similarity must be between 0 and 100'))
249 matcher = scmutil.match(repo[None], pats, opts)
249 matcher = scmutil.match(repo[None], pats, opts)
250 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
250 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
251
251
252 @command('^annotate|blame',
252 @command('^annotate|blame',
253 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
253 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
254 ('', 'follow', None,
254 ('', 'follow', None,
255 _('follow copies/renames and list the filename (DEPRECATED)')),
255 _('follow copies/renames and list the filename (DEPRECATED)')),
256 ('', 'no-follow', None, _("don't follow copies and renames")),
256 ('', 'no-follow', None, _("don't follow copies and renames")),
257 ('a', 'text', None, _('treat all files as text')),
257 ('a', 'text', None, _('treat all files as text')),
258 ('u', 'user', None, _('list the author (long with -v)')),
258 ('u', 'user', None, _('list the author (long with -v)')),
259 ('f', 'file', None, _('list the filename')),
259 ('f', 'file', None, _('list the filename')),
260 ('d', 'date', None, _('list the date (short with -q)')),
260 ('d', 'date', None, _('list the date (short with -q)')),
261 ('n', 'number', None, _('list the revision number (default)')),
261 ('n', 'number', None, _('list the revision number (default)')),
262 ('c', 'changeset', None, _('list the changeset')),
262 ('c', 'changeset', None, _('list the changeset')),
263 ('l', 'line-number', None, _('show line number at the first appearance')),
263 ('l', 'line-number', None, _('show line number at the first appearance')),
264 ('', 'skip', [], _('revision to not display (EXPERIMENTAL)'), _('REV')),
264 ('', 'skip', [], _('revision to not display (EXPERIMENTAL)'), _('REV')),
265 ] + diffwsopts + walkopts + formatteropts,
265 ] + diffwsopts + walkopts + formatteropts,
266 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
266 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
267 inferrepo=True)
267 inferrepo=True)
268 def annotate(ui, repo, *pats, **opts):
268 def annotate(ui, repo, *pats, **opts):
269 """show changeset information by line for each file
269 """show changeset information by line for each file
270
270
271 List changes in files, showing the revision id responsible for
271 List changes in files, showing the revision id responsible for
272 each line.
272 each line.
273
273
274 This command is useful for discovering when a change was made and
274 This command is useful for discovering when a change was made and
275 by whom.
275 by whom.
276
276
277 If you include --file, --user, or --date, the revision number is
277 If you include --file, --user, or --date, the revision number is
278 suppressed unless you also include --number.
278 suppressed unless you also include --number.
279
279
280 Without the -a/--text option, annotate will avoid processing files
280 Without the -a/--text option, annotate will avoid processing files
281 it detects as binary. With -a, annotate will annotate the file
281 it detects as binary. With -a, annotate will annotate the file
282 anyway, although the results will probably be neither useful
282 anyway, although the results will probably be neither useful
283 nor desirable.
283 nor desirable.
284
284
285 Returns 0 on success.
285 Returns 0 on success.
286 """
286 """
287 opts = pycompat.byteskwargs(opts)
287 opts = pycompat.byteskwargs(opts)
288 if not pats:
288 if not pats:
289 raise error.Abort(_('at least one filename or pattern is required'))
289 raise error.Abort(_('at least one filename or pattern is required'))
290
290
291 if opts.get('follow'):
291 if opts.get('follow'):
292 # --follow is deprecated and now just an alias for -f/--file
292 # --follow is deprecated and now just an alias for -f/--file
293 # to mimic the behavior of Mercurial before version 1.5
293 # to mimic the behavior of Mercurial before version 1.5
294 opts['file'] = True
294 opts['file'] = True
295
295
296 rev = opts.get('rev')
296 rev = opts.get('rev')
297 if rev:
297 if rev:
298 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
298 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
299 ctx = scmutil.revsingle(repo, rev)
299 ctx = scmutil.revsingle(repo, rev)
300
300
301 rootfm = ui.formatter('annotate', opts)
301 rootfm = ui.formatter('annotate', opts)
302 if ui.quiet:
302 if ui.quiet:
303 datefunc = util.shortdate
303 datefunc = util.shortdate
304 else:
304 else:
305 datefunc = util.datestr
305 datefunc = util.datestr
306 if ctx.rev() is None:
306 if ctx.rev() is None:
307 def hexfn(node):
307 def hexfn(node):
308 if node is None:
308 if node is None:
309 return None
309 return None
310 else:
310 else:
311 return rootfm.hexfunc(node)
311 return rootfm.hexfunc(node)
312 if opts.get('changeset'):
312 if opts.get('changeset'):
313 # omit "+" suffix which is appended to node hex
313 # omit "+" suffix which is appended to node hex
314 def formatrev(rev):
314 def formatrev(rev):
315 if rev is None:
315 if rev is None:
316 return '%d' % ctx.p1().rev()
316 return '%d' % ctx.p1().rev()
317 else:
317 else:
318 return '%d' % rev
318 return '%d' % rev
319 else:
319 else:
320 def formatrev(rev):
320 def formatrev(rev):
321 if rev is None:
321 if rev is None:
322 return '%d+' % ctx.p1().rev()
322 return '%d+' % ctx.p1().rev()
323 else:
323 else:
324 return '%d ' % rev
324 return '%d ' % rev
325 def formathex(hex):
325 def formathex(hex):
326 if hex is None:
326 if hex is None:
327 return '%s+' % rootfm.hexfunc(ctx.p1().node())
327 return '%s+' % rootfm.hexfunc(ctx.p1().node())
328 else:
328 else:
329 return '%s ' % hex
329 return '%s ' % hex
330 else:
330 else:
331 hexfn = rootfm.hexfunc
331 hexfn = rootfm.hexfunc
332 formatrev = formathex = pycompat.bytestr
332 formatrev = formathex = pycompat.bytestr
333
333
334 opmap = [('user', ' ', lambda x: x.fctx.user(), ui.shortuser),
334 opmap = [('user', ' ', lambda x: x.fctx.user(), ui.shortuser),
335 ('number', ' ', lambda x: x.fctx.rev(), formatrev),
335 ('number', ' ', lambda x: x.fctx.rev(), formatrev),
336 ('changeset', ' ', lambda x: hexfn(x.fctx.node()), formathex),
336 ('changeset', ' ', lambda x: hexfn(x.fctx.node()), formathex),
337 ('date', ' ', lambda x: x.fctx.date(), util.cachefunc(datefunc)),
337 ('date', ' ', lambda x: x.fctx.date(), util.cachefunc(datefunc)),
338 ('file', ' ', lambda x: x.fctx.path(), str),
338 ('file', ' ', lambda x: x.fctx.path(), str),
339 ('line_number', ':', lambda x: x.lineno, str),
339 ('line_number', ':', lambda x: x.lineno, str),
340 ]
340 ]
341 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
341 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
342
342
343 if (not opts.get('user') and not opts.get('changeset')
343 if (not opts.get('user') and not opts.get('changeset')
344 and not opts.get('date') and not opts.get('file')):
344 and not opts.get('date') and not opts.get('file')):
345 opts['number'] = True
345 opts['number'] = True
346
346
347 linenumber = opts.get('line_number') is not None
347 linenumber = opts.get('line_number') is not None
348 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
348 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
349 raise error.Abort(_('at least one of -n/-c is required for -l'))
349 raise error.Abort(_('at least one of -n/-c is required for -l'))
350
350
351 ui.pager('annotate')
351 ui.pager('annotate')
352
352
353 if rootfm.isplain():
353 if rootfm.isplain():
354 def makefunc(get, fmt):
354 def makefunc(get, fmt):
355 return lambda x: fmt(get(x))
355 return lambda x: fmt(get(x))
356 else:
356 else:
357 def makefunc(get, fmt):
357 def makefunc(get, fmt):
358 return get
358 return get
359 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
359 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
360 if opts.get(op)]
360 if opts.get(op)]
361 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
361 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
362 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
362 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
363 if opts.get(op))
363 if opts.get(op))
364
364
365 def bad(x, y):
365 def bad(x, y):
366 raise error.Abort("%s: %s" % (x, y))
366 raise error.Abort("%s: %s" % (x, y))
367
367
368 m = scmutil.match(ctx, pats, opts, badfn=bad)
368 m = scmutil.match(ctx, pats, opts, badfn=bad)
369
369
370 follow = not opts.get('no_follow')
370 follow = not opts.get('no_follow')
371 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
371 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
372 whitespace=True)
372 whitespace=True)
373 skiprevs = opts.get('skip')
373 skiprevs = opts.get('skip')
374 if skiprevs:
374 if skiprevs:
375 skiprevs = scmutil.revrange(repo, skiprevs)
375 skiprevs = scmutil.revrange(repo, skiprevs)
376
376
377 for abs in ctx.walk(m):
377 for abs in ctx.walk(m):
378 fctx = ctx[abs]
378 fctx = ctx[abs]
379 rootfm.startitem()
379 rootfm.startitem()
380 rootfm.data(abspath=abs, path=m.rel(abs))
380 rootfm.data(abspath=abs, path=m.rel(abs))
381 if not opts.get('text') and fctx.isbinary():
381 if not opts.get('text') and fctx.isbinary():
382 rootfm.plain(_("%s: binary file\n")
382 rootfm.plain(_("%s: binary file\n")
383 % ((pats and m.rel(abs)) or abs))
383 % ((pats and m.rel(abs)) or abs))
384 continue
384 continue
385
385
386 fm = rootfm.nested('lines')
386 fm = rootfm.nested('lines')
387 lines = fctx.annotate(follow=follow, linenumber=linenumber,
387 lines = fctx.annotate(follow=follow, linenumber=linenumber,
388 skiprevs=skiprevs, diffopts=diffopts)
388 skiprevs=skiprevs, diffopts=diffopts)
389 if not lines:
389 if not lines:
390 fm.end()
390 fm.end()
391 continue
391 continue
392 formats = []
392 formats = []
393 pieces = []
393 pieces = []
394
394
395 for f, sep in funcmap:
395 for f, sep in funcmap:
396 l = [f(n) for n, dummy in lines]
396 l = [f(n) for n, dummy in lines]
397 if fm.isplain():
397 if fm.isplain():
398 sizes = [encoding.colwidth(x) for x in l]
398 sizes = [encoding.colwidth(x) for x in l]
399 ml = max(sizes)
399 ml = max(sizes)
400 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
400 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
401 else:
401 else:
402 formats.append(['%s' for x in l])
402 formats.append(['%s' for x in l])
403 pieces.append(l)
403 pieces.append(l)
404
404
405 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
405 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
406 fm.startitem()
406 fm.startitem()
407 fm.write(fields, "".join(f), *p)
407 fm.write(fields, "".join(f), *p)
408 if l[0].skip:
408 if l[0].skip:
409 fmt = "* %s"
409 fmt = "* %s"
410 else:
410 else:
411 fmt = ": %s"
411 fmt = ": %s"
412 fm.write('line', fmt, l[1])
412 fm.write('line', fmt, l[1])
413
413
414 if not lines[-1][1].endswith('\n'):
414 if not lines[-1][1].endswith('\n'):
415 fm.plain('\n')
415 fm.plain('\n')
416 fm.end()
416 fm.end()
417
417
418 rootfm.end()
418 rootfm.end()
419
419
420 @command('archive',
420 @command('archive',
421 [('', 'no-decode', None, _('do not pass files through decoders')),
421 [('', 'no-decode', None, _('do not pass files through decoders')),
422 ('p', 'prefix', '', _('directory prefix for files in archive'),
422 ('p', 'prefix', '', _('directory prefix for files in archive'),
423 _('PREFIX')),
423 _('PREFIX')),
424 ('r', 'rev', '', _('revision to distribute'), _('REV')),
424 ('r', 'rev', '', _('revision to distribute'), _('REV')),
425 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
425 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
426 ] + subrepoopts + walkopts,
426 ] + subrepoopts + walkopts,
427 _('[OPTION]... DEST'))
427 _('[OPTION]... DEST'))
428 def archive(ui, repo, dest, **opts):
428 def archive(ui, repo, dest, **opts):
429 '''create an unversioned archive of a repository revision
429 '''create an unversioned archive of a repository revision
430
430
431 By default, the revision used is the parent of the working
431 By default, the revision used is the parent of the working
432 directory; use -r/--rev to specify a different revision.
432 directory; use -r/--rev to specify a different revision.
433
433
434 The archive type is automatically detected based on file
434 The archive type is automatically detected based on file
435 extension (to override, use -t/--type).
435 extension (to override, use -t/--type).
436
436
437 .. container:: verbose
437 .. container:: verbose
438
438
439 Examples:
439 Examples:
440
440
441 - create a zip file containing the 1.0 release::
441 - create a zip file containing the 1.0 release::
442
442
443 hg archive -r 1.0 project-1.0.zip
443 hg archive -r 1.0 project-1.0.zip
444
444
445 - create a tarball excluding .hg files::
445 - create a tarball excluding .hg files::
446
446
447 hg archive project.tar.gz -X ".hg*"
447 hg archive project.tar.gz -X ".hg*"
448
448
449 Valid types are:
449 Valid types are:
450
450
451 :``files``: a directory full of files (default)
451 :``files``: a directory full of files (default)
452 :``tar``: tar archive, uncompressed
452 :``tar``: tar archive, uncompressed
453 :``tbz2``: tar archive, compressed using bzip2
453 :``tbz2``: tar archive, compressed using bzip2
454 :``tgz``: tar archive, compressed using gzip
454 :``tgz``: tar archive, compressed using gzip
455 :``uzip``: zip archive, uncompressed
455 :``uzip``: zip archive, uncompressed
456 :``zip``: zip archive, compressed using deflate
456 :``zip``: zip archive, compressed using deflate
457
457
458 The exact name of the destination archive or directory is given
458 The exact name of the destination archive or directory is given
459 using a format string; see :hg:`help export` for details.
459 using a format string; see :hg:`help export` for details.
460
460
461 Each member added to an archive file has a directory prefix
461 Each member added to an archive file has a directory prefix
462 prepended. Use -p/--prefix to specify a format string for the
462 prepended. Use -p/--prefix to specify a format string for the
463 prefix. The default is the basename of the archive, with suffixes
463 prefix. The default is the basename of the archive, with suffixes
464 removed.
464 removed.
465
465
466 Returns 0 on success.
466 Returns 0 on success.
467 '''
467 '''
468
468
469 opts = pycompat.byteskwargs(opts)
469 opts = pycompat.byteskwargs(opts)
470 ctx = scmutil.revsingle(repo, opts.get('rev'))
470 rev = opts.get('rev')
471 if rev:
472 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
473 ctx = scmutil.revsingle(repo, rev)
471 if not ctx:
474 if not ctx:
472 raise error.Abort(_('no working directory: please specify a revision'))
475 raise error.Abort(_('no working directory: please specify a revision'))
473 node = ctx.node()
476 node = ctx.node()
474 dest = cmdutil.makefilename(repo, dest, node)
477 dest = cmdutil.makefilename(repo, dest, node)
475 if os.path.realpath(dest) == repo.root:
478 if os.path.realpath(dest) == repo.root:
476 raise error.Abort(_('repository root cannot be destination'))
479 raise error.Abort(_('repository root cannot be destination'))
477
480
478 kind = opts.get('type') or archival.guesskind(dest) or 'files'
481 kind = opts.get('type') or archival.guesskind(dest) or 'files'
479 prefix = opts.get('prefix')
482 prefix = opts.get('prefix')
480
483
481 if dest == '-':
484 if dest == '-':
482 if kind == 'files':
485 if kind == 'files':
483 raise error.Abort(_('cannot archive plain files to stdout'))
486 raise error.Abort(_('cannot archive plain files to stdout'))
484 dest = cmdutil.makefileobj(repo, dest)
487 dest = cmdutil.makefileobj(repo, dest)
485 if not prefix:
488 if not prefix:
486 prefix = os.path.basename(repo.root) + '-%h'
489 prefix = os.path.basename(repo.root) + '-%h'
487
490
488 prefix = cmdutil.makefilename(repo, prefix, node)
491 prefix = cmdutil.makefilename(repo, prefix, node)
489 match = scmutil.match(ctx, [], opts)
492 match = scmutil.match(ctx, [], opts)
490 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
493 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
491 match, prefix, subrepos=opts.get('subrepos'))
494 match, prefix, subrepos=opts.get('subrepos'))
492
495
493 @command('backout',
496 @command('backout',
494 [('', 'merge', None, _('merge with old dirstate parent after backout')),
497 [('', 'merge', None, _('merge with old dirstate parent after backout')),
495 ('', 'commit', None,
498 ('', 'commit', None,
496 _('commit if no conflicts were encountered (DEPRECATED)')),
499 _('commit if no conflicts were encountered (DEPRECATED)')),
497 ('', 'no-commit', None, _('do not commit')),
500 ('', 'no-commit', None, _('do not commit')),
498 ('', 'parent', '',
501 ('', 'parent', '',
499 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
502 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
500 ('r', 'rev', '', _('revision to backout'), _('REV')),
503 ('r', 'rev', '', _('revision to backout'), _('REV')),
501 ('e', 'edit', False, _('invoke editor on commit messages')),
504 ('e', 'edit', False, _('invoke editor on commit messages')),
502 ] + mergetoolopts + walkopts + commitopts + commitopts2,
505 ] + mergetoolopts + walkopts + commitopts + commitopts2,
503 _('[OPTION]... [-r] REV'))
506 _('[OPTION]... [-r] REV'))
504 def backout(ui, repo, node=None, rev=None, **opts):
507 def backout(ui, repo, node=None, rev=None, **opts):
505 '''reverse effect of earlier changeset
508 '''reverse effect of earlier changeset
506
509
507 Prepare a new changeset with the effect of REV undone in the
510 Prepare a new changeset with the effect of REV undone in the
508 current working directory. If no conflicts were encountered,
511 current working directory. If no conflicts were encountered,
509 it will be committed immediately.
512 it will be committed immediately.
510
513
511 If REV is the parent of the working directory, then this new changeset
514 If REV is the parent of the working directory, then this new changeset
512 is committed automatically (unless --no-commit is specified).
515 is committed automatically (unless --no-commit is specified).
513
516
514 .. note::
517 .. note::
515
518
516 :hg:`backout` cannot be used to fix either an unwanted or
519 :hg:`backout` cannot be used to fix either an unwanted or
517 incorrect merge.
520 incorrect merge.
518
521
519 .. container:: verbose
522 .. container:: verbose
520
523
521 Examples:
524 Examples:
522
525
523 - Reverse the effect of the parent of the working directory.
526 - Reverse the effect of the parent of the working directory.
524 This backout will be committed immediately::
527 This backout will be committed immediately::
525
528
526 hg backout -r .
529 hg backout -r .
527
530
528 - Reverse the effect of previous bad revision 23::
531 - Reverse the effect of previous bad revision 23::
529
532
530 hg backout -r 23
533 hg backout -r 23
531
534
532 - Reverse the effect of previous bad revision 23 and
535 - Reverse the effect of previous bad revision 23 and
533 leave changes uncommitted::
536 leave changes uncommitted::
534
537
535 hg backout -r 23 --no-commit
538 hg backout -r 23 --no-commit
536 hg commit -m "Backout revision 23"
539 hg commit -m "Backout revision 23"
537
540
538 By default, the pending changeset will have one parent,
541 By default, the pending changeset will have one parent,
539 maintaining a linear history. With --merge, the pending
542 maintaining a linear history. With --merge, the pending
540 changeset will instead have two parents: the old parent of the
543 changeset will instead have two parents: the old parent of the
541 working directory and a new child of REV that simply undoes REV.
544 working directory and a new child of REV that simply undoes REV.
542
545
543 Before version 1.7, the behavior without --merge was equivalent
546 Before version 1.7, the behavior without --merge was equivalent
544 to specifying --merge followed by :hg:`update --clean .` to
547 to specifying --merge followed by :hg:`update --clean .` to
545 cancel the merge and leave the child of REV as a head to be
548 cancel the merge and leave the child of REV as a head to be
546 merged separately.
549 merged separately.
547
550
548 See :hg:`help dates` for a list of formats valid for -d/--date.
551 See :hg:`help dates` for a list of formats valid for -d/--date.
549
552
550 See :hg:`help revert` for a way to restore files to the state
553 See :hg:`help revert` for a way to restore files to the state
551 of another revision.
554 of another revision.
552
555
553 Returns 0 on success, 1 if nothing to backout or there are unresolved
556 Returns 0 on success, 1 if nothing to backout or there are unresolved
554 files.
557 files.
555 '''
558 '''
556 wlock = lock = None
559 wlock = lock = None
557 try:
560 try:
558 wlock = repo.wlock()
561 wlock = repo.wlock()
559 lock = repo.lock()
562 lock = repo.lock()
560 return _dobackout(ui, repo, node, rev, **opts)
563 return _dobackout(ui, repo, node, rev, **opts)
561 finally:
564 finally:
562 release(lock, wlock)
565 release(lock, wlock)
563
566
564 def _dobackout(ui, repo, node=None, rev=None, **opts):
567 def _dobackout(ui, repo, node=None, rev=None, **opts):
565 opts = pycompat.byteskwargs(opts)
568 opts = pycompat.byteskwargs(opts)
566 if opts.get('commit') and opts.get('no_commit'):
569 if opts.get('commit') and opts.get('no_commit'):
567 raise error.Abort(_("cannot use --commit with --no-commit"))
570 raise error.Abort(_("cannot use --commit with --no-commit"))
568 if opts.get('merge') and opts.get('no_commit'):
571 if opts.get('merge') and opts.get('no_commit'):
569 raise error.Abort(_("cannot use --merge with --no-commit"))
572 raise error.Abort(_("cannot use --merge with --no-commit"))
570
573
571 if rev and node:
574 if rev and node:
572 raise error.Abort(_("please specify just one revision"))
575 raise error.Abort(_("please specify just one revision"))
573
576
574 if not rev:
577 if not rev:
575 rev = node
578 rev = node
576
579
577 if not rev:
580 if not rev:
578 raise error.Abort(_("please specify a revision to backout"))
581 raise error.Abort(_("please specify a revision to backout"))
579
582
580 date = opts.get('date')
583 date = opts.get('date')
581 if date:
584 if date:
582 opts['date'] = util.parsedate(date)
585 opts['date'] = util.parsedate(date)
583
586
584 cmdutil.checkunfinished(repo)
587 cmdutil.checkunfinished(repo)
585 cmdutil.bailifchanged(repo)
588 cmdutil.bailifchanged(repo)
586 node = scmutil.revsingle(repo, rev).node()
589 node = scmutil.revsingle(repo, rev).node()
587
590
588 op1, op2 = repo.dirstate.parents()
591 op1, op2 = repo.dirstate.parents()
589 if not repo.changelog.isancestor(node, op1):
592 if not repo.changelog.isancestor(node, op1):
590 raise error.Abort(_('cannot backout change that is not an ancestor'))
593 raise error.Abort(_('cannot backout change that is not an ancestor'))
591
594
592 p1, p2 = repo.changelog.parents(node)
595 p1, p2 = repo.changelog.parents(node)
593 if p1 == nullid:
596 if p1 == nullid:
594 raise error.Abort(_('cannot backout a change with no parents'))
597 raise error.Abort(_('cannot backout a change with no parents'))
595 if p2 != nullid:
598 if p2 != nullid:
596 if not opts.get('parent'):
599 if not opts.get('parent'):
597 raise error.Abort(_('cannot backout a merge changeset'))
600 raise error.Abort(_('cannot backout a merge changeset'))
598 p = repo.lookup(opts['parent'])
601 p = repo.lookup(opts['parent'])
599 if p not in (p1, p2):
602 if p not in (p1, p2):
600 raise error.Abort(_('%s is not a parent of %s') %
603 raise error.Abort(_('%s is not a parent of %s') %
601 (short(p), short(node)))
604 (short(p), short(node)))
602 parent = p
605 parent = p
603 else:
606 else:
604 if opts.get('parent'):
607 if opts.get('parent'):
605 raise error.Abort(_('cannot use --parent on non-merge changeset'))
608 raise error.Abort(_('cannot use --parent on non-merge changeset'))
606 parent = p1
609 parent = p1
607
610
608 # the backout should appear on the same branch
611 # the backout should appear on the same branch
609 branch = repo.dirstate.branch()
612 branch = repo.dirstate.branch()
610 bheads = repo.branchheads(branch)
613 bheads = repo.branchheads(branch)
611 rctx = scmutil.revsingle(repo, hex(parent))
614 rctx = scmutil.revsingle(repo, hex(parent))
612 if not opts.get('merge') and op1 != node:
615 if not opts.get('merge') and op1 != node:
613 dsguard = dirstateguard.dirstateguard(repo, 'backout')
616 dsguard = dirstateguard.dirstateguard(repo, 'backout')
614 try:
617 try:
615 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
618 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
616 'backout')
619 'backout')
617 stats = mergemod.update(repo, parent, True, True, node, False)
620 stats = mergemod.update(repo, parent, True, True, node, False)
618 repo.setparents(op1, op2)
621 repo.setparents(op1, op2)
619 dsguard.close()
622 dsguard.close()
620 hg._showstats(repo, stats)
623 hg._showstats(repo, stats)
621 if stats[3]:
624 if stats[3]:
622 repo.ui.status(_("use 'hg resolve' to retry unresolved "
625 repo.ui.status(_("use 'hg resolve' to retry unresolved "
623 "file merges\n"))
626 "file merges\n"))
624 return 1
627 return 1
625 finally:
628 finally:
626 ui.setconfig('ui', 'forcemerge', '', '')
629 ui.setconfig('ui', 'forcemerge', '', '')
627 lockmod.release(dsguard)
630 lockmod.release(dsguard)
628 else:
631 else:
629 hg.clean(repo, node, show_stats=False)
632 hg.clean(repo, node, show_stats=False)
630 repo.dirstate.setbranch(branch)
633 repo.dirstate.setbranch(branch)
631 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
634 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
632
635
633 if opts.get('no_commit'):
636 if opts.get('no_commit'):
634 msg = _("changeset %s backed out, "
637 msg = _("changeset %s backed out, "
635 "don't forget to commit.\n")
638 "don't forget to commit.\n")
636 ui.status(msg % short(node))
639 ui.status(msg % short(node))
637 return 0
640 return 0
638
641
639 def commitfunc(ui, repo, message, match, opts):
642 def commitfunc(ui, repo, message, match, opts):
640 editform = 'backout'
643 editform = 'backout'
641 e = cmdutil.getcommiteditor(editform=editform,
644 e = cmdutil.getcommiteditor(editform=editform,
642 **pycompat.strkwargs(opts))
645 **pycompat.strkwargs(opts))
643 if not message:
646 if not message:
644 # we don't translate commit messages
647 # we don't translate commit messages
645 message = "Backed out changeset %s" % short(node)
648 message = "Backed out changeset %s" % short(node)
646 e = cmdutil.getcommiteditor(edit=True, editform=editform)
649 e = cmdutil.getcommiteditor(edit=True, editform=editform)
647 return repo.commit(message, opts.get('user'), opts.get('date'),
650 return repo.commit(message, opts.get('user'), opts.get('date'),
648 match, editor=e)
651 match, editor=e)
649 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
652 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
650 if not newnode:
653 if not newnode:
651 ui.status(_("nothing changed\n"))
654 ui.status(_("nothing changed\n"))
652 return 1
655 return 1
653 cmdutil.commitstatus(repo, newnode, branch, bheads)
656 cmdutil.commitstatus(repo, newnode, branch, bheads)
654
657
655 def nice(node):
658 def nice(node):
656 return '%d:%s' % (repo.changelog.rev(node), short(node))
659 return '%d:%s' % (repo.changelog.rev(node), short(node))
657 ui.status(_('changeset %s backs out changeset %s\n') %
660 ui.status(_('changeset %s backs out changeset %s\n') %
658 (nice(repo.changelog.tip()), nice(node)))
661 (nice(repo.changelog.tip()), nice(node)))
659 if opts.get('merge') and op1 != node:
662 if opts.get('merge') and op1 != node:
660 hg.clean(repo, op1, show_stats=False)
663 hg.clean(repo, op1, show_stats=False)
661 ui.status(_('merging with changeset %s\n')
664 ui.status(_('merging with changeset %s\n')
662 % nice(repo.changelog.tip()))
665 % nice(repo.changelog.tip()))
663 try:
666 try:
664 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
667 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
665 'backout')
668 'backout')
666 return hg.merge(repo, hex(repo.changelog.tip()))
669 return hg.merge(repo, hex(repo.changelog.tip()))
667 finally:
670 finally:
668 ui.setconfig('ui', 'forcemerge', '', '')
671 ui.setconfig('ui', 'forcemerge', '', '')
669 return 0
672 return 0
670
673
671 @command('bisect',
674 @command('bisect',
672 [('r', 'reset', False, _('reset bisect state')),
675 [('r', 'reset', False, _('reset bisect state')),
673 ('g', 'good', False, _('mark changeset good')),
676 ('g', 'good', False, _('mark changeset good')),
674 ('b', 'bad', False, _('mark changeset bad')),
677 ('b', 'bad', False, _('mark changeset bad')),
675 ('s', 'skip', False, _('skip testing changeset')),
678 ('s', 'skip', False, _('skip testing changeset')),
676 ('e', 'extend', False, _('extend the bisect range')),
679 ('e', 'extend', False, _('extend the bisect range')),
677 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
680 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
678 ('U', 'noupdate', False, _('do not update to target'))],
681 ('U', 'noupdate', False, _('do not update to target'))],
679 _("[-gbsr] [-U] [-c CMD] [REV]"))
682 _("[-gbsr] [-U] [-c CMD] [REV]"))
680 def bisect(ui, repo, rev=None, extra=None, command=None,
683 def bisect(ui, repo, rev=None, extra=None, command=None,
681 reset=None, good=None, bad=None, skip=None, extend=None,
684 reset=None, good=None, bad=None, skip=None, extend=None,
682 noupdate=None):
685 noupdate=None):
683 """subdivision search of changesets
686 """subdivision search of changesets
684
687
685 This command helps to find changesets which introduce problems. To
688 This command helps to find changesets which introduce problems. To
686 use, mark the earliest changeset you know exhibits the problem as
689 use, mark the earliest changeset you know exhibits the problem as
687 bad, then mark the latest changeset which is free from the problem
690 bad, then mark the latest changeset which is free from the problem
688 as good. Bisect will update your working directory to a revision
691 as good. Bisect will update your working directory to a revision
689 for testing (unless the -U/--noupdate option is specified). Once
692 for testing (unless the -U/--noupdate option is specified). Once
690 you have performed tests, mark the working directory as good or
693 you have performed tests, mark the working directory as good or
691 bad, and bisect will either update to another candidate changeset
694 bad, and bisect will either update to another candidate changeset
692 or announce that it has found the bad revision.
695 or announce that it has found the bad revision.
693
696
694 As a shortcut, you can also use the revision argument to mark a
697 As a shortcut, you can also use the revision argument to mark a
695 revision as good or bad without checking it out first.
698 revision as good or bad without checking it out first.
696
699
697 If you supply a command, it will be used for automatic bisection.
700 If you supply a command, it will be used for automatic bisection.
698 The environment variable HG_NODE will contain the ID of the
701 The environment variable HG_NODE will contain the ID of the
699 changeset being tested. The exit status of the command will be
702 changeset being tested. The exit status of the command will be
700 used to mark revisions as good or bad: status 0 means good, 125
703 used to mark revisions as good or bad: status 0 means good, 125
701 means to skip the revision, 127 (command not found) will abort the
704 means to skip the revision, 127 (command not found) will abort the
702 bisection, and any other non-zero exit status means the revision
705 bisection, and any other non-zero exit status means the revision
703 is bad.
706 is bad.
704
707
705 .. container:: verbose
708 .. container:: verbose
706
709
707 Some examples:
710 Some examples:
708
711
709 - start a bisection with known bad revision 34, and good revision 12::
712 - start a bisection with known bad revision 34, and good revision 12::
710
713
711 hg bisect --bad 34
714 hg bisect --bad 34
712 hg bisect --good 12
715 hg bisect --good 12
713
716
714 - advance the current bisection by marking current revision as good or
717 - advance the current bisection by marking current revision as good or
715 bad::
718 bad::
716
719
717 hg bisect --good
720 hg bisect --good
718 hg bisect --bad
721 hg bisect --bad
719
722
720 - mark the current revision, or a known revision, to be skipped (e.g. if
723 - mark the current revision, or a known revision, to be skipped (e.g. if
721 that revision is not usable because of another issue)::
724 that revision is not usable because of another issue)::
722
725
723 hg bisect --skip
726 hg bisect --skip
724 hg bisect --skip 23
727 hg bisect --skip 23
725
728
726 - skip all revisions that do not touch directories ``foo`` or ``bar``::
729 - skip all revisions that do not touch directories ``foo`` or ``bar``::
727
730
728 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
731 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
729
732
730 - forget the current bisection::
733 - forget the current bisection::
731
734
732 hg bisect --reset
735 hg bisect --reset
733
736
734 - use 'make && make tests' to automatically find the first broken
737 - use 'make && make tests' to automatically find the first broken
735 revision::
738 revision::
736
739
737 hg bisect --reset
740 hg bisect --reset
738 hg bisect --bad 34
741 hg bisect --bad 34
739 hg bisect --good 12
742 hg bisect --good 12
740 hg bisect --command "make && make tests"
743 hg bisect --command "make && make tests"
741
744
742 - see all changesets whose states are already known in the current
745 - see all changesets whose states are already known in the current
743 bisection::
746 bisection::
744
747
745 hg log -r "bisect(pruned)"
748 hg log -r "bisect(pruned)"
746
749
747 - see the changeset currently being bisected (especially useful
750 - see the changeset currently being bisected (especially useful
748 if running with -U/--noupdate)::
751 if running with -U/--noupdate)::
749
752
750 hg log -r "bisect(current)"
753 hg log -r "bisect(current)"
751
754
752 - see all changesets that took part in the current bisection::
755 - see all changesets that took part in the current bisection::
753
756
754 hg log -r "bisect(range)"
757 hg log -r "bisect(range)"
755
758
756 - you can even get a nice graph::
759 - you can even get a nice graph::
757
760
758 hg log --graph -r "bisect(range)"
761 hg log --graph -r "bisect(range)"
759
762
760 See :hg:`help revisions.bisect` for more about the `bisect()` predicate.
763 See :hg:`help revisions.bisect` for more about the `bisect()` predicate.
761
764
762 Returns 0 on success.
765 Returns 0 on success.
763 """
766 """
764 # backward compatibility
767 # backward compatibility
765 if rev in "good bad reset init".split():
768 if rev in "good bad reset init".split():
766 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
769 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
767 cmd, rev, extra = rev, extra, None
770 cmd, rev, extra = rev, extra, None
768 if cmd == "good":
771 if cmd == "good":
769 good = True
772 good = True
770 elif cmd == "bad":
773 elif cmd == "bad":
771 bad = True
774 bad = True
772 else:
775 else:
773 reset = True
776 reset = True
774 elif extra:
777 elif extra:
775 raise error.Abort(_('incompatible arguments'))
778 raise error.Abort(_('incompatible arguments'))
776
779
777 incompatibles = {
780 incompatibles = {
778 '--bad': bad,
781 '--bad': bad,
779 '--command': bool(command),
782 '--command': bool(command),
780 '--extend': extend,
783 '--extend': extend,
781 '--good': good,
784 '--good': good,
782 '--reset': reset,
785 '--reset': reset,
783 '--skip': skip,
786 '--skip': skip,
784 }
787 }
785
788
786 enabled = [x for x in incompatibles if incompatibles[x]]
789 enabled = [x for x in incompatibles if incompatibles[x]]
787
790
788 if len(enabled) > 1:
791 if len(enabled) > 1:
789 raise error.Abort(_('%s and %s are incompatible') %
792 raise error.Abort(_('%s and %s are incompatible') %
790 tuple(sorted(enabled)[0:2]))
793 tuple(sorted(enabled)[0:2]))
791
794
792 if reset:
795 if reset:
793 hbisect.resetstate(repo)
796 hbisect.resetstate(repo)
794 return
797 return
795
798
796 state = hbisect.load_state(repo)
799 state = hbisect.load_state(repo)
797
800
798 # update state
801 # update state
799 if good or bad or skip:
802 if good or bad or skip:
800 if rev:
803 if rev:
801 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
804 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
802 else:
805 else:
803 nodes = [repo.lookup('.')]
806 nodes = [repo.lookup('.')]
804 if good:
807 if good:
805 state['good'] += nodes
808 state['good'] += nodes
806 elif bad:
809 elif bad:
807 state['bad'] += nodes
810 state['bad'] += nodes
808 elif skip:
811 elif skip:
809 state['skip'] += nodes
812 state['skip'] += nodes
810 hbisect.save_state(repo, state)
813 hbisect.save_state(repo, state)
811 if not (state['good'] and state['bad']):
814 if not (state['good'] and state['bad']):
812 return
815 return
813
816
814 def mayupdate(repo, node, show_stats=True):
817 def mayupdate(repo, node, show_stats=True):
815 """common used update sequence"""
818 """common used update sequence"""
816 if noupdate:
819 if noupdate:
817 return
820 return
818 cmdutil.checkunfinished(repo)
821 cmdutil.checkunfinished(repo)
819 cmdutil.bailifchanged(repo)
822 cmdutil.bailifchanged(repo)
820 return hg.clean(repo, node, show_stats=show_stats)
823 return hg.clean(repo, node, show_stats=show_stats)
821
824
822 displayer = cmdutil.show_changeset(ui, repo, {})
825 displayer = cmdutil.show_changeset(ui, repo, {})
823
826
824 if command:
827 if command:
825 changesets = 1
828 changesets = 1
826 if noupdate:
829 if noupdate:
827 try:
830 try:
828 node = state['current'][0]
831 node = state['current'][0]
829 except LookupError:
832 except LookupError:
830 raise error.Abort(_('current bisect revision is unknown - '
833 raise error.Abort(_('current bisect revision is unknown - '
831 'start a new bisect to fix'))
834 'start a new bisect to fix'))
832 else:
835 else:
833 node, p2 = repo.dirstate.parents()
836 node, p2 = repo.dirstate.parents()
834 if p2 != nullid:
837 if p2 != nullid:
835 raise error.Abort(_('current bisect revision is a merge'))
838 raise error.Abort(_('current bisect revision is a merge'))
836 if rev:
839 if rev:
837 node = repo[scmutil.revsingle(repo, rev, node)].node()
840 node = repo[scmutil.revsingle(repo, rev, node)].node()
838 try:
841 try:
839 while changesets:
842 while changesets:
840 # update state
843 # update state
841 state['current'] = [node]
844 state['current'] = [node]
842 hbisect.save_state(repo, state)
845 hbisect.save_state(repo, state)
843 status = ui.system(command, environ={'HG_NODE': hex(node)},
846 status = ui.system(command, environ={'HG_NODE': hex(node)},
844 blockedtag='bisect_check')
847 blockedtag='bisect_check')
845 if status == 125:
848 if status == 125:
846 transition = "skip"
849 transition = "skip"
847 elif status == 0:
850 elif status == 0:
848 transition = "good"
851 transition = "good"
849 # status < 0 means process was killed
852 # status < 0 means process was killed
850 elif status == 127:
853 elif status == 127:
851 raise error.Abort(_("failed to execute %s") % command)
854 raise error.Abort(_("failed to execute %s") % command)
852 elif status < 0:
855 elif status < 0:
853 raise error.Abort(_("%s killed") % command)
856 raise error.Abort(_("%s killed") % command)
854 else:
857 else:
855 transition = "bad"
858 transition = "bad"
856 state[transition].append(node)
859 state[transition].append(node)
857 ctx = repo[node]
860 ctx = repo[node]
858 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
861 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
859 hbisect.checkstate(state)
862 hbisect.checkstate(state)
860 # bisect
863 # bisect
861 nodes, changesets, bgood = hbisect.bisect(repo, state)
864 nodes, changesets, bgood = hbisect.bisect(repo, state)
862 # update to next check
865 # update to next check
863 node = nodes[0]
866 node = nodes[0]
864 mayupdate(repo, node, show_stats=False)
867 mayupdate(repo, node, show_stats=False)
865 finally:
868 finally:
866 state['current'] = [node]
869 state['current'] = [node]
867 hbisect.save_state(repo, state)
870 hbisect.save_state(repo, state)
868 hbisect.printresult(ui, repo, state, displayer, nodes, bgood)
871 hbisect.printresult(ui, repo, state, displayer, nodes, bgood)
869 return
872 return
870
873
871 hbisect.checkstate(state)
874 hbisect.checkstate(state)
872
875
873 # actually bisect
876 # actually bisect
874 nodes, changesets, good = hbisect.bisect(repo, state)
877 nodes, changesets, good = hbisect.bisect(repo, state)
875 if extend:
878 if extend:
876 if not changesets:
879 if not changesets:
877 extendnode = hbisect.extendrange(repo, state, nodes, good)
880 extendnode = hbisect.extendrange(repo, state, nodes, good)
878 if extendnode is not None:
881 if extendnode is not None:
879 ui.write(_("Extending search to changeset %d:%s\n")
882 ui.write(_("Extending search to changeset %d:%s\n")
880 % (extendnode.rev(), extendnode))
883 % (extendnode.rev(), extendnode))
881 state['current'] = [extendnode.node()]
884 state['current'] = [extendnode.node()]
882 hbisect.save_state(repo, state)
885 hbisect.save_state(repo, state)
883 return mayupdate(repo, extendnode.node())
886 return mayupdate(repo, extendnode.node())
884 raise error.Abort(_("nothing to extend"))
887 raise error.Abort(_("nothing to extend"))
885
888
886 if changesets == 0:
889 if changesets == 0:
887 hbisect.printresult(ui, repo, state, displayer, nodes, good)
890 hbisect.printresult(ui, repo, state, displayer, nodes, good)
888 else:
891 else:
889 assert len(nodes) == 1 # only a single node can be tested next
892 assert len(nodes) == 1 # only a single node can be tested next
890 node = nodes[0]
893 node = nodes[0]
891 # compute the approximate number of remaining tests
894 # compute the approximate number of remaining tests
892 tests, size = 0, 2
895 tests, size = 0, 2
893 while size <= changesets:
896 while size <= changesets:
894 tests, size = tests + 1, size * 2
897 tests, size = tests + 1, size * 2
895 rev = repo.changelog.rev(node)
898 rev = repo.changelog.rev(node)
896 ui.write(_("Testing changeset %d:%s "
899 ui.write(_("Testing changeset %d:%s "
897 "(%d changesets remaining, ~%d tests)\n")
900 "(%d changesets remaining, ~%d tests)\n")
898 % (rev, short(node), changesets, tests))
901 % (rev, short(node), changesets, tests))
899 state['current'] = [node]
902 state['current'] = [node]
900 hbisect.save_state(repo, state)
903 hbisect.save_state(repo, state)
901 return mayupdate(repo, node)
904 return mayupdate(repo, node)
902
905
903 @command('bookmarks|bookmark',
906 @command('bookmarks|bookmark',
904 [('f', 'force', False, _('force')),
907 [('f', 'force', False, _('force')),
905 ('r', 'rev', '', _('revision for bookmark action'), _('REV')),
908 ('r', 'rev', '', _('revision for bookmark action'), _('REV')),
906 ('d', 'delete', False, _('delete a given bookmark')),
909 ('d', 'delete', False, _('delete a given bookmark')),
907 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
910 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
908 ('i', 'inactive', False, _('mark a bookmark inactive')),
911 ('i', 'inactive', False, _('mark a bookmark inactive')),
909 ] + formatteropts,
912 ] + formatteropts,
910 _('hg bookmarks [OPTIONS]... [NAME]...'))
913 _('hg bookmarks [OPTIONS]... [NAME]...'))
911 def bookmark(ui, repo, *names, **opts):
914 def bookmark(ui, repo, *names, **opts):
912 '''create a new bookmark or list existing bookmarks
915 '''create a new bookmark or list existing bookmarks
913
916
914 Bookmarks are labels on changesets to help track lines of development.
917 Bookmarks are labels on changesets to help track lines of development.
915 Bookmarks are unversioned and can be moved, renamed and deleted.
918 Bookmarks are unversioned and can be moved, renamed and deleted.
916 Deleting or moving a bookmark has no effect on the associated changesets.
919 Deleting or moving a bookmark has no effect on the associated changesets.
917
920
918 Creating or updating to a bookmark causes it to be marked as 'active'.
921 Creating or updating to a bookmark causes it to be marked as 'active'.
919 The active bookmark is indicated with a '*'.
922 The active bookmark is indicated with a '*'.
920 When a commit is made, the active bookmark will advance to the new commit.
923 When a commit is made, the active bookmark will advance to the new commit.
921 A plain :hg:`update` will also advance an active bookmark, if possible.
924 A plain :hg:`update` will also advance an active bookmark, if possible.
922 Updating away from a bookmark will cause it to be deactivated.
925 Updating away from a bookmark will cause it to be deactivated.
923
926
924 Bookmarks can be pushed and pulled between repositories (see
927 Bookmarks can be pushed and pulled between repositories (see
925 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
928 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
926 diverged, a new 'divergent bookmark' of the form 'name@path' will
929 diverged, a new 'divergent bookmark' of the form 'name@path' will
927 be created. Using :hg:`merge` will resolve the divergence.
930 be created. Using :hg:`merge` will resolve the divergence.
928
931
929 Specifying bookmark as '.' to -m or -d options is equivalent to specifying
932 Specifying bookmark as '.' to -m or -d options is equivalent to specifying
930 the active bookmark's name.
933 the active bookmark's name.
931
934
932 A bookmark named '@' has the special property that :hg:`clone` will
935 A bookmark named '@' has the special property that :hg:`clone` will
933 check it out by default if it exists.
936 check it out by default if it exists.
934
937
935 .. container:: verbose
938 .. container:: verbose
936
939
937 Examples:
940 Examples:
938
941
939 - create an active bookmark for a new line of development::
942 - create an active bookmark for a new line of development::
940
943
941 hg book new-feature
944 hg book new-feature
942
945
943 - create an inactive bookmark as a place marker::
946 - create an inactive bookmark as a place marker::
944
947
945 hg book -i reviewed
948 hg book -i reviewed
946
949
947 - create an inactive bookmark on another changeset::
950 - create an inactive bookmark on another changeset::
948
951
949 hg book -r .^ tested
952 hg book -r .^ tested
950
953
951 - rename bookmark turkey to dinner::
954 - rename bookmark turkey to dinner::
952
955
953 hg book -m turkey dinner
956 hg book -m turkey dinner
954
957
955 - move the '@' bookmark from another branch::
958 - move the '@' bookmark from another branch::
956
959
957 hg book -f @
960 hg book -f @
958 '''
961 '''
959 force = opts.get(r'force')
962 force = opts.get(r'force')
960 rev = opts.get(r'rev')
963 rev = opts.get(r'rev')
961 delete = opts.get(r'delete')
964 delete = opts.get(r'delete')
962 rename = opts.get(r'rename')
965 rename = opts.get(r'rename')
963 inactive = opts.get(r'inactive')
966 inactive = opts.get(r'inactive')
964
967
965 if delete and rename:
968 if delete and rename:
966 raise error.Abort(_("--delete and --rename are incompatible"))
969 raise error.Abort(_("--delete and --rename are incompatible"))
967 if delete and rev:
970 if delete and rev:
968 raise error.Abort(_("--rev is incompatible with --delete"))
971 raise error.Abort(_("--rev is incompatible with --delete"))
969 if rename and rev:
972 if rename and rev:
970 raise error.Abort(_("--rev is incompatible with --rename"))
973 raise error.Abort(_("--rev is incompatible with --rename"))
971 if not names and (delete or rev):
974 if not names and (delete or rev):
972 raise error.Abort(_("bookmark name required"))
975 raise error.Abort(_("bookmark name required"))
973
976
974 if delete or rename or names or inactive:
977 if delete or rename or names or inactive:
975 with repo.wlock(), repo.lock(), repo.transaction('bookmark') as tr:
978 with repo.wlock(), repo.lock(), repo.transaction('bookmark') as tr:
976 if delete:
979 if delete:
977 names = pycompat.maplist(repo._bookmarks.expandname, names)
980 names = pycompat.maplist(repo._bookmarks.expandname, names)
978 bookmarks.delete(repo, tr, names)
981 bookmarks.delete(repo, tr, names)
979 elif rename:
982 elif rename:
980 if not names:
983 if not names:
981 raise error.Abort(_("new bookmark name required"))
984 raise error.Abort(_("new bookmark name required"))
982 elif len(names) > 1:
985 elif len(names) > 1:
983 raise error.Abort(_("only one new bookmark name allowed"))
986 raise error.Abort(_("only one new bookmark name allowed"))
984 rename = repo._bookmarks.expandname(rename)
987 rename = repo._bookmarks.expandname(rename)
985 bookmarks.rename(repo, tr, rename, names[0], force, inactive)
988 bookmarks.rename(repo, tr, rename, names[0], force, inactive)
986 elif names:
989 elif names:
987 bookmarks.addbookmarks(repo, tr, names, rev, force, inactive)
990 bookmarks.addbookmarks(repo, tr, names, rev, force, inactive)
988 elif inactive:
991 elif inactive:
989 if len(repo._bookmarks) == 0:
992 if len(repo._bookmarks) == 0:
990 ui.status(_("no bookmarks set\n"))
993 ui.status(_("no bookmarks set\n"))
991 elif not repo._activebookmark:
994 elif not repo._activebookmark:
992 ui.status(_("no active bookmark\n"))
995 ui.status(_("no active bookmark\n"))
993 else:
996 else:
994 bookmarks.deactivate(repo)
997 bookmarks.deactivate(repo)
995 else: # show bookmarks
998 else: # show bookmarks
996 bookmarks.printbookmarks(ui, repo, **opts)
999 bookmarks.printbookmarks(ui, repo, **opts)
997
1000
998 @command('branch',
1001 @command('branch',
999 [('f', 'force', None,
1002 [('f', 'force', None,
1000 _('set branch name even if it shadows an existing branch')),
1003 _('set branch name even if it shadows an existing branch')),
1001 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1004 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1002 _('[-fC] [NAME]'))
1005 _('[-fC] [NAME]'))
1003 def branch(ui, repo, label=None, **opts):
1006 def branch(ui, repo, label=None, **opts):
1004 """set or show the current branch name
1007 """set or show the current branch name
1005
1008
1006 .. note::
1009 .. note::
1007
1010
1008 Branch names are permanent and global. Use :hg:`bookmark` to create a
1011 Branch names are permanent and global. Use :hg:`bookmark` to create a
1009 light-weight bookmark instead. See :hg:`help glossary` for more
1012 light-weight bookmark instead. See :hg:`help glossary` for more
1010 information about named branches and bookmarks.
1013 information about named branches and bookmarks.
1011
1014
1012 With no argument, show the current branch name. With one argument,
1015 With no argument, show the current branch name. With one argument,
1013 set the working directory branch name (the branch will not exist
1016 set the working directory branch name (the branch will not exist
1014 in the repository until the next commit). Standard practice
1017 in the repository until the next commit). Standard practice
1015 recommends that primary development take place on the 'default'
1018 recommends that primary development take place on the 'default'
1016 branch.
1019 branch.
1017
1020
1018 Unless -f/--force is specified, branch will not let you set a
1021 Unless -f/--force is specified, branch will not let you set a
1019 branch name that already exists.
1022 branch name that already exists.
1020
1023
1021 Use -C/--clean to reset the working directory branch to that of
1024 Use -C/--clean to reset the working directory branch to that of
1022 the parent of the working directory, negating a previous branch
1025 the parent of the working directory, negating a previous branch
1023 change.
1026 change.
1024
1027
1025 Use the command :hg:`update` to switch to an existing branch. Use
1028 Use the command :hg:`update` to switch to an existing branch. Use
1026 :hg:`commit --close-branch` to mark this branch head as closed.
1029 :hg:`commit --close-branch` to mark this branch head as closed.
1027 When all heads of a branch are closed, the branch will be
1030 When all heads of a branch are closed, the branch will be
1028 considered closed.
1031 considered closed.
1029
1032
1030 Returns 0 on success.
1033 Returns 0 on success.
1031 """
1034 """
1032 opts = pycompat.byteskwargs(opts)
1035 opts = pycompat.byteskwargs(opts)
1033 if label:
1036 if label:
1034 label = label.strip()
1037 label = label.strip()
1035
1038
1036 if not opts.get('clean') and not label:
1039 if not opts.get('clean') and not label:
1037 ui.write("%s\n" % repo.dirstate.branch())
1040 ui.write("%s\n" % repo.dirstate.branch())
1038 return
1041 return
1039
1042
1040 with repo.wlock():
1043 with repo.wlock():
1041 if opts.get('clean'):
1044 if opts.get('clean'):
1042 label = repo[None].p1().branch()
1045 label = repo[None].p1().branch()
1043 repo.dirstate.setbranch(label)
1046 repo.dirstate.setbranch(label)
1044 ui.status(_('reset working directory to branch %s\n') % label)
1047 ui.status(_('reset working directory to branch %s\n') % label)
1045 elif label:
1048 elif label:
1046 if not opts.get('force') and label in repo.branchmap():
1049 if not opts.get('force') and label in repo.branchmap():
1047 if label not in [p.branch() for p in repo[None].parents()]:
1050 if label not in [p.branch() for p in repo[None].parents()]:
1048 raise error.Abort(_('a branch of the same name already'
1051 raise error.Abort(_('a branch of the same name already'
1049 ' exists'),
1052 ' exists'),
1050 # i18n: "it" refers to an existing branch
1053 # i18n: "it" refers to an existing branch
1051 hint=_("use 'hg update' to switch to it"))
1054 hint=_("use 'hg update' to switch to it"))
1052 scmutil.checknewlabel(repo, label, 'branch')
1055 scmutil.checknewlabel(repo, label, 'branch')
1053 repo.dirstate.setbranch(label)
1056 repo.dirstate.setbranch(label)
1054 ui.status(_('marked working directory as branch %s\n') % label)
1057 ui.status(_('marked working directory as branch %s\n') % label)
1055
1058
1056 # find any open named branches aside from default
1059 # find any open named branches aside from default
1057 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1060 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1058 if n != "default" and not c]
1061 if n != "default" and not c]
1059 if not others:
1062 if not others:
1060 ui.status(_('(branches are permanent and global, '
1063 ui.status(_('(branches are permanent and global, '
1061 'did you want a bookmark?)\n'))
1064 'did you want a bookmark?)\n'))
1062
1065
1063 @command('branches',
1066 @command('branches',
1064 [('a', 'active', False,
1067 [('a', 'active', False,
1065 _('show only branches that have unmerged heads (DEPRECATED)')),
1068 _('show only branches that have unmerged heads (DEPRECATED)')),
1066 ('c', 'closed', False, _('show normal and closed branches')),
1069 ('c', 'closed', False, _('show normal and closed branches')),
1067 ] + formatteropts,
1070 ] + formatteropts,
1068 _('[-c]'), cmdtype=readonly)
1071 _('[-c]'), cmdtype=readonly)
1069 def branches(ui, repo, active=False, closed=False, **opts):
1072 def branches(ui, repo, active=False, closed=False, **opts):
1070 """list repository named branches
1073 """list repository named branches
1071
1074
1072 List the repository's named branches, indicating which ones are
1075 List the repository's named branches, indicating which ones are
1073 inactive. If -c/--closed is specified, also list branches which have
1076 inactive. If -c/--closed is specified, also list branches which have
1074 been marked closed (see :hg:`commit --close-branch`).
1077 been marked closed (see :hg:`commit --close-branch`).
1075
1078
1076 Use the command :hg:`update` to switch to an existing branch.
1079 Use the command :hg:`update` to switch to an existing branch.
1077
1080
1078 Returns 0.
1081 Returns 0.
1079 """
1082 """
1080
1083
1081 opts = pycompat.byteskwargs(opts)
1084 opts = pycompat.byteskwargs(opts)
1082 ui.pager('branches')
1085 ui.pager('branches')
1083 fm = ui.formatter('branches', opts)
1086 fm = ui.formatter('branches', opts)
1084 hexfunc = fm.hexfunc
1087 hexfunc = fm.hexfunc
1085
1088
1086 allheads = set(repo.heads())
1089 allheads = set(repo.heads())
1087 branches = []
1090 branches = []
1088 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1091 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1089 isactive = False
1092 isactive = False
1090 if not isclosed:
1093 if not isclosed:
1091 openheads = set(repo.branchmap().iteropen(heads))
1094 openheads = set(repo.branchmap().iteropen(heads))
1092 isactive = bool(openheads & allheads)
1095 isactive = bool(openheads & allheads)
1093 branches.append((tag, repo[tip], isactive, not isclosed))
1096 branches.append((tag, repo[tip], isactive, not isclosed))
1094 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1097 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1095 reverse=True)
1098 reverse=True)
1096
1099
1097 for tag, ctx, isactive, isopen in branches:
1100 for tag, ctx, isactive, isopen in branches:
1098 if active and not isactive:
1101 if active and not isactive:
1099 continue
1102 continue
1100 if isactive:
1103 if isactive:
1101 label = 'branches.active'
1104 label = 'branches.active'
1102 notice = ''
1105 notice = ''
1103 elif not isopen:
1106 elif not isopen:
1104 if not closed:
1107 if not closed:
1105 continue
1108 continue
1106 label = 'branches.closed'
1109 label = 'branches.closed'
1107 notice = _(' (closed)')
1110 notice = _(' (closed)')
1108 else:
1111 else:
1109 label = 'branches.inactive'
1112 label = 'branches.inactive'
1110 notice = _(' (inactive)')
1113 notice = _(' (inactive)')
1111 current = (tag == repo.dirstate.branch())
1114 current = (tag == repo.dirstate.branch())
1112 if current:
1115 if current:
1113 label = 'branches.current'
1116 label = 'branches.current'
1114
1117
1115 fm.startitem()
1118 fm.startitem()
1116 fm.write('branch', '%s', tag, label=label)
1119 fm.write('branch', '%s', tag, label=label)
1117 rev = ctx.rev()
1120 rev = ctx.rev()
1118 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1121 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1119 fmt = ' ' * padsize + ' %d:%s'
1122 fmt = ' ' * padsize + ' %d:%s'
1120 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1123 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1121 label='log.changeset changeset.%s' % ctx.phasestr())
1124 label='log.changeset changeset.%s' % ctx.phasestr())
1122 fm.context(ctx=ctx)
1125 fm.context(ctx=ctx)
1123 fm.data(active=isactive, closed=not isopen, current=current)
1126 fm.data(active=isactive, closed=not isopen, current=current)
1124 if not ui.quiet:
1127 if not ui.quiet:
1125 fm.plain(notice)
1128 fm.plain(notice)
1126 fm.plain('\n')
1129 fm.plain('\n')
1127 fm.end()
1130 fm.end()
1128
1131
1129 @command('bundle',
1132 @command('bundle',
1130 [('f', 'force', None, _('run even when the destination is unrelated')),
1133 [('f', 'force', None, _('run even when the destination is unrelated')),
1131 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1134 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1132 _('REV')),
1135 _('REV')),
1133 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1136 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1134 _('BRANCH')),
1137 _('BRANCH')),
1135 ('', 'base', [],
1138 ('', 'base', [],
1136 _('a base changeset assumed to be available at the destination'),
1139 _('a base changeset assumed to be available at the destination'),
1137 _('REV')),
1140 _('REV')),
1138 ('a', 'all', None, _('bundle all changesets in the repository')),
1141 ('a', 'all', None, _('bundle all changesets in the repository')),
1139 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1142 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1140 ] + remoteopts,
1143 ] + remoteopts,
1141 _('[-f] [-t BUNDLESPEC] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1144 _('[-f] [-t BUNDLESPEC] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1142 def bundle(ui, repo, fname, dest=None, **opts):
1145 def bundle(ui, repo, fname, dest=None, **opts):
1143 """create a bundle file
1146 """create a bundle file
1144
1147
1145 Generate a bundle file containing data to be added to a repository.
1148 Generate a bundle file containing data to be added to a repository.
1146
1149
1147 To create a bundle containing all changesets, use -a/--all
1150 To create a bundle containing all changesets, use -a/--all
1148 (or --base null). Otherwise, hg assumes the destination will have
1151 (or --base null). Otherwise, hg assumes the destination will have
1149 all the nodes you specify with --base parameters. Otherwise, hg
1152 all the nodes you specify with --base parameters. Otherwise, hg
1150 will assume the repository has all the nodes in destination, or
1153 will assume the repository has all the nodes in destination, or
1151 default-push/default if no destination is specified.
1154 default-push/default if no destination is specified.
1152
1155
1153 You can change bundle format with the -t/--type option. See
1156 You can change bundle format with the -t/--type option. See
1154 :hg:`help bundlespec` for documentation on this format. By default,
1157 :hg:`help bundlespec` for documentation on this format. By default,
1155 the most appropriate format is used and compression defaults to
1158 the most appropriate format is used and compression defaults to
1156 bzip2.
1159 bzip2.
1157
1160
1158 The bundle file can then be transferred using conventional means
1161 The bundle file can then be transferred using conventional means
1159 and applied to another repository with the unbundle or pull
1162 and applied to another repository with the unbundle or pull
1160 command. This is useful when direct push and pull are not
1163 command. This is useful when direct push and pull are not
1161 available or when exporting an entire repository is undesirable.
1164 available or when exporting an entire repository is undesirable.
1162
1165
1163 Applying bundles preserves all changeset contents including
1166 Applying bundles preserves all changeset contents including
1164 permissions, copy/rename information, and revision history.
1167 permissions, copy/rename information, and revision history.
1165
1168
1166 Returns 0 on success, 1 if no changes found.
1169 Returns 0 on success, 1 if no changes found.
1167 """
1170 """
1168 opts = pycompat.byteskwargs(opts)
1171 opts = pycompat.byteskwargs(opts)
1169 revs = None
1172 revs = None
1170 if 'rev' in opts:
1173 if 'rev' in opts:
1171 revstrings = opts['rev']
1174 revstrings = opts['rev']
1172 revs = scmutil.revrange(repo, revstrings)
1175 revs = scmutil.revrange(repo, revstrings)
1173 if revstrings and not revs:
1176 if revstrings and not revs:
1174 raise error.Abort(_('no commits to bundle'))
1177 raise error.Abort(_('no commits to bundle'))
1175
1178
1176 bundletype = opts.get('type', 'bzip2').lower()
1179 bundletype = opts.get('type', 'bzip2').lower()
1177 try:
1180 try:
1178 bcompression, cgversion, params = exchange.parsebundlespec(
1181 bcompression, cgversion, params = exchange.parsebundlespec(
1179 repo, bundletype, strict=False)
1182 repo, bundletype, strict=False)
1180 except error.UnsupportedBundleSpecification as e:
1183 except error.UnsupportedBundleSpecification as e:
1181 raise error.Abort(str(e),
1184 raise error.Abort(str(e),
1182 hint=_("see 'hg help bundlespec' for supported "
1185 hint=_("see 'hg help bundlespec' for supported "
1183 "values for --type"))
1186 "values for --type"))
1184
1187
1185 # Packed bundles are a pseudo bundle format for now.
1188 # Packed bundles are a pseudo bundle format for now.
1186 if cgversion == 's1':
1189 if cgversion == 's1':
1187 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1190 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1188 hint=_("use 'hg debugcreatestreamclonebundle'"))
1191 hint=_("use 'hg debugcreatestreamclonebundle'"))
1189
1192
1190 if opts.get('all'):
1193 if opts.get('all'):
1191 if dest:
1194 if dest:
1192 raise error.Abort(_("--all is incompatible with specifying "
1195 raise error.Abort(_("--all is incompatible with specifying "
1193 "a destination"))
1196 "a destination"))
1194 if opts.get('base'):
1197 if opts.get('base'):
1195 ui.warn(_("ignoring --base because --all was specified\n"))
1198 ui.warn(_("ignoring --base because --all was specified\n"))
1196 base = ['null']
1199 base = ['null']
1197 else:
1200 else:
1198 base = scmutil.revrange(repo, opts.get('base'))
1201 base = scmutil.revrange(repo, opts.get('base'))
1199 if cgversion not in changegroup.supportedoutgoingversions(repo):
1202 if cgversion not in changegroup.supportedoutgoingversions(repo):
1200 raise error.Abort(_("repository does not support bundle version %s") %
1203 raise error.Abort(_("repository does not support bundle version %s") %
1201 cgversion)
1204 cgversion)
1202
1205
1203 if base:
1206 if base:
1204 if dest:
1207 if dest:
1205 raise error.Abort(_("--base is incompatible with specifying "
1208 raise error.Abort(_("--base is incompatible with specifying "
1206 "a destination"))
1209 "a destination"))
1207 common = [repo.lookup(rev) for rev in base]
1210 common = [repo.lookup(rev) for rev in base]
1208 heads = revs and map(repo.lookup, revs) or None
1211 heads = revs and map(repo.lookup, revs) or None
1209 outgoing = discovery.outgoing(repo, common, heads)
1212 outgoing = discovery.outgoing(repo, common, heads)
1210 else:
1213 else:
1211 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1214 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1212 dest, branches = hg.parseurl(dest, opts.get('branch'))
1215 dest, branches = hg.parseurl(dest, opts.get('branch'))
1213 other = hg.peer(repo, opts, dest)
1216 other = hg.peer(repo, opts, dest)
1214 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1217 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1215 heads = revs and map(repo.lookup, revs) or revs
1218 heads = revs and map(repo.lookup, revs) or revs
1216 outgoing = discovery.findcommonoutgoing(repo, other,
1219 outgoing = discovery.findcommonoutgoing(repo, other,
1217 onlyheads=heads,
1220 onlyheads=heads,
1218 force=opts.get('force'),
1221 force=opts.get('force'),
1219 portable=True)
1222 portable=True)
1220
1223
1221 if not outgoing.missing:
1224 if not outgoing.missing:
1222 scmutil.nochangesfound(ui, repo, not base and outgoing.excluded)
1225 scmutil.nochangesfound(ui, repo, not base and outgoing.excluded)
1223 return 1
1226 return 1
1224
1227
1225 if cgversion == '01': #bundle1
1228 if cgversion == '01': #bundle1
1226 if bcompression is None:
1229 if bcompression is None:
1227 bcompression = 'UN'
1230 bcompression = 'UN'
1228 bversion = 'HG10' + bcompression
1231 bversion = 'HG10' + bcompression
1229 bcompression = None
1232 bcompression = None
1230 elif cgversion in ('02', '03'):
1233 elif cgversion in ('02', '03'):
1231 bversion = 'HG20'
1234 bversion = 'HG20'
1232 else:
1235 else:
1233 raise error.ProgrammingError(
1236 raise error.ProgrammingError(
1234 'bundle: unexpected changegroup version %s' % cgversion)
1237 'bundle: unexpected changegroup version %s' % cgversion)
1235
1238
1236 # TODO compression options should be derived from bundlespec parsing.
1239 # TODO compression options should be derived from bundlespec parsing.
1237 # This is a temporary hack to allow adjusting bundle compression
1240 # This is a temporary hack to allow adjusting bundle compression
1238 # level without a) formalizing the bundlespec changes to declare it
1241 # level without a) formalizing the bundlespec changes to declare it
1239 # b) introducing a command flag.
1242 # b) introducing a command flag.
1240 compopts = {}
1243 compopts = {}
1241 complevel = ui.configint('experimental', 'bundlecomplevel')
1244 complevel = ui.configint('experimental', 'bundlecomplevel')
1242 if complevel is not None:
1245 if complevel is not None:
1243 compopts['level'] = complevel
1246 compopts['level'] = complevel
1244
1247
1245
1248
1246 contentopts = {'cg.version': cgversion}
1249 contentopts = {'cg.version': cgversion}
1247 if repo.ui.configbool('experimental', 'evolution.bundle-obsmarker'):
1250 if repo.ui.configbool('experimental', 'evolution.bundle-obsmarker'):
1248 contentopts['obsolescence'] = True
1251 contentopts['obsolescence'] = True
1249 if repo.ui.configbool('experimental', 'bundle-phases'):
1252 if repo.ui.configbool('experimental', 'bundle-phases'):
1250 contentopts['phases'] = True
1253 contentopts['phases'] = True
1251 bundle2.writenewbundle(ui, repo, 'bundle', fname, bversion, outgoing,
1254 bundle2.writenewbundle(ui, repo, 'bundle', fname, bversion, outgoing,
1252 contentopts, compression=bcompression,
1255 contentopts, compression=bcompression,
1253 compopts=compopts)
1256 compopts=compopts)
1254
1257
1255 @command('cat',
1258 @command('cat',
1256 [('o', 'output', '',
1259 [('o', 'output', '',
1257 _('print output to file with formatted name'), _('FORMAT')),
1260 _('print output to file with formatted name'), _('FORMAT')),
1258 ('r', 'rev', '', _('print the given revision'), _('REV')),
1261 ('r', 'rev', '', _('print the given revision'), _('REV')),
1259 ('', 'decode', None, _('apply any matching decode filter')),
1262 ('', 'decode', None, _('apply any matching decode filter')),
1260 ] + walkopts + formatteropts,
1263 ] + walkopts + formatteropts,
1261 _('[OPTION]... FILE...'),
1264 _('[OPTION]... FILE...'),
1262 inferrepo=True, cmdtype=readonly)
1265 inferrepo=True, cmdtype=readonly)
1263 def cat(ui, repo, file1, *pats, **opts):
1266 def cat(ui, repo, file1, *pats, **opts):
1264 """output the current or given revision of files
1267 """output the current or given revision of files
1265
1268
1266 Print the specified files as they were at the given revision. If
1269 Print the specified files as they were at the given revision. If
1267 no revision is given, the parent of the working directory is used.
1270 no revision is given, the parent of the working directory is used.
1268
1271
1269 Output may be to a file, in which case the name of the file is
1272 Output may be to a file, in which case the name of the file is
1270 given using a format string. The formatting rules as follows:
1273 given using a format string. The formatting rules as follows:
1271
1274
1272 :``%%``: literal "%" character
1275 :``%%``: literal "%" character
1273 :``%s``: basename of file being printed
1276 :``%s``: basename of file being printed
1274 :``%d``: dirname of file being printed, or '.' if in repository root
1277 :``%d``: dirname of file being printed, or '.' if in repository root
1275 :``%p``: root-relative path name of file being printed
1278 :``%p``: root-relative path name of file being printed
1276 :``%H``: changeset hash (40 hexadecimal digits)
1279 :``%H``: changeset hash (40 hexadecimal digits)
1277 :``%R``: changeset revision number
1280 :``%R``: changeset revision number
1278 :``%h``: short-form changeset hash (12 hexadecimal digits)
1281 :``%h``: short-form changeset hash (12 hexadecimal digits)
1279 :``%r``: zero-padded changeset revision number
1282 :``%r``: zero-padded changeset revision number
1280 :``%b``: basename of the exporting repository
1283 :``%b``: basename of the exporting repository
1281
1284
1282 Returns 0 on success.
1285 Returns 0 on success.
1283 """
1286 """
1284 opts = pycompat.byteskwargs(opts)
1287 opts = pycompat.byteskwargs(opts)
1285 rev = opts.get('rev')
1288 rev = opts.get('rev')
1286 if rev:
1289 if rev:
1287 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
1290 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
1288 ctx = scmutil.revsingle(repo, rev)
1291 ctx = scmutil.revsingle(repo, rev)
1289 m = scmutil.match(ctx, (file1,) + pats, opts)
1292 m = scmutil.match(ctx, (file1,) + pats, opts)
1290 fntemplate = opts.pop('output', '')
1293 fntemplate = opts.pop('output', '')
1291 if cmdutil.isstdiofilename(fntemplate):
1294 if cmdutil.isstdiofilename(fntemplate):
1292 fntemplate = ''
1295 fntemplate = ''
1293
1296
1294 if fntemplate:
1297 if fntemplate:
1295 fm = formatter.nullformatter(ui, 'cat')
1298 fm = formatter.nullformatter(ui, 'cat')
1296 else:
1299 else:
1297 ui.pager('cat')
1300 ui.pager('cat')
1298 fm = ui.formatter('cat', opts)
1301 fm = ui.formatter('cat', opts)
1299 with fm:
1302 with fm:
1300 return cmdutil.cat(ui, repo, ctx, m, fm, fntemplate, '',
1303 return cmdutil.cat(ui, repo, ctx, m, fm, fntemplate, '',
1301 **pycompat.strkwargs(opts))
1304 **pycompat.strkwargs(opts))
1302
1305
1303 @command('^clone',
1306 @command('^clone',
1304 [('U', 'noupdate', None, _('the clone will include an empty working '
1307 [('U', 'noupdate', None, _('the clone will include an empty working '
1305 'directory (only a repository)')),
1308 'directory (only a repository)')),
1306 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1309 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1307 _('REV')),
1310 _('REV')),
1308 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1311 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1309 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1312 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1310 ('', 'pull', None, _('use pull protocol to copy metadata')),
1313 ('', 'pull', None, _('use pull protocol to copy metadata')),
1311 ('', 'uncompressed', None,
1314 ('', 'uncompressed', None,
1312 _('an alias to --stream (DEPRECATED)')),
1315 _('an alias to --stream (DEPRECATED)')),
1313 ('', 'stream', None,
1316 ('', 'stream', None,
1314 _('clone with minimal data processing')),
1317 _('clone with minimal data processing')),
1315 ] + remoteopts,
1318 ] + remoteopts,
1316 _('[OPTION]... SOURCE [DEST]'),
1319 _('[OPTION]... SOURCE [DEST]'),
1317 norepo=True)
1320 norepo=True)
1318 def clone(ui, source, dest=None, **opts):
1321 def clone(ui, source, dest=None, **opts):
1319 """make a copy of an existing repository
1322 """make a copy of an existing repository
1320
1323
1321 Create a copy of an existing repository in a new directory.
1324 Create a copy of an existing repository in a new directory.
1322
1325
1323 If no destination directory name is specified, it defaults to the
1326 If no destination directory name is specified, it defaults to the
1324 basename of the source.
1327 basename of the source.
1325
1328
1326 The location of the source is added to the new repository's
1329 The location of the source is added to the new repository's
1327 ``.hg/hgrc`` file, as the default to be used for future pulls.
1330 ``.hg/hgrc`` file, as the default to be used for future pulls.
1328
1331
1329 Only local paths and ``ssh://`` URLs are supported as
1332 Only local paths and ``ssh://`` URLs are supported as
1330 destinations. For ``ssh://`` destinations, no working directory or
1333 destinations. For ``ssh://`` destinations, no working directory or
1331 ``.hg/hgrc`` will be created on the remote side.
1334 ``.hg/hgrc`` will be created on the remote side.
1332
1335
1333 If the source repository has a bookmark called '@' set, that
1336 If the source repository has a bookmark called '@' set, that
1334 revision will be checked out in the new repository by default.
1337 revision will be checked out in the new repository by default.
1335
1338
1336 To check out a particular version, use -u/--update, or
1339 To check out a particular version, use -u/--update, or
1337 -U/--noupdate to create a clone with no working directory.
1340 -U/--noupdate to create a clone with no working directory.
1338
1341
1339 To pull only a subset of changesets, specify one or more revisions
1342 To pull only a subset of changesets, specify one or more revisions
1340 identifiers with -r/--rev or branches with -b/--branch. The
1343 identifiers with -r/--rev or branches with -b/--branch. The
1341 resulting clone will contain only the specified changesets and
1344 resulting clone will contain only the specified changesets and
1342 their ancestors. These options (or 'clone src#rev dest') imply
1345 their ancestors. These options (or 'clone src#rev dest') imply
1343 --pull, even for local source repositories.
1346 --pull, even for local source repositories.
1344
1347
1345 In normal clone mode, the remote normalizes repository data into a common
1348 In normal clone mode, the remote normalizes repository data into a common
1346 exchange format and the receiving end translates this data into its local
1349 exchange format and the receiving end translates this data into its local
1347 storage format. --stream activates a different clone mode that essentially
1350 storage format. --stream activates a different clone mode that essentially
1348 copies repository files from the remote with minimal data processing. This
1351 copies repository files from the remote with minimal data processing. This
1349 significantly reduces the CPU cost of a clone both remotely and locally.
1352 significantly reduces the CPU cost of a clone both remotely and locally.
1350 However, it often increases the transferred data size by 30-40%. This can
1353 However, it often increases the transferred data size by 30-40%. This can
1351 result in substantially faster clones where I/O throughput is plentiful,
1354 result in substantially faster clones where I/O throughput is plentiful,
1352 especially for larger repositories. A side-effect of --stream clones is
1355 especially for larger repositories. A side-effect of --stream clones is
1353 that storage settings and requirements on the remote are applied locally:
1356 that storage settings and requirements on the remote are applied locally:
1354 a modern client may inherit legacy or inefficient storage used by the
1357 a modern client may inherit legacy or inefficient storage used by the
1355 remote or a legacy Mercurial client may not be able to clone from a
1358 remote or a legacy Mercurial client may not be able to clone from a
1356 modern Mercurial remote.
1359 modern Mercurial remote.
1357
1360
1358 .. note::
1361 .. note::
1359
1362
1360 Specifying a tag will include the tagged changeset but not the
1363 Specifying a tag will include the tagged changeset but not the
1361 changeset containing the tag.
1364 changeset containing the tag.
1362
1365
1363 .. container:: verbose
1366 .. container:: verbose
1364
1367
1365 For efficiency, hardlinks are used for cloning whenever the
1368 For efficiency, hardlinks are used for cloning whenever the
1366 source and destination are on the same filesystem (note this
1369 source and destination are on the same filesystem (note this
1367 applies only to the repository data, not to the working
1370 applies only to the repository data, not to the working
1368 directory). Some filesystems, such as AFS, implement hardlinking
1371 directory). Some filesystems, such as AFS, implement hardlinking
1369 incorrectly, but do not report errors. In these cases, use the
1372 incorrectly, but do not report errors. In these cases, use the
1370 --pull option to avoid hardlinking.
1373 --pull option to avoid hardlinking.
1371
1374
1372 Mercurial will update the working directory to the first applicable
1375 Mercurial will update the working directory to the first applicable
1373 revision from this list:
1376 revision from this list:
1374
1377
1375 a) null if -U or the source repository has no changesets
1378 a) null if -U or the source repository has no changesets
1376 b) if -u . and the source repository is local, the first parent of
1379 b) if -u . and the source repository is local, the first parent of
1377 the source repository's working directory
1380 the source repository's working directory
1378 c) the changeset specified with -u (if a branch name, this means the
1381 c) the changeset specified with -u (if a branch name, this means the
1379 latest head of that branch)
1382 latest head of that branch)
1380 d) the changeset specified with -r
1383 d) the changeset specified with -r
1381 e) the tipmost head specified with -b
1384 e) the tipmost head specified with -b
1382 f) the tipmost head specified with the url#branch source syntax
1385 f) the tipmost head specified with the url#branch source syntax
1383 g) the revision marked with the '@' bookmark, if present
1386 g) the revision marked with the '@' bookmark, if present
1384 h) the tipmost head of the default branch
1387 h) the tipmost head of the default branch
1385 i) tip
1388 i) tip
1386
1389
1387 When cloning from servers that support it, Mercurial may fetch
1390 When cloning from servers that support it, Mercurial may fetch
1388 pre-generated data from a server-advertised URL. When this is done,
1391 pre-generated data from a server-advertised URL. When this is done,
1389 hooks operating on incoming changesets and changegroups may fire twice,
1392 hooks operating on incoming changesets and changegroups may fire twice,
1390 once for the bundle fetched from the URL and another for any additional
1393 once for the bundle fetched from the URL and another for any additional
1391 data not fetched from this URL. In addition, if an error occurs, the
1394 data not fetched from this URL. In addition, if an error occurs, the
1392 repository may be rolled back to a partial clone. This behavior may
1395 repository may be rolled back to a partial clone. This behavior may
1393 change in future releases. See :hg:`help -e clonebundles` for more.
1396 change in future releases. See :hg:`help -e clonebundles` for more.
1394
1397
1395 Examples:
1398 Examples:
1396
1399
1397 - clone a remote repository to a new directory named hg/::
1400 - clone a remote repository to a new directory named hg/::
1398
1401
1399 hg clone https://www.mercurial-scm.org/repo/hg/
1402 hg clone https://www.mercurial-scm.org/repo/hg/
1400
1403
1401 - create a lightweight local clone::
1404 - create a lightweight local clone::
1402
1405
1403 hg clone project/ project-feature/
1406 hg clone project/ project-feature/
1404
1407
1405 - clone from an absolute path on an ssh server (note double-slash)::
1408 - clone from an absolute path on an ssh server (note double-slash)::
1406
1409
1407 hg clone ssh://user@server//home/projects/alpha/
1410 hg clone ssh://user@server//home/projects/alpha/
1408
1411
1409 - do a streaming clone while checking out a specified version::
1412 - do a streaming clone while checking out a specified version::
1410
1413
1411 hg clone --stream http://server/repo -u 1.5
1414 hg clone --stream http://server/repo -u 1.5
1412
1415
1413 - create a repository without changesets after a particular revision::
1416 - create a repository without changesets after a particular revision::
1414
1417
1415 hg clone -r 04e544 experimental/ good/
1418 hg clone -r 04e544 experimental/ good/
1416
1419
1417 - clone (and track) a particular named branch::
1420 - clone (and track) a particular named branch::
1418
1421
1419 hg clone https://www.mercurial-scm.org/repo/hg/#stable
1422 hg clone https://www.mercurial-scm.org/repo/hg/#stable
1420
1423
1421 See :hg:`help urls` for details on specifying URLs.
1424 See :hg:`help urls` for details on specifying URLs.
1422
1425
1423 Returns 0 on success.
1426 Returns 0 on success.
1424 """
1427 """
1425 opts = pycompat.byteskwargs(opts)
1428 opts = pycompat.byteskwargs(opts)
1426 if opts.get('noupdate') and opts.get('updaterev'):
1429 if opts.get('noupdate') and opts.get('updaterev'):
1427 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1430 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1428
1431
1429 r = hg.clone(ui, opts, source, dest,
1432 r = hg.clone(ui, opts, source, dest,
1430 pull=opts.get('pull'),
1433 pull=opts.get('pull'),
1431 stream=opts.get('stream') or opts.get('uncompressed'),
1434 stream=opts.get('stream') or opts.get('uncompressed'),
1432 rev=opts.get('rev'),
1435 rev=opts.get('rev'),
1433 update=opts.get('updaterev') or not opts.get('noupdate'),
1436 update=opts.get('updaterev') or not opts.get('noupdate'),
1434 branch=opts.get('branch'),
1437 branch=opts.get('branch'),
1435 shareopts=opts.get('shareopts'))
1438 shareopts=opts.get('shareopts'))
1436
1439
1437 return r is None
1440 return r is None
1438
1441
1439 @command('^commit|ci',
1442 @command('^commit|ci',
1440 [('A', 'addremove', None,
1443 [('A', 'addremove', None,
1441 _('mark new/missing files as added/removed before committing')),
1444 _('mark new/missing files as added/removed before committing')),
1442 ('', 'close-branch', None,
1445 ('', 'close-branch', None,
1443 _('mark a branch head as closed')),
1446 _('mark a branch head as closed')),
1444 ('', 'amend', None, _('amend the parent of the working directory')),
1447 ('', 'amend', None, _('amend the parent of the working directory')),
1445 ('s', 'secret', None, _('use the secret phase for committing')),
1448 ('s', 'secret', None, _('use the secret phase for committing')),
1446 ('e', 'edit', None, _('invoke editor on commit messages')),
1449 ('e', 'edit', None, _('invoke editor on commit messages')),
1447 ('i', 'interactive', None, _('use interactive mode')),
1450 ('i', 'interactive', None, _('use interactive mode')),
1448 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1451 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1449 _('[OPTION]... [FILE]...'),
1452 _('[OPTION]... [FILE]...'),
1450 inferrepo=True)
1453 inferrepo=True)
1451 def commit(ui, repo, *pats, **opts):
1454 def commit(ui, repo, *pats, **opts):
1452 """commit the specified files or all outstanding changes
1455 """commit the specified files or all outstanding changes
1453
1456
1454 Commit changes to the given files into the repository. Unlike a
1457 Commit changes to the given files into the repository. Unlike a
1455 centralized SCM, this operation is a local operation. See
1458 centralized SCM, this operation is a local operation. See
1456 :hg:`push` for a way to actively distribute your changes.
1459 :hg:`push` for a way to actively distribute your changes.
1457
1460
1458 If a list of files is omitted, all changes reported by :hg:`status`
1461 If a list of files is omitted, all changes reported by :hg:`status`
1459 will be committed.
1462 will be committed.
1460
1463
1461 If you are committing the result of a merge, do not provide any
1464 If you are committing the result of a merge, do not provide any
1462 filenames or -I/-X filters.
1465 filenames or -I/-X filters.
1463
1466
1464 If no commit message is specified, Mercurial starts your
1467 If no commit message is specified, Mercurial starts your
1465 configured editor where you can enter a message. In case your
1468 configured editor where you can enter a message. In case your
1466 commit fails, you will find a backup of your message in
1469 commit fails, you will find a backup of your message in
1467 ``.hg/last-message.txt``.
1470 ``.hg/last-message.txt``.
1468
1471
1469 The --close-branch flag can be used to mark the current branch
1472 The --close-branch flag can be used to mark the current branch
1470 head closed. When all heads of a branch are closed, the branch
1473 head closed. When all heads of a branch are closed, the branch
1471 will be considered closed and no longer listed.
1474 will be considered closed and no longer listed.
1472
1475
1473 The --amend flag can be used to amend the parent of the
1476 The --amend flag can be used to amend the parent of the
1474 working directory with a new commit that contains the changes
1477 working directory with a new commit that contains the changes
1475 in the parent in addition to those currently reported by :hg:`status`,
1478 in the parent in addition to those currently reported by :hg:`status`,
1476 if there are any. The old commit is stored in a backup bundle in
1479 if there are any. The old commit is stored in a backup bundle in
1477 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1480 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1478 on how to restore it).
1481 on how to restore it).
1479
1482
1480 Message, user and date are taken from the amended commit unless
1483 Message, user and date are taken from the amended commit unless
1481 specified. When a message isn't specified on the command line,
1484 specified. When a message isn't specified on the command line,
1482 the editor will open with the message of the amended commit.
1485 the editor will open with the message of the amended commit.
1483
1486
1484 It is not possible to amend public changesets (see :hg:`help phases`)
1487 It is not possible to amend public changesets (see :hg:`help phases`)
1485 or changesets that have children.
1488 or changesets that have children.
1486
1489
1487 See :hg:`help dates` for a list of formats valid for -d/--date.
1490 See :hg:`help dates` for a list of formats valid for -d/--date.
1488
1491
1489 Returns 0 on success, 1 if nothing changed.
1492 Returns 0 on success, 1 if nothing changed.
1490
1493
1491 .. container:: verbose
1494 .. container:: verbose
1492
1495
1493 Examples:
1496 Examples:
1494
1497
1495 - commit all files ending in .py::
1498 - commit all files ending in .py::
1496
1499
1497 hg commit --include "set:**.py"
1500 hg commit --include "set:**.py"
1498
1501
1499 - commit all non-binary files::
1502 - commit all non-binary files::
1500
1503
1501 hg commit --exclude "set:binary()"
1504 hg commit --exclude "set:binary()"
1502
1505
1503 - amend the current commit and set the date to now::
1506 - amend the current commit and set the date to now::
1504
1507
1505 hg commit --amend --date now
1508 hg commit --amend --date now
1506 """
1509 """
1507 wlock = lock = None
1510 wlock = lock = None
1508 try:
1511 try:
1509 wlock = repo.wlock()
1512 wlock = repo.wlock()
1510 lock = repo.lock()
1513 lock = repo.lock()
1511 return _docommit(ui, repo, *pats, **opts)
1514 return _docommit(ui, repo, *pats, **opts)
1512 finally:
1515 finally:
1513 release(lock, wlock)
1516 release(lock, wlock)
1514
1517
1515 def _docommit(ui, repo, *pats, **opts):
1518 def _docommit(ui, repo, *pats, **opts):
1516 if opts.get(r'interactive'):
1519 if opts.get(r'interactive'):
1517 opts.pop(r'interactive')
1520 opts.pop(r'interactive')
1518 ret = cmdutil.dorecord(ui, repo, commit, None, False,
1521 ret = cmdutil.dorecord(ui, repo, commit, None, False,
1519 cmdutil.recordfilter, *pats,
1522 cmdutil.recordfilter, *pats,
1520 **opts)
1523 **opts)
1521 # ret can be 0 (no changes to record) or the value returned by
1524 # ret can be 0 (no changes to record) or the value returned by
1522 # commit(), 1 if nothing changed or None on success.
1525 # commit(), 1 if nothing changed or None on success.
1523 return 1 if ret == 0 else ret
1526 return 1 if ret == 0 else ret
1524
1527
1525 opts = pycompat.byteskwargs(opts)
1528 opts = pycompat.byteskwargs(opts)
1526 if opts.get('subrepos'):
1529 if opts.get('subrepos'):
1527 if opts.get('amend'):
1530 if opts.get('amend'):
1528 raise error.Abort(_('cannot amend with --subrepos'))
1531 raise error.Abort(_('cannot amend with --subrepos'))
1529 # Let --subrepos on the command line override config setting.
1532 # Let --subrepos on the command line override config setting.
1530 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1533 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1531
1534
1532 cmdutil.checkunfinished(repo, commit=True)
1535 cmdutil.checkunfinished(repo, commit=True)
1533
1536
1534 branch = repo[None].branch()
1537 branch = repo[None].branch()
1535 bheads = repo.branchheads(branch)
1538 bheads = repo.branchheads(branch)
1536
1539
1537 extra = {}
1540 extra = {}
1538 if opts.get('close_branch'):
1541 if opts.get('close_branch'):
1539 extra['close'] = 1
1542 extra['close'] = 1
1540
1543
1541 if not bheads:
1544 if not bheads:
1542 raise error.Abort(_('can only close branch heads'))
1545 raise error.Abort(_('can only close branch heads'))
1543 elif opts.get('amend'):
1546 elif opts.get('amend'):
1544 if repo[None].parents()[0].p1().branch() != branch and \
1547 if repo[None].parents()[0].p1().branch() != branch and \
1545 repo[None].parents()[0].p2().branch() != branch:
1548 repo[None].parents()[0].p2().branch() != branch:
1546 raise error.Abort(_('can only close branch heads'))
1549 raise error.Abort(_('can only close branch heads'))
1547
1550
1548 if opts.get('amend'):
1551 if opts.get('amend'):
1549 if ui.configbool('ui', 'commitsubrepos'):
1552 if ui.configbool('ui', 'commitsubrepos'):
1550 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1553 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1551
1554
1552 old = repo['.']
1555 old = repo['.']
1553 rewriteutil.precheck(repo, [old.rev()], 'amend')
1556 rewriteutil.precheck(repo, [old.rev()], 'amend')
1554
1557
1555 # Currently histedit gets confused if an amend happens while histedit
1558 # Currently histedit gets confused if an amend happens while histedit
1556 # is in progress. Since we have a checkunfinished command, we are
1559 # is in progress. Since we have a checkunfinished command, we are
1557 # temporarily honoring it.
1560 # temporarily honoring it.
1558 #
1561 #
1559 # Note: eventually this guard will be removed. Please do not expect
1562 # Note: eventually this guard will be removed. Please do not expect
1560 # this behavior to remain.
1563 # this behavior to remain.
1561 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
1564 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
1562 cmdutil.checkunfinished(repo)
1565 cmdutil.checkunfinished(repo)
1563
1566
1564 node = cmdutil.amend(ui, repo, old, extra, pats, opts)
1567 node = cmdutil.amend(ui, repo, old, extra, pats, opts)
1565 if node == old.node():
1568 if node == old.node():
1566 ui.status(_("nothing changed\n"))
1569 ui.status(_("nothing changed\n"))
1567 return 1
1570 return 1
1568 else:
1571 else:
1569 def commitfunc(ui, repo, message, match, opts):
1572 def commitfunc(ui, repo, message, match, opts):
1570 overrides = {}
1573 overrides = {}
1571 if opts.get('secret'):
1574 if opts.get('secret'):
1572 overrides[('phases', 'new-commit')] = 'secret'
1575 overrides[('phases', 'new-commit')] = 'secret'
1573
1576
1574 baseui = repo.baseui
1577 baseui = repo.baseui
1575 with baseui.configoverride(overrides, 'commit'):
1578 with baseui.configoverride(overrides, 'commit'):
1576 with ui.configoverride(overrides, 'commit'):
1579 with ui.configoverride(overrides, 'commit'):
1577 editform = cmdutil.mergeeditform(repo[None],
1580 editform = cmdutil.mergeeditform(repo[None],
1578 'commit.normal')
1581 'commit.normal')
1579 editor = cmdutil.getcommiteditor(
1582 editor = cmdutil.getcommiteditor(
1580 editform=editform, **pycompat.strkwargs(opts))
1583 editform=editform, **pycompat.strkwargs(opts))
1581 return repo.commit(message,
1584 return repo.commit(message,
1582 opts.get('user'),
1585 opts.get('user'),
1583 opts.get('date'),
1586 opts.get('date'),
1584 match,
1587 match,
1585 editor=editor,
1588 editor=editor,
1586 extra=extra)
1589 extra=extra)
1587
1590
1588 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1591 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1589
1592
1590 if not node:
1593 if not node:
1591 stat = cmdutil.postcommitstatus(repo, pats, opts)
1594 stat = cmdutil.postcommitstatus(repo, pats, opts)
1592 if stat[3]:
1595 if stat[3]:
1593 ui.status(_("nothing changed (%d missing files, see "
1596 ui.status(_("nothing changed (%d missing files, see "
1594 "'hg status')\n") % len(stat[3]))
1597 "'hg status')\n") % len(stat[3]))
1595 else:
1598 else:
1596 ui.status(_("nothing changed\n"))
1599 ui.status(_("nothing changed\n"))
1597 return 1
1600 return 1
1598
1601
1599 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1602 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1600
1603
1601 @command('config|showconfig|debugconfig',
1604 @command('config|showconfig|debugconfig',
1602 [('u', 'untrusted', None, _('show untrusted configuration options')),
1605 [('u', 'untrusted', None, _('show untrusted configuration options')),
1603 ('e', 'edit', None, _('edit user config')),
1606 ('e', 'edit', None, _('edit user config')),
1604 ('l', 'local', None, _('edit repository config')),
1607 ('l', 'local', None, _('edit repository config')),
1605 ('g', 'global', None, _('edit global config'))] + formatteropts,
1608 ('g', 'global', None, _('edit global config'))] + formatteropts,
1606 _('[-u] [NAME]...'),
1609 _('[-u] [NAME]...'),
1607 optionalrepo=True, cmdtype=readonly)
1610 optionalrepo=True, cmdtype=readonly)
1608 def config(ui, repo, *values, **opts):
1611 def config(ui, repo, *values, **opts):
1609 """show combined config settings from all hgrc files
1612 """show combined config settings from all hgrc files
1610
1613
1611 With no arguments, print names and values of all config items.
1614 With no arguments, print names and values of all config items.
1612
1615
1613 With one argument of the form section.name, print just the value
1616 With one argument of the form section.name, print just the value
1614 of that config item.
1617 of that config item.
1615
1618
1616 With multiple arguments, print names and values of all config
1619 With multiple arguments, print names and values of all config
1617 items with matching section names.
1620 items with matching section names.
1618
1621
1619 With --edit, start an editor on the user-level config file. With
1622 With --edit, start an editor on the user-level config file. With
1620 --global, edit the system-wide config file. With --local, edit the
1623 --global, edit the system-wide config file. With --local, edit the
1621 repository-level config file.
1624 repository-level config file.
1622
1625
1623 With --debug, the source (filename and line number) is printed
1626 With --debug, the source (filename and line number) is printed
1624 for each config item.
1627 for each config item.
1625
1628
1626 See :hg:`help config` for more information about config files.
1629 See :hg:`help config` for more information about config files.
1627
1630
1628 Returns 0 on success, 1 if NAME does not exist.
1631 Returns 0 on success, 1 if NAME does not exist.
1629
1632
1630 """
1633 """
1631
1634
1632 opts = pycompat.byteskwargs(opts)
1635 opts = pycompat.byteskwargs(opts)
1633 if opts.get('edit') or opts.get('local') or opts.get('global'):
1636 if opts.get('edit') or opts.get('local') or opts.get('global'):
1634 if opts.get('local') and opts.get('global'):
1637 if opts.get('local') and opts.get('global'):
1635 raise error.Abort(_("can't use --local and --global together"))
1638 raise error.Abort(_("can't use --local and --global together"))
1636
1639
1637 if opts.get('local'):
1640 if opts.get('local'):
1638 if not repo:
1641 if not repo:
1639 raise error.Abort(_("can't use --local outside a repository"))
1642 raise error.Abort(_("can't use --local outside a repository"))
1640 paths = [repo.vfs.join('hgrc')]
1643 paths = [repo.vfs.join('hgrc')]
1641 elif opts.get('global'):
1644 elif opts.get('global'):
1642 paths = rcutil.systemrcpath()
1645 paths = rcutil.systemrcpath()
1643 else:
1646 else:
1644 paths = rcutil.userrcpath()
1647 paths = rcutil.userrcpath()
1645
1648
1646 for f in paths:
1649 for f in paths:
1647 if os.path.exists(f):
1650 if os.path.exists(f):
1648 break
1651 break
1649 else:
1652 else:
1650 if opts.get('global'):
1653 if opts.get('global'):
1651 samplehgrc = uimod.samplehgrcs['global']
1654 samplehgrc = uimod.samplehgrcs['global']
1652 elif opts.get('local'):
1655 elif opts.get('local'):
1653 samplehgrc = uimod.samplehgrcs['local']
1656 samplehgrc = uimod.samplehgrcs['local']
1654 else:
1657 else:
1655 samplehgrc = uimod.samplehgrcs['user']
1658 samplehgrc = uimod.samplehgrcs['user']
1656
1659
1657 f = paths[0]
1660 f = paths[0]
1658 fp = open(f, "wb")
1661 fp = open(f, "wb")
1659 fp.write(util.tonativeeol(samplehgrc))
1662 fp.write(util.tonativeeol(samplehgrc))
1660 fp.close()
1663 fp.close()
1661
1664
1662 editor = ui.geteditor()
1665 editor = ui.geteditor()
1663 ui.system("%s \"%s\"" % (editor, f),
1666 ui.system("%s \"%s\"" % (editor, f),
1664 onerr=error.Abort, errprefix=_("edit failed"),
1667 onerr=error.Abort, errprefix=_("edit failed"),
1665 blockedtag='config_edit')
1668 blockedtag='config_edit')
1666 return
1669 return
1667 ui.pager('config')
1670 ui.pager('config')
1668 fm = ui.formatter('config', opts)
1671 fm = ui.formatter('config', opts)
1669 for t, f in rcutil.rccomponents():
1672 for t, f in rcutil.rccomponents():
1670 if t == 'path':
1673 if t == 'path':
1671 ui.debug('read config from: %s\n' % f)
1674 ui.debug('read config from: %s\n' % f)
1672 elif t == 'items':
1675 elif t == 'items':
1673 for section, name, value, source in f:
1676 for section, name, value, source in f:
1674 ui.debug('set config by: %s\n' % source)
1677 ui.debug('set config by: %s\n' % source)
1675 else:
1678 else:
1676 raise error.ProgrammingError('unknown rctype: %s' % t)
1679 raise error.ProgrammingError('unknown rctype: %s' % t)
1677 untrusted = bool(opts.get('untrusted'))
1680 untrusted = bool(opts.get('untrusted'))
1678 if values:
1681 if values:
1679 sections = [v for v in values if '.' not in v]
1682 sections = [v for v in values if '.' not in v]
1680 items = [v for v in values if '.' in v]
1683 items = [v for v in values if '.' in v]
1681 if len(items) > 1 or items and sections:
1684 if len(items) > 1 or items and sections:
1682 raise error.Abort(_('only one config item permitted'))
1685 raise error.Abort(_('only one config item permitted'))
1683 matched = False
1686 matched = False
1684 for section, name, value in ui.walkconfig(untrusted=untrusted):
1687 for section, name, value in ui.walkconfig(untrusted=untrusted):
1685 source = ui.configsource(section, name, untrusted)
1688 source = ui.configsource(section, name, untrusted)
1686 value = pycompat.bytestr(value)
1689 value = pycompat.bytestr(value)
1687 if fm.isplain():
1690 if fm.isplain():
1688 source = source or 'none'
1691 source = source or 'none'
1689 value = value.replace('\n', '\\n')
1692 value = value.replace('\n', '\\n')
1690 entryname = section + '.' + name
1693 entryname = section + '.' + name
1691 if values:
1694 if values:
1692 for v in values:
1695 for v in values:
1693 if v == section:
1696 if v == section:
1694 fm.startitem()
1697 fm.startitem()
1695 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1698 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1696 fm.write('name value', '%s=%s\n', entryname, value)
1699 fm.write('name value', '%s=%s\n', entryname, value)
1697 matched = True
1700 matched = True
1698 elif v == entryname:
1701 elif v == entryname:
1699 fm.startitem()
1702 fm.startitem()
1700 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1703 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1701 fm.write('value', '%s\n', value)
1704 fm.write('value', '%s\n', value)
1702 fm.data(name=entryname)
1705 fm.data(name=entryname)
1703 matched = True
1706 matched = True
1704 else:
1707 else:
1705 fm.startitem()
1708 fm.startitem()
1706 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1709 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1707 fm.write('name value', '%s=%s\n', entryname, value)
1710 fm.write('name value', '%s=%s\n', entryname, value)
1708 matched = True
1711 matched = True
1709 fm.end()
1712 fm.end()
1710 if matched:
1713 if matched:
1711 return 0
1714 return 0
1712 return 1
1715 return 1
1713
1716
1714 @command('copy|cp',
1717 @command('copy|cp',
1715 [('A', 'after', None, _('record a copy that has already occurred')),
1718 [('A', 'after', None, _('record a copy that has already occurred')),
1716 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1719 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1717 ] + walkopts + dryrunopts,
1720 ] + walkopts + dryrunopts,
1718 _('[OPTION]... [SOURCE]... DEST'))
1721 _('[OPTION]... [SOURCE]... DEST'))
1719 def copy(ui, repo, *pats, **opts):
1722 def copy(ui, repo, *pats, **opts):
1720 """mark files as copied for the next commit
1723 """mark files as copied for the next commit
1721
1724
1722 Mark dest as having copies of source files. If dest is a
1725 Mark dest as having copies of source files. If dest is a
1723 directory, copies are put in that directory. If dest is a file,
1726 directory, copies are put in that directory. If dest is a file,
1724 the source must be a single file.
1727 the source must be a single file.
1725
1728
1726 By default, this command copies the contents of files as they
1729 By default, this command copies the contents of files as they
1727 exist in the working directory. If invoked with -A/--after, the
1730 exist in the working directory. If invoked with -A/--after, the
1728 operation is recorded, but no copying is performed.
1731 operation is recorded, but no copying is performed.
1729
1732
1730 This command takes effect with the next commit. To undo a copy
1733 This command takes effect with the next commit. To undo a copy
1731 before that, see :hg:`revert`.
1734 before that, see :hg:`revert`.
1732
1735
1733 Returns 0 on success, 1 if errors are encountered.
1736 Returns 0 on success, 1 if errors are encountered.
1734 """
1737 """
1735 opts = pycompat.byteskwargs(opts)
1738 opts = pycompat.byteskwargs(opts)
1736 with repo.wlock(False):
1739 with repo.wlock(False):
1737 return cmdutil.copy(ui, repo, pats, opts)
1740 return cmdutil.copy(ui, repo, pats, opts)
1738
1741
1739 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1742 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1740 def debugcommands(ui, cmd='', *args):
1743 def debugcommands(ui, cmd='', *args):
1741 """list all available commands and options"""
1744 """list all available commands and options"""
1742 for cmd, vals in sorted(table.iteritems()):
1745 for cmd, vals in sorted(table.iteritems()):
1743 cmd = cmd.split('|')[0].strip('^')
1746 cmd = cmd.split('|')[0].strip('^')
1744 opts = ', '.join([i[1] for i in vals[1]])
1747 opts = ', '.join([i[1] for i in vals[1]])
1745 ui.write('%s: %s\n' % (cmd, opts))
1748 ui.write('%s: %s\n' % (cmd, opts))
1746
1749
1747 @command('debugcomplete',
1750 @command('debugcomplete',
1748 [('o', 'options', None, _('show the command options'))],
1751 [('o', 'options', None, _('show the command options'))],
1749 _('[-o] CMD'),
1752 _('[-o] CMD'),
1750 norepo=True)
1753 norepo=True)
1751 def debugcomplete(ui, cmd='', **opts):
1754 def debugcomplete(ui, cmd='', **opts):
1752 """returns the completion list associated with the given command"""
1755 """returns the completion list associated with the given command"""
1753
1756
1754 if opts.get(r'options'):
1757 if opts.get(r'options'):
1755 options = []
1758 options = []
1756 otables = [globalopts]
1759 otables = [globalopts]
1757 if cmd:
1760 if cmd:
1758 aliases, entry = cmdutil.findcmd(cmd, table, False)
1761 aliases, entry = cmdutil.findcmd(cmd, table, False)
1759 otables.append(entry[1])
1762 otables.append(entry[1])
1760 for t in otables:
1763 for t in otables:
1761 for o in t:
1764 for o in t:
1762 if "(DEPRECATED)" in o[3]:
1765 if "(DEPRECATED)" in o[3]:
1763 continue
1766 continue
1764 if o[0]:
1767 if o[0]:
1765 options.append('-%s' % o[0])
1768 options.append('-%s' % o[0])
1766 options.append('--%s' % o[1])
1769 options.append('--%s' % o[1])
1767 ui.write("%s\n" % "\n".join(options))
1770 ui.write("%s\n" % "\n".join(options))
1768 return
1771 return
1769
1772
1770 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
1773 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
1771 if ui.verbose:
1774 if ui.verbose:
1772 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1775 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1773 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1776 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1774
1777
1775 @command('^diff',
1778 @command('^diff',
1776 [('r', 'rev', [], _('revision'), _('REV')),
1779 [('r', 'rev', [], _('revision'), _('REV')),
1777 ('c', 'change', '', _('change made by revision'), _('REV'))
1780 ('c', 'change', '', _('change made by revision'), _('REV'))
1778 ] + diffopts + diffopts2 + walkopts + subrepoopts,
1781 ] + diffopts + diffopts2 + walkopts + subrepoopts,
1779 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
1782 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
1780 inferrepo=True, cmdtype=readonly)
1783 inferrepo=True, cmdtype=readonly)
1781 def diff(ui, repo, *pats, **opts):
1784 def diff(ui, repo, *pats, **opts):
1782 """diff repository (or selected files)
1785 """diff repository (or selected files)
1783
1786
1784 Show differences between revisions for the specified files.
1787 Show differences between revisions for the specified files.
1785
1788
1786 Differences between files are shown using the unified diff format.
1789 Differences between files are shown using the unified diff format.
1787
1790
1788 .. note::
1791 .. note::
1789
1792
1790 :hg:`diff` may generate unexpected results for merges, as it will
1793 :hg:`diff` may generate unexpected results for merges, as it will
1791 default to comparing against the working directory's first
1794 default to comparing against the working directory's first
1792 parent changeset if no revisions are specified.
1795 parent changeset if no revisions are specified.
1793
1796
1794 When two revision arguments are given, then changes are shown
1797 When two revision arguments are given, then changes are shown
1795 between those revisions. If only one revision is specified then
1798 between those revisions. If only one revision is specified then
1796 that revision is compared to the working directory, and, when no
1799 that revision is compared to the working directory, and, when no
1797 revisions are specified, the working directory files are compared
1800 revisions are specified, the working directory files are compared
1798 to its first parent.
1801 to its first parent.
1799
1802
1800 Alternatively you can specify -c/--change with a revision to see
1803 Alternatively you can specify -c/--change with a revision to see
1801 the changes in that changeset relative to its first parent.
1804 the changes in that changeset relative to its first parent.
1802
1805
1803 Without the -a/--text option, diff will avoid generating diffs of
1806 Without the -a/--text option, diff will avoid generating diffs of
1804 files it detects as binary. With -a, diff will generate a diff
1807 files it detects as binary. With -a, diff will generate a diff
1805 anyway, probably with undesirable results.
1808 anyway, probably with undesirable results.
1806
1809
1807 Use the -g/--git option to generate diffs in the git extended diff
1810 Use the -g/--git option to generate diffs in the git extended diff
1808 format. For more information, read :hg:`help diffs`.
1811 format. For more information, read :hg:`help diffs`.
1809
1812
1810 .. container:: verbose
1813 .. container:: verbose
1811
1814
1812 Examples:
1815 Examples:
1813
1816
1814 - compare a file in the current working directory to its parent::
1817 - compare a file in the current working directory to its parent::
1815
1818
1816 hg diff foo.c
1819 hg diff foo.c
1817
1820
1818 - compare two historical versions of a directory, with rename info::
1821 - compare two historical versions of a directory, with rename info::
1819
1822
1820 hg diff --git -r 1.0:1.2 lib/
1823 hg diff --git -r 1.0:1.2 lib/
1821
1824
1822 - get change stats relative to the last change on some date::
1825 - get change stats relative to the last change on some date::
1823
1826
1824 hg diff --stat -r "date('may 2')"
1827 hg diff --stat -r "date('may 2')"
1825
1828
1826 - diff all newly-added files that contain a keyword::
1829 - diff all newly-added files that contain a keyword::
1827
1830
1828 hg diff "set:added() and grep(GNU)"
1831 hg diff "set:added() and grep(GNU)"
1829
1832
1830 - compare a revision and its parents::
1833 - compare a revision and its parents::
1831
1834
1832 hg diff -c 9353 # compare against first parent
1835 hg diff -c 9353 # compare against first parent
1833 hg diff -r 9353^:9353 # same using revset syntax
1836 hg diff -r 9353^:9353 # same using revset syntax
1834 hg diff -r 9353^2:9353 # compare against the second parent
1837 hg diff -r 9353^2:9353 # compare against the second parent
1835
1838
1836 Returns 0 on success.
1839 Returns 0 on success.
1837 """
1840 """
1838
1841
1839 opts = pycompat.byteskwargs(opts)
1842 opts = pycompat.byteskwargs(opts)
1840 revs = opts.get('rev')
1843 revs = opts.get('rev')
1841 change = opts.get('change')
1844 change = opts.get('change')
1842 stat = opts.get('stat')
1845 stat = opts.get('stat')
1843 reverse = opts.get('reverse')
1846 reverse = opts.get('reverse')
1844
1847
1845 if revs and change:
1848 if revs and change:
1846 msg = _('cannot specify --rev and --change at the same time')
1849 msg = _('cannot specify --rev and --change at the same time')
1847 raise error.Abort(msg)
1850 raise error.Abort(msg)
1848 elif change:
1851 elif change:
1849 repo = scmutil.unhidehashlikerevs(repo, [change], 'nowarn')
1852 repo = scmutil.unhidehashlikerevs(repo, [change], 'nowarn')
1850 node2 = scmutil.revsingle(repo, change, None).node()
1853 node2 = scmutil.revsingle(repo, change, None).node()
1851 node1 = repo[node2].p1().node()
1854 node1 = repo[node2].p1().node()
1852 else:
1855 else:
1853 repo = scmutil.unhidehashlikerevs(repo, revs, 'nowarn')
1856 repo = scmutil.unhidehashlikerevs(repo, revs, 'nowarn')
1854 node1, node2 = scmutil.revpair(repo, revs)
1857 node1, node2 = scmutil.revpair(repo, revs)
1855
1858
1856 if reverse:
1859 if reverse:
1857 node1, node2 = node2, node1
1860 node1, node2 = node2, node1
1858
1861
1859 diffopts = patch.diffallopts(ui, opts)
1862 diffopts = patch.diffallopts(ui, opts)
1860 m = scmutil.match(repo[node2], pats, opts)
1863 m = scmutil.match(repo[node2], pats, opts)
1861 ui.pager('diff')
1864 ui.pager('diff')
1862 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
1865 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
1863 listsubrepos=opts.get('subrepos'),
1866 listsubrepos=opts.get('subrepos'),
1864 root=opts.get('root'))
1867 root=opts.get('root'))
1865
1868
1866 @command('^export',
1869 @command('^export',
1867 [('o', 'output', '',
1870 [('o', 'output', '',
1868 _('print output to file with formatted name'), _('FORMAT')),
1871 _('print output to file with formatted name'), _('FORMAT')),
1869 ('', 'switch-parent', None, _('diff against the second parent')),
1872 ('', 'switch-parent', None, _('diff against the second parent')),
1870 ('r', 'rev', [], _('revisions to export'), _('REV')),
1873 ('r', 'rev', [], _('revisions to export'), _('REV')),
1871 ] + diffopts,
1874 ] + diffopts,
1872 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'), cmdtype=readonly)
1875 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'), cmdtype=readonly)
1873 def export(ui, repo, *changesets, **opts):
1876 def export(ui, repo, *changesets, **opts):
1874 """dump the header and diffs for one or more changesets
1877 """dump the header and diffs for one or more changesets
1875
1878
1876 Print the changeset header and diffs for one or more revisions.
1879 Print the changeset header and diffs for one or more revisions.
1877 If no revision is given, the parent of the working directory is used.
1880 If no revision is given, the parent of the working directory is used.
1878
1881
1879 The information shown in the changeset header is: author, date,
1882 The information shown in the changeset header is: author, date,
1880 branch name (if non-default), changeset hash, parent(s) and commit
1883 branch name (if non-default), changeset hash, parent(s) and commit
1881 comment.
1884 comment.
1882
1885
1883 .. note::
1886 .. note::
1884
1887
1885 :hg:`export` may generate unexpected diff output for merge
1888 :hg:`export` may generate unexpected diff output for merge
1886 changesets, as it will compare the merge changeset against its
1889 changesets, as it will compare the merge changeset against its
1887 first parent only.
1890 first parent only.
1888
1891
1889 Output may be to a file, in which case the name of the file is
1892 Output may be to a file, in which case the name of the file is
1890 given using a format string. The formatting rules are as follows:
1893 given using a format string. The formatting rules are as follows:
1891
1894
1892 :``%%``: literal "%" character
1895 :``%%``: literal "%" character
1893 :``%H``: changeset hash (40 hexadecimal digits)
1896 :``%H``: changeset hash (40 hexadecimal digits)
1894 :``%N``: number of patches being generated
1897 :``%N``: number of patches being generated
1895 :``%R``: changeset revision number
1898 :``%R``: changeset revision number
1896 :``%b``: basename of the exporting repository
1899 :``%b``: basename of the exporting repository
1897 :``%h``: short-form changeset hash (12 hexadecimal digits)
1900 :``%h``: short-form changeset hash (12 hexadecimal digits)
1898 :``%m``: first line of the commit message (only alphanumeric characters)
1901 :``%m``: first line of the commit message (only alphanumeric characters)
1899 :``%n``: zero-padded sequence number, starting at 1
1902 :``%n``: zero-padded sequence number, starting at 1
1900 :``%r``: zero-padded changeset revision number
1903 :``%r``: zero-padded changeset revision number
1901
1904
1902 Without the -a/--text option, export will avoid generating diffs
1905 Without the -a/--text option, export will avoid generating diffs
1903 of files it detects as binary. With -a, export will generate a
1906 of files it detects as binary. With -a, export will generate a
1904 diff anyway, probably with undesirable results.
1907 diff anyway, probably with undesirable results.
1905
1908
1906 Use the -g/--git option to generate diffs in the git extended diff
1909 Use the -g/--git option to generate diffs in the git extended diff
1907 format. See :hg:`help diffs` for more information.
1910 format. See :hg:`help diffs` for more information.
1908
1911
1909 With the --switch-parent option, the diff will be against the
1912 With the --switch-parent option, the diff will be against the
1910 second parent. It can be useful to review a merge.
1913 second parent. It can be useful to review a merge.
1911
1914
1912 .. container:: verbose
1915 .. container:: verbose
1913
1916
1914 Examples:
1917 Examples:
1915
1918
1916 - use export and import to transplant a bugfix to the current
1919 - use export and import to transplant a bugfix to the current
1917 branch::
1920 branch::
1918
1921
1919 hg export -r 9353 | hg import -
1922 hg export -r 9353 | hg import -
1920
1923
1921 - export all the changesets between two revisions to a file with
1924 - export all the changesets between two revisions to a file with
1922 rename information::
1925 rename information::
1923
1926
1924 hg export --git -r 123:150 > changes.txt
1927 hg export --git -r 123:150 > changes.txt
1925
1928
1926 - split outgoing changes into a series of patches with
1929 - split outgoing changes into a series of patches with
1927 descriptive names::
1930 descriptive names::
1928
1931
1929 hg export -r "outgoing()" -o "%n-%m.patch"
1932 hg export -r "outgoing()" -o "%n-%m.patch"
1930
1933
1931 Returns 0 on success.
1934 Returns 0 on success.
1932 """
1935 """
1933 opts = pycompat.byteskwargs(opts)
1936 opts = pycompat.byteskwargs(opts)
1934 changesets += tuple(opts.get('rev', []))
1937 changesets += tuple(opts.get('rev', []))
1935 if not changesets:
1938 if not changesets:
1936 changesets = ['.']
1939 changesets = ['.']
1937 repo = scmutil.unhidehashlikerevs(repo, changesets, 'nowarn')
1940 repo = scmutil.unhidehashlikerevs(repo, changesets, 'nowarn')
1938 revs = scmutil.revrange(repo, changesets)
1941 revs = scmutil.revrange(repo, changesets)
1939 if not revs:
1942 if not revs:
1940 raise error.Abort(_("export requires at least one changeset"))
1943 raise error.Abort(_("export requires at least one changeset"))
1941 if len(revs) > 1:
1944 if len(revs) > 1:
1942 ui.note(_('exporting patches:\n'))
1945 ui.note(_('exporting patches:\n'))
1943 else:
1946 else:
1944 ui.note(_('exporting patch:\n'))
1947 ui.note(_('exporting patch:\n'))
1945 ui.pager('export')
1948 ui.pager('export')
1946 cmdutil.export(repo, revs, fntemplate=opts.get('output'),
1949 cmdutil.export(repo, revs, fntemplate=opts.get('output'),
1947 switch_parent=opts.get('switch_parent'),
1950 switch_parent=opts.get('switch_parent'),
1948 opts=patch.diffallopts(ui, opts))
1951 opts=patch.diffallopts(ui, opts))
1949
1952
1950 @command('files',
1953 @command('files',
1951 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
1954 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
1952 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
1955 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
1953 ] + walkopts + formatteropts + subrepoopts,
1956 ] + walkopts + formatteropts + subrepoopts,
1954 _('[OPTION]... [FILE]...'), cmdtype=readonly)
1957 _('[OPTION]... [FILE]...'), cmdtype=readonly)
1955 def files(ui, repo, *pats, **opts):
1958 def files(ui, repo, *pats, **opts):
1956 """list tracked files
1959 """list tracked files
1957
1960
1958 Print files under Mercurial control in the working directory or
1961 Print files under Mercurial control in the working directory or
1959 specified revision for given files (excluding removed files).
1962 specified revision for given files (excluding removed files).
1960 Files can be specified as filenames or filesets.
1963 Files can be specified as filenames or filesets.
1961
1964
1962 If no files are given to match, this command prints the names
1965 If no files are given to match, this command prints the names
1963 of all files under Mercurial control.
1966 of all files under Mercurial control.
1964
1967
1965 .. container:: verbose
1968 .. container:: verbose
1966
1969
1967 Examples:
1970 Examples:
1968
1971
1969 - list all files under the current directory::
1972 - list all files under the current directory::
1970
1973
1971 hg files .
1974 hg files .
1972
1975
1973 - shows sizes and flags for current revision::
1976 - shows sizes and flags for current revision::
1974
1977
1975 hg files -vr .
1978 hg files -vr .
1976
1979
1977 - list all files named README::
1980 - list all files named README::
1978
1981
1979 hg files -I "**/README"
1982 hg files -I "**/README"
1980
1983
1981 - list all binary files::
1984 - list all binary files::
1982
1985
1983 hg files "set:binary()"
1986 hg files "set:binary()"
1984
1987
1985 - find files containing a regular expression::
1988 - find files containing a regular expression::
1986
1989
1987 hg files "set:grep('bob')"
1990 hg files "set:grep('bob')"
1988
1991
1989 - search tracked file contents with xargs and grep::
1992 - search tracked file contents with xargs and grep::
1990
1993
1991 hg files -0 | xargs -0 grep foo
1994 hg files -0 | xargs -0 grep foo
1992
1995
1993 See :hg:`help patterns` and :hg:`help filesets` for more information
1996 See :hg:`help patterns` and :hg:`help filesets` for more information
1994 on specifying file patterns.
1997 on specifying file patterns.
1995
1998
1996 Returns 0 if a match is found, 1 otherwise.
1999 Returns 0 if a match is found, 1 otherwise.
1997
2000
1998 """
2001 """
1999
2002
2000 opts = pycompat.byteskwargs(opts)
2003 opts = pycompat.byteskwargs(opts)
2001 rev = opts.get('rev')
2004 rev = opts.get('rev')
2002 if rev:
2005 if rev:
2003 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
2006 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
2004 ctx = scmutil.revsingle(repo, rev, None)
2007 ctx = scmutil.revsingle(repo, rev, None)
2005
2008
2006 end = '\n'
2009 end = '\n'
2007 if opts.get('print0'):
2010 if opts.get('print0'):
2008 end = '\0'
2011 end = '\0'
2009 fmt = '%s' + end
2012 fmt = '%s' + end
2010
2013
2011 m = scmutil.match(ctx, pats, opts)
2014 m = scmutil.match(ctx, pats, opts)
2012 ui.pager('files')
2015 ui.pager('files')
2013 with ui.formatter('files', opts) as fm:
2016 with ui.formatter('files', opts) as fm:
2014 return cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
2017 return cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
2015
2018
2016 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
2019 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
2017 def forget(ui, repo, *pats, **opts):
2020 def forget(ui, repo, *pats, **opts):
2018 """forget the specified files on the next commit
2021 """forget the specified files on the next commit
2019
2022
2020 Mark the specified files so they will no longer be tracked
2023 Mark the specified files so they will no longer be tracked
2021 after the next commit.
2024 after the next commit.
2022
2025
2023 This only removes files from the current branch, not from the
2026 This only removes files from the current branch, not from the
2024 entire project history, and it does not delete them from the
2027 entire project history, and it does not delete them from the
2025 working directory.
2028 working directory.
2026
2029
2027 To delete the file from the working directory, see :hg:`remove`.
2030 To delete the file from the working directory, see :hg:`remove`.
2028
2031
2029 To undo a forget before the next commit, see :hg:`add`.
2032 To undo a forget before the next commit, see :hg:`add`.
2030
2033
2031 .. container:: verbose
2034 .. container:: verbose
2032
2035
2033 Examples:
2036 Examples:
2034
2037
2035 - forget newly-added binary files::
2038 - forget newly-added binary files::
2036
2039
2037 hg forget "set:added() and binary()"
2040 hg forget "set:added() and binary()"
2038
2041
2039 - forget files that would be excluded by .hgignore::
2042 - forget files that would be excluded by .hgignore::
2040
2043
2041 hg forget "set:hgignore()"
2044 hg forget "set:hgignore()"
2042
2045
2043 Returns 0 on success.
2046 Returns 0 on success.
2044 """
2047 """
2045
2048
2046 opts = pycompat.byteskwargs(opts)
2049 opts = pycompat.byteskwargs(opts)
2047 if not pats:
2050 if not pats:
2048 raise error.Abort(_('no files specified'))
2051 raise error.Abort(_('no files specified'))
2049
2052
2050 m = scmutil.match(repo[None], pats, opts)
2053 m = scmutil.match(repo[None], pats, opts)
2051 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2054 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2052 return rejected and 1 or 0
2055 return rejected and 1 or 0
2053
2056
2054 @command(
2057 @command(
2055 'graft',
2058 'graft',
2056 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2059 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2057 ('c', 'continue', False, _('resume interrupted graft')),
2060 ('c', 'continue', False, _('resume interrupted graft')),
2058 ('e', 'edit', False, _('invoke editor on commit messages')),
2061 ('e', 'edit', False, _('invoke editor on commit messages')),
2059 ('', 'log', None, _('append graft info to log message')),
2062 ('', 'log', None, _('append graft info to log message')),
2060 ('f', 'force', False, _('force graft')),
2063 ('f', 'force', False, _('force graft')),
2061 ('D', 'currentdate', False,
2064 ('D', 'currentdate', False,
2062 _('record the current date as commit date')),
2065 _('record the current date as commit date')),
2063 ('U', 'currentuser', False,
2066 ('U', 'currentuser', False,
2064 _('record the current user as committer'), _('DATE'))]
2067 _('record the current user as committer'), _('DATE'))]
2065 + commitopts2 + mergetoolopts + dryrunopts,
2068 + commitopts2 + mergetoolopts + dryrunopts,
2066 _('[OPTION]... [-r REV]... REV...'))
2069 _('[OPTION]... [-r REV]... REV...'))
2067 def graft(ui, repo, *revs, **opts):
2070 def graft(ui, repo, *revs, **opts):
2068 '''copy changes from other branches onto the current branch
2071 '''copy changes from other branches onto the current branch
2069
2072
2070 This command uses Mercurial's merge logic to copy individual
2073 This command uses Mercurial's merge logic to copy individual
2071 changes from other branches without merging branches in the
2074 changes from other branches without merging branches in the
2072 history graph. This is sometimes known as 'backporting' or
2075 history graph. This is sometimes known as 'backporting' or
2073 'cherry-picking'. By default, graft will copy user, date, and
2076 'cherry-picking'. By default, graft will copy user, date, and
2074 description from the source changesets.
2077 description from the source changesets.
2075
2078
2076 Changesets that are ancestors of the current revision, that have
2079 Changesets that are ancestors of the current revision, that have
2077 already been grafted, or that are merges will be skipped.
2080 already been grafted, or that are merges will be skipped.
2078
2081
2079 If --log is specified, log messages will have a comment appended
2082 If --log is specified, log messages will have a comment appended
2080 of the form::
2083 of the form::
2081
2084
2082 (grafted from CHANGESETHASH)
2085 (grafted from CHANGESETHASH)
2083
2086
2084 If --force is specified, revisions will be grafted even if they
2087 If --force is specified, revisions will be grafted even if they
2085 are already ancestors of, or have been grafted to, the destination.
2088 are already ancestors of, or have been grafted to, the destination.
2086 This is useful when the revisions have since been backed out.
2089 This is useful when the revisions have since been backed out.
2087
2090
2088 If a graft merge results in conflicts, the graft process is
2091 If a graft merge results in conflicts, the graft process is
2089 interrupted so that the current merge can be manually resolved.
2092 interrupted so that the current merge can be manually resolved.
2090 Once all conflicts are addressed, the graft process can be
2093 Once all conflicts are addressed, the graft process can be
2091 continued with the -c/--continue option.
2094 continued with the -c/--continue option.
2092
2095
2093 .. note::
2096 .. note::
2094
2097
2095 The -c/--continue option does not reapply earlier options, except
2098 The -c/--continue option does not reapply earlier options, except
2096 for --force.
2099 for --force.
2097
2100
2098 .. container:: verbose
2101 .. container:: verbose
2099
2102
2100 Examples:
2103 Examples:
2101
2104
2102 - copy a single change to the stable branch and edit its description::
2105 - copy a single change to the stable branch and edit its description::
2103
2106
2104 hg update stable
2107 hg update stable
2105 hg graft --edit 9393
2108 hg graft --edit 9393
2106
2109
2107 - graft a range of changesets with one exception, updating dates::
2110 - graft a range of changesets with one exception, updating dates::
2108
2111
2109 hg graft -D "2085::2093 and not 2091"
2112 hg graft -D "2085::2093 and not 2091"
2110
2113
2111 - continue a graft after resolving conflicts::
2114 - continue a graft after resolving conflicts::
2112
2115
2113 hg graft -c
2116 hg graft -c
2114
2117
2115 - show the source of a grafted changeset::
2118 - show the source of a grafted changeset::
2116
2119
2117 hg log --debug -r .
2120 hg log --debug -r .
2118
2121
2119 - show revisions sorted by date::
2122 - show revisions sorted by date::
2120
2123
2121 hg log -r "sort(all(), date)"
2124 hg log -r "sort(all(), date)"
2122
2125
2123 See :hg:`help revisions` for more about specifying revisions.
2126 See :hg:`help revisions` for more about specifying revisions.
2124
2127
2125 Returns 0 on successful completion.
2128 Returns 0 on successful completion.
2126 '''
2129 '''
2127 with repo.wlock():
2130 with repo.wlock():
2128 return _dograft(ui, repo, *revs, **opts)
2131 return _dograft(ui, repo, *revs, **opts)
2129
2132
2130 def _dograft(ui, repo, *revs, **opts):
2133 def _dograft(ui, repo, *revs, **opts):
2131 opts = pycompat.byteskwargs(opts)
2134 opts = pycompat.byteskwargs(opts)
2132 if revs and opts.get('rev'):
2135 if revs and opts.get('rev'):
2133 ui.warn(_('warning: inconsistent use of --rev might give unexpected '
2136 ui.warn(_('warning: inconsistent use of --rev might give unexpected '
2134 'revision ordering!\n'))
2137 'revision ordering!\n'))
2135
2138
2136 revs = list(revs)
2139 revs = list(revs)
2137 revs.extend(opts.get('rev'))
2140 revs.extend(opts.get('rev'))
2138
2141
2139 if not opts.get('user') and opts.get('currentuser'):
2142 if not opts.get('user') and opts.get('currentuser'):
2140 opts['user'] = ui.username()
2143 opts['user'] = ui.username()
2141 if not opts.get('date') and opts.get('currentdate'):
2144 if not opts.get('date') and opts.get('currentdate'):
2142 opts['date'] = "%d %d" % util.makedate()
2145 opts['date'] = "%d %d" % util.makedate()
2143
2146
2144 editor = cmdutil.getcommiteditor(editform='graft',
2147 editor = cmdutil.getcommiteditor(editform='graft',
2145 **pycompat.strkwargs(opts))
2148 **pycompat.strkwargs(opts))
2146
2149
2147 cont = False
2150 cont = False
2148 if opts.get('continue'):
2151 if opts.get('continue'):
2149 cont = True
2152 cont = True
2150 if revs:
2153 if revs:
2151 raise error.Abort(_("can't specify --continue and revisions"))
2154 raise error.Abort(_("can't specify --continue and revisions"))
2152 # read in unfinished revisions
2155 # read in unfinished revisions
2153 try:
2156 try:
2154 nodes = repo.vfs.read('graftstate').splitlines()
2157 nodes = repo.vfs.read('graftstate').splitlines()
2155 revs = [repo[node].rev() for node in nodes]
2158 revs = [repo[node].rev() for node in nodes]
2156 except IOError as inst:
2159 except IOError as inst:
2157 if inst.errno != errno.ENOENT:
2160 if inst.errno != errno.ENOENT:
2158 raise
2161 raise
2159 cmdutil.wrongtooltocontinue(repo, _('graft'))
2162 cmdutil.wrongtooltocontinue(repo, _('graft'))
2160 else:
2163 else:
2161 cmdutil.checkunfinished(repo)
2164 cmdutil.checkunfinished(repo)
2162 cmdutil.bailifchanged(repo)
2165 cmdutil.bailifchanged(repo)
2163 if not revs:
2166 if not revs:
2164 raise error.Abort(_('no revisions specified'))
2167 raise error.Abort(_('no revisions specified'))
2165 revs = scmutil.revrange(repo, revs)
2168 revs = scmutil.revrange(repo, revs)
2166
2169
2167 skipped = set()
2170 skipped = set()
2168 # check for merges
2171 # check for merges
2169 for rev in repo.revs('%ld and merge()', revs):
2172 for rev in repo.revs('%ld and merge()', revs):
2170 ui.warn(_('skipping ungraftable merge revision %d\n') % rev)
2173 ui.warn(_('skipping ungraftable merge revision %d\n') % rev)
2171 skipped.add(rev)
2174 skipped.add(rev)
2172 revs = [r for r in revs if r not in skipped]
2175 revs = [r for r in revs if r not in skipped]
2173 if not revs:
2176 if not revs:
2174 return -1
2177 return -1
2175
2178
2176 # Don't check in the --continue case, in effect retaining --force across
2179 # Don't check in the --continue case, in effect retaining --force across
2177 # --continues. That's because without --force, any revisions we decided to
2180 # --continues. That's because without --force, any revisions we decided to
2178 # skip would have been filtered out here, so they wouldn't have made their
2181 # skip would have been filtered out here, so they wouldn't have made their
2179 # way to the graftstate. With --force, any revisions we would have otherwise
2182 # way to the graftstate. With --force, any revisions we would have otherwise
2180 # skipped would not have been filtered out, and if they hadn't been applied
2183 # skipped would not have been filtered out, and if they hadn't been applied
2181 # already, they'd have been in the graftstate.
2184 # already, they'd have been in the graftstate.
2182 if not (cont or opts.get('force')):
2185 if not (cont or opts.get('force')):
2183 # check for ancestors of dest branch
2186 # check for ancestors of dest branch
2184 crev = repo['.'].rev()
2187 crev = repo['.'].rev()
2185 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2188 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2186 # XXX make this lazy in the future
2189 # XXX make this lazy in the future
2187 # don't mutate while iterating, create a copy
2190 # don't mutate while iterating, create a copy
2188 for rev in list(revs):
2191 for rev in list(revs):
2189 if rev in ancestors:
2192 if rev in ancestors:
2190 ui.warn(_('skipping ancestor revision %d:%s\n') %
2193 ui.warn(_('skipping ancestor revision %d:%s\n') %
2191 (rev, repo[rev]))
2194 (rev, repo[rev]))
2192 # XXX remove on list is slow
2195 # XXX remove on list is slow
2193 revs.remove(rev)
2196 revs.remove(rev)
2194 if not revs:
2197 if not revs:
2195 return -1
2198 return -1
2196
2199
2197 # analyze revs for earlier grafts
2200 # analyze revs for earlier grafts
2198 ids = {}
2201 ids = {}
2199 for ctx in repo.set("%ld", revs):
2202 for ctx in repo.set("%ld", revs):
2200 ids[ctx.hex()] = ctx.rev()
2203 ids[ctx.hex()] = ctx.rev()
2201 n = ctx.extra().get('source')
2204 n = ctx.extra().get('source')
2202 if n:
2205 if n:
2203 ids[n] = ctx.rev()
2206 ids[n] = ctx.rev()
2204
2207
2205 # check ancestors for earlier grafts
2208 # check ancestors for earlier grafts
2206 ui.debug('scanning for duplicate grafts\n')
2209 ui.debug('scanning for duplicate grafts\n')
2207
2210
2208 # The only changesets we can be sure doesn't contain grafts of any
2211 # The only changesets we can be sure doesn't contain grafts of any
2209 # revs, are the ones that are common ancestors of *all* revs:
2212 # revs, are the ones that are common ancestors of *all* revs:
2210 for rev in repo.revs('only(%d,ancestor(%ld))', crev, revs):
2213 for rev in repo.revs('only(%d,ancestor(%ld))', crev, revs):
2211 ctx = repo[rev]
2214 ctx = repo[rev]
2212 n = ctx.extra().get('source')
2215 n = ctx.extra().get('source')
2213 if n in ids:
2216 if n in ids:
2214 try:
2217 try:
2215 r = repo[n].rev()
2218 r = repo[n].rev()
2216 except error.RepoLookupError:
2219 except error.RepoLookupError:
2217 r = None
2220 r = None
2218 if r in revs:
2221 if r in revs:
2219 ui.warn(_('skipping revision %d:%s '
2222 ui.warn(_('skipping revision %d:%s '
2220 '(already grafted to %d:%s)\n')
2223 '(already grafted to %d:%s)\n')
2221 % (r, repo[r], rev, ctx))
2224 % (r, repo[r], rev, ctx))
2222 revs.remove(r)
2225 revs.remove(r)
2223 elif ids[n] in revs:
2226 elif ids[n] in revs:
2224 if r is None:
2227 if r is None:
2225 ui.warn(_('skipping already grafted revision %d:%s '
2228 ui.warn(_('skipping already grafted revision %d:%s '
2226 '(%d:%s also has unknown origin %s)\n')
2229 '(%d:%s also has unknown origin %s)\n')
2227 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
2230 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
2228 else:
2231 else:
2229 ui.warn(_('skipping already grafted revision %d:%s '
2232 ui.warn(_('skipping already grafted revision %d:%s '
2230 '(%d:%s also has origin %d:%s)\n')
2233 '(%d:%s also has origin %d:%s)\n')
2231 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
2234 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
2232 revs.remove(ids[n])
2235 revs.remove(ids[n])
2233 elif ctx.hex() in ids:
2236 elif ctx.hex() in ids:
2234 r = ids[ctx.hex()]
2237 r = ids[ctx.hex()]
2235 ui.warn(_('skipping already grafted revision %d:%s '
2238 ui.warn(_('skipping already grafted revision %d:%s '
2236 '(was grafted from %d:%s)\n') %
2239 '(was grafted from %d:%s)\n') %
2237 (r, repo[r], rev, ctx))
2240 (r, repo[r], rev, ctx))
2238 revs.remove(r)
2241 revs.remove(r)
2239 if not revs:
2242 if not revs:
2240 return -1
2243 return -1
2241
2244
2242 for pos, ctx in enumerate(repo.set("%ld", revs)):
2245 for pos, ctx in enumerate(repo.set("%ld", revs)):
2243 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
2246 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
2244 ctx.description().split('\n', 1)[0])
2247 ctx.description().split('\n', 1)[0])
2245 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
2248 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
2246 if names:
2249 if names:
2247 desc += ' (%s)' % ' '.join(names)
2250 desc += ' (%s)' % ' '.join(names)
2248 ui.status(_('grafting %s\n') % desc)
2251 ui.status(_('grafting %s\n') % desc)
2249 if opts.get('dry_run'):
2252 if opts.get('dry_run'):
2250 continue
2253 continue
2251
2254
2252 source = ctx.extra().get('source')
2255 source = ctx.extra().get('source')
2253 extra = {}
2256 extra = {}
2254 if source:
2257 if source:
2255 extra['source'] = source
2258 extra['source'] = source
2256 extra['intermediate-source'] = ctx.hex()
2259 extra['intermediate-source'] = ctx.hex()
2257 else:
2260 else:
2258 extra['source'] = ctx.hex()
2261 extra['source'] = ctx.hex()
2259 user = ctx.user()
2262 user = ctx.user()
2260 if opts.get('user'):
2263 if opts.get('user'):
2261 user = opts['user']
2264 user = opts['user']
2262 date = ctx.date()
2265 date = ctx.date()
2263 if opts.get('date'):
2266 if opts.get('date'):
2264 date = opts['date']
2267 date = opts['date']
2265 message = ctx.description()
2268 message = ctx.description()
2266 if opts.get('log'):
2269 if opts.get('log'):
2267 message += '\n(grafted from %s)' % ctx.hex()
2270 message += '\n(grafted from %s)' % ctx.hex()
2268
2271
2269 # we don't merge the first commit when continuing
2272 # we don't merge the first commit when continuing
2270 if not cont:
2273 if not cont:
2271 # perform the graft merge with p1(rev) as 'ancestor'
2274 # perform the graft merge with p1(rev) as 'ancestor'
2272 try:
2275 try:
2273 # ui.forcemerge is an internal variable, do not document
2276 # ui.forcemerge is an internal variable, do not document
2274 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
2277 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
2275 'graft')
2278 'graft')
2276 stats = mergemod.graft(repo, ctx, ctx.p1(),
2279 stats = mergemod.graft(repo, ctx, ctx.p1(),
2277 ['local', 'graft'])
2280 ['local', 'graft'])
2278 finally:
2281 finally:
2279 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
2282 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
2280 # report any conflicts
2283 # report any conflicts
2281 if stats and stats[3] > 0:
2284 if stats and stats[3] > 0:
2282 # write out state for --continue
2285 # write out state for --continue
2283 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2286 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2284 repo.vfs.write('graftstate', ''.join(nodelines))
2287 repo.vfs.write('graftstate', ''.join(nodelines))
2285 extra = ''
2288 extra = ''
2286 if opts.get('user'):
2289 if opts.get('user'):
2287 extra += ' --user %s' % util.shellquote(opts['user'])
2290 extra += ' --user %s' % util.shellquote(opts['user'])
2288 if opts.get('date'):
2291 if opts.get('date'):
2289 extra += ' --date %s' % util.shellquote(opts['date'])
2292 extra += ' --date %s' % util.shellquote(opts['date'])
2290 if opts.get('log'):
2293 if opts.get('log'):
2291 extra += ' --log'
2294 extra += ' --log'
2292 hint=_("use 'hg resolve' and 'hg graft --continue%s'") % extra
2295 hint=_("use 'hg resolve' and 'hg graft --continue%s'") % extra
2293 raise error.Abort(
2296 raise error.Abort(
2294 _("unresolved conflicts, can't continue"),
2297 _("unresolved conflicts, can't continue"),
2295 hint=hint)
2298 hint=hint)
2296 else:
2299 else:
2297 cont = False
2300 cont = False
2298
2301
2299 # commit
2302 # commit
2300 node = repo.commit(text=message, user=user,
2303 node = repo.commit(text=message, user=user,
2301 date=date, extra=extra, editor=editor)
2304 date=date, extra=extra, editor=editor)
2302 if node is None:
2305 if node is None:
2303 ui.warn(
2306 ui.warn(
2304 _('note: graft of %d:%s created no changes to commit\n') %
2307 _('note: graft of %d:%s created no changes to commit\n') %
2305 (ctx.rev(), ctx))
2308 (ctx.rev(), ctx))
2306
2309
2307 # remove state when we complete successfully
2310 # remove state when we complete successfully
2308 if not opts.get('dry_run'):
2311 if not opts.get('dry_run'):
2309 repo.vfs.unlinkpath('graftstate', ignoremissing=True)
2312 repo.vfs.unlinkpath('graftstate', ignoremissing=True)
2310
2313
2311 return 0
2314 return 0
2312
2315
2313 @command('grep',
2316 @command('grep',
2314 [('0', 'print0', None, _('end fields with NUL')),
2317 [('0', 'print0', None, _('end fields with NUL')),
2315 ('', 'all', None, _('print all revisions that match')),
2318 ('', 'all', None, _('print all revisions that match')),
2316 ('a', 'text', None, _('treat all files as text')),
2319 ('a', 'text', None, _('treat all files as text')),
2317 ('f', 'follow', None,
2320 ('f', 'follow', None,
2318 _('follow changeset history,'
2321 _('follow changeset history,'
2319 ' or file history across copies and renames')),
2322 ' or file history across copies and renames')),
2320 ('i', 'ignore-case', None, _('ignore case when matching')),
2323 ('i', 'ignore-case', None, _('ignore case when matching')),
2321 ('l', 'files-with-matches', None,
2324 ('l', 'files-with-matches', None,
2322 _('print only filenames and revisions that match')),
2325 _('print only filenames and revisions that match')),
2323 ('n', 'line-number', None, _('print matching line numbers')),
2326 ('n', 'line-number', None, _('print matching line numbers')),
2324 ('r', 'rev', [],
2327 ('r', 'rev', [],
2325 _('only search files changed within revision range'), _('REV')),
2328 _('only search files changed within revision range'), _('REV')),
2326 ('u', 'user', None, _('list the author (long with -v)')),
2329 ('u', 'user', None, _('list the author (long with -v)')),
2327 ('d', 'date', None, _('list the date (short with -q)')),
2330 ('d', 'date', None, _('list the date (short with -q)')),
2328 ] + formatteropts + walkopts,
2331 ] + formatteropts + walkopts,
2329 _('[OPTION]... PATTERN [FILE]...'),
2332 _('[OPTION]... PATTERN [FILE]...'),
2330 inferrepo=True, cmdtype=readonly)
2333 inferrepo=True, cmdtype=readonly)
2331 def grep(ui, repo, pattern, *pats, **opts):
2334 def grep(ui, repo, pattern, *pats, **opts):
2332 """search revision history for a pattern in specified files
2335 """search revision history for a pattern in specified files
2333
2336
2334 Search revision history for a regular expression in the specified
2337 Search revision history for a regular expression in the specified
2335 files or the entire project.
2338 files or the entire project.
2336
2339
2337 By default, grep prints the most recent revision number for each
2340 By default, grep prints the most recent revision number for each
2338 file in which it finds a match. To get it to print every revision
2341 file in which it finds a match. To get it to print every revision
2339 that contains a change in match status ("-" for a match that becomes
2342 that contains a change in match status ("-" for a match that becomes
2340 a non-match, or "+" for a non-match that becomes a match), use the
2343 a non-match, or "+" for a non-match that becomes a match), use the
2341 --all flag.
2344 --all flag.
2342
2345
2343 PATTERN can be any Python (roughly Perl-compatible) regular
2346 PATTERN can be any Python (roughly Perl-compatible) regular
2344 expression.
2347 expression.
2345
2348
2346 If no FILEs are specified (and -f/--follow isn't set), all files in
2349 If no FILEs are specified (and -f/--follow isn't set), all files in
2347 the repository are searched, including those that don't exist in the
2350 the repository are searched, including those that don't exist in the
2348 current branch or have been deleted in a prior changeset.
2351 current branch or have been deleted in a prior changeset.
2349
2352
2350 Returns 0 if a match is found, 1 otherwise.
2353 Returns 0 if a match is found, 1 otherwise.
2351 """
2354 """
2352 opts = pycompat.byteskwargs(opts)
2355 opts = pycompat.byteskwargs(opts)
2353 reflags = re.M
2356 reflags = re.M
2354 if opts.get('ignore_case'):
2357 if opts.get('ignore_case'):
2355 reflags |= re.I
2358 reflags |= re.I
2356 try:
2359 try:
2357 regexp = util.re.compile(pattern, reflags)
2360 regexp = util.re.compile(pattern, reflags)
2358 except re.error as inst:
2361 except re.error as inst:
2359 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2362 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2360 return 1
2363 return 1
2361 sep, eol = ':', '\n'
2364 sep, eol = ':', '\n'
2362 if opts.get('print0'):
2365 if opts.get('print0'):
2363 sep = eol = '\0'
2366 sep = eol = '\0'
2364
2367
2365 getfile = util.lrucachefunc(repo.file)
2368 getfile = util.lrucachefunc(repo.file)
2366
2369
2367 def matchlines(body):
2370 def matchlines(body):
2368 begin = 0
2371 begin = 0
2369 linenum = 0
2372 linenum = 0
2370 while begin < len(body):
2373 while begin < len(body):
2371 match = regexp.search(body, begin)
2374 match = regexp.search(body, begin)
2372 if not match:
2375 if not match:
2373 break
2376 break
2374 mstart, mend = match.span()
2377 mstart, mend = match.span()
2375 linenum += body.count('\n', begin, mstart) + 1
2378 linenum += body.count('\n', begin, mstart) + 1
2376 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2379 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2377 begin = body.find('\n', mend) + 1 or len(body) + 1
2380 begin = body.find('\n', mend) + 1 or len(body) + 1
2378 lend = begin - 1
2381 lend = begin - 1
2379 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2382 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2380
2383
2381 class linestate(object):
2384 class linestate(object):
2382 def __init__(self, line, linenum, colstart, colend):
2385 def __init__(self, line, linenum, colstart, colend):
2383 self.line = line
2386 self.line = line
2384 self.linenum = linenum
2387 self.linenum = linenum
2385 self.colstart = colstart
2388 self.colstart = colstart
2386 self.colend = colend
2389 self.colend = colend
2387
2390
2388 def __hash__(self):
2391 def __hash__(self):
2389 return hash((self.linenum, self.line))
2392 return hash((self.linenum, self.line))
2390
2393
2391 def __eq__(self, other):
2394 def __eq__(self, other):
2392 return self.line == other.line
2395 return self.line == other.line
2393
2396
2394 def findpos(self):
2397 def findpos(self):
2395 """Iterate all (start, end) indices of matches"""
2398 """Iterate all (start, end) indices of matches"""
2396 yield self.colstart, self.colend
2399 yield self.colstart, self.colend
2397 p = self.colend
2400 p = self.colend
2398 while p < len(self.line):
2401 while p < len(self.line):
2399 m = regexp.search(self.line, p)
2402 m = regexp.search(self.line, p)
2400 if not m:
2403 if not m:
2401 break
2404 break
2402 yield m.span()
2405 yield m.span()
2403 p = m.end()
2406 p = m.end()
2404
2407
2405 matches = {}
2408 matches = {}
2406 copies = {}
2409 copies = {}
2407 def grepbody(fn, rev, body):
2410 def grepbody(fn, rev, body):
2408 matches[rev].setdefault(fn, [])
2411 matches[rev].setdefault(fn, [])
2409 m = matches[rev][fn]
2412 m = matches[rev][fn]
2410 for lnum, cstart, cend, line in matchlines(body):
2413 for lnum, cstart, cend, line in matchlines(body):
2411 s = linestate(line, lnum, cstart, cend)
2414 s = linestate(line, lnum, cstart, cend)
2412 m.append(s)
2415 m.append(s)
2413
2416
2414 def difflinestates(a, b):
2417 def difflinestates(a, b):
2415 sm = difflib.SequenceMatcher(None, a, b)
2418 sm = difflib.SequenceMatcher(None, a, b)
2416 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2419 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2417 if tag == 'insert':
2420 if tag == 'insert':
2418 for i in xrange(blo, bhi):
2421 for i in xrange(blo, bhi):
2419 yield ('+', b[i])
2422 yield ('+', b[i])
2420 elif tag == 'delete':
2423 elif tag == 'delete':
2421 for i in xrange(alo, ahi):
2424 for i in xrange(alo, ahi):
2422 yield ('-', a[i])
2425 yield ('-', a[i])
2423 elif tag == 'replace':
2426 elif tag == 'replace':
2424 for i in xrange(alo, ahi):
2427 for i in xrange(alo, ahi):
2425 yield ('-', a[i])
2428 yield ('-', a[i])
2426 for i in xrange(blo, bhi):
2429 for i in xrange(blo, bhi):
2427 yield ('+', b[i])
2430 yield ('+', b[i])
2428
2431
2429 def display(fm, fn, ctx, pstates, states):
2432 def display(fm, fn, ctx, pstates, states):
2430 rev = ctx.rev()
2433 rev = ctx.rev()
2431 if fm.isplain():
2434 if fm.isplain():
2432 formatuser = ui.shortuser
2435 formatuser = ui.shortuser
2433 else:
2436 else:
2434 formatuser = str
2437 formatuser = str
2435 if ui.quiet:
2438 if ui.quiet:
2436 datefmt = '%Y-%m-%d'
2439 datefmt = '%Y-%m-%d'
2437 else:
2440 else:
2438 datefmt = '%a %b %d %H:%M:%S %Y %1%2'
2441 datefmt = '%a %b %d %H:%M:%S %Y %1%2'
2439 found = False
2442 found = False
2440 @util.cachefunc
2443 @util.cachefunc
2441 def binary():
2444 def binary():
2442 flog = getfile(fn)
2445 flog = getfile(fn)
2443 return util.binary(flog.read(ctx.filenode(fn)))
2446 return util.binary(flog.read(ctx.filenode(fn)))
2444
2447
2445 fieldnamemap = {'filename': 'file', 'linenumber': 'line_number'}
2448 fieldnamemap = {'filename': 'file', 'linenumber': 'line_number'}
2446 if opts.get('all'):
2449 if opts.get('all'):
2447 iter = difflinestates(pstates, states)
2450 iter = difflinestates(pstates, states)
2448 else:
2451 else:
2449 iter = [('', l) for l in states]
2452 iter = [('', l) for l in states]
2450 for change, l in iter:
2453 for change, l in iter:
2451 fm.startitem()
2454 fm.startitem()
2452 fm.data(node=fm.hexfunc(ctx.node()))
2455 fm.data(node=fm.hexfunc(ctx.node()))
2453 cols = [
2456 cols = [
2454 ('filename', fn, True),
2457 ('filename', fn, True),
2455 ('rev', rev, True),
2458 ('rev', rev, True),
2456 ('linenumber', l.linenum, opts.get('line_number')),
2459 ('linenumber', l.linenum, opts.get('line_number')),
2457 ]
2460 ]
2458 if opts.get('all'):
2461 if opts.get('all'):
2459 cols.append(('change', change, True))
2462 cols.append(('change', change, True))
2460 cols.extend([
2463 cols.extend([
2461 ('user', formatuser(ctx.user()), opts.get('user')),
2464 ('user', formatuser(ctx.user()), opts.get('user')),
2462 ('date', fm.formatdate(ctx.date(), datefmt), opts.get('date')),
2465 ('date', fm.formatdate(ctx.date(), datefmt), opts.get('date')),
2463 ])
2466 ])
2464 lastcol = next(name for name, data, cond in reversed(cols) if cond)
2467 lastcol = next(name for name, data, cond in reversed(cols) if cond)
2465 for name, data, cond in cols:
2468 for name, data, cond in cols:
2466 field = fieldnamemap.get(name, name)
2469 field = fieldnamemap.get(name, name)
2467 fm.condwrite(cond, field, '%s', data, label='grep.%s' % name)
2470 fm.condwrite(cond, field, '%s', data, label='grep.%s' % name)
2468 if cond and name != lastcol:
2471 if cond and name != lastcol:
2469 fm.plain(sep, label='grep.sep')
2472 fm.plain(sep, label='grep.sep')
2470 if not opts.get('files_with_matches'):
2473 if not opts.get('files_with_matches'):
2471 fm.plain(sep, label='grep.sep')
2474 fm.plain(sep, label='grep.sep')
2472 if not opts.get('text') and binary():
2475 if not opts.get('text') and binary():
2473 fm.plain(_(" Binary file matches"))
2476 fm.plain(_(" Binary file matches"))
2474 else:
2477 else:
2475 displaymatches(fm.nested('texts'), l)
2478 displaymatches(fm.nested('texts'), l)
2476 fm.plain(eol)
2479 fm.plain(eol)
2477 found = True
2480 found = True
2478 if opts.get('files_with_matches'):
2481 if opts.get('files_with_matches'):
2479 break
2482 break
2480 return found
2483 return found
2481
2484
2482 def displaymatches(fm, l):
2485 def displaymatches(fm, l):
2483 p = 0
2486 p = 0
2484 for s, e in l.findpos():
2487 for s, e in l.findpos():
2485 if p < s:
2488 if p < s:
2486 fm.startitem()
2489 fm.startitem()
2487 fm.write('text', '%s', l.line[p:s])
2490 fm.write('text', '%s', l.line[p:s])
2488 fm.data(matched=False)
2491 fm.data(matched=False)
2489 fm.startitem()
2492 fm.startitem()
2490 fm.write('text', '%s', l.line[s:e], label='grep.match')
2493 fm.write('text', '%s', l.line[s:e], label='grep.match')
2491 fm.data(matched=True)
2494 fm.data(matched=True)
2492 p = e
2495 p = e
2493 if p < len(l.line):
2496 if p < len(l.line):
2494 fm.startitem()
2497 fm.startitem()
2495 fm.write('text', '%s', l.line[p:])
2498 fm.write('text', '%s', l.line[p:])
2496 fm.data(matched=False)
2499 fm.data(matched=False)
2497 fm.end()
2500 fm.end()
2498
2501
2499 skip = {}
2502 skip = {}
2500 revfiles = {}
2503 revfiles = {}
2501 match = scmutil.match(repo[None], pats, opts)
2504 match = scmutil.match(repo[None], pats, opts)
2502 found = False
2505 found = False
2503 follow = opts.get('follow')
2506 follow = opts.get('follow')
2504
2507
2505 def prep(ctx, fns):
2508 def prep(ctx, fns):
2506 rev = ctx.rev()
2509 rev = ctx.rev()
2507 pctx = ctx.p1()
2510 pctx = ctx.p1()
2508 parent = pctx.rev()
2511 parent = pctx.rev()
2509 matches.setdefault(rev, {})
2512 matches.setdefault(rev, {})
2510 matches.setdefault(parent, {})
2513 matches.setdefault(parent, {})
2511 files = revfiles.setdefault(rev, [])
2514 files = revfiles.setdefault(rev, [])
2512 for fn in fns:
2515 for fn in fns:
2513 flog = getfile(fn)
2516 flog = getfile(fn)
2514 try:
2517 try:
2515 fnode = ctx.filenode(fn)
2518 fnode = ctx.filenode(fn)
2516 except error.LookupError:
2519 except error.LookupError:
2517 continue
2520 continue
2518
2521
2519 copied = flog.renamed(fnode)
2522 copied = flog.renamed(fnode)
2520 copy = follow and copied and copied[0]
2523 copy = follow and copied and copied[0]
2521 if copy:
2524 if copy:
2522 copies.setdefault(rev, {})[fn] = copy
2525 copies.setdefault(rev, {})[fn] = copy
2523 if fn in skip:
2526 if fn in skip:
2524 if copy:
2527 if copy:
2525 skip[copy] = True
2528 skip[copy] = True
2526 continue
2529 continue
2527 files.append(fn)
2530 files.append(fn)
2528
2531
2529 if fn not in matches[rev]:
2532 if fn not in matches[rev]:
2530 grepbody(fn, rev, flog.read(fnode))
2533 grepbody(fn, rev, flog.read(fnode))
2531
2534
2532 pfn = copy or fn
2535 pfn = copy or fn
2533 if pfn not in matches[parent]:
2536 if pfn not in matches[parent]:
2534 try:
2537 try:
2535 fnode = pctx.filenode(pfn)
2538 fnode = pctx.filenode(pfn)
2536 grepbody(pfn, parent, flog.read(fnode))
2539 grepbody(pfn, parent, flog.read(fnode))
2537 except error.LookupError:
2540 except error.LookupError:
2538 pass
2541 pass
2539
2542
2540 ui.pager('grep')
2543 ui.pager('grep')
2541 fm = ui.formatter('grep', opts)
2544 fm = ui.formatter('grep', opts)
2542 for ctx in cmdutil.walkchangerevs(repo, match, opts, prep):
2545 for ctx in cmdutil.walkchangerevs(repo, match, opts, prep):
2543 rev = ctx.rev()
2546 rev = ctx.rev()
2544 parent = ctx.p1().rev()
2547 parent = ctx.p1().rev()
2545 for fn in sorted(revfiles.get(rev, [])):
2548 for fn in sorted(revfiles.get(rev, [])):
2546 states = matches[rev][fn]
2549 states = matches[rev][fn]
2547 copy = copies.get(rev, {}).get(fn)
2550 copy = copies.get(rev, {}).get(fn)
2548 if fn in skip:
2551 if fn in skip:
2549 if copy:
2552 if copy:
2550 skip[copy] = True
2553 skip[copy] = True
2551 continue
2554 continue
2552 pstates = matches.get(parent, {}).get(copy or fn, [])
2555 pstates = matches.get(parent, {}).get(copy or fn, [])
2553 if pstates or states:
2556 if pstates or states:
2554 r = display(fm, fn, ctx, pstates, states)
2557 r = display(fm, fn, ctx, pstates, states)
2555 found = found or r
2558 found = found or r
2556 if r and not opts.get('all'):
2559 if r and not opts.get('all'):
2557 skip[fn] = True
2560 skip[fn] = True
2558 if copy:
2561 if copy:
2559 skip[copy] = True
2562 skip[copy] = True
2560 del matches[rev]
2563 del matches[rev]
2561 del revfiles[rev]
2564 del revfiles[rev]
2562 fm.end()
2565 fm.end()
2563
2566
2564 return not found
2567 return not found
2565
2568
2566 @command('heads',
2569 @command('heads',
2567 [('r', 'rev', '',
2570 [('r', 'rev', '',
2568 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2571 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2569 ('t', 'topo', False, _('show topological heads only')),
2572 ('t', 'topo', False, _('show topological heads only')),
2570 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2573 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2571 ('c', 'closed', False, _('show normal and closed branch heads')),
2574 ('c', 'closed', False, _('show normal and closed branch heads')),
2572 ] + templateopts,
2575 ] + templateopts,
2573 _('[-ct] [-r STARTREV] [REV]...'), cmdtype=readonly)
2576 _('[-ct] [-r STARTREV] [REV]...'), cmdtype=readonly)
2574 def heads(ui, repo, *branchrevs, **opts):
2577 def heads(ui, repo, *branchrevs, **opts):
2575 """show branch heads
2578 """show branch heads
2576
2579
2577 With no arguments, show all open branch heads in the repository.
2580 With no arguments, show all open branch heads in the repository.
2578 Branch heads are changesets that have no descendants on the
2581 Branch heads are changesets that have no descendants on the
2579 same branch. They are where development generally takes place and
2582 same branch. They are where development generally takes place and
2580 are the usual targets for update and merge operations.
2583 are the usual targets for update and merge operations.
2581
2584
2582 If one or more REVs are given, only open branch heads on the
2585 If one or more REVs are given, only open branch heads on the
2583 branches associated with the specified changesets are shown. This
2586 branches associated with the specified changesets are shown. This
2584 means that you can use :hg:`heads .` to see the heads on the
2587 means that you can use :hg:`heads .` to see the heads on the
2585 currently checked-out branch.
2588 currently checked-out branch.
2586
2589
2587 If -c/--closed is specified, also show branch heads marked closed
2590 If -c/--closed is specified, also show branch heads marked closed
2588 (see :hg:`commit --close-branch`).
2591 (see :hg:`commit --close-branch`).
2589
2592
2590 If STARTREV is specified, only those heads that are descendants of
2593 If STARTREV is specified, only those heads that are descendants of
2591 STARTREV will be displayed.
2594 STARTREV will be displayed.
2592
2595
2593 If -t/--topo is specified, named branch mechanics will be ignored and only
2596 If -t/--topo is specified, named branch mechanics will be ignored and only
2594 topological heads (changesets with no children) will be shown.
2597 topological heads (changesets with no children) will be shown.
2595
2598
2596 Returns 0 if matching heads are found, 1 if not.
2599 Returns 0 if matching heads are found, 1 if not.
2597 """
2600 """
2598
2601
2599 opts = pycompat.byteskwargs(opts)
2602 opts = pycompat.byteskwargs(opts)
2600 start = None
2603 start = None
2601 rev = opts.get('rev')
2604 rev = opts.get('rev')
2602 if rev:
2605 if rev:
2603 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
2606 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
2604 start = scmutil.revsingle(repo, rev, None).node()
2607 start = scmutil.revsingle(repo, rev, None).node()
2605
2608
2606 if opts.get('topo'):
2609 if opts.get('topo'):
2607 heads = [repo[h] for h in repo.heads(start)]
2610 heads = [repo[h] for h in repo.heads(start)]
2608 else:
2611 else:
2609 heads = []
2612 heads = []
2610 for branch in repo.branchmap():
2613 for branch in repo.branchmap():
2611 heads += repo.branchheads(branch, start, opts.get('closed'))
2614 heads += repo.branchheads(branch, start, opts.get('closed'))
2612 heads = [repo[h] for h in heads]
2615 heads = [repo[h] for h in heads]
2613
2616
2614 if branchrevs:
2617 if branchrevs:
2615 branches = set(repo[br].branch() for br in branchrevs)
2618 branches = set(repo[br].branch() for br in branchrevs)
2616 heads = [h for h in heads if h.branch() in branches]
2619 heads = [h for h in heads if h.branch() in branches]
2617
2620
2618 if opts.get('active') and branchrevs:
2621 if opts.get('active') and branchrevs:
2619 dagheads = repo.heads(start)
2622 dagheads = repo.heads(start)
2620 heads = [h for h in heads if h.node() in dagheads]
2623 heads = [h for h in heads if h.node() in dagheads]
2621
2624
2622 if branchrevs:
2625 if branchrevs:
2623 haveheads = set(h.branch() for h in heads)
2626 haveheads = set(h.branch() for h in heads)
2624 if branches - haveheads:
2627 if branches - haveheads:
2625 headless = ', '.join(b for b in branches - haveheads)
2628 headless = ', '.join(b for b in branches - haveheads)
2626 msg = _('no open branch heads found on branches %s')
2629 msg = _('no open branch heads found on branches %s')
2627 if opts.get('rev'):
2630 if opts.get('rev'):
2628 msg += _(' (started at %s)') % opts['rev']
2631 msg += _(' (started at %s)') % opts['rev']
2629 ui.warn((msg + '\n') % headless)
2632 ui.warn((msg + '\n') % headless)
2630
2633
2631 if not heads:
2634 if not heads:
2632 return 1
2635 return 1
2633
2636
2634 ui.pager('heads')
2637 ui.pager('heads')
2635 heads = sorted(heads, key=lambda x: -x.rev())
2638 heads = sorted(heads, key=lambda x: -x.rev())
2636 displayer = cmdutil.show_changeset(ui, repo, opts)
2639 displayer = cmdutil.show_changeset(ui, repo, opts)
2637 for ctx in heads:
2640 for ctx in heads:
2638 displayer.show(ctx)
2641 displayer.show(ctx)
2639 displayer.close()
2642 displayer.close()
2640
2643
2641 @command('help',
2644 @command('help',
2642 [('e', 'extension', None, _('show only help for extensions')),
2645 [('e', 'extension', None, _('show only help for extensions')),
2643 ('c', 'command', None, _('show only help for commands')),
2646 ('c', 'command', None, _('show only help for commands')),
2644 ('k', 'keyword', None, _('show topics matching keyword')),
2647 ('k', 'keyword', None, _('show topics matching keyword')),
2645 ('s', 'system', [], _('show help for specific platform(s)')),
2648 ('s', 'system', [], _('show help for specific platform(s)')),
2646 ],
2649 ],
2647 _('[-ecks] [TOPIC]'),
2650 _('[-ecks] [TOPIC]'),
2648 norepo=True, cmdtype=readonly)
2651 norepo=True, cmdtype=readonly)
2649 def help_(ui, name=None, **opts):
2652 def help_(ui, name=None, **opts):
2650 """show help for a given topic or a help overview
2653 """show help for a given topic or a help overview
2651
2654
2652 With no arguments, print a list of commands with short help messages.
2655 With no arguments, print a list of commands with short help messages.
2653
2656
2654 Given a topic, extension, or command name, print help for that
2657 Given a topic, extension, or command name, print help for that
2655 topic.
2658 topic.
2656
2659
2657 Returns 0 if successful.
2660 Returns 0 if successful.
2658 """
2661 """
2659
2662
2660 keep = opts.get(r'system') or []
2663 keep = opts.get(r'system') or []
2661 if len(keep) == 0:
2664 if len(keep) == 0:
2662 if pycompat.sysplatform.startswith('win'):
2665 if pycompat.sysplatform.startswith('win'):
2663 keep.append('windows')
2666 keep.append('windows')
2664 elif pycompat.sysplatform == 'OpenVMS':
2667 elif pycompat.sysplatform == 'OpenVMS':
2665 keep.append('vms')
2668 keep.append('vms')
2666 elif pycompat.sysplatform == 'plan9':
2669 elif pycompat.sysplatform == 'plan9':
2667 keep.append('plan9')
2670 keep.append('plan9')
2668 else:
2671 else:
2669 keep.append('unix')
2672 keep.append('unix')
2670 keep.append(pycompat.sysplatform.lower())
2673 keep.append(pycompat.sysplatform.lower())
2671 if ui.verbose:
2674 if ui.verbose:
2672 keep.append('verbose')
2675 keep.append('verbose')
2673
2676
2674 commands = sys.modules[__name__]
2677 commands = sys.modules[__name__]
2675 formatted = help.formattedhelp(ui, commands, name, keep=keep, **opts)
2678 formatted = help.formattedhelp(ui, commands, name, keep=keep, **opts)
2676 ui.pager('help')
2679 ui.pager('help')
2677 ui.write(formatted)
2680 ui.write(formatted)
2678
2681
2679
2682
2680 @command('identify|id',
2683 @command('identify|id',
2681 [('r', 'rev', '',
2684 [('r', 'rev', '',
2682 _('identify the specified revision'), _('REV')),
2685 _('identify the specified revision'), _('REV')),
2683 ('n', 'num', None, _('show local revision number')),
2686 ('n', 'num', None, _('show local revision number')),
2684 ('i', 'id', None, _('show global revision id')),
2687 ('i', 'id', None, _('show global revision id')),
2685 ('b', 'branch', None, _('show branch')),
2688 ('b', 'branch', None, _('show branch')),
2686 ('t', 'tags', None, _('show tags')),
2689 ('t', 'tags', None, _('show tags')),
2687 ('B', 'bookmarks', None, _('show bookmarks')),
2690 ('B', 'bookmarks', None, _('show bookmarks')),
2688 ] + remoteopts + formatteropts,
2691 ] + remoteopts + formatteropts,
2689 _('[-nibtB] [-r REV] [SOURCE]'),
2692 _('[-nibtB] [-r REV] [SOURCE]'),
2690 optionalrepo=True, cmdtype=readonly)
2693 optionalrepo=True, cmdtype=readonly)
2691 def identify(ui, repo, source=None, rev=None,
2694 def identify(ui, repo, source=None, rev=None,
2692 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
2695 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
2693 """identify the working directory or specified revision
2696 """identify the working directory or specified revision
2694
2697
2695 Print a summary identifying the repository state at REV using one or
2698 Print a summary identifying the repository state at REV using one or
2696 two parent hash identifiers, followed by a "+" if the working
2699 two parent hash identifiers, followed by a "+" if the working
2697 directory has uncommitted changes, the branch name (if not default),
2700 directory has uncommitted changes, the branch name (if not default),
2698 a list of tags, and a list of bookmarks.
2701 a list of tags, and a list of bookmarks.
2699
2702
2700 When REV is not given, print a summary of the current state of the
2703 When REV is not given, print a summary of the current state of the
2701 repository.
2704 repository.
2702
2705
2703 Specifying a path to a repository root or Mercurial bundle will
2706 Specifying a path to a repository root or Mercurial bundle will
2704 cause lookup to operate on that repository/bundle.
2707 cause lookup to operate on that repository/bundle.
2705
2708
2706 .. container:: verbose
2709 .. container:: verbose
2707
2710
2708 Examples:
2711 Examples:
2709
2712
2710 - generate a build identifier for the working directory::
2713 - generate a build identifier for the working directory::
2711
2714
2712 hg id --id > build-id.dat
2715 hg id --id > build-id.dat
2713
2716
2714 - find the revision corresponding to a tag::
2717 - find the revision corresponding to a tag::
2715
2718
2716 hg id -n -r 1.3
2719 hg id -n -r 1.3
2717
2720
2718 - check the most recent revision of a remote repository::
2721 - check the most recent revision of a remote repository::
2719
2722
2720 hg id -r tip https://www.mercurial-scm.org/repo/hg/
2723 hg id -r tip https://www.mercurial-scm.org/repo/hg/
2721
2724
2722 See :hg:`log` for generating more information about specific revisions,
2725 See :hg:`log` for generating more information about specific revisions,
2723 including full hash identifiers.
2726 including full hash identifiers.
2724
2727
2725 Returns 0 if successful.
2728 Returns 0 if successful.
2726 """
2729 """
2727
2730
2728 opts = pycompat.byteskwargs(opts)
2731 opts = pycompat.byteskwargs(opts)
2729 if not repo and not source:
2732 if not repo and not source:
2730 raise error.Abort(_("there is no Mercurial repository here "
2733 raise error.Abort(_("there is no Mercurial repository here "
2731 "(.hg not found)"))
2734 "(.hg not found)"))
2732
2735
2733 if ui.debugflag:
2736 if ui.debugflag:
2734 hexfunc = hex
2737 hexfunc = hex
2735 else:
2738 else:
2736 hexfunc = short
2739 hexfunc = short
2737 default = not (num or id or branch or tags or bookmarks)
2740 default = not (num or id or branch or tags or bookmarks)
2738 output = []
2741 output = []
2739 revs = []
2742 revs = []
2740
2743
2741 if source:
2744 if source:
2742 source, branches = hg.parseurl(ui.expandpath(source))
2745 source, branches = hg.parseurl(ui.expandpath(source))
2743 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
2746 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
2744 repo = peer.local()
2747 repo = peer.local()
2745 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
2748 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
2746
2749
2747 fm = ui.formatter('identify', opts)
2750 fm = ui.formatter('identify', opts)
2748 fm.startitem()
2751 fm.startitem()
2749
2752
2750 if not repo:
2753 if not repo:
2751 if num or branch or tags:
2754 if num or branch or tags:
2752 raise error.Abort(
2755 raise error.Abort(
2753 _("can't query remote revision number, branch, or tags"))
2756 _("can't query remote revision number, branch, or tags"))
2754 if not rev and revs:
2757 if not rev and revs:
2755 rev = revs[0]
2758 rev = revs[0]
2756 if not rev:
2759 if not rev:
2757 rev = "tip"
2760 rev = "tip"
2758
2761
2759 remoterev = peer.lookup(rev)
2762 remoterev = peer.lookup(rev)
2760 hexrev = hexfunc(remoterev)
2763 hexrev = hexfunc(remoterev)
2761 if default or id:
2764 if default or id:
2762 output = [hexrev]
2765 output = [hexrev]
2763 fm.data(id=hexrev)
2766 fm.data(id=hexrev)
2764
2767
2765 def getbms():
2768 def getbms():
2766 bms = []
2769 bms = []
2767
2770
2768 if 'bookmarks' in peer.listkeys('namespaces'):
2771 if 'bookmarks' in peer.listkeys('namespaces'):
2769 hexremoterev = hex(remoterev)
2772 hexremoterev = hex(remoterev)
2770 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
2773 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
2771 if bmr == hexremoterev]
2774 if bmr == hexremoterev]
2772
2775
2773 return sorted(bms)
2776 return sorted(bms)
2774
2777
2775 bms = getbms()
2778 bms = getbms()
2776 if bookmarks:
2779 if bookmarks:
2777 output.extend(bms)
2780 output.extend(bms)
2778 elif default and not ui.quiet:
2781 elif default and not ui.quiet:
2779 # multiple bookmarks for a single parent separated by '/'
2782 # multiple bookmarks for a single parent separated by '/'
2780 bm = '/'.join(bms)
2783 bm = '/'.join(bms)
2781 if bm:
2784 if bm:
2782 output.append(bm)
2785 output.append(bm)
2783
2786
2784 fm.data(node=hex(remoterev))
2787 fm.data(node=hex(remoterev))
2785 fm.data(bookmarks=fm.formatlist(bms, name='bookmark'))
2788 fm.data(bookmarks=fm.formatlist(bms, name='bookmark'))
2786 else:
2789 else:
2787 if rev:
2790 if rev:
2788 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
2791 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
2789 ctx = scmutil.revsingle(repo, rev, None)
2792 ctx = scmutil.revsingle(repo, rev, None)
2790
2793
2791 if ctx.rev() is None:
2794 if ctx.rev() is None:
2792 ctx = repo[None]
2795 ctx = repo[None]
2793 parents = ctx.parents()
2796 parents = ctx.parents()
2794 taglist = []
2797 taglist = []
2795 for p in parents:
2798 for p in parents:
2796 taglist.extend(p.tags())
2799 taglist.extend(p.tags())
2797
2800
2798 dirty = ""
2801 dirty = ""
2799 if ctx.dirty(missing=True, merge=False, branch=False):
2802 if ctx.dirty(missing=True, merge=False, branch=False):
2800 dirty = '+'
2803 dirty = '+'
2801 fm.data(dirty=dirty)
2804 fm.data(dirty=dirty)
2802
2805
2803 hexoutput = [hexfunc(p.node()) for p in parents]
2806 hexoutput = [hexfunc(p.node()) for p in parents]
2804 if default or id:
2807 if default or id:
2805 output = ["%s%s" % ('+'.join(hexoutput), dirty)]
2808 output = ["%s%s" % ('+'.join(hexoutput), dirty)]
2806 fm.data(id="%s%s" % ('+'.join(hexoutput), dirty))
2809 fm.data(id="%s%s" % ('+'.join(hexoutput), dirty))
2807
2810
2808 if num:
2811 if num:
2809 numoutput = ["%d" % p.rev() for p in parents]
2812 numoutput = ["%d" % p.rev() for p in parents]
2810 output.append("%s%s" % ('+'.join(numoutput), dirty))
2813 output.append("%s%s" % ('+'.join(numoutput), dirty))
2811
2814
2812 fn = fm.nested('parents')
2815 fn = fm.nested('parents')
2813 for p in parents:
2816 for p in parents:
2814 fn.startitem()
2817 fn.startitem()
2815 fn.data(rev=p.rev())
2818 fn.data(rev=p.rev())
2816 fn.data(node=p.hex())
2819 fn.data(node=p.hex())
2817 fn.context(ctx=p)
2820 fn.context(ctx=p)
2818 fn.end()
2821 fn.end()
2819 else:
2822 else:
2820 hexoutput = hexfunc(ctx.node())
2823 hexoutput = hexfunc(ctx.node())
2821 if default or id:
2824 if default or id:
2822 output = [hexoutput]
2825 output = [hexoutput]
2823 fm.data(id=hexoutput)
2826 fm.data(id=hexoutput)
2824
2827
2825 if num:
2828 if num:
2826 output.append(pycompat.bytestr(ctx.rev()))
2829 output.append(pycompat.bytestr(ctx.rev()))
2827 taglist = ctx.tags()
2830 taglist = ctx.tags()
2828
2831
2829 if default and not ui.quiet:
2832 if default and not ui.quiet:
2830 b = ctx.branch()
2833 b = ctx.branch()
2831 if b != 'default':
2834 if b != 'default':
2832 output.append("(%s)" % b)
2835 output.append("(%s)" % b)
2833
2836
2834 # multiple tags for a single parent separated by '/'
2837 # multiple tags for a single parent separated by '/'
2835 t = '/'.join(taglist)
2838 t = '/'.join(taglist)
2836 if t:
2839 if t:
2837 output.append(t)
2840 output.append(t)
2838
2841
2839 # multiple bookmarks for a single parent separated by '/'
2842 # multiple bookmarks for a single parent separated by '/'
2840 bm = '/'.join(ctx.bookmarks())
2843 bm = '/'.join(ctx.bookmarks())
2841 if bm:
2844 if bm:
2842 output.append(bm)
2845 output.append(bm)
2843 else:
2846 else:
2844 if branch:
2847 if branch:
2845 output.append(ctx.branch())
2848 output.append(ctx.branch())
2846
2849
2847 if tags:
2850 if tags:
2848 output.extend(taglist)
2851 output.extend(taglist)
2849
2852
2850 if bookmarks:
2853 if bookmarks:
2851 output.extend(ctx.bookmarks())
2854 output.extend(ctx.bookmarks())
2852
2855
2853 fm.data(node=ctx.hex())
2856 fm.data(node=ctx.hex())
2854 fm.data(branch=ctx.branch())
2857 fm.data(branch=ctx.branch())
2855 fm.data(tags=fm.formatlist(taglist, name='tag', sep=':'))
2858 fm.data(tags=fm.formatlist(taglist, name='tag', sep=':'))
2856 fm.data(bookmarks=fm.formatlist(ctx.bookmarks(), name='bookmark'))
2859 fm.data(bookmarks=fm.formatlist(ctx.bookmarks(), name='bookmark'))
2857 fm.context(ctx=ctx)
2860 fm.context(ctx=ctx)
2858
2861
2859 fm.plain("%s\n" % ' '.join(output))
2862 fm.plain("%s\n" % ' '.join(output))
2860 fm.end()
2863 fm.end()
2861
2864
2862 @command('import|patch',
2865 @command('import|patch',
2863 [('p', 'strip', 1,
2866 [('p', 'strip', 1,
2864 _('directory strip option for patch. This has the same '
2867 _('directory strip option for patch. This has the same '
2865 'meaning as the corresponding patch option'), _('NUM')),
2868 'meaning as the corresponding patch option'), _('NUM')),
2866 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
2869 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
2867 ('e', 'edit', False, _('invoke editor on commit messages')),
2870 ('e', 'edit', False, _('invoke editor on commit messages')),
2868 ('f', 'force', None,
2871 ('f', 'force', None,
2869 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
2872 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
2870 ('', 'no-commit', None,
2873 ('', 'no-commit', None,
2871 _("don't commit, just update the working directory")),
2874 _("don't commit, just update the working directory")),
2872 ('', 'bypass', None,
2875 ('', 'bypass', None,
2873 _("apply patch without touching the working directory")),
2876 _("apply patch without touching the working directory")),
2874 ('', 'partial', None,
2877 ('', 'partial', None,
2875 _('commit even if some hunks fail')),
2878 _('commit even if some hunks fail')),
2876 ('', 'exact', None,
2879 ('', 'exact', None,
2877 _('abort if patch would apply lossily')),
2880 _('abort if patch would apply lossily')),
2878 ('', 'prefix', '',
2881 ('', 'prefix', '',
2879 _('apply patch to subdirectory'), _('DIR')),
2882 _('apply patch to subdirectory'), _('DIR')),
2880 ('', 'import-branch', None,
2883 ('', 'import-branch', None,
2881 _('use any branch information in patch (implied by --exact)'))] +
2884 _('use any branch information in patch (implied by --exact)'))] +
2882 commitopts + commitopts2 + similarityopts,
2885 commitopts + commitopts2 + similarityopts,
2883 _('[OPTION]... PATCH...'))
2886 _('[OPTION]... PATCH...'))
2884 def import_(ui, repo, patch1=None, *patches, **opts):
2887 def import_(ui, repo, patch1=None, *patches, **opts):
2885 """import an ordered set of patches
2888 """import an ordered set of patches
2886
2889
2887 Import a list of patches and commit them individually (unless
2890 Import a list of patches and commit them individually (unless
2888 --no-commit is specified).
2891 --no-commit is specified).
2889
2892
2890 To read a patch from standard input (stdin), use "-" as the patch
2893 To read a patch from standard input (stdin), use "-" as the patch
2891 name. If a URL is specified, the patch will be downloaded from
2894 name. If a URL is specified, the patch will be downloaded from
2892 there.
2895 there.
2893
2896
2894 Import first applies changes to the working directory (unless
2897 Import first applies changes to the working directory (unless
2895 --bypass is specified), import will abort if there are outstanding
2898 --bypass is specified), import will abort if there are outstanding
2896 changes.
2899 changes.
2897
2900
2898 Use --bypass to apply and commit patches directly to the
2901 Use --bypass to apply and commit patches directly to the
2899 repository, without affecting the working directory. Without
2902 repository, without affecting the working directory. Without
2900 --exact, patches will be applied on top of the working directory
2903 --exact, patches will be applied on top of the working directory
2901 parent revision.
2904 parent revision.
2902
2905
2903 You can import a patch straight from a mail message. Even patches
2906 You can import a patch straight from a mail message. Even patches
2904 as attachments work (to use the body part, it must have type
2907 as attachments work (to use the body part, it must have type
2905 text/plain or text/x-patch). From and Subject headers of email
2908 text/plain or text/x-patch). From and Subject headers of email
2906 message are used as default committer and commit message. All
2909 message are used as default committer and commit message. All
2907 text/plain body parts before first diff are added to the commit
2910 text/plain body parts before first diff are added to the commit
2908 message.
2911 message.
2909
2912
2910 If the imported patch was generated by :hg:`export`, user and
2913 If the imported patch was generated by :hg:`export`, user and
2911 description from patch override values from message headers and
2914 description from patch override values from message headers and
2912 body. Values given on command line with -m/--message and -u/--user
2915 body. Values given on command line with -m/--message and -u/--user
2913 override these.
2916 override these.
2914
2917
2915 If --exact is specified, import will set the working directory to
2918 If --exact is specified, import will set the working directory to
2916 the parent of each patch before applying it, and will abort if the
2919 the parent of each patch before applying it, and will abort if the
2917 resulting changeset has a different ID than the one recorded in
2920 resulting changeset has a different ID than the one recorded in
2918 the patch. This will guard against various ways that portable
2921 the patch. This will guard against various ways that portable
2919 patch formats and mail systems might fail to transfer Mercurial
2922 patch formats and mail systems might fail to transfer Mercurial
2920 data or metadata. See :hg:`bundle` for lossless transmission.
2923 data or metadata. See :hg:`bundle` for lossless transmission.
2921
2924
2922 Use --partial to ensure a changeset will be created from the patch
2925 Use --partial to ensure a changeset will be created from the patch
2923 even if some hunks fail to apply. Hunks that fail to apply will be
2926 even if some hunks fail to apply. Hunks that fail to apply will be
2924 written to a <target-file>.rej file. Conflicts can then be resolved
2927 written to a <target-file>.rej file. Conflicts can then be resolved
2925 by hand before :hg:`commit --amend` is run to update the created
2928 by hand before :hg:`commit --amend` is run to update the created
2926 changeset. This flag exists to let people import patches that
2929 changeset. This flag exists to let people import patches that
2927 partially apply without losing the associated metadata (author,
2930 partially apply without losing the associated metadata (author,
2928 date, description, ...).
2931 date, description, ...).
2929
2932
2930 .. note::
2933 .. note::
2931
2934
2932 When no hunks apply cleanly, :hg:`import --partial` will create
2935 When no hunks apply cleanly, :hg:`import --partial` will create
2933 an empty changeset, importing only the patch metadata.
2936 an empty changeset, importing only the patch metadata.
2934
2937
2935 With -s/--similarity, hg will attempt to discover renames and
2938 With -s/--similarity, hg will attempt to discover renames and
2936 copies in the patch in the same way as :hg:`addremove`.
2939 copies in the patch in the same way as :hg:`addremove`.
2937
2940
2938 It is possible to use external patch programs to perform the patch
2941 It is possible to use external patch programs to perform the patch
2939 by setting the ``ui.patch`` configuration option. For the default
2942 by setting the ``ui.patch`` configuration option. For the default
2940 internal tool, the fuzz can also be configured via ``patch.fuzz``.
2943 internal tool, the fuzz can also be configured via ``patch.fuzz``.
2941 See :hg:`help config` for more information about configuration
2944 See :hg:`help config` for more information about configuration
2942 files and how to use these options.
2945 files and how to use these options.
2943
2946
2944 See :hg:`help dates` for a list of formats valid for -d/--date.
2947 See :hg:`help dates` for a list of formats valid for -d/--date.
2945
2948
2946 .. container:: verbose
2949 .. container:: verbose
2947
2950
2948 Examples:
2951 Examples:
2949
2952
2950 - import a traditional patch from a website and detect renames::
2953 - import a traditional patch from a website and detect renames::
2951
2954
2952 hg import -s 80 http://example.com/bugfix.patch
2955 hg import -s 80 http://example.com/bugfix.patch
2953
2956
2954 - import a changeset from an hgweb server::
2957 - import a changeset from an hgweb server::
2955
2958
2956 hg import https://www.mercurial-scm.org/repo/hg/rev/5ca8c111e9aa
2959 hg import https://www.mercurial-scm.org/repo/hg/rev/5ca8c111e9aa
2957
2960
2958 - import all the patches in an Unix-style mbox::
2961 - import all the patches in an Unix-style mbox::
2959
2962
2960 hg import incoming-patches.mbox
2963 hg import incoming-patches.mbox
2961
2964
2962 - import patches from stdin::
2965 - import patches from stdin::
2963
2966
2964 hg import -
2967 hg import -
2965
2968
2966 - attempt to exactly restore an exported changeset (not always
2969 - attempt to exactly restore an exported changeset (not always
2967 possible)::
2970 possible)::
2968
2971
2969 hg import --exact proposed-fix.patch
2972 hg import --exact proposed-fix.patch
2970
2973
2971 - use an external tool to apply a patch which is too fuzzy for
2974 - use an external tool to apply a patch which is too fuzzy for
2972 the default internal tool.
2975 the default internal tool.
2973
2976
2974 hg import --config ui.patch="patch --merge" fuzzy.patch
2977 hg import --config ui.patch="patch --merge" fuzzy.patch
2975
2978
2976 - change the default fuzzing from 2 to a less strict 7
2979 - change the default fuzzing from 2 to a less strict 7
2977
2980
2978 hg import --config ui.fuzz=7 fuzz.patch
2981 hg import --config ui.fuzz=7 fuzz.patch
2979
2982
2980 Returns 0 on success, 1 on partial success (see --partial).
2983 Returns 0 on success, 1 on partial success (see --partial).
2981 """
2984 """
2982
2985
2983 opts = pycompat.byteskwargs(opts)
2986 opts = pycompat.byteskwargs(opts)
2984 if not patch1:
2987 if not patch1:
2985 raise error.Abort(_('need at least one patch to import'))
2988 raise error.Abort(_('need at least one patch to import'))
2986
2989
2987 patches = (patch1,) + patches
2990 patches = (patch1,) + patches
2988
2991
2989 date = opts.get('date')
2992 date = opts.get('date')
2990 if date:
2993 if date:
2991 opts['date'] = util.parsedate(date)
2994 opts['date'] = util.parsedate(date)
2992
2995
2993 exact = opts.get('exact')
2996 exact = opts.get('exact')
2994 update = not opts.get('bypass')
2997 update = not opts.get('bypass')
2995 if not update and opts.get('no_commit'):
2998 if not update and opts.get('no_commit'):
2996 raise error.Abort(_('cannot use --no-commit with --bypass'))
2999 raise error.Abort(_('cannot use --no-commit with --bypass'))
2997 try:
3000 try:
2998 sim = float(opts.get('similarity') or 0)
3001 sim = float(opts.get('similarity') or 0)
2999 except ValueError:
3002 except ValueError:
3000 raise error.Abort(_('similarity must be a number'))
3003 raise error.Abort(_('similarity must be a number'))
3001 if sim < 0 or sim > 100:
3004 if sim < 0 or sim > 100:
3002 raise error.Abort(_('similarity must be between 0 and 100'))
3005 raise error.Abort(_('similarity must be between 0 and 100'))
3003 if sim and not update:
3006 if sim and not update:
3004 raise error.Abort(_('cannot use --similarity with --bypass'))
3007 raise error.Abort(_('cannot use --similarity with --bypass'))
3005 if exact:
3008 if exact:
3006 if opts.get('edit'):
3009 if opts.get('edit'):
3007 raise error.Abort(_('cannot use --exact with --edit'))
3010 raise error.Abort(_('cannot use --exact with --edit'))
3008 if opts.get('prefix'):
3011 if opts.get('prefix'):
3009 raise error.Abort(_('cannot use --exact with --prefix'))
3012 raise error.Abort(_('cannot use --exact with --prefix'))
3010
3013
3011 base = opts["base"]
3014 base = opts["base"]
3012 wlock = dsguard = lock = tr = None
3015 wlock = dsguard = lock = tr = None
3013 msgs = []
3016 msgs = []
3014 ret = 0
3017 ret = 0
3015
3018
3016
3019
3017 try:
3020 try:
3018 wlock = repo.wlock()
3021 wlock = repo.wlock()
3019
3022
3020 if update:
3023 if update:
3021 cmdutil.checkunfinished(repo)
3024 cmdutil.checkunfinished(repo)
3022 if (exact or not opts.get('force')):
3025 if (exact or not opts.get('force')):
3023 cmdutil.bailifchanged(repo)
3026 cmdutil.bailifchanged(repo)
3024
3027
3025 if not opts.get('no_commit'):
3028 if not opts.get('no_commit'):
3026 lock = repo.lock()
3029 lock = repo.lock()
3027 tr = repo.transaction('import')
3030 tr = repo.transaction('import')
3028 else:
3031 else:
3029 dsguard = dirstateguard.dirstateguard(repo, 'import')
3032 dsguard = dirstateguard.dirstateguard(repo, 'import')
3030 parents = repo[None].parents()
3033 parents = repo[None].parents()
3031 for patchurl in patches:
3034 for patchurl in patches:
3032 if patchurl == '-':
3035 if patchurl == '-':
3033 ui.status(_('applying patch from stdin\n'))
3036 ui.status(_('applying patch from stdin\n'))
3034 patchfile = ui.fin
3037 patchfile = ui.fin
3035 patchurl = 'stdin' # for error message
3038 patchurl = 'stdin' # for error message
3036 else:
3039 else:
3037 patchurl = os.path.join(base, patchurl)
3040 patchurl = os.path.join(base, patchurl)
3038 ui.status(_('applying %s\n') % patchurl)
3041 ui.status(_('applying %s\n') % patchurl)
3039 patchfile = hg.openpath(ui, patchurl)
3042 patchfile = hg.openpath(ui, patchurl)
3040
3043
3041 haspatch = False
3044 haspatch = False
3042 for hunk in patch.split(patchfile):
3045 for hunk in patch.split(patchfile):
3043 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
3046 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
3044 parents, opts,
3047 parents, opts,
3045 msgs, hg.clean)
3048 msgs, hg.clean)
3046 if msg:
3049 if msg:
3047 haspatch = True
3050 haspatch = True
3048 ui.note(msg + '\n')
3051 ui.note(msg + '\n')
3049 if update or exact:
3052 if update or exact:
3050 parents = repo[None].parents()
3053 parents = repo[None].parents()
3051 else:
3054 else:
3052 parents = [repo[node]]
3055 parents = [repo[node]]
3053 if rej:
3056 if rej:
3054 ui.write_err(_("patch applied partially\n"))
3057 ui.write_err(_("patch applied partially\n"))
3055 ui.write_err(_("(fix the .rej files and run "
3058 ui.write_err(_("(fix the .rej files and run "
3056 "`hg commit --amend`)\n"))
3059 "`hg commit --amend`)\n"))
3057 ret = 1
3060 ret = 1
3058 break
3061 break
3059
3062
3060 if not haspatch:
3063 if not haspatch:
3061 raise error.Abort(_('%s: no diffs found') % patchurl)
3064 raise error.Abort(_('%s: no diffs found') % patchurl)
3062
3065
3063 if tr:
3066 if tr:
3064 tr.close()
3067 tr.close()
3065 if msgs:
3068 if msgs:
3066 repo.savecommitmessage('\n* * *\n'.join(msgs))
3069 repo.savecommitmessage('\n* * *\n'.join(msgs))
3067 if dsguard:
3070 if dsguard:
3068 dsguard.close()
3071 dsguard.close()
3069 return ret
3072 return ret
3070 finally:
3073 finally:
3071 if tr:
3074 if tr:
3072 tr.release()
3075 tr.release()
3073 release(lock, dsguard, wlock)
3076 release(lock, dsguard, wlock)
3074
3077
3075 @command('incoming|in',
3078 @command('incoming|in',
3076 [('f', 'force', None,
3079 [('f', 'force', None,
3077 _('run even if remote repository is unrelated')),
3080 _('run even if remote repository is unrelated')),
3078 ('n', 'newest-first', None, _('show newest record first')),
3081 ('n', 'newest-first', None, _('show newest record first')),
3079 ('', 'bundle', '',
3082 ('', 'bundle', '',
3080 _('file to store the bundles into'), _('FILE')),
3083 _('file to store the bundles into'), _('FILE')),
3081 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3084 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3082 ('B', 'bookmarks', False, _("compare bookmarks")),
3085 ('B', 'bookmarks', False, _("compare bookmarks")),
3083 ('b', 'branch', [],
3086 ('b', 'branch', [],
3084 _('a specific branch you would like to pull'), _('BRANCH')),
3087 _('a specific branch you would like to pull'), _('BRANCH')),
3085 ] + logopts + remoteopts + subrepoopts,
3088 ] + logopts + remoteopts + subrepoopts,
3086 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3089 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3087 def incoming(ui, repo, source="default", **opts):
3090 def incoming(ui, repo, source="default", **opts):
3088 """show new changesets found in source
3091 """show new changesets found in source
3089
3092
3090 Show new changesets found in the specified path/URL or the default
3093 Show new changesets found in the specified path/URL or the default
3091 pull location. These are the changesets that would have been pulled
3094 pull location. These are the changesets that would have been pulled
3092 by :hg:`pull` at the time you issued this command.
3095 by :hg:`pull` at the time you issued this command.
3093
3096
3094 See pull for valid source format details.
3097 See pull for valid source format details.
3095
3098
3096 .. container:: verbose
3099 .. container:: verbose
3097
3100
3098 With -B/--bookmarks, the result of bookmark comparison between
3101 With -B/--bookmarks, the result of bookmark comparison between
3099 local and remote repositories is displayed. With -v/--verbose,
3102 local and remote repositories is displayed. With -v/--verbose,
3100 status is also displayed for each bookmark like below::
3103 status is also displayed for each bookmark like below::
3101
3104
3102 BM1 01234567890a added
3105 BM1 01234567890a added
3103 BM2 1234567890ab advanced
3106 BM2 1234567890ab advanced
3104 BM3 234567890abc diverged
3107 BM3 234567890abc diverged
3105 BM4 34567890abcd changed
3108 BM4 34567890abcd changed
3106
3109
3107 The action taken locally when pulling depends on the
3110 The action taken locally when pulling depends on the
3108 status of each bookmark:
3111 status of each bookmark:
3109
3112
3110 :``added``: pull will create it
3113 :``added``: pull will create it
3111 :``advanced``: pull will update it
3114 :``advanced``: pull will update it
3112 :``diverged``: pull will create a divergent bookmark
3115 :``diverged``: pull will create a divergent bookmark
3113 :``changed``: result depends on remote changesets
3116 :``changed``: result depends on remote changesets
3114
3117
3115 From the point of view of pulling behavior, bookmark
3118 From the point of view of pulling behavior, bookmark
3116 existing only in the remote repository are treated as ``added``,
3119 existing only in the remote repository are treated as ``added``,
3117 even if it is in fact locally deleted.
3120 even if it is in fact locally deleted.
3118
3121
3119 .. container:: verbose
3122 .. container:: verbose
3120
3123
3121 For remote repository, using --bundle avoids downloading the
3124 For remote repository, using --bundle avoids downloading the
3122 changesets twice if the incoming is followed by a pull.
3125 changesets twice if the incoming is followed by a pull.
3123
3126
3124 Examples:
3127 Examples:
3125
3128
3126 - show incoming changes with patches and full description::
3129 - show incoming changes with patches and full description::
3127
3130
3128 hg incoming -vp
3131 hg incoming -vp
3129
3132
3130 - show incoming changes excluding merges, store a bundle::
3133 - show incoming changes excluding merges, store a bundle::
3131
3134
3132 hg in -vpM --bundle incoming.hg
3135 hg in -vpM --bundle incoming.hg
3133 hg pull incoming.hg
3136 hg pull incoming.hg
3134
3137
3135 - briefly list changes inside a bundle::
3138 - briefly list changes inside a bundle::
3136
3139
3137 hg in changes.hg -T "{desc|firstline}\\n"
3140 hg in changes.hg -T "{desc|firstline}\\n"
3138
3141
3139 Returns 0 if there are incoming changes, 1 otherwise.
3142 Returns 0 if there are incoming changes, 1 otherwise.
3140 """
3143 """
3141 opts = pycompat.byteskwargs(opts)
3144 opts = pycompat.byteskwargs(opts)
3142 if opts.get('graph'):
3145 if opts.get('graph'):
3143 cmdutil.checkunsupportedgraphflags([], opts)
3146 cmdutil.checkunsupportedgraphflags([], opts)
3144 def display(other, chlist, displayer):
3147 def display(other, chlist, displayer):
3145 revdag = cmdutil.graphrevs(other, chlist, opts)
3148 revdag = cmdutil.graphrevs(other, chlist, opts)
3146 cmdutil.displaygraph(ui, repo, revdag, displayer,
3149 cmdutil.displaygraph(ui, repo, revdag, displayer,
3147 graphmod.asciiedges)
3150 graphmod.asciiedges)
3148
3151
3149 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3152 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3150 return 0
3153 return 0
3151
3154
3152 if opts.get('bundle') and opts.get('subrepos'):
3155 if opts.get('bundle') and opts.get('subrepos'):
3153 raise error.Abort(_('cannot combine --bundle and --subrepos'))
3156 raise error.Abort(_('cannot combine --bundle and --subrepos'))
3154
3157
3155 if opts.get('bookmarks'):
3158 if opts.get('bookmarks'):
3156 source, branches = hg.parseurl(ui.expandpath(source),
3159 source, branches = hg.parseurl(ui.expandpath(source),
3157 opts.get('branch'))
3160 opts.get('branch'))
3158 other = hg.peer(repo, opts, source)
3161 other = hg.peer(repo, opts, source)
3159 if 'bookmarks' not in other.listkeys('namespaces'):
3162 if 'bookmarks' not in other.listkeys('namespaces'):
3160 ui.warn(_("remote doesn't support bookmarks\n"))
3163 ui.warn(_("remote doesn't support bookmarks\n"))
3161 return 0
3164 return 0
3162 ui.pager('incoming')
3165 ui.pager('incoming')
3163 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3166 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3164 return bookmarks.incoming(ui, repo, other)
3167 return bookmarks.incoming(ui, repo, other)
3165
3168
3166 repo._subtoppath = ui.expandpath(source)
3169 repo._subtoppath = ui.expandpath(source)
3167 try:
3170 try:
3168 return hg.incoming(ui, repo, source, opts)
3171 return hg.incoming(ui, repo, source, opts)
3169 finally:
3172 finally:
3170 del repo._subtoppath
3173 del repo._subtoppath
3171
3174
3172
3175
3173 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
3176 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
3174 norepo=True)
3177 norepo=True)
3175 def init(ui, dest=".", **opts):
3178 def init(ui, dest=".", **opts):
3176 """create a new repository in the given directory
3179 """create a new repository in the given directory
3177
3180
3178 Initialize a new repository in the given directory. If the given
3181 Initialize a new repository in the given directory. If the given
3179 directory does not exist, it will be created.
3182 directory does not exist, it will be created.
3180
3183
3181 If no directory is given, the current directory is used.
3184 If no directory is given, the current directory is used.
3182
3185
3183 It is possible to specify an ``ssh://`` URL as the destination.
3186 It is possible to specify an ``ssh://`` URL as the destination.
3184 See :hg:`help urls` for more information.
3187 See :hg:`help urls` for more information.
3185
3188
3186 Returns 0 on success.
3189 Returns 0 on success.
3187 """
3190 """
3188 opts = pycompat.byteskwargs(opts)
3191 opts = pycompat.byteskwargs(opts)
3189 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3192 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3190
3193
3191 @command('locate',
3194 @command('locate',
3192 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3195 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3193 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3196 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3194 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3197 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3195 ] + walkopts,
3198 ] + walkopts,
3196 _('[OPTION]... [PATTERN]...'))
3199 _('[OPTION]... [PATTERN]...'))
3197 def locate(ui, repo, *pats, **opts):
3200 def locate(ui, repo, *pats, **opts):
3198 """locate files matching specific patterns (DEPRECATED)
3201 """locate files matching specific patterns (DEPRECATED)
3199
3202
3200 Print files under Mercurial control in the working directory whose
3203 Print files under Mercurial control in the working directory whose
3201 names match the given patterns.
3204 names match the given patterns.
3202
3205
3203 By default, this command searches all directories in the working
3206 By default, this command searches all directories in the working
3204 directory. To search just the current directory and its
3207 directory. To search just the current directory and its
3205 subdirectories, use "--include .".
3208 subdirectories, use "--include .".
3206
3209
3207 If no patterns are given to match, this command prints the names
3210 If no patterns are given to match, this command prints the names
3208 of all files under Mercurial control in the working directory.
3211 of all files under Mercurial control in the working directory.
3209
3212
3210 If you want to feed the output of this command into the "xargs"
3213 If you want to feed the output of this command into the "xargs"
3211 command, use the -0 option to both this command and "xargs". This
3214 command, use the -0 option to both this command and "xargs". This
3212 will avoid the problem of "xargs" treating single filenames that
3215 will avoid the problem of "xargs" treating single filenames that
3213 contain whitespace as multiple filenames.
3216 contain whitespace as multiple filenames.
3214
3217
3215 See :hg:`help files` for a more versatile command.
3218 See :hg:`help files` for a more versatile command.
3216
3219
3217 Returns 0 if a match is found, 1 otherwise.
3220 Returns 0 if a match is found, 1 otherwise.
3218 """
3221 """
3219 opts = pycompat.byteskwargs(opts)
3222 opts = pycompat.byteskwargs(opts)
3220 if opts.get('print0'):
3223 if opts.get('print0'):
3221 end = '\0'
3224 end = '\0'
3222 else:
3225 else:
3223 end = '\n'
3226 end = '\n'
3224 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3227 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3225
3228
3226 ret = 1
3229 ret = 1
3227 ctx = repo[rev]
3230 ctx = repo[rev]
3228 m = scmutil.match(ctx, pats, opts, default='relglob',
3231 m = scmutil.match(ctx, pats, opts, default='relglob',
3229 badfn=lambda x, y: False)
3232 badfn=lambda x, y: False)
3230
3233
3231 ui.pager('locate')
3234 ui.pager('locate')
3232 for abs in ctx.matches(m):
3235 for abs in ctx.matches(m):
3233 if opts.get('fullpath'):
3236 if opts.get('fullpath'):
3234 ui.write(repo.wjoin(abs), end)
3237 ui.write(repo.wjoin(abs), end)
3235 else:
3238 else:
3236 ui.write(((pats and m.rel(abs)) or abs), end)
3239 ui.write(((pats and m.rel(abs)) or abs), end)
3237 ret = 0
3240 ret = 0
3238
3241
3239 return ret
3242 return ret
3240
3243
3241 @command('^log|history',
3244 @command('^log|history',
3242 [('f', 'follow', None,
3245 [('f', 'follow', None,
3243 _('follow changeset history, or file history across copies and renames')),
3246 _('follow changeset history, or file history across copies and renames')),
3244 ('', 'follow-first', None,
3247 ('', 'follow-first', None,
3245 _('only follow the first parent of merge changesets (DEPRECATED)')),
3248 _('only follow the first parent of merge changesets (DEPRECATED)')),
3246 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3249 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3247 ('C', 'copies', None, _('show copied files')),
3250 ('C', 'copies', None, _('show copied files')),
3248 ('k', 'keyword', [],
3251 ('k', 'keyword', [],
3249 _('do case-insensitive search for a given text'), _('TEXT')),
3252 _('do case-insensitive search for a given text'), _('TEXT')),
3250 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
3253 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
3251 ('L', 'line-range', [],
3254 ('L', 'line-range', [],
3252 _('follow line range of specified file (EXPERIMENTAL)'),
3255 _('follow line range of specified file (EXPERIMENTAL)'),
3253 _('FILE,RANGE')),
3256 _('FILE,RANGE')),
3254 ('', 'removed', None, _('include revisions where files were removed')),
3257 ('', 'removed', None, _('include revisions where files were removed')),
3255 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3258 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3256 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3259 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3257 ('', 'only-branch', [],
3260 ('', 'only-branch', [],
3258 _('show only changesets within the given named branch (DEPRECATED)'),
3261 _('show only changesets within the given named branch (DEPRECATED)'),
3259 _('BRANCH')),
3262 _('BRANCH')),
3260 ('b', 'branch', [],
3263 ('b', 'branch', [],
3261 _('show changesets within the given named branch'), _('BRANCH')),
3264 _('show changesets within the given named branch'), _('BRANCH')),
3262 ('P', 'prune', [],
3265 ('P', 'prune', [],
3263 _('do not display revision or any of its ancestors'), _('REV')),
3266 _('do not display revision or any of its ancestors'), _('REV')),
3264 ] + logopts + walkopts,
3267 ] + logopts + walkopts,
3265 _('[OPTION]... [FILE]'),
3268 _('[OPTION]... [FILE]'),
3266 inferrepo=True, cmdtype=readonly)
3269 inferrepo=True, cmdtype=readonly)
3267 def log(ui, repo, *pats, **opts):
3270 def log(ui, repo, *pats, **opts):
3268 """show revision history of entire repository or files
3271 """show revision history of entire repository or files
3269
3272
3270 Print the revision history of the specified files or the entire
3273 Print the revision history of the specified files or the entire
3271 project.
3274 project.
3272
3275
3273 If no revision range is specified, the default is ``tip:0`` unless
3276 If no revision range is specified, the default is ``tip:0`` unless
3274 --follow is set, in which case the working directory parent is
3277 --follow is set, in which case the working directory parent is
3275 used as the starting revision.
3278 used as the starting revision.
3276
3279
3277 File history is shown without following rename or copy history of
3280 File history is shown without following rename or copy history of
3278 files. Use -f/--follow with a filename to follow history across
3281 files. Use -f/--follow with a filename to follow history across
3279 renames and copies. --follow without a filename will only show
3282 renames and copies. --follow without a filename will only show
3280 ancestors or descendants of the starting revision.
3283 ancestors or descendants of the starting revision.
3281
3284
3282 By default this command prints revision number and changeset id,
3285 By default this command prints revision number and changeset id,
3283 tags, non-trivial parents, user, date and time, and a summary for
3286 tags, non-trivial parents, user, date and time, and a summary for
3284 each commit. When the -v/--verbose switch is used, the list of
3287 each commit. When the -v/--verbose switch is used, the list of
3285 changed files and full commit message are shown.
3288 changed files and full commit message are shown.
3286
3289
3287 With --graph the revisions are shown as an ASCII art DAG with the most
3290 With --graph the revisions are shown as an ASCII art DAG with the most
3288 recent changeset at the top.
3291 recent changeset at the top.
3289 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
3292 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
3290 and '+' represents a fork where the changeset from the lines below is a
3293 and '+' represents a fork where the changeset from the lines below is a
3291 parent of the 'o' merge on the same line.
3294 parent of the 'o' merge on the same line.
3292 Paths in the DAG are represented with '|', '/' and so forth. ':' in place
3295 Paths in the DAG are represented with '|', '/' and so forth. ':' in place
3293 of a '|' indicates one or more revisions in a path are omitted.
3296 of a '|' indicates one or more revisions in a path are omitted.
3294
3297
3295 .. container:: verbose
3298 .. container:: verbose
3296
3299
3297 Use -L/--line-range FILE,M:N options to follow the history of lines
3300 Use -L/--line-range FILE,M:N options to follow the history of lines
3298 from M to N in FILE. With -p/--patch only diff hunks affecting
3301 from M to N in FILE. With -p/--patch only diff hunks affecting
3299 specified line range will be shown. This option requires --follow;
3302 specified line range will be shown. This option requires --follow;
3300 it can be specified multiple times. Currently, this option is not
3303 it can be specified multiple times. Currently, this option is not
3301 compatible with --graph. This option is experimental.
3304 compatible with --graph. This option is experimental.
3302
3305
3303 .. note::
3306 .. note::
3304
3307
3305 :hg:`log --patch` may generate unexpected diff output for merge
3308 :hg:`log --patch` may generate unexpected diff output for merge
3306 changesets, as it will only compare the merge changeset against
3309 changesets, as it will only compare the merge changeset against
3307 its first parent. Also, only files different from BOTH parents
3310 its first parent. Also, only files different from BOTH parents
3308 will appear in files:.
3311 will appear in files:.
3309
3312
3310 .. note::
3313 .. note::
3311
3314
3312 For performance reasons, :hg:`log FILE` may omit duplicate changes
3315 For performance reasons, :hg:`log FILE` may omit duplicate changes
3313 made on branches and will not show removals or mode changes. To
3316 made on branches and will not show removals or mode changes. To
3314 see all such changes, use the --removed switch.
3317 see all such changes, use the --removed switch.
3315
3318
3316 .. container:: verbose
3319 .. container:: verbose
3317
3320
3318 .. note::
3321 .. note::
3319
3322
3320 The history resulting from -L/--line-range options depends on diff
3323 The history resulting from -L/--line-range options depends on diff
3321 options; for instance if white-spaces are ignored, respective changes
3324 options; for instance if white-spaces are ignored, respective changes
3322 with only white-spaces in specified line range will not be listed.
3325 with only white-spaces in specified line range will not be listed.
3323
3326
3324 .. container:: verbose
3327 .. container:: verbose
3325
3328
3326 Some examples:
3329 Some examples:
3327
3330
3328 - changesets with full descriptions and file lists::
3331 - changesets with full descriptions and file lists::
3329
3332
3330 hg log -v
3333 hg log -v
3331
3334
3332 - changesets ancestral to the working directory::
3335 - changesets ancestral to the working directory::
3333
3336
3334 hg log -f
3337 hg log -f
3335
3338
3336 - last 10 commits on the current branch::
3339 - last 10 commits on the current branch::
3337
3340
3338 hg log -l 10 -b .
3341 hg log -l 10 -b .
3339
3342
3340 - changesets showing all modifications of a file, including removals::
3343 - changesets showing all modifications of a file, including removals::
3341
3344
3342 hg log --removed file.c
3345 hg log --removed file.c
3343
3346
3344 - all changesets that touch a directory, with diffs, excluding merges::
3347 - all changesets that touch a directory, with diffs, excluding merges::
3345
3348
3346 hg log -Mp lib/
3349 hg log -Mp lib/
3347
3350
3348 - all revision numbers that match a keyword::
3351 - all revision numbers that match a keyword::
3349
3352
3350 hg log -k bug --template "{rev}\\n"
3353 hg log -k bug --template "{rev}\\n"
3351
3354
3352 - the full hash identifier of the working directory parent::
3355 - the full hash identifier of the working directory parent::
3353
3356
3354 hg log -r . --template "{node}\\n"
3357 hg log -r . --template "{node}\\n"
3355
3358
3356 - list available log templates::
3359 - list available log templates::
3357
3360
3358 hg log -T list
3361 hg log -T list
3359
3362
3360 - check if a given changeset is included in a tagged release::
3363 - check if a given changeset is included in a tagged release::
3361
3364
3362 hg log -r "a21ccf and ancestor(1.9)"
3365 hg log -r "a21ccf and ancestor(1.9)"
3363
3366
3364 - find all changesets by some user in a date range::
3367 - find all changesets by some user in a date range::
3365
3368
3366 hg log -k alice -d "may 2008 to jul 2008"
3369 hg log -k alice -d "may 2008 to jul 2008"
3367
3370
3368 - summary of all changesets after the last tag::
3371 - summary of all changesets after the last tag::
3369
3372
3370 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3373 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3371
3374
3372 - changesets touching lines 13 to 23 for file.c::
3375 - changesets touching lines 13 to 23 for file.c::
3373
3376
3374 hg log -L file.c,13:23
3377 hg log -L file.c,13:23
3375
3378
3376 - changesets touching lines 13 to 23 for file.c and lines 2 to 6 of
3379 - changesets touching lines 13 to 23 for file.c and lines 2 to 6 of
3377 main.c with patch::
3380 main.c with patch::
3378
3381
3379 hg log -L file.c,13:23 -L main.c,2:6 -p
3382 hg log -L file.c,13:23 -L main.c,2:6 -p
3380
3383
3381 See :hg:`help dates` for a list of formats valid for -d/--date.
3384 See :hg:`help dates` for a list of formats valid for -d/--date.
3382
3385
3383 See :hg:`help revisions` for more about specifying and ordering
3386 See :hg:`help revisions` for more about specifying and ordering
3384 revisions.
3387 revisions.
3385
3388
3386 See :hg:`help templates` for more about pre-packaged styles and
3389 See :hg:`help templates` for more about pre-packaged styles and
3387 specifying custom templates. The default template used by the log
3390 specifying custom templates. The default template used by the log
3388 command can be customized via the ``ui.logtemplate`` configuration
3391 command can be customized via the ``ui.logtemplate`` configuration
3389 setting.
3392 setting.
3390
3393
3391 Returns 0 on success.
3394 Returns 0 on success.
3392
3395
3393 """
3396 """
3394 opts = pycompat.byteskwargs(opts)
3397 opts = pycompat.byteskwargs(opts)
3395 linerange = opts.get('line_range')
3398 linerange = opts.get('line_range')
3396
3399
3397 if linerange and not opts.get('follow'):
3400 if linerange and not opts.get('follow'):
3398 raise error.Abort(_('--line-range requires --follow'))
3401 raise error.Abort(_('--line-range requires --follow'))
3399
3402
3400 if linerange and pats:
3403 if linerange and pats:
3401 raise error.Abort(
3404 raise error.Abort(
3402 _('FILE arguments are not compatible with --line-range option')
3405 _('FILE arguments are not compatible with --line-range option')
3403 )
3406 )
3404
3407
3405 if opts.get('follow') and opts.get('rev'):
3408 if opts.get('follow') and opts.get('rev'):
3406 opts['rev'] = [revsetlang.formatspec('reverse(::%lr)', opts.get('rev'))]
3409 opts['rev'] = [revsetlang.formatspec('reverse(::%lr)', opts.get('rev'))]
3407 del opts['follow']
3410 del opts['follow']
3408
3411
3409 if opts.get('graph'):
3412 if opts.get('graph'):
3410 if linerange:
3413 if linerange:
3411 raise error.Abort(_('graph not supported with line range patterns'))
3414 raise error.Abort(_('graph not supported with line range patterns'))
3412 return cmdutil.graphlog(ui, repo, pats, opts)
3415 return cmdutil.graphlog(ui, repo, pats, opts)
3413
3416
3414 repo = scmutil.unhidehashlikerevs(repo, opts.get('rev'), 'nowarn')
3417 repo = scmutil.unhidehashlikerevs(repo, opts.get('rev'), 'nowarn')
3415 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
3418 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
3416 hunksfilter = None
3419 hunksfilter = None
3417
3420
3418 if linerange:
3421 if linerange:
3419 revs, lrfilematcher, hunksfilter = cmdutil.getloglinerangerevs(
3422 revs, lrfilematcher, hunksfilter = cmdutil.getloglinerangerevs(
3420 repo, revs, opts)
3423 repo, revs, opts)
3421
3424
3422 if filematcher is not None and lrfilematcher is not None:
3425 if filematcher is not None and lrfilematcher is not None:
3423 basefilematcher = filematcher
3426 basefilematcher = filematcher
3424
3427
3425 def filematcher(rev):
3428 def filematcher(rev):
3426 files = (basefilematcher(rev).files()
3429 files = (basefilematcher(rev).files()
3427 + lrfilematcher(rev).files())
3430 + lrfilematcher(rev).files())
3428 return scmutil.matchfiles(repo, files)
3431 return scmutil.matchfiles(repo, files)
3429
3432
3430 elif filematcher is None:
3433 elif filematcher is None:
3431 filematcher = lrfilematcher
3434 filematcher = lrfilematcher
3432
3435
3433 limit = cmdutil.loglimit(opts)
3436 limit = cmdutil.loglimit(opts)
3434 count = 0
3437 count = 0
3435
3438
3436 getrenamed = None
3439 getrenamed = None
3437 if opts.get('copies'):
3440 if opts.get('copies'):
3438 endrev = None
3441 endrev = None
3439 if opts.get('rev'):
3442 if opts.get('rev'):
3440 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
3443 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
3441 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3444 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3442
3445
3443 ui.pager('log')
3446 ui.pager('log')
3444 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
3447 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
3445 for rev in revs:
3448 for rev in revs:
3446 if count == limit:
3449 if count == limit:
3447 break
3450 break
3448 ctx = repo[rev]
3451 ctx = repo[rev]
3449 copies = None
3452 copies = None
3450 if getrenamed is not None and rev:
3453 if getrenamed is not None and rev:
3451 copies = []
3454 copies = []
3452 for fn in ctx.files():
3455 for fn in ctx.files():
3453 rename = getrenamed(fn, rev)
3456 rename = getrenamed(fn, rev)
3454 if rename:
3457 if rename:
3455 copies.append((fn, rename[0]))
3458 copies.append((fn, rename[0]))
3456 if filematcher:
3459 if filematcher:
3457 revmatchfn = filematcher(ctx.rev())
3460 revmatchfn = filematcher(ctx.rev())
3458 else:
3461 else:
3459 revmatchfn = None
3462 revmatchfn = None
3460 if hunksfilter:
3463 if hunksfilter:
3461 revhunksfilter = hunksfilter(rev)
3464 revhunksfilter = hunksfilter(rev)
3462 else:
3465 else:
3463 revhunksfilter = None
3466 revhunksfilter = None
3464 displayer.show(ctx, copies=copies, matchfn=revmatchfn,
3467 displayer.show(ctx, copies=copies, matchfn=revmatchfn,
3465 hunksfilterfn=revhunksfilter)
3468 hunksfilterfn=revhunksfilter)
3466 if displayer.flush(ctx):
3469 if displayer.flush(ctx):
3467 count += 1
3470 count += 1
3468
3471
3469 displayer.close()
3472 displayer.close()
3470
3473
3471 @command('manifest',
3474 @command('manifest',
3472 [('r', 'rev', '', _('revision to display'), _('REV')),
3475 [('r', 'rev', '', _('revision to display'), _('REV')),
3473 ('', 'all', False, _("list files from all revisions"))]
3476 ('', 'all', False, _("list files from all revisions"))]
3474 + formatteropts,
3477 + formatteropts,
3475 _('[-r REV]'), cmdtype=readonly)
3478 _('[-r REV]'), cmdtype=readonly)
3476 def manifest(ui, repo, node=None, rev=None, **opts):
3479 def manifest(ui, repo, node=None, rev=None, **opts):
3477 """output the current or given revision of the project manifest
3480 """output the current or given revision of the project manifest
3478
3481
3479 Print a list of version controlled files for the given revision.
3482 Print a list of version controlled files for the given revision.
3480 If no revision is given, the first parent of the working directory
3483 If no revision is given, the first parent of the working directory
3481 is used, or the null revision if no revision is checked out.
3484 is used, or the null revision if no revision is checked out.
3482
3485
3483 With -v, print file permissions, symlink and executable bits.
3486 With -v, print file permissions, symlink and executable bits.
3484 With --debug, print file revision hashes.
3487 With --debug, print file revision hashes.
3485
3488
3486 If option --all is specified, the list of all files from all revisions
3489 If option --all is specified, the list of all files from all revisions
3487 is printed. This includes deleted and renamed files.
3490 is printed. This includes deleted and renamed files.
3488
3491
3489 Returns 0 on success.
3492 Returns 0 on success.
3490 """
3493 """
3491 opts = pycompat.byteskwargs(opts)
3494 opts = pycompat.byteskwargs(opts)
3492 fm = ui.formatter('manifest', opts)
3495 fm = ui.formatter('manifest', opts)
3493
3496
3494 if opts.get('all'):
3497 if opts.get('all'):
3495 if rev or node:
3498 if rev or node:
3496 raise error.Abort(_("can't specify a revision with --all"))
3499 raise error.Abort(_("can't specify a revision with --all"))
3497
3500
3498 res = []
3501 res = []
3499 prefix = "data/"
3502 prefix = "data/"
3500 suffix = ".i"
3503 suffix = ".i"
3501 plen = len(prefix)
3504 plen = len(prefix)
3502 slen = len(suffix)
3505 slen = len(suffix)
3503 with repo.lock():
3506 with repo.lock():
3504 for fn, b, size in repo.store.datafiles():
3507 for fn, b, size in repo.store.datafiles():
3505 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
3508 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
3506 res.append(fn[plen:-slen])
3509 res.append(fn[plen:-slen])
3507 ui.pager('manifest')
3510 ui.pager('manifest')
3508 for f in res:
3511 for f in res:
3509 fm.startitem()
3512 fm.startitem()
3510 fm.write("path", '%s\n', f)
3513 fm.write("path", '%s\n', f)
3511 fm.end()
3514 fm.end()
3512 return
3515 return
3513
3516
3514 if rev and node:
3517 if rev and node:
3515 raise error.Abort(_("please specify just one revision"))
3518 raise error.Abort(_("please specify just one revision"))
3516
3519
3517 if not node:
3520 if not node:
3518 node = rev
3521 node = rev
3519
3522
3520 char = {'l': '@', 'x': '*', '': ''}
3523 char = {'l': '@', 'x': '*', '': ''}
3521 mode = {'l': '644', 'x': '755', '': '644'}
3524 mode = {'l': '644', 'x': '755', '': '644'}
3522 if node:
3525 if node:
3523 repo = scmutil.unhidehashlikerevs(repo, [node], 'nowarn')
3526 repo = scmutil.unhidehashlikerevs(repo, [node], 'nowarn')
3524 ctx = scmutil.revsingle(repo, node)
3527 ctx = scmutil.revsingle(repo, node)
3525 mf = ctx.manifest()
3528 mf = ctx.manifest()
3526 ui.pager('manifest')
3529 ui.pager('manifest')
3527 for f in ctx:
3530 for f in ctx:
3528 fm.startitem()
3531 fm.startitem()
3529 fl = ctx[f].flags()
3532 fl = ctx[f].flags()
3530 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
3533 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
3531 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
3534 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
3532 fm.write('path', '%s\n', f)
3535 fm.write('path', '%s\n', f)
3533 fm.end()
3536 fm.end()
3534
3537
3535 @command('^merge',
3538 @command('^merge',
3536 [('f', 'force', None,
3539 [('f', 'force', None,
3537 _('force a merge including outstanding changes (DEPRECATED)')),
3540 _('force a merge including outstanding changes (DEPRECATED)')),
3538 ('r', 'rev', '', _('revision to merge'), _('REV')),
3541 ('r', 'rev', '', _('revision to merge'), _('REV')),
3539 ('P', 'preview', None,
3542 ('P', 'preview', None,
3540 _('review revisions to merge (no merge is performed)'))
3543 _('review revisions to merge (no merge is performed)'))
3541 ] + mergetoolopts,
3544 ] + mergetoolopts,
3542 _('[-P] [[-r] REV]'))
3545 _('[-P] [[-r] REV]'))
3543 def merge(ui, repo, node=None, **opts):
3546 def merge(ui, repo, node=None, **opts):
3544 """merge another revision into working directory
3547 """merge another revision into working directory
3545
3548
3546 The current working directory is updated with all changes made in
3549 The current working directory is updated with all changes made in
3547 the requested revision since the last common predecessor revision.
3550 the requested revision since the last common predecessor revision.
3548
3551
3549 Files that changed between either parent are marked as changed for
3552 Files that changed between either parent are marked as changed for
3550 the next commit and a commit must be performed before any further
3553 the next commit and a commit must be performed before any further
3551 updates to the repository are allowed. The next commit will have
3554 updates to the repository are allowed. The next commit will have
3552 two parents.
3555 two parents.
3553
3556
3554 ``--tool`` can be used to specify the merge tool used for file
3557 ``--tool`` can be used to specify the merge tool used for file
3555 merges. It overrides the HGMERGE environment variable and your
3558 merges. It overrides the HGMERGE environment variable and your
3556 configuration files. See :hg:`help merge-tools` for options.
3559 configuration files. See :hg:`help merge-tools` for options.
3557
3560
3558 If no revision is specified, the working directory's parent is a
3561 If no revision is specified, the working directory's parent is a
3559 head revision, and the current branch contains exactly one other
3562 head revision, and the current branch contains exactly one other
3560 head, the other head is merged with by default. Otherwise, an
3563 head, the other head is merged with by default. Otherwise, an
3561 explicit revision with which to merge with must be provided.
3564 explicit revision with which to merge with must be provided.
3562
3565
3563 See :hg:`help resolve` for information on handling file conflicts.
3566 See :hg:`help resolve` for information on handling file conflicts.
3564
3567
3565 To undo an uncommitted merge, use :hg:`update --clean .` which
3568 To undo an uncommitted merge, use :hg:`update --clean .` which
3566 will check out a clean copy of the original merge parent, losing
3569 will check out a clean copy of the original merge parent, losing
3567 all changes.
3570 all changes.
3568
3571
3569 Returns 0 on success, 1 if there are unresolved files.
3572 Returns 0 on success, 1 if there are unresolved files.
3570 """
3573 """
3571
3574
3572 opts = pycompat.byteskwargs(opts)
3575 opts = pycompat.byteskwargs(opts)
3573 if opts.get('rev') and node:
3576 if opts.get('rev') and node:
3574 raise error.Abort(_("please specify just one revision"))
3577 raise error.Abort(_("please specify just one revision"))
3575 if not node:
3578 if not node:
3576 node = opts.get('rev')
3579 node = opts.get('rev')
3577
3580
3578 if node:
3581 if node:
3579 node = scmutil.revsingle(repo, node).node()
3582 node = scmutil.revsingle(repo, node).node()
3580
3583
3581 if not node:
3584 if not node:
3582 node = repo[destutil.destmerge(repo)].node()
3585 node = repo[destutil.destmerge(repo)].node()
3583
3586
3584 if opts.get('preview'):
3587 if opts.get('preview'):
3585 # find nodes that are ancestors of p2 but not of p1
3588 # find nodes that are ancestors of p2 but not of p1
3586 p1 = repo.lookup('.')
3589 p1 = repo.lookup('.')
3587 p2 = repo.lookup(node)
3590 p2 = repo.lookup(node)
3588 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
3591 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
3589
3592
3590 displayer = cmdutil.show_changeset(ui, repo, opts)
3593 displayer = cmdutil.show_changeset(ui, repo, opts)
3591 for node in nodes:
3594 for node in nodes:
3592 displayer.show(repo[node])
3595 displayer.show(repo[node])
3593 displayer.close()
3596 displayer.close()
3594 return 0
3597 return 0
3595
3598
3596 try:
3599 try:
3597 # ui.forcemerge is an internal variable, do not document
3600 # ui.forcemerge is an internal variable, do not document
3598 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
3601 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
3599 force = opts.get('force')
3602 force = opts.get('force')
3600 labels = ['working copy', 'merge rev']
3603 labels = ['working copy', 'merge rev']
3601 return hg.merge(repo, node, force=force, mergeforce=force,
3604 return hg.merge(repo, node, force=force, mergeforce=force,
3602 labels=labels)
3605 labels=labels)
3603 finally:
3606 finally:
3604 ui.setconfig('ui', 'forcemerge', '', 'merge')
3607 ui.setconfig('ui', 'forcemerge', '', 'merge')
3605
3608
3606 @command('outgoing|out',
3609 @command('outgoing|out',
3607 [('f', 'force', None, _('run even when the destination is unrelated')),
3610 [('f', 'force', None, _('run even when the destination is unrelated')),
3608 ('r', 'rev', [],
3611 ('r', 'rev', [],
3609 _('a changeset intended to be included in the destination'), _('REV')),
3612 _('a changeset intended to be included in the destination'), _('REV')),
3610 ('n', 'newest-first', None, _('show newest record first')),
3613 ('n', 'newest-first', None, _('show newest record first')),
3611 ('B', 'bookmarks', False, _('compare bookmarks')),
3614 ('B', 'bookmarks', False, _('compare bookmarks')),
3612 ('b', 'branch', [], _('a specific branch you would like to push'),
3615 ('b', 'branch', [], _('a specific branch you would like to push'),
3613 _('BRANCH')),
3616 _('BRANCH')),
3614 ] + logopts + remoteopts + subrepoopts,
3617 ] + logopts + remoteopts + subrepoopts,
3615 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
3618 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
3616 def outgoing(ui, repo, dest=None, **opts):
3619 def outgoing(ui, repo, dest=None, **opts):
3617 """show changesets not found in the destination
3620 """show changesets not found in the destination
3618
3621
3619 Show changesets not found in the specified destination repository
3622 Show changesets not found in the specified destination repository
3620 or the default push location. These are the changesets that would
3623 or the default push location. These are the changesets that would
3621 be pushed if a push was requested.
3624 be pushed if a push was requested.
3622
3625
3623 See pull for details of valid destination formats.
3626 See pull for details of valid destination formats.
3624
3627
3625 .. container:: verbose
3628 .. container:: verbose
3626
3629
3627 With -B/--bookmarks, the result of bookmark comparison between
3630 With -B/--bookmarks, the result of bookmark comparison between
3628 local and remote repositories is displayed. With -v/--verbose,
3631 local and remote repositories is displayed. With -v/--verbose,
3629 status is also displayed for each bookmark like below::
3632 status is also displayed for each bookmark like below::
3630
3633
3631 BM1 01234567890a added
3634 BM1 01234567890a added
3632 BM2 deleted
3635 BM2 deleted
3633 BM3 234567890abc advanced
3636 BM3 234567890abc advanced
3634 BM4 34567890abcd diverged
3637 BM4 34567890abcd diverged
3635 BM5 4567890abcde changed
3638 BM5 4567890abcde changed
3636
3639
3637 The action taken when pushing depends on the
3640 The action taken when pushing depends on the
3638 status of each bookmark:
3641 status of each bookmark:
3639
3642
3640 :``added``: push with ``-B`` will create it
3643 :``added``: push with ``-B`` will create it
3641 :``deleted``: push with ``-B`` will delete it
3644 :``deleted``: push with ``-B`` will delete it
3642 :``advanced``: push will update it
3645 :``advanced``: push will update it
3643 :``diverged``: push with ``-B`` will update it
3646 :``diverged``: push with ``-B`` will update it
3644 :``changed``: push with ``-B`` will update it
3647 :``changed``: push with ``-B`` will update it
3645
3648
3646 From the point of view of pushing behavior, bookmarks
3649 From the point of view of pushing behavior, bookmarks
3647 existing only in the remote repository are treated as
3650 existing only in the remote repository are treated as
3648 ``deleted``, even if it is in fact added remotely.
3651 ``deleted``, even if it is in fact added remotely.
3649
3652
3650 Returns 0 if there are outgoing changes, 1 otherwise.
3653 Returns 0 if there are outgoing changes, 1 otherwise.
3651 """
3654 """
3652 opts = pycompat.byteskwargs(opts)
3655 opts = pycompat.byteskwargs(opts)
3653 if opts.get('graph'):
3656 if opts.get('graph'):
3654 cmdutil.checkunsupportedgraphflags([], opts)
3657 cmdutil.checkunsupportedgraphflags([], opts)
3655 o, other = hg._outgoing(ui, repo, dest, opts)
3658 o, other = hg._outgoing(ui, repo, dest, opts)
3656 if not o:
3659 if not o:
3657 cmdutil.outgoinghooks(ui, repo, other, opts, o)
3660 cmdutil.outgoinghooks(ui, repo, other, opts, o)
3658 return
3661 return
3659
3662
3660 revdag = cmdutil.graphrevs(repo, o, opts)
3663 revdag = cmdutil.graphrevs(repo, o, opts)
3661 ui.pager('outgoing')
3664 ui.pager('outgoing')
3662 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
3665 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
3663 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
3666 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
3664 cmdutil.outgoinghooks(ui, repo, other, opts, o)
3667 cmdutil.outgoinghooks(ui, repo, other, opts, o)
3665 return 0
3668 return 0
3666
3669
3667 if opts.get('bookmarks'):
3670 if opts.get('bookmarks'):
3668 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3671 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3669 dest, branches = hg.parseurl(dest, opts.get('branch'))
3672 dest, branches = hg.parseurl(dest, opts.get('branch'))
3670 other = hg.peer(repo, opts, dest)
3673 other = hg.peer(repo, opts, dest)
3671 if 'bookmarks' not in other.listkeys('namespaces'):
3674 if 'bookmarks' not in other.listkeys('namespaces'):
3672 ui.warn(_("remote doesn't support bookmarks\n"))
3675 ui.warn(_("remote doesn't support bookmarks\n"))
3673 return 0
3676 return 0
3674 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
3677 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
3675 ui.pager('outgoing')
3678 ui.pager('outgoing')
3676 return bookmarks.outgoing(ui, repo, other)
3679 return bookmarks.outgoing(ui, repo, other)
3677
3680
3678 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
3681 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
3679 try:
3682 try:
3680 return hg.outgoing(ui, repo, dest, opts)
3683 return hg.outgoing(ui, repo, dest, opts)
3681 finally:
3684 finally:
3682 del repo._subtoppath
3685 del repo._subtoppath
3683
3686
3684 @command('parents',
3687 @command('parents',
3685 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
3688 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
3686 ] + templateopts,
3689 ] + templateopts,
3687 _('[-r REV] [FILE]'),
3690 _('[-r REV] [FILE]'),
3688 inferrepo=True)
3691 inferrepo=True)
3689 def parents(ui, repo, file_=None, **opts):
3692 def parents(ui, repo, file_=None, **opts):
3690 """show the parents of the working directory or revision (DEPRECATED)
3693 """show the parents of the working directory or revision (DEPRECATED)
3691
3694
3692 Print the working directory's parent revisions. If a revision is
3695 Print the working directory's parent revisions. If a revision is
3693 given via -r/--rev, the parent of that revision will be printed.
3696 given via -r/--rev, the parent of that revision will be printed.
3694 If a file argument is given, the revision in which the file was
3697 If a file argument is given, the revision in which the file was
3695 last changed (before the working directory revision or the
3698 last changed (before the working directory revision or the
3696 argument to --rev if given) is printed.
3699 argument to --rev if given) is printed.
3697
3700
3698 This command is equivalent to::
3701 This command is equivalent to::
3699
3702
3700 hg log -r "p1()+p2()" or
3703 hg log -r "p1()+p2()" or
3701 hg log -r "p1(REV)+p2(REV)" or
3704 hg log -r "p1(REV)+p2(REV)" or
3702 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
3705 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
3703 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
3706 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
3704
3707
3705 See :hg:`summary` and :hg:`help revsets` for related information.
3708 See :hg:`summary` and :hg:`help revsets` for related information.
3706
3709
3707 Returns 0 on success.
3710 Returns 0 on success.
3708 """
3711 """
3709
3712
3710 opts = pycompat.byteskwargs(opts)
3713 opts = pycompat.byteskwargs(opts)
3711 rev = opts.get('rev')
3714 rev = opts.get('rev')
3712 if rev:
3715 if rev:
3713 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
3716 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
3714 ctx = scmutil.revsingle(repo, rev, None)
3717 ctx = scmutil.revsingle(repo, rev, None)
3715
3718
3716 if file_:
3719 if file_:
3717 m = scmutil.match(ctx, (file_,), opts)
3720 m = scmutil.match(ctx, (file_,), opts)
3718 if m.anypats() or len(m.files()) != 1:
3721 if m.anypats() or len(m.files()) != 1:
3719 raise error.Abort(_('can only specify an explicit filename'))
3722 raise error.Abort(_('can only specify an explicit filename'))
3720 file_ = m.files()[0]
3723 file_ = m.files()[0]
3721 filenodes = []
3724 filenodes = []
3722 for cp in ctx.parents():
3725 for cp in ctx.parents():
3723 if not cp:
3726 if not cp:
3724 continue
3727 continue
3725 try:
3728 try:
3726 filenodes.append(cp.filenode(file_))
3729 filenodes.append(cp.filenode(file_))
3727 except error.LookupError:
3730 except error.LookupError:
3728 pass
3731 pass
3729 if not filenodes:
3732 if not filenodes:
3730 raise error.Abort(_("'%s' not found in manifest!") % file_)
3733 raise error.Abort(_("'%s' not found in manifest!") % file_)
3731 p = []
3734 p = []
3732 for fn in filenodes:
3735 for fn in filenodes:
3733 fctx = repo.filectx(file_, fileid=fn)
3736 fctx = repo.filectx(file_, fileid=fn)
3734 p.append(fctx.node())
3737 p.append(fctx.node())
3735 else:
3738 else:
3736 p = [cp.node() for cp in ctx.parents()]
3739 p = [cp.node() for cp in ctx.parents()]
3737
3740
3738 displayer = cmdutil.show_changeset(ui, repo, opts)
3741 displayer = cmdutil.show_changeset(ui, repo, opts)
3739 for n in p:
3742 for n in p:
3740 if n != nullid:
3743 if n != nullid:
3741 displayer.show(repo[n])
3744 displayer.show(repo[n])
3742 displayer.close()
3745 displayer.close()
3743
3746
3744 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True,
3747 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True,
3745 cmdtype=readonly)
3748 cmdtype=readonly)
3746 def paths(ui, repo, search=None, **opts):
3749 def paths(ui, repo, search=None, **opts):
3747 """show aliases for remote repositories
3750 """show aliases for remote repositories
3748
3751
3749 Show definition of symbolic path name NAME. If no name is given,
3752 Show definition of symbolic path name NAME. If no name is given,
3750 show definition of all available names.
3753 show definition of all available names.
3751
3754
3752 Option -q/--quiet suppresses all output when searching for NAME
3755 Option -q/--quiet suppresses all output when searching for NAME
3753 and shows only the path names when listing all definitions.
3756 and shows only the path names when listing all definitions.
3754
3757
3755 Path names are defined in the [paths] section of your
3758 Path names are defined in the [paths] section of your
3756 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
3759 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
3757 repository, ``.hg/hgrc`` is used, too.
3760 repository, ``.hg/hgrc`` is used, too.
3758
3761
3759 The path names ``default`` and ``default-push`` have a special
3762 The path names ``default`` and ``default-push`` have a special
3760 meaning. When performing a push or pull operation, they are used
3763 meaning. When performing a push or pull operation, they are used
3761 as fallbacks if no location is specified on the command-line.
3764 as fallbacks if no location is specified on the command-line.
3762 When ``default-push`` is set, it will be used for push and
3765 When ``default-push`` is set, it will be used for push and
3763 ``default`` will be used for pull; otherwise ``default`` is used
3766 ``default`` will be used for pull; otherwise ``default`` is used
3764 as the fallback for both. When cloning a repository, the clone
3767 as the fallback for both. When cloning a repository, the clone
3765 source is written as ``default`` in ``.hg/hgrc``.
3768 source is written as ``default`` in ``.hg/hgrc``.
3766
3769
3767 .. note::
3770 .. note::
3768
3771
3769 ``default`` and ``default-push`` apply to all inbound (e.g.
3772 ``default`` and ``default-push`` apply to all inbound (e.g.
3770 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
3773 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
3771 and :hg:`bundle`) operations.
3774 and :hg:`bundle`) operations.
3772
3775
3773 See :hg:`help urls` for more information.
3776 See :hg:`help urls` for more information.
3774
3777
3775 Returns 0 on success.
3778 Returns 0 on success.
3776 """
3779 """
3777
3780
3778 opts = pycompat.byteskwargs(opts)
3781 opts = pycompat.byteskwargs(opts)
3779 ui.pager('paths')
3782 ui.pager('paths')
3780 if search:
3783 if search:
3781 pathitems = [(name, path) for name, path in ui.paths.iteritems()
3784 pathitems = [(name, path) for name, path in ui.paths.iteritems()
3782 if name == search]
3785 if name == search]
3783 else:
3786 else:
3784 pathitems = sorted(ui.paths.iteritems())
3787 pathitems = sorted(ui.paths.iteritems())
3785
3788
3786 fm = ui.formatter('paths', opts)
3789 fm = ui.formatter('paths', opts)
3787 if fm.isplain():
3790 if fm.isplain():
3788 hidepassword = util.hidepassword
3791 hidepassword = util.hidepassword
3789 else:
3792 else:
3790 hidepassword = str
3793 hidepassword = str
3791 if ui.quiet:
3794 if ui.quiet:
3792 namefmt = '%s\n'
3795 namefmt = '%s\n'
3793 else:
3796 else:
3794 namefmt = '%s = '
3797 namefmt = '%s = '
3795 showsubopts = not search and not ui.quiet
3798 showsubopts = not search and not ui.quiet
3796
3799
3797 for name, path in pathitems:
3800 for name, path in pathitems:
3798 fm.startitem()
3801 fm.startitem()
3799 fm.condwrite(not search, 'name', namefmt, name)
3802 fm.condwrite(not search, 'name', namefmt, name)
3800 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
3803 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
3801 for subopt, value in sorted(path.suboptions.items()):
3804 for subopt, value in sorted(path.suboptions.items()):
3802 assert subopt not in ('name', 'url')
3805 assert subopt not in ('name', 'url')
3803 if showsubopts:
3806 if showsubopts:
3804 fm.plain('%s:%s = ' % (name, subopt))
3807 fm.plain('%s:%s = ' % (name, subopt))
3805 fm.condwrite(showsubopts, subopt, '%s\n', value)
3808 fm.condwrite(showsubopts, subopt, '%s\n', value)
3806
3809
3807 fm.end()
3810 fm.end()
3808
3811
3809 if search and not pathitems:
3812 if search and not pathitems:
3810 if not ui.quiet:
3813 if not ui.quiet:
3811 ui.warn(_("not found!\n"))
3814 ui.warn(_("not found!\n"))
3812 return 1
3815 return 1
3813 else:
3816 else:
3814 return 0
3817 return 0
3815
3818
3816 @command('phase',
3819 @command('phase',
3817 [('p', 'public', False, _('set changeset phase to public')),
3820 [('p', 'public', False, _('set changeset phase to public')),
3818 ('d', 'draft', False, _('set changeset phase to draft')),
3821 ('d', 'draft', False, _('set changeset phase to draft')),
3819 ('s', 'secret', False, _('set changeset phase to secret')),
3822 ('s', 'secret', False, _('set changeset phase to secret')),
3820 ('f', 'force', False, _('allow to move boundary backward')),
3823 ('f', 'force', False, _('allow to move boundary backward')),
3821 ('r', 'rev', [], _('target revision'), _('REV')),
3824 ('r', 'rev', [], _('target revision'), _('REV')),
3822 ],
3825 ],
3823 _('[-p|-d|-s] [-f] [-r] [REV...]'))
3826 _('[-p|-d|-s] [-f] [-r] [REV...]'))
3824 def phase(ui, repo, *revs, **opts):
3827 def phase(ui, repo, *revs, **opts):
3825 """set or show the current phase name
3828 """set or show the current phase name
3826
3829
3827 With no argument, show the phase name of the current revision(s).
3830 With no argument, show the phase name of the current revision(s).
3828
3831
3829 With one of -p/--public, -d/--draft or -s/--secret, change the
3832 With one of -p/--public, -d/--draft or -s/--secret, change the
3830 phase value of the specified revisions.
3833 phase value of the specified revisions.
3831
3834
3832 Unless -f/--force is specified, :hg:`phase` won't move changesets from a
3835 Unless -f/--force is specified, :hg:`phase` won't move changesets from a
3833 lower phase to a higher phase. Phases are ordered as follows::
3836 lower phase to a higher phase. Phases are ordered as follows::
3834
3837
3835 public < draft < secret
3838 public < draft < secret
3836
3839
3837 Returns 0 on success, 1 if some phases could not be changed.
3840 Returns 0 on success, 1 if some phases could not be changed.
3838
3841
3839 (For more information about the phases concept, see :hg:`help phases`.)
3842 (For more information about the phases concept, see :hg:`help phases`.)
3840 """
3843 """
3841 opts = pycompat.byteskwargs(opts)
3844 opts = pycompat.byteskwargs(opts)
3842 # search for a unique phase argument
3845 # search for a unique phase argument
3843 targetphase = None
3846 targetphase = None
3844 for idx, name in enumerate(phases.phasenames):
3847 for idx, name in enumerate(phases.phasenames):
3845 if opts[name]:
3848 if opts[name]:
3846 if targetphase is not None:
3849 if targetphase is not None:
3847 raise error.Abort(_('only one phase can be specified'))
3850 raise error.Abort(_('only one phase can be specified'))
3848 targetphase = idx
3851 targetphase = idx
3849
3852
3850 # look for specified revision
3853 # look for specified revision
3851 revs = list(revs)
3854 revs = list(revs)
3852 revs.extend(opts['rev'])
3855 revs.extend(opts['rev'])
3853 if not revs:
3856 if not revs:
3854 # display both parents as the second parent phase can influence
3857 # display both parents as the second parent phase can influence
3855 # the phase of a merge commit
3858 # the phase of a merge commit
3856 revs = [c.rev() for c in repo[None].parents()]
3859 revs = [c.rev() for c in repo[None].parents()]
3857
3860
3858 revs = scmutil.revrange(repo, revs)
3861 revs = scmutil.revrange(repo, revs)
3859
3862
3860 lock = None
3863 lock = None
3861 ret = 0
3864 ret = 0
3862 if targetphase is None:
3865 if targetphase is None:
3863 # display
3866 # display
3864 for r in revs:
3867 for r in revs:
3865 ctx = repo[r]
3868 ctx = repo[r]
3866 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
3869 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
3867 else:
3870 else:
3868 tr = None
3871 tr = None
3869 lock = repo.lock()
3872 lock = repo.lock()
3870 try:
3873 try:
3871 tr = repo.transaction("phase")
3874 tr = repo.transaction("phase")
3872 # set phase
3875 # set phase
3873 if not revs:
3876 if not revs:
3874 raise error.Abort(_('empty revision set'))
3877 raise error.Abort(_('empty revision set'))
3875 nodes = [repo[r].node() for r in revs]
3878 nodes = [repo[r].node() for r in revs]
3876 # moving revision from public to draft may hide them
3879 # moving revision from public to draft may hide them
3877 # We have to check result on an unfiltered repository
3880 # We have to check result on an unfiltered repository
3878 unfi = repo.unfiltered()
3881 unfi = repo.unfiltered()
3879 getphase = unfi._phasecache.phase
3882 getphase = unfi._phasecache.phase
3880 olddata = [getphase(unfi, r) for r in unfi]
3883 olddata = [getphase(unfi, r) for r in unfi]
3881 phases.advanceboundary(repo, tr, targetphase, nodes)
3884 phases.advanceboundary(repo, tr, targetphase, nodes)
3882 if opts['force']:
3885 if opts['force']:
3883 phases.retractboundary(repo, tr, targetphase, nodes)
3886 phases.retractboundary(repo, tr, targetphase, nodes)
3884 tr.close()
3887 tr.close()
3885 finally:
3888 finally:
3886 if tr is not None:
3889 if tr is not None:
3887 tr.release()
3890 tr.release()
3888 lock.release()
3891 lock.release()
3889 getphase = unfi._phasecache.phase
3892 getphase = unfi._phasecache.phase
3890 newdata = [getphase(unfi, r) for r in unfi]
3893 newdata = [getphase(unfi, r) for r in unfi]
3891 changes = sum(newdata[r] != olddata[r] for r in unfi)
3894 changes = sum(newdata[r] != olddata[r] for r in unfi)
3892 cl = unfi.changelog
3895 cl = unfi.changelog
3893 rejected = [n for n in nodes
3896 rejected = [n for n in nodes
3894 if newdata[cl.rev(n)] < targetphase]
3897 if newdata[cl.rev(n)] < targetphase]
3895 if rejected:
3898 if rejected:
3896 ui.warn(_('cannot move %i changesets to a higher '
3899 ui.warn(_('cannot move %i changesets to a higher '
3897 'phase, use --force\n') % len(rejected))
3900 'phase, use --force\n') % len(rejected))
3898 ret = 1
3901 ret = 1
3899 if changes:
3902 if changes:
3900 msg = _('phase changed for %i changesets\n') % changes
3903 msg = _('phase changed for %i changesets\n') % changes
3901 if ret:
3904 if ret:
3902 ui.status(msg)
3905 ui.status(msg)
3903 else:
3906 else:
3904 ui.note(msg)
3907 ui.note(msg)
3905 else:
3908 else:
3906 ui.warn(_('no phases changed\n'))
3909 ui.warn(_('no phases changed\n'))
3907 return ret
3910 return ret
3908
3911
3909 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
3912 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
3910 """Run after a changegroup has been added via pull/unbundle
3913 """Run after a changegroup has been added via pull/unbundle
3911
3914
3912 This takes arguments below:
3915 This takes arguments below:
3913
3916
3914 :modheads: change of heads by pull/unbundle
3917 :modheads: change of heads by pull/unbundle
3915 :optupdate: updating working directory is needed or not
3918 :optupdate: updating working directory is needed or not
3916 :checkout: update destination revision (or None to default destination)
3919 :checkout: update destination revision (or None to default destination)
3917 :brev: a name, which might be a bookmark to be activated after updating
3920 :brev: a name, which might be a bookmark to be activated after updating
3918 """
3921 """
3919 if modheads == 0:
3922 if modheads == 0:
3920 return
3923 return
3921 if optupdate:
3924 if optupdate:
3922 try:
3925 try:
3923 return hg.updatetotally(ui, repo, checkout, brev)
3926 return hg.updatetotally(ui, repo, checkout, brev)
3924 except error.UpdateAbort as inst:
3927 except error.UpdateAbort as inst:
3925 msg = _("not updating: %s") % str(inst)
3928 msg = _("not updating: %s") % str(inst)
3926 hint = inst.hint
3929 hint = inst.hint
3927 raise error.UpdateAbort(msg, hint=hint)
3930 raise error.UpdateAbort(msg, hint=hint)
3928 if modheads > 1:
3931 if modheads > 1:
3929 currentbranchheads = len(repo.branchheads())
3932 currentbranchheads = len(repo.branchheads())
3930 if currentbranchheads == modheads:
3933 if currentbranchheads == modheads:
3931 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
3934 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
3932 elif currentbranchheads > 1:
3935 elif currentbranchheads > 1:
3933 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
3936 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
3934 "merge)\n"))
3937 "merge)\n"))
3935 else:
3938 else:
3936 ui.status(_("(run 'hg heads' to see heads)\n"))
3939 ui.status(_("(run 'hg heads' to see heads)\n"))
3937 elif not ui.configbool('commands', 'update.requiredest'):
3940 elif not ui.configbool('commands', 'update.requiredest'):
3938 ui.status(_("(run 'hg update' to get a working copy)\n"))
3941 ui.status(_("(run 'hg update' to get a working copy)\n"))
3939
3942
3940 @command('^pull',
3943 @command('^pull',
3941 [('u', 'update', None,
3944 [('u', 'update', None,
3942 _('update to new branch head if new descendants were pulled')),
3945 _('update to new branch head if new descendants were pulled')),
3943 ('f', 'force', None, _('run even when remote repository is unrelated')),
3946 ('f', 'force', None, _('run even when remote repository is unrelated')),
3944 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3947 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3945 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
3948 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
3946 ('b', 'branch', [], _('a specific branch you would like to pull'),
3949 ('b', 'branch', [], _('a specific branch you would like to pull'),
3947 _('BRANCH')),
3950 _('BRANCH')),
3948 ] + remoteopts,
3951 ] + remoteopts,
3949 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
3952 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
3950 def pull(ui, repo, source="default", **opts):
3953 def pull(ui, repo, source="default", **opts):
3951 """pull changes from the specified source
3954 """pull changes from the specified source
3952
3955
3953 Pull changes from a remote repository to a local one.
3956 Pull changes from a remote repository to a local one.
3954
3957
3955 This finds all changes from the repository at the specified path
3958 This finds all changes from the repository at the specified path
3956 or URL and adds them to a local repository (the current one unless
3959 or URL and adds them to a local repository (the current one unless
3957 -R is specified). By default, this does not update the copy of the
3960 -R is specified). By default, this does not update the copy of the
3958 project in the working directory.
3961 project in the working directory.
3959
3962
3960 Use :hg:`incoming` if you want to see what would have been added
3963 Use :hg:`incoming` if you want to see what would have been added
3961 by a pull at the time you issued this command. If you then decide
3964 by a pull at the time you issued this command. If you then decide
3962 to add those changes to the repository, you should use :hg:`pull
3965 to add those changes to the repository, you should use :hg:`pull
3963 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
3966 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
3964
3967
3965 If SOURCE is omitted, the 'default' path will be used.
3968 If SOURCE is omitted, the 'default' path will be used.
3966 See :hg:`help urls` for more information.
3969 See :hg:`help urls` for more information.
3967
3970
3968 Specifying bookmark as ``.`` is equivalent to specifying the active
3971 Specifying bookmark as ``.`` is equivalent to specifying the active
3969 bookmark's name.
3972 bookmark's name.
3970
3973
3971 Returns 0 on success, 1 if an update had unresolved files.
3974 Returns 0 on success, 1 if an update had unresolved files.
3972 """
3975 """
3973
3976
3974 opts = pycompat.byteskwargs(opts)
3977 opts = pycompat.byteskwargs(opts)
3975 if ui.configbool('commands', 'update.requiredest') and opts.get('update'):
3978 if ui.configbool('commands', 'update.requiredest') and opts.get('update'):
3976 msg = _('update destination required by configuration')
3979 msg = _('update destination required by configuration')
3977 hint = _('use hg pull followed by hg update DEST')
3980 hint = _('use hg pull followed by hg update DEST')
3978 raise error.Abort(msg, hint=hint)
3981 raise error.Abort(msg, hint=hint)
3979
3982
3980 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
3983 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
3981 ui.status(_('pulling from %s\n') % util.hidepassword(source))
3984 ui.status(_('pulling from %s\n') % util.hidepassword(source))
3982 other = hg.peer(repo, opts, source)
3985 other = hg.peer(repo, opts, source)
3983 try:
3986 try:
3984 revs, checkout = hg.addbranchrevs(repo, other, branches,
3987 revs, checkout = hg.addbranchrevs(repo, other, branches,
3985 opts.get('rev'))
3988 opts.get('rev'))
3986
3989
3987
3990
3988 pullopargs = {}
3991 pullopargs = {}
3989 if opts.get('bookmark'):
3992 if opts.get('bookmark'):
3990 if not revs:
3993 if not revs:
3991 revs = []
3994 revs = []
3992 # The list of bookmark used here is not the one used to actually
3995 # The list of bookmark used here is not the one used to actually
3993 # update the bookmark name. This can result in the revision pulled
3996 # update the bookmark name. This can result in the revision pulled
3994 # not ending up with the name of the bookmark because of a race
3997 # not ending up with the name of the bookmark because of a race
3995 # condition on the server. (See issue 4689 for details)
3998 # condition on the server. (See issue 4689 for details)
3996 remotebookmarks = other.listkeys('bookmarks')
3999 remotebookmarks = other.listkeys('bookmarks')
3997 remotebookmarks = bookmarks.unhexlifybookmarks(remotebookmarks)
4000 remotebookmarks = bookmarks.unhexlifybookmarks(remotebookmarks)
3998 pullopargs['remotebookmarks'] = remotebookmarks
4001 pullopargs['remotebookmarks'] = remotebookmarks
3999 for b in opts['bookmark']:
4002 for b in opts['bookmark']:
4000 b = repo._bookmarks.expandname(b)
4003 b = repo._bookmarks.expandname(b)
4001 if b not in remotebookmarks:
4004 if b not in remotebookmarks:
4002 raise error.Abort(_('remote bookmark %s not found!') % b)
4005 raise error.Abort(_('remote bookmark %s not found!') % b)
4003 revs.append(hex(remotebookmarks[b]))
4006 revs.append(hex(remotebookmarks[b]))
4004
4007
4005 if revs:
4008 if revs:
4006 try:
4009 try:
4007 # When 'rev' is a bookmark name, we cannot guarantee that it
4010 # When 'rev' is a bookmark name, we cannot guarantee that it
4008 # will be updated with that name because of a race condition
4011 # will be updated with that name because of a race condition
4009 # server side. (See issue 4689 for details)
4012 # server side. (See issue 4689 for details)
4010 oldrevs = revs
4013 oldrevs = revs
4011 revs = [] # actually, nodes
4014 revs = [] # actually, nodes
4012 for r in oldrevs:
4015 for r in oldrevs:
4013 node = other.lookup(r)
4016 node = other.lookup(r)
4014 revs.append(node)
4017 revs.append(node)
4015 if r == checkout:
4018 if r == checkout:
4016 checkout = node
4019 checkout = node
4017 except error.CapabilityError:
4020 except error.CapabilityError:
4018 err = _("other repository doesn't support revision lookup, "
4021 err = _("other repository doesn't support revision lookup, "
4019 "so a rev cannot be specified.")
4022 "so a rev cannot be specified.")
4020 raise error.Abort(err)
4023 raise error.Abort(err)
4021
4024
4022 pullopargs.update(opts.get('opargs', {}))
4025 pullopargs.update(opts.get('opargs', {}))
4023 modheads = exchange.pull(repo, other, heads=revs,
4026 modheads = exchange.pull(repo, other, heads=revs,
4024 force=opts.get('force'),
4027 force=opts.get('force'),
4025 bookmarks=opts.get('bookmark', ()),
4028 bookmarks=opts.get('bookmark', ()),
4026 opargs=pullopargs).cgresult
4029 opargs=pullopargs).cgresult
4027
4030
4028 # brev is a name, which might be a bookmark to be activated at
4031 # brev is a name, which might be a bookmark to be activated at
4029 # the end of the update. In other words, it is an explicit
4032 # the end of the update. In other words, it is an explicit
4030 # destination of the update
4033 # destination of the update
4031 brev = None
4034 brev = None
4032
4035
4033 if checkout:
4036 if checkout:
4034 checkout = str(repo.changelog.rev(checkout))
4037 checkout = str(repo.changelog.rev(checkout))
4035
4038
4036 # order below depends on implementation of
4039 # order below depends on implementation of
4037 # hg.addbranchrevs(). opts['bookmark'] is ignored,
4040 # hg.addbranchrevs(). opts['bookmark'] is ignored,
4038 # because 'checkout' is determined without it.
4041 # because 'checkout' is determined without it.
4039 if opts.get('rev'):
4042 if opts.get('rev'):
4040 brev = opts['rev'][0]
4043 brev = opts['rev'][0]
4041 elif opts.get('branch'):
4044 elif opts.get('branch'):
4042 brev = opts['branch'][0]
4045 brev = opts['branch'][0]
4043 else:
4046 else:
4044 brev = branches[0]
4047 brev = branches[0]
4045 repo._subtoppath = source
4048 repo._subtoppath = source
4046 try:
4049 try:
4047 ret = postincoming(ui, repo, modheads, opts.get('update'),
4050 ret = postincoming(ui, repo, modheads, opts.get('update'),
4048 checkout, brev)
4051 checkout, brev)
4049
4052
4050 finally:
4053 finally:
4051 del repo._subtoppath
4054 del repo._subtoppath
4052
4055
4053 finally:
4056 finally:
4054 other.close()
4057 other.close()
4055 return ret
4058 return ret
4056
4059
4057 @command('^push',
4060 @command('^push',
4058 [('f', 'force', None, _('force push')),
4061 [('f', 'force', None, _('force push')),
4059 ('r', 'rev', [],
4062 ('r', 'rev', [],
4060 _('a changeset intended to be included in the destination'),
4063 _('a changeset intended to be included in the destination'),
4061 _('REV')),
4064 _('REV')),
4062 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4065 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4063 ('b', 'branch', [],
4066 ('b', 'branch', [],
4064 _('a specific branch you would like to push'), _('BRANCH')),
4067 _('a specific branch you would like to push'), _('BRANCH')),
4065 ('', 'new-branch', False, _('allow pushing a new branch')),
4068 ('', 'new-branch', False, _('allow pushing a new branch')),
4066 ('', 'pushvars', [], _('variables that can be sent to server (ADVANCED)')),
4069 ('', 'pushvars', [], _('variables that can be sent to server (ADVANCED)')),
4067 ] + remoteopts,
4070 ] + remoteopts,
4068 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4071 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4069 def push(ui, repo, dest=None, **opts):
4072 def push(ui, repo, dest=None, **opts):
4070 """push changes to the specified destination
4073 """push changes to the specified destination
4071
4074
4072 Push changesets from the local repository to the specified
4075 Push changesets from the local repository to the specified
4073 destination.
4076 destination.
4074
4077
4075 This operation is symmetrical to pull: it is identical to a pull
4078 This operation is symmetrical to pull: it is identical to a pull
4076 in the destination repository from the current one.
4079 in the destination repository from the current one.
4077
4080
4078 By default, push will not allow creation of new heads at the
4081 By default, push will not allow creation of new heads at the
4079 destination, since multiple heads would make it unclear which head
4082 destination, since multiple heads would make it unclear which head
4080 to use. In this situation, it is recommended to pull and merge
4083 to use. In this situation, it is recommended to pull and merge
4081 before pushing.
4084 before pushing.
4082
4085
4083 Use --new-branch if you want to allow push to create a new named
4086 Use --new-branch if you want to allow push to create a new named
4084 branch that is not present at the destination. This allows you to
4087 branch that is not present at the destination. This allows you to
4085 only create a new branch without forcing other changes.
4088 only create a new branch without forcing other changes.
4086
4089
4087 .. note::
4090 .. note::
4088
4091
4089 Extra care should be taken with the -f/--force option,
4092 Extra care should be taken with the -f/--force option,
4090 which will push all new heads on all branches, an action which will
4093 which will push all new heads on all branches, an action which will
4091 almost always cause confusion for collaborators.
4094 almost always cause confusion for collaborators.
4092
4095
4093 If -r/--rev is used, the specified revision and all its ancestors
4096 If -r/--rev is used, the specified revision and all its ancestors
4094 will be pushed to the remote repository.
4097 will be pushed to the remote repository.
4095
4098
4096 If -B/--bookmark is used, the specified bookmarked revision, its
4099 If -B/--bookmark is used, the specified bookmarked revision, its
4097 ancestors, and the bookmark will be pushed to the remote
4100 ancestors, and the bookmark will be pushed to the remote
4098 repository. Specifying ``.`` is equivalent to specifying the active
4101 repository. Specifying ``.`` is equivalent to specifying the active
4099 bookmark's name.
4102 bookmark's name.
4100
4103
4101 Please see :hg:`help urls` for important details about ``ssh://``
4104 Please see :hg:`help urls` for important details about ``ssh://``
4102 URLs. If DESTINATION is omitted, a default path will be used.
4105 URLs. If DESTINATION is omitted, a default path will be used.
4103
4106
4104 .. container:: verbose
4107 .. container:: verbose
4105
4108
4106 The --pushvars option sends strings to the server that become
4109 The --pushvars option sends strings to the server that become
4107 environment variables prepended with ``HG_USERVAR_``. For example,
4110 environment variables prepended with ``HG_USERVAR_``. For example,
4108 ``--pushvars ENABLE_FEATURE=true``, provides the server side hooks with
4111 ``--pushvars ENABLE_FEATURE=true``, provides the server side hooks with
4109 ``HG_USERVAR_ENABLE_FEATURE=true`` as part of their environment.
4112 ``HG_USERVAR_ENABLE_FEATURE=true`` as part of their environment.
4110
4113
4111 pushvars can provide for user-overridable hooks as well as set debug
4114 pushvars can provide for user-overridable hooks as well as set debug
4112 levels. One example is having a hook that blocks commits containing
4115 levels. One example is having a hook that blocks commits containing
4113 conflict markers, but enables the user to override the hook if the file
4116 conflict markers, but enables the user to override the hook if the file
4114 is using conflict markers for testing purposes or the file format has
4117 is using conflict markers for testing purposes or the file format has
4115 strings that look like conflict markers.
4118 strings that look like conflict markers.
4116
4119
4117 By default, servers will ignore `--pushvars`. To enable it add the
4120 By default, servers will ignore `--pushvars`. To enable it add the
4118 following to your configuration file::
4121 following to your configuration file::
4119
4122
4120 [push]
4123 [push]
4121 pushvars.server = true
4124 pushvars.server = true
4122
4125
4123 Returns 0 if push was successful, 1 if nothing to push.
4126 Returns 0 if push was successful, 1 if nothing to push.
4124 """
4127 """
4125
4128
4126 opts = pycompat.byteskwargs(opts)
4129 opts = pycompat.byteskwargs(opts)
4127 if opts.get('bookmark'):
4130 if opts.get('bookmark'):
4128 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
4131 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
4129 for b in opts['bookmark']:
4132 for b in opts['bookmark']:
4130 # translate -B options to -r so changesets get pushed
4133 # translate -B options to -r so changesets get pushed
4131 b = repo._bookmarks.expandname(b)
4134 b = repo._bookmarks.expandname(b)
4132 if b in repo._bookmarks:
4135 if b in repo._bookmarks:
4133 opts.setdefault('rev', []).append(b)
4136 opts.setdefault('rev', []).append(b)
4134 else:
4137 else:
4135 # if we try to push a deleted bookmark, translate it to null
4138 # if we try to push a deleted bookmark, translate it to null
4136 # this lets simultaneous -r, -b options continue working
4139 # this lets simultaneous -r, -b options continue working
4137 opts.setdefault('rev', []).append("null")
4140 opts.setdefault('rev', []).append("null")
4138
4141
4139 path = ui.paths.getpath(dest, default=('default-push', 'default'))
4142 path = ui.paths.getpath(dest, default=('default-push', 'default'))
4140 if not path:
4143 if not path:
4141 raise error.Abort(_('default repository not configured!'),
4144 raise error.Abort(_('default repository not configured!'),
4142 hint=_("see 'hg help config.paths'"))
4145 hint=_("see 'hg help config.paths'"))
4143 dest = path.pushloc or path.loc
4146 dest = path.pushloc or path.loc
4144 branches = (path.branch, opts.get('branch') or [])
4147 branches = (path.branch, opts.get('branch') or [])
4145 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4148 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4146 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4149 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4147 other = hg.peer(repo, opts, dest)
4150 other = hg.peer(repo, opts, dest)
4148
4151
4149 if revs:
4152 if revs:
4150 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4153 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4151 if not revs:
4154 if not revs:
4152 raise error.Abort(_("specified revisions evaluate to an empty set"),
4155 raise error.Abort(_("specified revisions evaluate to an empty set"),
4153 hint=_("use different revision arguments"))
4156 hint=_("use different revision arguments"))
4154 elif path.pushrev:
4157 elif path.pushrev:
4155 # It doesn't make any sense to specify ancestor revisions. So limit
4158 # It doesn't make any sense to specify ancestor revisions. So limit
4156 # to DAG heads to make discovery simpler.
4159 # to DAG heads to make discovery simpler.
4157 expr = revsetlang.formatspec('heads(%r)', path.pushrev)
4160 expr = revsetlang.formatspec('heads(%r)', path.pushrev)
4158 revs = scmutil.revrange(repo, [expr])
4161 revs = scmutil.revrange(repo, [expr])
4159 revs = [repo[rev].node() for rev in revs]
4162 revs = [repo[rev].node() for rev in revs]
4160 if not revs:
4163 if not revs:
4161 raise error.Abort(_('default push revset for path evaluates to an '
4164 raise error.Abort(_('default push revset for path evaluates to an '
4162 'empty set'))
4165 'empty set'))
4163
4166
4164 repo._subtoppath = dest
4167 repo._subtoppath = dest
4165 try:
4168 try:
4166 # push subrepos depth-first for coherent ordering
4169 # push subrepos depth-first for coherent ordering
4167 c = repo['']
4170 c = repo['']
4168 subs = c.substate # only repos that are committed
4171 subs = c.substate # only repos that are committed
4169 for s in sorted(subs):
4172 for s in sorted(subs):
4170 result = c.sub(s).push(opts)
4173 result = c.sub(s).push(opts)
4171 if result == 0:
4174 if result == 0:
4172 return not result
4175 return not result
4173 finally:
4176 finally:
4174 del repo._subtoppath
4177 del repo._subtoppath
4175
4178
4176 opargs = dict(opts.get('opargs', {})) # copy opargs since we may mutate it
4179 opargs = dict(opts.get('opargs', {})) # copy opargs since we may mutate it
4177 opargs.setdefault('pushvars', []).extend(opts.get('pushvars', []))
4180 opargs.setdefault('pushvars', []).extend(opts.get('pushvars', []))
4178
4181
4179 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
4182 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
4180 newbranch=opts.get('new_branch'),
4183 newbranch=opts.get('new_branch'),
4181 bookmarks=opts.get('bookmark', ()),
4184 bookmarks=opts.get('bookmark', ()),
4182 opargs=opargs)
4185 opargs=opargs)
4183
4186
4184 result = not pushop.cgresult
4187 result = not pushop.cgresult
4185
4188
4186 if pushop.bkresult is not None:
4189 if pushop.bkresult is not None:
4187 if pushop.bkresult == 2:
4190 if pushop.bkresult == 2:
4188 result = 2
4191 result = 2
4189 elif not result and pushop.bkresult:
4192 elif not result and pushop.bkresult:
4190 result = 2
4193 result = 2
4191
4194
4192 return result
4195 return result
4193
4196
4194 @command('recover', [])
4197 @command('recover', [])
4195 def recover(ui, repo):
4198 def recover(ui, repo):
4196 """roll back an interrupted transaction
4199 """roll back an interrupted transaction
4197
4200
4198 Recover from an interrupted commit or pull.
4201 Recover from an interrupted commit or pull.
4199
4202
4200 This command tries to fix the repository status after an
4203 This command tries to fix the repository status after an
4201 interrupted operation. It should only be necessary when Mercurial
4204 interrupted operation. It should only be necessary when Mercurial
4202 suggests it.
4205 suggests it.
4203
4206
4204 Returns 0 if successful, 1 if nothing to recover or verify fails.
4207 Returns 0 if successful, 1 if nothing to recover or verify fails.
4205 """
4208 """
4206 if repo.recover():
4209 if repo.recover():
4207 return hg.verify(repo)
4210 return hg.verify(repo)
4208 return 1
4211 return 1
4209
4212
4210 @command('^remove|rm',
4213 @command('^remove|rm',
4211 [('A', 'after', None, _('record delete for missing files')),
4214 [('A', 'after', None, _('record delete for missing files')),
4212 ('f', 'force', None,
4215 ('f', 'force', None,
4213 _('forget added files, delete modified files')),
4216 _('forget added files, delete modified files')),
4214 ] + subrepoopts + walkopts,
4217 ] + subrepoopts + walkopts,
4215 _('[OPTION]... FILE...'),
4218 _('[OPTION]... FILE...'),
4216 inferrepo=True)
4219 inferrepo=True)
4217 def remove(ui, repo, *pats, **opts):
4220 def remove(ui, repo, *pats, **opts):
4218 """remove the specified files on the next commit
4221 """remove the specified files on the next commit
4219
4222
4220 Schedule the indicated files for removal from the current branch.
4223 Schedule the indicated files for removal from the current branch.
4221
4224
4222 This command schedules the files to be removed at the next commit.
4225 This command schedules the files to be removed at the next commit.
4223 To undo a remove before that, see :hg:`revert`. To undo added
4226 To undo a remove before that, see :hg:`revert`. To undo added
4224 files, see :hg:`forget`.
4227 files, see :hg:`forget`.
4225
4228
4226 .. container:: verbose
4229 .. container:: verbose
4227
4230
4228 -A/--after can be used to remove only files that have already
4231 -A/--after can be used to remove only files that have already
4229 been deleted, -f/--force can be used to force deletion, and -Af
4232 been deleted, -f/--force can be used to force deletion, and -Af
4230 can be used to remove files from the next revision without
4233 can be used to remove files from the next revision without
4231 deleting them from the working directory.
4234 deleting them from the working directory.
4232
4235
4233 The following table details the behavior of remove for different
4236 The following table details the behavior of remove for different
4234 file states (columns) and option combinations (rows). The file
4237 file states (columns) and option combinations (rows). The file
4235 states are Added [A], Clean [C], Modified [M] and Missing [!]
4238 states are Added [A], Clean [C], Modified [M] and Missing [!]
4236 (as reported by :hg:`status`). The actions are Warn, Remove
4239 (as reported by :hg:`status`). The actions are Warn, Remove
4237 (from branch) and Delete (from disk):
4240 (from branch) and Delete (from disk):
4238
4241
4239 ========= == == == ==
4242 ========= == == == ==
4240 opt/state A C M !
4243 opt/state A C M !
4241 ========= == == == ==
4244 ========= == == == ==
4242 none W RD W R
4245 none W RD W R
4243 -f R RD RD R
4246 -f R RD RD R
4244 -A W W W R
4247 -A W W W R
4245 -Af R R R R
4248 -Af R R R R
4246 ========= == == == ==
4249 ========= == == == ==
4247
4250
4248 .. note::
4251 .. note::
4249
4252
4250 :hg:`remove` never deletes files in Added [A] state from the
4253 :hg:`remove` never deletes files in Added [A] state from the
4251 working directory, not even if ``--force`` is specified.
4254 working directory, not even if ``--force`` is specified.
4252
4255
4253 Returns 0 on success, 1 if any warnings encountered.
4256 Returns 0 on success, 1 if any warnings encountered.
4254 """
4257 """
4255
4258
4256 opts = pycompat.byteskwargs(opts)
4259 opts = pycompat.byteskwargs(opts)
4257 after, force = opts.get('after'), opts.get('force')
4260 after, force = opts.get('after'), opts.get('force')
4258 if not pats and not after:
4261 if not pats and not after:
4259 raise error.Abort(_('no files specified'))
4262 raise error.Abort(_('no files specified'))
4260
4263
4261 m = scmutil.match(repo[None], pats, opts)
4264 m = scmutil.match(repo[None], pats, opts)
4262 subrepos = opts.get('subrepos')
4265 subrepos = opts.get('subrepos')
4263 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
4266 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
4264
4267
4265 @command('rename|move|mv',
4268 @command('rename|move|mv',
4266 [('A', 'after', None, _('record a rename that has already occurred')),
4269 [('A', 'after', None, _('record a rename that has already occurred')),
4267 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4270 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4268 ] + walkopts + dryrunopts,
4271 ] + walkopts + dryrunopts,
4269 _('[OPTION]... SOURCE... DEST'))
4272 _('[OPTION]... SOURCE... DEST'))
4270 def rename(ui, repo, *pats, **opts):
4273 def rename(ui, repo, *pats, **opts):
4271 """rename files; equivalent of copy + remove
4274 """rename files; equivalent of copy + remove
4272
4275
4273 Mark dest as copies of sources; mark sources for deletion. If dest
4276 Mark dest as copies of sources; mark sources for deletion. If dest
4274 is a directory, copies are put in that directory. If dest is a
4277 is a directory, copies are put in that directory. If dest is a
4275 file, there can only be one source.
4278 file, there can only be one source.
4276
4279
4277 By default, this command copies the contents of files as they
4280 By default, this command copies the contents of files as they
4278 exist in the working directory. If invoked with -A/--after, the
4281 exist in the working directory. If invoked with -A/--after, the
4279 operation is recorded, but no copying is performed.
4282 operation is recorded, but no copying is performed.
4280
4283
4281 This command takes effect at the next commit. To undo a rename
4284 This command takes effect at the next commit. To undo a rename
4282 before that, see :hg:`revert`.
4285 before that, see :hg:`revert`.
4283
4286
4284 Returns 0 on success, 1 if errors are encountered.
4287 Returns 0 on success, 1 if errors are encountered.
4285 """
4288 """
4286 opts = pycompat.byteskwargs(opts)
4289 opts = pycompat.byteskwargs(opts)
4287 with repo.wlock(False):
4290 with repo.wlock(False):
4288 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4291 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4289
4292
4290 @command('resolve',
4293 @command('resolve',
4291 [('a', 'all', None, _('select all unresolved files')),
4294 [('a', 'all', None, _('select all unresolved files')),
4292 ('l', 'list', None, _('list state of files needing merge')),
4295 ('l', 'list', None, _('list state of files needing merge')),
4293 ('m', 'mark', None, _('mark files as resolved')),
4296 ('m', 'mark', None, _('mark files as resolved')),
4294 ('u', 'unmark', None, _('mark files as unresolved')),
4297 ('u', 'unmark', None, _('mark files as unresolved')),
4295 ('n', 'no-status', None, _('hide status prefix'))]
4298 ('n', 'no-status', None, _('hide status prefix'))]
4296 + mergetoolopts + walkopts + formatteropts,
4299 + mergetoolopts + walkopts + formatteropts,
4297 _('[OPTION]... [FILE]...'),
4300 _('[OPTION]... [FILE]...'),
4298 inferrepo=True)
4301 inferrepo=True)
4299 def resolve(ui, repo, *pats, **opts):
4302 def resolve(ui, repo, *pats, **opts):
4300 """redo merges or set/view the merge status of files
4303 """redo merges or set/view the merge status of files
4301
4304
4302 Merges with unresolved conflicts are often the result of
4305 Merges with unresolved conflicts are often the result of
4303 non-interactive merging using the ``internal:merge`` configuration
4306 non-interactive merging using the ``internal:merge`` configuration
4304 setting, or a command-line merge tool like ``diff3``. The resolve
4307 setting, or a command-line merge tool like ``diff3``. The resolve
4305 command is used to manage the files involved in a merge, after
4308 command is used to manage the files involved in a merge, after
4306 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4309 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4307 working directory must have two parents). See :hg:`help
4310 working directory must have two parents). See :hg:`help
4308 merge-tools` for information on configuring merge tools.
4311 merge-tools` for information on configuring merge tools.
4309
4312
4310 The resolve command can be used in the following ways:
4313 The resolve command can be used in the following ways:
4311
4314
4312 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4315 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4313 files, discarding any previous merge attempts. Re-merging is not
4316 files, discarding any previous merge attempts. Re-merging is not
4314 performed for files already marked as resolved. Use ``--all/-a``
4317 performed for files already marked as resolved. Use ``--all/-a``
4315 to select all unresolved files. ``--tool`` can be used to specify
4318 to select all unresolved files. ``--tool`` can be used to specify
4316 the merge tool used for the given files. It overrides the HGMERGE
4319 the merge tool used for the given files. It overrides the HGMERGE
4317 environment variable and your configuration files. Previous file
4320 environment variable and your configuration files. Previous file
4318 contents are saved with a ``.orig`` suffix.
4321 contents are saved with a ``.orig`` suffix.
4319
4322
4320 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4323 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4321 (e.g. after having manually fixed-up the files). The default is
4324 (e.g. after having manually fixed-up the files). The default is
4322 to mark all unresolved files.
4325 to mark all unresolved files.
4323
4326
4324 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4327 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4325 default is to mark all resolved files.
4328 default is to mark all resolved files.
4326
4329
4327 - :hg:`resolve -l`: list files which had or still have conflicts.
4330 - :hg:`resolve -l`: list files which had or still have conflicts.
4328 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4331 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4329 You can use ``set:unresolved()`` or ``set:resolved()`` to filter
4332 You can use ``set:unresolved()`` or ``set:resolved()`` to filter
4330 the list. See :hg:`help filesets` for details.
4333 the list. See :hg:`help filesets` for details.
4331
4334
4332 .. note::
4335 .. note::
4333
4336
4334 Mercurial will not let you commit files with unresolved merge
4337 Mercurial will not let you commit files with unresolved merge
4335 conflicts. You must use :hg:`resolve -m ...` before you can
4338 conflicts. You must use :hg:`resolve -m ...` before you can
4336 commit after a conflicting merge.
4339 commit after a conflicting merge.
4337
4340
4338 Returns 0 on success, 1 if any files fail a resolve attempt.
4341 Returns 0 on success, 1 if any files fail a resolve attempt.
4339 """
4342 """
4340
4343
4341 opts = pycompat.byteskwargs(opts)
4344 opts = pycompat.byteskwargs(opts)
4342 flaglist = 'all mark unmark list no_status'.split()
4345 flaglist = 'all mark unmark list no_status'.split()
4343 all, mark, unmark, show, nostatus = \
4346 all, mark, unmark, show, nostatus = \
4344 [opts.get(o) for o in flaglist]
4347 [opts.get(o) for o in flaglist]
4345
4348
4346 if (show and (mark or unmark)) or (mark and unmark):
4349 if (show and (mark or unmark)) or (mark and unmark):
4347 raise error.Abort(_("too many options specified"))
4350 raise error.Abort(_("too many options specified"))
4348 if pats and all:
4351 if pats and all:
4349 raise error.Abort(_("can't specify --all and patterns"))
4352 raise error.Abort(_("can't specify --all and patterns"))
4350 if not (all or pats or show or mark or unmark):
4353 if not (all or pats or show or mark or unmark):
4351 raise error.Abort(_('no files or directories specified'),
4354 raise error.Abort(_('no files or directories specified'),
4352 hint=('use --all to re-merge all unresolved files'))
4355 hint=('use --all to re-merge all unresolved files'))
4353
4356
4354 if show:
4357 if show:
4355 ui.pager('resolve')
4358 ui.pager('resolve')
4356 fm = ui.formatter('resolve', opts)
4359 fm = ui.formatter('resolve', opts)
4357 ms = mergemod.mergestate.read(repo)
4360 ms = mergemod.mergestate.read(repo)
4358 m = scmutil.match(repo[None], pats, opts)
4361 m = scmutil.match(repo[None], pats, opts)
4359
4362
4360 # Labels and keys based on merge state. Unresolved path conflicts show
4363 # Labels and keys based on merge state. Unresolved path conflicts show
4361 # as 'P'. Resolved path conflicts show as 'R', the same as normal
4364 # as 'P'. Resolved path conflicts show as 'R', the same as normal
4362 # resolved conflicts.
4365 # resolved conflicts.
4363 mergestateinfo = {
4366 mergestateinfo = {
4364 'u': ('resolve.unresolved', 'U'),
4367 'u': ('resolve.unresolved', 'U'),
4365 'r': ('resolve.resolved', 'R'),
4368 'r': ('resolve.resolved', 'R'),
4366 'pu': ('resolve.unresolved', 'P'),
4369 'pu': ('resolve.unresolved', 'P'),
4367 'pr': ('resolve.resolved', 'R'),
4370 'pr': ('resolve.resolved', 'R'),
4368 'd': ('resolve.driverresolved', 'D'),
4371 'd': ('resolve.driverresolved', 'D'),
4369 }
4372 }
4370
4373
4371 for f in ms:
4374 for f in ms:
4372 if not m(f):
4375 if not m(f):
4373 continue
4376 continue
4374
4377
4375 label, key = mergestateinfo[ms[f]]
4378 label, key = mergestateinfo[ms[f]]
4376 fm.startitem()
4379 fm.startitem()
4377 fm.condwrite(not nostatus, 'status', '%s ', key, label=label)
4380 fm.condwrite(not nostatus, 'status', '%s ', key, label=label)
4378 fm.write('path', '%s\n', f, label=label)
4381 fm.write('path', '%s\n', f, label=label)
4379 fm.end()
4382 fm.end()
4380 return 0
4383 return 0
4381
4384
4382 with repo.wlock():
4385 with repo.wlock():
4383 ms = mergemod.mergestate.read(repo)
4386 ms = mergemod.mergestate.read(repo)
4384
4387
4385 if not (ms.active() or repo.dirstate.p2() != nullid):
4388 if not (ms.active() or repo.dirstate.p2() != nullid):
4386 raise error.Abort(
4389 raise error.Abort(
4387 _('resolve command not applicable when not merging'))
4390 _('resolve command not applicable when not merging'))
4388
4391
4389 wctx = repo[None]
4392 wctx = repo[None]
4390
4393
4391 if ms.mergedriver and ms.mdstate() == 'u':
4394 if ms.mergedriver and ms.mdstate() == 'u':
4392 proceed = mergemod.driverpreprocess(repo, ms, wctx)
4395 proceed = mergemod.driverpreprocess(repo, ms, wctx)
4393 ms.commit()
4396 ms.commit()
4394 # allow mark and unmark to go through
4397 # allow mark and unmark to go through
4395 if not mark and not unmark and not proceed:
4398 if not mark and not unmark and not proceed:
4396 return 1
4399 return 1
4397
4400
4398 m = scmutil.match(wctx, pats, opts)
4401 m = scmutil.match(wctx, pats, opts)
4399 ret = 0
4402 ret = 0
4400 didwork = False
4403 didwork = False
4401 runconclude = False
4404 runconclude = False
4402
4405
4403 tocomplete = []
4406 tocomplete = []
4404 for f in ms:
4407 for f in ms:
4405 if not m(f):
4408 if not m(f):
4406 continue
4409 continue
4407
4410
4408 didwork = True
4411 didwork = True
4409
4412
4410 # don't let driver-resolved files be marked, and run the conclude
4413 # don't let driver-resolved files be marked, and run the conclude
4411 # step if asked to resolve
4414 # step if asked to resolve
4412 if ms[f] == "d":
4415 if ms[f] == "d":
4413 exact = m.exact(f)
4416 exact = m.exact(f)
4414 if mark:
4417 if mark:
4415 if exact:
4418 if exact:
4416 ui.warn(_('not marking %s as it is driver-resolved\n')
4419 ui.warn(_('not marking %s as it is driver-resolved\n')
4417 % f)
4420 % f)
4418 elif unmark:
4421 elif unmark:
4419 if exact:
4422 if exact:
4420 ui.warn(_('not unmarking %s as it is driver-resolved\n')
4423 ui.warn(_('not unmarking %s as it is driver-resolved\n')
4421 % f)
4424 % f)
4422 else:
4425 else:
4423 runconclude = True
4426 runconclude = True
4424 continue
4427 continue
4425
4428
4426 # path conflicts must be resolved manually
4429 # path conflicts must be resolved manually
4427 if ms[f] in ("pu", "pr"):
4430 if ms[f] in ("pu", "pr"):
4428 if mark:
4431 if mark:
4429 ms.mark(f, "pr")
4432 ms.mark(f, "pr")
4430 elif unmark:
4433 elif unmark:
4431 ms.mark(f, "pu")
4434 ms.mark(f, "pu")
4432 elif ms[f] == "pu":
4435 elif ms[f] == "pu":
4433 ui.warn(_('%s: path conflict must be resolved manually\n')
4436 ui.warn(_('%s: path conflict must be resolved manually\n')
4434 % f)
4437 % f)
4435 continue
4438 continue
4436
4439
4437 if mark:
4440 if mark:
4438 ms.mark(f, "r")
4441 ms.mark(f, "r")
4439 elif unmark:
4442 elif unmark:
4440 ms.mark(f, "u")
4443 ms.mark(f, "u")
4441 else:
4444 else:
4442 # backup pre-resolve (merge uses .orig for its own purposes)
4445 # backup pre-resolve (merge uses .orig for its own purposes)
4443 a = repo.wjoin(f)
4446 a = repo.wjoin(f)
4444 try:
4447 try:
4445 util.copyfile(a, a + ".resolve")
4448 util.copyfile(a, a + ".resolve")
4446 except (IOError, OSError) as inst:
4449 except (IOError, OSError) as inst:
4447 if inst.errno != errno.ENOENT:
4450 if inst.errno != errno.ENOENT:
4448 raise
4451 raise
4449
4452
4450 try:
4453 try:
4451 # preresolve file
4454 # preresolve file
4452 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4455 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4453 'resolve')
4456 'resolve')
4454 complete, r = ms.preresolve(f, wctx)
4457 complete, r = ms.preresolve(f, wctx)
4455 if not complete:
4458 if not complete:
4456 tocomplete.append(f)
4459 tocomplete.append(f)
4457 elif r:
4460 elif r:
4458 ret = 1
4461 ret = 1
4459 finally:
4462 finally:
4460 ui.setconfig('ui', 'forcemerge', '', 'resolve')
4463 ui.setconfig('ui', 'forcemerge', '', 'resolve')
4461 ms.commit()
4464 ms.commit()
4462
4465
4463 # replace filemerge's .orig file with our resolve file, but only
4466 # replace filemerge's .orig file with our resolve file, but only
4464 # for merges that are complete
4467 # for merges that are complete
4465 if complete:
4468 if complete:
4466 try:
4469 try:
4467 util.rename(a + ".resolve",
4470 util.rename(a + ".resolve",
4468 scmutil.origpath(ui, repo, a))
4471 scmutil.origpath(ui, repo, a))
4469 except OSError as inst:
4472 except OSError as inst:
4470 if inst.errno != errno.ENOENT:
4473 if inst.errno != errno.ENOENT:
4471 raise
4474 raise
4472
4475
4473 for f in tocomplete:
4476 for f in tocomplete:
4474 try:
4477 try:
4475 # resolve file
4478 # resolve file
4476 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4479 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4477 'resolve')
4480 'resolve')
4478 r = ms.resolve(f, wctx)
4481 r = ms.resolve(f, wctx)
4479 if r:
4482 if r:
4480 ret = 1
4483 ret = 1
4481 finally:
4484 finally:
4482 ui.setconfig('ui', 'forcemerge', '', 'resolve')
4485 ui.setconfig('ui', 'forcemerge', '', 'resolve')
4483 ms.commit()
4486 ms.commit()
4484
4487
4485 # replace filemerge's .orig file with our resolve file
4488 # replace filemerge's .orig file with our resolve file
4486 a = repo.wjoin(f)
4489 a = repo.wjoin(f)
4487 try:
4490 try:
4488 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
4491 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
4489 except OSError as inst:
4492 except OSError as inst:
4490 if inst.errno != errno.ENOENT:
4493 if inst.errno != errno.ENOENT:
4491 raise
4494 raise
4492
4495
4493 ms.commit()
4496 ms.commit()
4494 ms.recordactions()
4497 ms.recordactions()
4495
4498
4496 if not didwork and pats:
4499 if not didwork and pats:
4497 hint = None
4500 hint = None
4498 if not any([p for p in pats if p.find(':') >= 0]):
4501 if not any([p for p in pats if p.find(':') >= 0]):
4499 pats = ['path:%s' % p for p in pats]
4502 pats = ['path:%s' % p for p in pats]
4500 m = scmutil.match(wctx, pats, opts)
4503 m = scmutil.match(wctx, pats, opts)
4501 for f in ms:
4504 for f in ms:
4502 if not m(f):
4505 if not m(f):
4503 continue
4506 continue
4504 flags = ''.join(['-%s ' % o[0] for o in flaglist
4507 flags = ''.join(['-%s ' % o[0] for o in flaglist
4505 if opts.get(o)])
4508 if opts.get(o)])
4506 hint = _("(try: hg resolve %s%s)\n") % (
4509 hint = _("(try: hg resolve %s%s)\n") % (
4507 flags,
4510 flags,
4508 ' '.join(pats))
4511 ' '.join(pats))
4509 break
4512 break
4510 ui.warn(_("arguments do not match paths that need resolving\n"))
4513 ui.warn(_("arguments do not match paths that need resolving\n"))
4511 if hint:
4514 if hint:
4512 ui.warn(hint)
4515 ui.warn(hint)
4513 elif ms.mergedriver and ms.mdstate() != 's':
4516 elif ms.mergedriver and ms.mdstate() != 's':
4514 # run conclude step when either a driver-resolved file is requested
4517 # run conclude step when either a driver-resolved file is requested
4515 # or there are no driver-resolved files
4518 # or there are no driver-resolved files
4516 # we can't use 'ret' to determine whether any files are unresolved
4519 # we can't use 'ret' to determine whether any files are unresolved
4517 # because we might not have tried to resolve some
4520 # because we might not have tried to resolve some
4518 if ((runconclude or not list(ms.driverresolved()))
4521 if ((runconclude or not list(ms.driverresolved()))
4519 and not list(ms.unresolved())):
4522 and not list(ms.unresolved())):
4520 proceed = mergemod.driverconclude(repo, ms, wctx)
4523 proceed = mergemod.driverconclude(repo, ms, wctx)
4521 ms.commit()
4524 ms.commit()
4522 if not proceed:
4525 if not proceed:
4523 return 1
4526 return 1
4524
4527
4525 # Nudge users into finishing an unfinished operation
4528 # Nudge users into finishing an unfinished operation
4526 unresolvedf = list(ms.unresolved())
4529 unresolvedf = list(ms.unresolved())
4527 driverresolvedf = list(ms.driverresolved())
4530 driverresolvedf = list(ms.driverresolved())
4528 if not unresolvedf and not driverresolvedf:
4531 if not unresolvedf and not driverresolvedf:
4529 ui.status(_('(no more unresolved files)\n'))
4532 ui.status(_('(no more unresolved files)\n'))
4530 cmdutil.checkafterresolved(repo)
4533 cmdutil.checkafterresolved(repo)
4531 elif not unresolvedf:
4534 elif not unresolvedf:
4532 ui.status(_('(no more unresolved files -- '
4535 ui.status(_('(no more unresolved files -- '
4533 'run "hg resolve --all" to conclude)\n'))
4536 'run "hg resolve --all" to conclude)\n'))
4534
4537
4535 return ret
4538 return ret
4536
4539
4537 @command('revert',
4540 @command('revert',
4538 [('a', 'all', None, _('revert all changes when no arguments given')),
4541 [('a', 'all', None, _('revert all changes when no arguments given')),
4539 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4542 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4540 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4543 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4541 ('C', 'no-backup', None, _('do not save backup copies of files')),
4544 ('C', 'no-backup', None, _('do not save backup copies of files')),
4542 ('i', 'interactive', None, _('interactively select the changes')),
4545 ('i', 'interactive', None, _('interactively select the changes')),
4543 ] + walkopts + dryrunopts,
4546 ] + walkopts + dryrunopts,
4544 _('[OPTION]... [-r REV] [NAME]...'))
4547 _('[OPTION]... [-r REV] [NAME]...'))
4545 def revert(ui, repo, *pats, **opts):
4548 def revert(ui, repo, *pats, **opts):
4546 """restore files to their checkout state
4549 """restore files to their checkout state
4547
4550
4548 .. note::
4551 .. note::
4549
4552
4550 To check out earlier revisions, you should use :hg:`update REV`.
4553 To check out earlier revisions, you should use :hg:`update REV`.
4551 To cancel an uncommitted merge (and lose your changes),
4554 To cancel an uncommitted merge (and lose your changes),
4552 use :hg:`update --clean .`.
4555 use :hg:`update --clean .`.
4553
4556
4554 With no revision specified, revert the specified files or directories
4557 With no revision specified, revert the specified files or directories
4555 to the contents they had in the parent of the working directory.
4558 to the contents they had in the parent of the working directory.
4556 This restores the contents of files to an unmodified
4559 This restores the contents of files to an unmodified
4557 state and unschedules adds, removes, copies, and renames. If the
4560 state and unschedules adds, removes, copies, and renames. If the
4558 working directory has two parents, you must explicitly specify a
4561 working directory has two parents, you must explicitly specify a
4559 revision.
4562 revision.
4560
4563
4561 Using the -r/--rev or -d/--date options, revert the given files or
4564 Using the -r/--rev or -d/--date options, revert the given files or
4562 directories to their states as of a specific revision. Because
4565 directories to their states as of a specific revision. Because
4563 revert does not change the working directory parents, this will
4566 revert does not change the working directory parents, this will
4564 cause these files to appear modified. This can be helpful to "back
4567 cause these files to appear modified. This can be helpful to "back
4565 out" some or all of an earlier change. See :hg:`backout` for a
4568 out" some or all of an earlier change. See :hg:`backout` for a
4566 related method.
4569 related method.
4567
4570
4568 Modified files are saved with a .orig suffix before reverting.
4571 Modified files are saved with a .orig suffix before reverting.
4569 To disable these backups, use --no-backup. It is possible to store
4572 To disable these backups, use --no-backup. It is possible to store
4570 the backup files in a custom directory relative to the root of the
4573 the backup files in a custom directory relative to the root of the
4571 repository by setting the ``ui.origbackuppath`` configuration
4574 repository by setting the ``ui.origbackuppath`` configuration
4572 option.
4575 option.
4573
4576
4574 See :hg:`help dates` for a list of formats valid for -d/--date.
4577 See :hg:`help dates` for a list of formats valid for -d/--date.
4575
4578
4576 See :hg:`help backout` for a way to reverse the effect of an
4579 See :hg:`help backout` for a way to reverse the effect of an
4577 earlier changeset.
4580 earlier changeset.
4578
4581
4579 Returns 0 on success.
4582 Returns 0 on success.
4580 """
4583 """
4581
4584
4582 opts = pycompat.byteskwargs(opts)
4585 opts = pycompat.byteskwargs(opts)
4583 if opts.get("date"):
4586 if opts.get("date"):
4584 if opts.get("rev"):
4587 if opts.get("rev"):
4585 raise error.Abort(_("you can't specify a revision and a date"))
4588 raise error.Abort(_("you can't specify a revision and a date"))
4586 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4589 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4587
4590
4588 parent, p2 = repo.dirstate.parents()
4591 parent, p2 = repo.dirstate.parents()
4589 if not opts.get('rev') and p2 != nullid:
4592 if not opts.get('rev') and p2 != nullid:
4590 # revert after merge is a trap for new users (issue2915)
4593 # revert after merge is a trap for new users (issue2915)
4591 raise error.Abort(_('uncommitted merge with no revision specified'),
4594 raise error.Abort(_('uncommitted merge with no revision specified'),
4592 hint=_("use 'hg update' or see 'hg help revert'"))
4595 hint=_("use 'hg update' or see 'hg help revert'"))
4593
4596
4594 rev = opts.get('rev')
4597 rev = opts.get('rev')
4595 if rev:
4598 if rev:
4596 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
4599 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
4597 ctx = scmutil.revsingle(repo, rev)
4600 ctx = scmutil.revsingle(repo, rev)
4598
4601
4599 if (not (pats or opts.get('include') or opts.get('exclude') or
4602 if (not (pats or opts.get('include') or opts.get('exclude') or
4600 opts.get('all') or opts.get('interactive'))):
4603 opts.get('all') or opts.get('interactive'))):
4601 msg = _("no files or directories specified")
4604 msg = _("no files or directories specified")
4602 if p2 != nullid:
4605 if p2 != nullid:
4603 hint = _("uncommitted merge, use --all to discard all changes,"
4606 hint = _("uncommitted merge, use --all to discard all changes,"
4604 " or 'hg update -C .' to abort the merge")
4607 " or 'hg update -C .' to abort the merge")
4605 raise error.Abort(msg, hint=hint)
4608 raise error.Abort(msg, hint=hint)
4606 dirty = any(repo.status())
4609 dirty = any(repo.status())
4607 node = ctx.node()
4610 node = ctx.node()
4608 if node != parent:
4611 if node != parent:
4609 if dirty:
4612 if dirty:
4610 hint = _("uncommitted changes, use --all to discard all"
4613 hint = _("uncommitted changes, use --all to discard all"
4611 " changes, or 'hg update %s' to update") % ctx.rev()
4614 " changes, or 'hg update %s' to update") % ctx.rev()
4612 else:
4615 else:
4613 hint = _("use --all to revert all files,"
4616 hint = _("use --all to revert all files,"
4614 " or 'hg update %s' to update") % ctx.rev()
4617 " or 'hg update %s' to update") % ctx.rev()
4615 elif dirty:
4618 elif dirty:
4616 hint = _("uncommitted changes, use --all to discard all changes")
4619 hint = _("uncommitted changes, use --all to discard all changes")
4617 else:
4620 else:
4618 hint = _("use --all to revert all files")
4621 hint = _("use --all to revert all files")
4619 raise error.Abort(msg, hint=hint)
4622 raise error.Abort(msg, hint=hint)
4620
4623
4621 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats,
4624 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats,
4622 **pycompat.strkwargs(opts))
4625 **pycompat.strkwargs(opts))
4623
4626
4624 @command('rollback', dryrunopts +
4627 @command('rollback', dryrunopts +
4625 [('f', 'force', False, _('ignore safety measures'))])
4628 [('f', 'force', False, _('ignore safety measures'))])
4626 def rollback(ui, repo, **opts):
4629 def rollback(ui, repo, **opts):
4627 """roll back the last transaction (DANGEROUS) (DEPRECATED)
4630 """roll back the last transaction (DANGEROUS) (DEPRECATED)
4628
4631
4629 Please use :hg:`commit --amend` instead of rollback to correct
4632 Please use :hg:`commit --amend` instead of rollback to correct
4630 mistakes in the last commit.
4633 mistakes in the last commit.
4631
4634
4632 This command should be used with care. There is only one level of
4635 This command should be used with care. There is only one level of
4633 rollback, and there is no way to undo a rollback. It will also
4636 rollback, and there is no way to undo a rollback. It will also
4634 restore the dirstate at the time of the last transaction, losing
4637 restore the dirstate at the time of the last transaction, losing
4635 any dirstate changes since that time. This command does not alter
4638 any dirstate changes since that time. This command does not alter
4636 the working directory.
4639 the working directory.
4637
4640
4638 Transactions are used to encapsulate the effects of all commands
4641 Transactions are used to encapsulate the effects of all commands
4639 that create new changesets or propagate existing changesets into a
4642 that create new changesets or propagate existing changesets into a
4640 repository.
4643 repository.
4641
4644
4642 .. container:: verbose
4645 .. container:: verbose
4643
4646
4644 For example, the following commands are transactional, and their
4647 For example, the following commands are transactional, and their
4645 effects can be rolled back:
4648 effects can be rolled back:
4646
4649
4647 - commit
4650 - commit
4648 - import
4651 - import
4649 - pull
4652 - pull
4650 - push (with this repository as the destination)
4653 - push (with this repository as the destination)
4651 - unbundle
4654 - unbundle
4652
4655
4653 To avoid permanent data loss, rollback will refuse to rollback a
4656 To avoid permanent data loss, rollback will refuse to rollback a
4654 commit transaction if it isn't checked out. Use --force to
4657 commit transaction if it isn't checked out. Use --force to
4655 override this protection.
4658 override this protection.
4656
4659
4657 The rollback command can be entirely disabled by setting the
4660 The rollback command can be entirely disabled by setting the
4658 ``ui.rollback`` configuration setting to false. If you're here
4661 ``ui.rollback`` configuration setting to false. If you're here
4659 because you want to use rollback and it's disabled, you can
4662 because you want to use rollback and it's disabled, you can
4660 re-enable the command by setting ``ui.rollback`` to true.
4663 re-enable the command by setting ``ui.rollback`` to true.
4661
4664
4662 This command is not intended for use on public repositories. Once
4665 This command is not intended for use on public repositories. Once
4663 changes are visible for pull by other users, rolling a transaction
4666 changes are visible for pull by other users, rolling a transaction
4664 back locally is ineffective (someone else may already have pulled
4667 back locally is ineffective (someone else may already have pulled
4665 the changes). Furthermore, a race is possible with readers of the
4668 the changes). Furthermore, a race is possible with readers of the
4666 repository; for example an in-progress pull from the repository
4669 repository; for example an in-progress pull from the repository
4667 may fail if a rollback is performed.
4670 may fail if a rollback is performed.
4668
4671
4669 Returns 0 on success, 1 if no rollback data is available.
4672 Returns 0 on success, 1 if no rollback data is available.
4670 """
4673 """
4671 if not ui.configbool('ui', 'rollback'):
4674 if not ui.configbool('ui', 'rollback'):
4672 raise error.Abort(_('rollback is disabled because it is unsafe'),
4675 raise error.Abort(_('rollback is disabled because it is unsafe'),
4673 hint=('see `hg help -v rollback` for information'))
4676 hint=('see `hg help -v rollback` for information'))
4674 return repo.rollback(dryrun=opts.get(r'dry_run'),
4677 return repo.rollback(dryrun=opts.get(r'dry_run'),
4675 force=opts.get(r'force'))
4678 force=opts.get(r'force'))
4676
4679
4677 @command('root', [], cmdtype=readonly)
4680 @command('root', [], cmdtype=readonly)
4678 def root(ui, repo):
4681 def root(ui, repo):
4679 """print the root (top) of the current working directory
4682 """print the root (top) of the current working directory
4680
4683
4681 Print the root directory of the current repository.
4684 Print the root directory of the current repository.
4682
4685
4683 Returns 0 on success.
4686 Returns 0 on success.
4684 """
4687 """
4685 ui.write(repo.root + "\n")
4688 ui.write(repo.root + "\n")
4686
4689
4687 @command('^serve',
4690 @command('^serve',
4688 [('A', 'accesslog', '', _('name of access log file to write to'),
4691 [('A', 'accesslog', '', _('name of access log file to write to'),
4689 _('FILE')),
4692 _('FILE')),
4690 ('d', 'daemon', None, _('run server in background')),
4693 ('d', 'daemon', None, _('run server in background')),
4691 ('', 'daemon-postexec', [], _('used internally by daemon mode')),
4694 ('', 'daemon-postexec', [], _('used internally by daemon mode')),
4692 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4695 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4693 # use string type, then we can check if something was passed
4696 # use string type, then we can check if something was passed
4694 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4697 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4695 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4698 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4696 _('ADDR')),
4699 _('ADDR')),
4697 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4700 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4698 _('PREFIX')),
4701 _('PREFIX')),
4699 ('n', 'name', '',
4702 ('n', 'name', '',
4700 _('name to show in web pages (default: working directory)'), _('NAME')),
4703 _('name to show in web pages (default: working directory)'), _('NAME')),
4701 ('', 'web-conf', '',
4704 ('', 'web-conf', '',
4702 _("name of the hgweb config file (see 'hg help hgweb')"), _('FILE')),
4705 _("name of the hgweb config file (see 'hg help hgweb')"), _('FILE')),
4703 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4706 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4704 _('FILE')),
4707 _('FILE')),
4705 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4708 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4706 ('', 'stdio', None, _('for remote clients (ADVANCED)')),
4709 ('', 'stdio', None, _('for remote clients (ADVANCED)')),
4707 ('', 'cmdserver', '', _('for remote clients (ADVANCED)'), _('MODE')),
4710 ('', 'cmdserver', '', _('for remote clients (ADVANCED)'), _('MODE')),
4708 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4711 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4709 ('', 'style', '', _('template style to use'), _('STYLE')),
4712 ('', 'style', '', _('template style to use'), _('STYLE')),
4710 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4713 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4711 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))]
4714 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))]
4712 + subrepoopts,
4715 + subrepoopts,
4713 _('[OPTION]...'),
4716 _('[OPTION]...'),
4714 optionalrepo=True)
4717 optionalrepo=True)
4715 def serve(ui, repo, **opts):
4718 def serve(ui, repo, **opts):
4716 """start stand-alone webserver
4719 """start stand-alone webserver
4717
4720
4718 Start a local HTTP repository browser and pull server. You can use
4721 Start a local HTTP repository browser and pull server. You can use
4719 this for ad-hoc sharing and browsing of repositories. It is
4722 this for ad-hoc sharing and browsing of repositories. It is
4720 recommended to use a real web server to serve a repository for
4723 recommended to use a real web server to serve a repository for
4721 longer periods of time.
4724 longer periods of time.
4722
4725
4723 Please note that the server does not implement access control.
4726 Please note that the server does not implement access control.
4724 This means that, by default, anybody can read from the server and
4727 This means that, by default, anybody can read from the server and
4725 nobody can write to it by default. Set the ``web.allow-push``
4728 nobody can write to it by default. Set the ``web.allow-push``
4726 option to ``*`` to allow everybody to push to the server. You
4729 option to ``*`` to allow everybody to push to the server. You
4727 should use a real web server if you need to authenticate users.
4730 should use a real web server if you need to authenticate users.
4728
4731
4729 By default, the server logs accesses to stdout and errors to
4732 By default, the server logs accesses to stdout and errors to
4730 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
4733 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
4731 files.
4734 files.
4732
4735
4733 To have the server choose a free port number to listen on, specify
4736 To have the server choose a free port number to listen on, specify
4734 a port number of 0; in this case, the server will print the port
4737 a port number of 0; in this case, the server will print the port
4735 number it uses.
4738 number it uses.
4736
4739
4737 Returns 0 on success.
4740 Returns 0 on success.
4738 """
4741 """
4739
4742
4740 opts = pycompat.byteskwargs(opts)
4743 opts = pycompat.byteskwargs(opts)
4741 if opts["stdio"] and opts["cmdserver"]:
4744 if opts["stdio"] and opts["cmdserver"]:
4742 raise error.Abort(_("cannot use --stdio with --cmdserver"))
4745 raise error.Abort(_("cannot use --stdio with --cmdserver"))
4743
4746
4744 if opts["stdio"]:
4747 if opts["stdio"]:
4745 if repo is None:
4748 if repo is None:
4746 raise error.RepoError(_("there is no Mercurial repository here"
4749 raise error.RepoError(_("there is no Mercurial repository here"
4747 " (.hg not found)"))
4750 " (.hg not found)"))
4748 s = sshserver.sshserver(ui, repo)
4751 s = sshserver.sshserver(ui, repo)
4749 s.serve_forever()
4752 s.serve_forever()
4750
4753
4751 service = server.createservice(ui, repo, opts)
4754 service = server.createservice(ui, repo, opts)
4752 return server.runservice(opts, initfn=service.init, runfn=service.run)
4755 return server.runservice(opts, initfn=service.init, runfn=service.run)
4753
4756
4754 @command('^status|st',
4757 @command('^status|st',
4755 [('A', 'all', None, _('show status of all files')),
4758 [('A', 'all', None, _('show status of all files')),
4756 ('m', 'modified', None, _('show only modified files')),
4759 ('m', 'modified', None, _('show only modified files')),
4757 ('a', 'added', None, _('show only added files')),
4760 ('a', 'added', None, _('show only added files')),
4758 ('r', 'removed', None, _('show only removed files')),
4761 ('r', 'removed', None, _('show only removed files')),
4759 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4762 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4760 ('c', 'clean', None, _('show only files without changes')),
4763 ('c', 'clean', None, _('show only files without changes')),
4761 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4764 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4762 ('i', 'ignored', None, _('show only ignored files')),
4765 ('i', 'ignored', None, _('show only ignored files')),
4763 ('n', 'no-status', None, _('hide status prefix')),
4766 ('n', 'no-status', None, _('hide status prefix')),
4764 ('t', 'terse', '', _('show the terse output (EXPERIMENTAL)')),
4767 ('t', 'terse', '', _('show the terse output (EXPERIMENTAL)')),
4765 ('C', 'copies', None, _('show source of copied files')),
4768 ('C', 'copies', None, _('show source of copied files')),
4766 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4769 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4767 ('', 'rev', [], _('show difference from revision'), _('REV')),
4770 ('', 'rev', [], _('show difference from revision'), _('REV')),
4768 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
4771 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
4769 ] + walkopts + subrepoopts + formatteropts,
4772 ] + walkopts + subrepoopts + formatteropts,
4770 _('[OPTION]... [FILE]...'),
4773 _('[OPTION]... [FILE]...'),
4771 inferrepo=True, cmdtype=readonly)
4774 inferrepo=True, cmdtype=readonly)
4772 def status(ui, repo, *pats, **opts):
4775 def status(ui, repo, *pats, **opts):
4773 """show changed files in the working directory
4776 """show changed files in the working directory
4774
4777
4775 Show status of files in the repository. If names are given, only
4778 Show status of files in the repository. If names are given, only
4776 files that match are shown. Files that are clean or ignored or
4779 files that match are shown. Files that are clean or ignored or
4777 the source of a copy/move operation, are not listed unless
4780 the source of a copy/move operation, are not listed unless
4778 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
4781 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
4779 Unless options described with "show only ..." are given, the
4782 Unless options described with "show only ..." are given, the
4780 options -mardu are used.
4783 options -mardu are used.
4781
4784
4782 Option -q/--quiet hides untracked (unknown and ignored) files
4785 Option -q/--quiet hides untracked (unknown and ignored) files
4783 unless explicitly requested with -u/--unknown or -i/--ignored.
4786 unless explicitly requested with -u/--unknown or -i/--ignored.
4784
4787
4785 .. note::
4788 .. note::
4786
4789
4787 :hg:`status` may appear to disagree with diff if permissions have
4790 :hg:`status` may appear to disagree with diff if permissions have
4788 changed or a merge has occurred. The standard diff format does
4791 changed or a merge has occurred. The standard diff format does
4789 not report permission changes and diff only reports changes
4792 not report permission changes and diff only reports changes
4790 relative to one merge parent.
4793 relative to one merge parent.
4791
4794
4792 If one revision is given, it is used as the base revision.
4795 If one revision is given, it is used as the base revision.
4793 If two revisions are given, the differences between them are
4796 If two revisions are given, the differences between them are
4794 shown. The --change option can also be used as a shortcut to list
4797 shown. The --change option can also be used as a shortcut to list
4795 the changed files of a revision from its first parent.
4798 the changed files of a revision from its first parent.
4796
4799
4797 The codes used to show the status of files are::
4800 The codes used to show the status of files are::
4798
4801
4799 M = modified
4802 M = modified
4800 A = added
4803 A = added
4801 R = removed
4804 R = removed
4802 C = clean
4805 C = clean
4803 ! = missing (deleted by non-hg command, but still tracked)
4806 ! = missing (deleted by non-hg command, but still tracked)
4804 ? = not tracked
4807 ? = not tracked
4805 I = ignored
4808 I = ignored
4806 = origin of the previous file (with --copies)
4809 = origin of the previous file (with --copies)
4807
4810
4808 .. container:: verbose
4811 .. container:: verbose
4809
4812
4810 The -t/--terse option abbreviates the output by showing only the directory
4813 The -t/--terse option abbreviates the output by showing only the directory
4811 name if all the files in it share the same status. The option takes an
4814 name if all the files in it share the same status. The option takes an
4812 argument indicating the statuses to abbreviate: 'm' for 'modified', 'a'
4815 argument indicating the statuses to abbreviate: 'm' for 'modified', 'a'
4813 for 'added', 'r' for 'removed', 'd' for 'deleted', 'u' for 'unknown', 'i'
4816 for 'added', 'r' for 'removed', 'd' for 'deleted', 'u' for 'unknown', 'i'
4814 for 'ignored' and 'c' for clean.
4817 for 'ignored' and 'c' for clean.
4815
4818
4816 It abbreviates only those statuses which are passed. Note that clean and
4819 It abbreviates only those statuses which are passed. Note that clean and
4817 ignored files are not displayed with '--terse ic' unless the -c/--clean
4820 ignored files are not displayed with '--terse ic' unless the -c/--clean
4818 and -i/--ignored options are also used.
4821 and -i/--ignored options are also used.
4819
4822
4820 The -v/--verbose option shows information when the repository is in an
4823 The -v/--verbose option shows information when the repository is in an
4821 unfinished merge, shelve, rebase state etc. You can have this behavior
4824 unfinished merge, shelve, rebase state etc. You can have this behavior
4822 turned on by default by enabling the ``commands.status.verbose`` option.
4825 turned on by default by enabling the ``commands.status.verbose`` option.
4823
4826
4824 You can skip displaying some of these states by setting
4827 You can skip displaying some of these states by setting
4825 ``commands.status.skipstates`` to one or more of: 'bisect', 'graft',
4828 ``commands.status.skipstates`` to one or more of: 'bisect', 'graft',
4826 'histedit', 'merge', 'rebase', or 'unshelve'.
4829 'histedit', 'merge', 'rebase', or 'unshelve'.
4827
4830
4828 Examples:
4831 Examples:
4829
4832
4830 - show changes in the working directory relative to a
4833 - show changes in the working directory relative to a
4831 changeset::
4834 changeset::
4832
4835
4833 hg status --rev 9353
4836 hg status --rev 9353
4834
4837
4835 - show changes in the working directory relative to the
4838 - show changes in the working directory relative to the
4836 current directory (see :hg:`help patterns` for more information)::
4839 current directory (see :hg:`help patterns` for more information)::
4837
4840
4838 hg status re:
4841 hg status re:
4839
4842
4840 - show all changes including copies in an existing changeset::
4843 - show all changes including copies in an existing changeset::
4841
4844
4842 hg status --copies --change 9353
4845 hg status --copies --change 9353
4843
4846
4844 - get a NUL separated list of added files, suitable for xargs::
4847 - get a NUL separated list of added files, suitable for xargs::
4845
4848
4846 hg status -an0
4849 hg status -an0
4847
4850
4848 - show more information about the repository status, abbreviating
4851 - show more information about the repository status, abbreviating
4849 added, removed, modified, deleted, and untracked paths::
4852 added, removed, modified, deleted, and untracked paths::
4850
4853
4851 hg status -v -t mardu
4854 hg status -v -t mardu
4852
4855
4853 Returns 0 on success.
4856 Returns 0 on success.
4854
4857
4855 """
4858 """
4856
4859
4857 opts = pycompat.byteskwargs(opts)
4860 opts = pycompat.byteskwargs(opts)
4858 revs = opts.get('rev')
4861 revs = opts.get('rev')
4859 change = opts.get('change')
4862 change = opts.get('change')
4860 terse = opts.get('terse')
4863 terse = opts.get('terse')
4861
4864
4862 if revs and change:
4865 if revs and change:
4863 msg = _('cannot specify --rev and --change at the same time')
4866 msg = _('cannot specify --rev and --change at the same time')
4864 raise error.Abort(msg)
4867 raise error.Abort(msg)
4865 elif revs and terse:
4868 elif revs and terse:
4866 msg = _('cannot use --terse with --rev')
4869 msg = _('cannot use --terse with --rev')
4867 raise error.Abort(msg)
4870 raise error.Abort(msg)
4868 elif change:
4871 elif change:
4869 repo = scmutil.unhidehashlikerevs(repo, [change], 'nowarn')
4872 repo = scmutil.unhidehashlikerevs(repo, [change], 'nowarn')
4870 node2 = scmutil.revsingle(repo, change, None).node()
4873 node2 = scmutil.revsingle(repo, change, None).node()
4871 node1 = repo[node2].p1().node()
4874 node1 = repo[node2].p1().node()
4872 else:
4875 else:
4873 repo = scmutil.unhidehashlikerevs(repo, revs, 'nowarn')
4876 repo = scmutil.unhidehashlikerevs(repo, revs, 'nowarn')
4874 node1, node2 = scmutil.revpair(repo, revs)
4877 node1, node2 = scmutil.revpair(repo, revs)
4875
4878
4876 if pats or ui.configbool('commands', 'status.relative'):
4879 if pats or ui.configbool('commands', 'status.relative'):
4877 cwd = repo.getcwd()
4880 cwd = repo.getcwd()
4878 else:
4881 else:
4879 cwd = ''
4882 cwd = ''
4880
4883
4881 if opts.get('print0'):
4884 if opts.get('print0'):
4882 end = '\0'
4885 end = '\0'
4883 else:
4886 else:
4884 end = '\n'
4887 end = '\n'
4885 copy = {}
4888 copy = {}
4886 states = 'modified added removed deleted unknown ignored clean'.split()
4889 states = 'modified added removed deleted unknown ignored clean'.split()
4887 show = [k for k in states if opts.get(k)]
4890 show = [k for k in states if opts.get(k)]
4888 if opts.get('all'):
4891 if opts.get('all'):
4889 show += ui.quiet and (states[:4] + ['clean']) or states
4892 show += ui.quiet and (states[:4] + ['clean']) or states
4890
4893
4891 if not show:
4894 if not show:
4892 if ui.quiet:
4895 if ui.quiet:
4893 show = states[:4]
4896 show = states[:4]
4894 else:
4897 else:
4895 show = states[:5]
4898 show = states[:5]
4896
4899
4897 m = scmutil.match(repo[node2], pats, opts)
4900 m = scmutil.match(repo[node2], pats, opts)
4898 if terse:
4901 if terse:
4899 # we need to compute clean and unknown to terse
4902 # we need to compute clean and unknown to terse
4900 stat = repo.status(node1, node2, m,
4903 stat = repo.status(node1, node2, m,
4901 'ignored' in show or 'i' in terse,
4904 'ignored' in show or 'i' in terse,
4902 True, True, opts.get('subrepos'))
4905 True, True, opts.get('subrepos'))
4903
4906
4904 stat = cmdutil.tersedir(stat, terse)
4907 stat = cmdutil.tersedir(stat, terse)
4905 else:
4908 else:
4906 stat = repo.status(node1, node2, m,
4909 stat = repo.status(node1, node2, m,
4907 'ignored' in show, 'clean' in show,
4910 'ignored' in show, 'clean' in show,
4908 'unknown' in show, opts.get('subrepos'))
4911 'unknown' in show, opts.get('subrepos'))
4909
4912
4910 changestates = zip(states, pycompat.iterbytestr('MAR!?IC'), stat)
4913 changestates = zip(states, pycompat.iterbytestr('MAR!?IC'), stat)
4911
4914
4912 if (opts.get('all') or opts.get('copies')
4915 if (opts.get('all') or opts.get('copies')
4913 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
4916 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
4914 copy = copies.pathcopies(repo[node1], repo[node2], m)
4917 copy = copies.pathcopies(repo[node1], repo[node2], m)
4915
4918
4916 ui.pager('status')
4919 ui.pager('status')
4917 fm = ui.formatter('status', opts)
4920 fm = ui.formatter('status', opts)
4918 fmt = '%s' + end
4921 fmt = '%s' + end
4919 showchar = not opts.get('no_status')
4922 showchar = not opts.get('no_status')
4920
4923
4921 for state, char, files in changestates:
4924 for state, char, files in changestates:
4922 if state in show:
4925 if state in show:
4923 label = 'status.' + state
4926 label = 'status.' + state
4924 for f in files:
4927 for f in files:
4925 fm.startitem()
4928 fm.startitem()
4926 fm.condwrite(showchar, 'status', '%s ', char, label=label)
4929 fm.condwrite(showchar, 'status', '%s ', char, label=label)
4927 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
4930 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
4928 if f in copy:
4931 if f in copy:
4929 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
4932 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
4930 label='status.copied')
4933 label='status.copied')
4931
4934
4932 if ((ui.verbose or ui.configbool('commands', 'status.verbose'))
4935 if ((ui.verbose or ui.configbool('commands', 'status.verbose'))
4933 and not ui.plain()):
4936 and not ui.plain()):
4934 cmdutil.morestatus(repo, fm)
4937 cmdutil.morestatus(repo, fm)
4935 fm.end()
4938 fm.end()
4936
4939
4937 @command('^summary|sum',
4940 @command('^summary|sum',
4938 [('', 'remote', None, _('check for push and pull'))],
4941 [('', 'remote', None, _('check for push and pull'))],
4939 '[--remote]', cmdtype=readonly)
4942 '[--remote]', cmdtype=readonly)
4940 def summary(ui, repo, **opts):
4943 def summary(ui, repo, **opts):
4941 """summarize working directory state
4944 """summarize working directory state
4942
4945
4943 This generates a brief summary of the working directory state,
4946 This generates a brief summary of the working directory state,
4944 including parents, branch, commit status, phase and available updates.
4947 including parents, branch, commit status, phase and available updates.
4945
4948
4946 With the --remote option, this will check the default paths for
4949 With the --remote option, this will check the default paths for
4947 incoming and outgoing changes. This can be time-consuming.
4950 incoming and outgoing changes. This can be time-consuming.
4948
4951
4949 Returns 0 on success.
4952 Returns 0 on success.
4950 """
4953 """
4951
4954
4952 opts = pycompat.byteskwargs(opts)
4955 opts = pycompat.byteskwargs(opts)
4953 ui.pager('summary')
4956 ui.pager('summary')
4954 ctx = repo[None]
4957 ctx = repo[None]
4955 parents = ctx.parents()
4958 parents = ctx.parents()
4956 pnode = parents[0].node()
4959 pnode = parents[0].node()
4957 marks = []
4960 marks = []
4958
4961
4959 ms = None
4962 ms = None
4960 try:
4963 try:
4961 ms = mergemod.mergestate.read(repo)
4964 ms = mergemod.mergestate.read(repo)
4962 except error.UnsupportedMergeRecords as e:
4965 except error.UnsupportedMergeRecords as e:
4963 s = ' '.join(e.recordtypes)
4966 s = ' '.join(e.recordtypes)
4964 ui.warn(
4967 ui.warn(
4965 _('warning: merge state has unsupported record types: %s\n') % s)
4968 _('warning: merge state has unsupported record types: %s\n') % s)
4966 unresolved = []
4969 unresolved = []
4967 else:
4970 else:
4968 unresolved = list(ms.unresolved())
4971 unresolved = list(ms.unresolved())
4969
4972
4970 for p in parents:
4973 for p in parents:
4971 # label with log.changeset (instead of log.parent) since this
4974 # label with log.changeset (instead of log.parent) since this
4972 # shows a working directory parent *changeset*:
4975 # shows a working directory parent *changeset*:
4973 # i18n: column positioning for "hg summary"
4976 # i18n: column positioning for "hg summary"
4974 ui.write(_('parent: %d:%s ') % (p.rev(), p),
4977 ui.write(_('parent: %d:%s ') % (p.rev(), p),
4975 label=cmdutil._changesetlabels(p))
4978 label=cmdutil._changesetlabels(p))
4976 ui.write(' '.join(p.tags()), label='log.tag')
4979 ui.write(' '.join(p.tags()), label='log.tag')
4977 if p.bookmarks():
4980 if p.bookmarks():
4978 marks.extend(p.bookmarks())
4981 marks.extend(p.bookmarks())
4979 if p.rev() == -1:
4982 if p.rev() == -1:
4980 if not len(repo):
4983 if not len(repo):
4981 ui.write(_(' (empty repository)'))
4984 ui.write(_(' (empty repository)'))
4982 else:
4985 else:
4983 ui.write(_(' (no revision checked out)'))
4986 ui.write(_(' (no revision checked out)'))
4984 if p.obsolete():
4987 if p.obsolete():
4985 ui.write(_(' (obsolete)'))
4988 ui.write(_(' (obsolete)'))
4986 if p.isunstable():
4989 if p.isunstable():
4987 instabilities = (ui.label(instability, 'trouble.%s' % instability)
4990 instabilities = (ui.label(instability, 'trouble.%s' % instability)
4988 for instability in p.instabilities())
4991 for instability in p.instabilities())
4989 ui.write(' ('
4992 ui.write(' ('
4990 + ', '.join(instabilities)
4993 + ', '.join(instabilities)
4991 + ')')
4994 + ')')
4992 ui.write('\n')
4995 ui.write('\n')
4993 if p.description():
4996 if p.description():
4994 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
4997 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
4995 label='log.summary')
4998 label='log.summary')
4996
4999
4997 branch = ctx.branch()
5000 branch = ctx.branch()
4998 bheads = repo.branchheads(branch)
5001 bheads = repo.branchheads(branch)
4999 # i18n: column positioning for "hg summary"
5002 # i18n: column positioning for "hg summary"
5000 m = _('branch: %s\n') % branch
5003 m = _('branch: %s\n') % branch
5001 if branch != 'default':
5004 if branch != 'default':
5002 ui.write(m, label='log.branch')
5005 ui.write(m, label='log.branch')
5003 else:
5006 else:
5004 ui.status(m, label='log.branch')
5007 ui.status(m, label='log.branch')
5005
5008
5006 if marks:
5009 if marks:
5007 active = repo._activebookmark
5010 active = repo._activebookmark
5008 # i18n: column positioning for "hg summary"
5011 # i18n: column positioning for "hg summary"
5009 ui.write(_('bookmarks:'), label='log.bookmark')
5012 ui.write(_('bookmarks:'), label='log.bookmark')
5010 if active is not None:
5013 if active is not None:
5011 if active in marks:
5014 if active in marks:
5012 ui.write(' *' + active, label=bookmarks.activebookmarklabel)
5015 ui.write(' *' + active, label=bookmarks.activebookmarklabel)
5013 marks.remove(active)
5016 marks.remove(active)
5014 else:
5017 else:
5015 ui.write(' [%s]' % active, label=bookmarks.activebookmarklabel)
5018 ui.write(' [%s]' % active, label=bookmarks.activebookmarklabel)
5016 for m in marks:
5019 for m in marks:
5017 ui.write(' ' + m, label='log.bookmark')
5020 ui.write(' ' + m, label='log.bookmark')
5018 ui.write('\n', label='log.bookmark')
5021 ui.write('\n', label='log.bookmark')
5019
5022
5020 status = repo.status(unknown=True)
5023 status = repo.status(unknown=True)
5021
5024
5022 c = repo.dirstate.copies()
5025 c = repo.dirstate.copies()
5023 copied, renamed = [], []
5026 copied, renamed = [], []
5024 for d, s in c.iteritems():
5027 for d, s in c.iteritems():
5025 if s in status.removed:
5028 if s in status.removed:
5026 status.removed.remove(s)
5029 status.removed.remove(s)
5027 renamed.append(d)
5030 renamed.append(d)
5028 else:
5031 else:
5029 copied.append(d)
5032 copied.append(d)
5030 if d in status.added:
5033 if d in status.added:
5031 status.added.remove(d)
5034 status.added.remove(d)
5032
5035
5033 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5036 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5034
5037
5035 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
5038 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
5036 (ui.label(_('%d added'), 'status.added'), status.added),
5039 (ui.label(_('%d added'), 'status.added'), status.added),
5037 (ui.label(_('%d removed'), 'status.removed'), status.removed),
5040 (ui.label(_('%d removed'), 'status.removed'), status.removed),
5038 (ui.label(_('%d renamed'), 'status.copied'), renamed),
5041 (ui.label(_('%d renamed'), 'status.copied'), renamed),
5039 (ui.label(_('%d copied'), 'status.copied'), copied),
5042 (ui.label(_('%d copied'), 'status.copied'), copied),
5040 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
5043 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
5041 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
5044 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
5042 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
5045 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
5043 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
5046 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
5044 t = []
5047 t = []
5045 for l, s in labels:
5048 for l, s in labels:
5046 if s:
5049 if s:
5047 t.append(l % len(s))
5050 t.append(l % len(s))
5048
5051
5049 t = ', '.join(t)
5052 t = ', '.join(t)
5050 cleanworkdir = False
5053 cleanworkdir = False
5051
5054
5052 if repo.vfs.exists('graftstate'):
5055 if repo.vfs.exists('graftstate'):
5053 t += _(' (graft in progress)')
5056 t += _(' (graft in progress)')
5054 if repo.vfs.exists('updatestate'):
5057 if repo.vfs.exists('updatestate'):
5055 t += _(' (interrupted update)')
5058 t += _(' (interrupted update)')
5056 elif len(parents) > 1:
5059 elif len(parents) > 1:
5057 t += _(' (merge)')
5060 t += _(' (merge)')
5058 elif branch != parents[0].branch():
5061 elif branch != parents[0].branch():
5059 t += _(' (new branch)')
5062 t += _(' (new branch)')
5060 elif (parents[0].closesbranch() and
5063 elif (parents[0].closesbranch() and
5061 pnode in repo.branchheads(branch, closed=True)):
5064 pnode in repo.branchheads(branch, closed=True)):
5062 t += _(' (head closed)')
5065 t += _(' (head closed)')
5063 elif not (status.modified or status.added or status.removed or renamed or
5066 elif not (status.modified or status.added or status.removed or renamed or
5064 copied or subs):
5067 copied or subs):
5065 t += _(' (clean)')
5068 t += _(' (clean)')
5066 cleanworkdir = True
5069 cleanworkdir = True
5067 elif pnode not in bheads:
5070 elif pnode not in bheads:
5068 t += _(' (new branch head)')
5071 t += _(' (new branch head)')
5069
5072
5070 if parents:
5073 if parents:
5071 pendingphase = max(p.phase() for p in parents)
5074 pendingphase = max(p.phase() for p in parents)
5072 else:
5075 else:
5073 pendingphase = phases.public
5076 pendingphase = phases.public
5074
5077
5075 if pendingphase > phases.newcommitphase(ui):
5078 if pendingphase > phases.newcommitphase(ui):
5076 t += ' (%s)' % phases.phasenames[pendingphase]
5079 t += ' (%s)' % phases.phasenames[pendingphase]
5077
5080
5078 if cleanworkdir:
5081 if cleanworkdir:
5079 # i18n: column positioning for "hg summary"
5082 # i18n: column positioning for "hg summary"
5080 ui.status(_('commit: %s\n') % t.strip())
5083 ui.status(_('commit: %s\n') % t.strip())
5081 else:
5084 else:
5082 # i18n: column positioning for "hg summary"
5085 # i18n: column positioning for "hg summary"
5083 ui.write(_('commit: %s\n') % t.strip())
5086 ui.write(_('commit: %s\n') % t.strip())
5084
5087
5085 # all ancestors of branch heads - all ancestors of parent = new csets
5088 # all ancestors of branch heads - all ancestors of parent = new csets
5086 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
5089 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
5087 bheads))
5090 bheads))
5088
5091
5089 if new == 0:
5092 if new == 0:
5090 # i18n: column positioning for "hg summary"
5093 # i18n: column positioning for "hg summary"
5091 ui.status(_('update: (current)\n'))
5094 ui.status(_('update: (current)\n'))
5092 elif pnode not in bheads:
5095 elif pnode not in bheads:
5093 # i18n: column positioning for "hg summary"
5096 # i18n: column positioning for "hg summary"
5094 ui.write(_('update: %d new changesets (update)\n') % new)
5097 ui.write(_('update: %d new changesets (update)\n') % new)
5095 else:
5098 else:
5096 # i18n: column positioning for "hg summary"
5099 # i18n: column positioning for "hg summary"
5097 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5100 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5098 (new, len(bheads)))
5101 (new, len(bheads)))
5099
5102
5100 t = []
5103 t = []
5101 draft = len(repo.revs('draft()'))
5104 draft = len(repo.revs('draft()'))
5102 if draft:
5105 if draft:
5103 t.append(_('%d draft') % draft)
5106 t.append(_('%d draft') % draft)
5104 secret = len(repo.revs('secret()'))
5107 secret = len(repo.revs('secret()'))
5105 if secret:
5108 if secret:
5106 t.append(_('%d secret') % secret)
5109 t.append(_('%d secret') % secret)
5107
5110
5108 if draft or secret:
5111 if draft or secret:
5109 ui.status(_('phases: %s\n') % ', '.join(t))
5112 ui.status(_('phases: %s\n') % ', '.join(t))
5110
5113
5111 if obsolete.isenabled(repo, obsolete.createmarkersopt):
5114 if obsolete.isenabled(repo, obsolete.createmarkersopt):
5112 for trouble in ("orphan", "contentdivergent", "phasedivergent"):
5115 for trouble in ("orphan", "contentdivergent", "phasedivergent"):
5113 numtrouble = len(repo.revs(trouble + "()"))
5116 numtrouble = len(repo.revs(trouble + "()"))
5114 # We write all the possibilities to ease translation
5117 # We write all the possibilities to ease translation
5115 troublemsg = {
5118 troublemsg = {
5116 "orphan": _("orphan: %d changesets"),
5119 "orphan": _("orphan: %d changesets"),
5117 "contentdivergent": _("content-divergent: %d changesets"),
5120 "contentdivergent": _("content-divergent: %d changesets"),
5118 "phasedivergent": _("phase-divergent: %d changesets"),
5121 "phasedivergent": _("phase-divergent: %d changesets"),
5119 }
5122 }
5120 if numtrouble > 0:
5123 if numtrouble > 0:
5121 ui.status(troublemsg[trouble] % numtrouble + "\n")
5124 ui.status(troublemsg[trouble] % numtrouble + "\n")
5122
5125
5123 cmdutil.summaryhooks(ui, repo)
5126 cmdutil.summaryhooks(ui, repo)
5124
5127
5125 if opts.get('remote'):
5128 if opts.get('remote'):
5126 needsincoming, needsoutgoing = True, True
5129 needsincoming, needsoutgoing = True, True
5127 else:
5130 else:
5128 needsincoming, needsoutgoing = False, False
5131 needsincoming, needsoutgoing = False, False
5129 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5132 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5130 if i:
5133 if i:
5131 needsincoming = True
5134 needsincoming = True
5132 if o:
5135 if o:
5133 needsoutgoing = True
5136 needsoutgoing = True
5134 if not needsincoming and not needsoutgoing:
5137 if not needsincoming and not needsoutgoing:
5135 return
5138 return
5136
5139
5137 def getincoming():
5140 def getincoming():
5138 source, branches = hg.parseurl(ui.expandpath('default'))
5141 source, branches = hg.parseurl(ui.expandpath('default'))
5139 sbranch = branches[0]
5142 sbranch = branches[0]
5140 try:
5143 try:
5141 other = hg.peer(repo, {}, source)
5144 other = hg.peer(repo, {}, source)
5142 except error.RepoError:
5145 except error.RepoError:
5143 if opts.get('remote'):
5146 if opts.get('remote'):
5144 raise
5147 raise
5145 return source, sbranch, None, None, None
5148 return source, sbranch, None, None, None
5146 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5149 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5147 if revs:
5150 if revs:
5148 revs = [other.lookup(rev) for rev in revs]
5151 revs = [other.lookup(rev) for rev in revs]
5149 ui.debug('comparing with %s\n' % util.hidepassword(source))
5152 ui.debug('comparing with %s\n' % util.hidepassword(source))
5150 repo.ui.pushbuffer()
5153 repo.ui.pushbuffer()
5151 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5154 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5152 repo.ui.popbuffer()
5155 repo.ui.popbuffer()
5153 return source, sbranch, other, commoninc, commoninc[1]
5156 return source, sbranch, other, commoninc, commoninc[1]
5154
5157
5155 if needsincoming:
5158 if needsincoming:
5156 source, sbranch, sother, commoninc, incoming = getincoming()
5159 source, sbranch, sother, commoninc, incoming = getincoming()
5157 else:
5160 else:
5158 source = sbranch = sother = commoninc = incoming = None
5161 source = sbranch = sother = commoninc = incoming = None
5159
5162
5160 def getoutgoing():
5163 def getoutgoing():
5161 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5164 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5162 dbranch = branches[0]
5165 dbranch = branches[0]
5163 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5166 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5164 if source != dest:
5167 if source != dest:
5165 try:
5168 try:
5166 dother = hg.peer(repo, {}, dest)
5169 dother = hg.peer(repo, {}, dest)
5167 except error.RepoError:
5170 except error.RepoError:
5168 if opts.get('remote'):
5171 if opts.get('remote'):
5169 raise
5172 raise
5170 return dest, dbranch, None, None
5173 return dest, dbranch, None, None
5171 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5174 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5172 elif sother is None:
5175 elif sother is None:
5173 # there is no explicit destination peer, but source one is invalid
5176 # there is no explicit destination peer, but source one is invalid
5174 return dest, dbranch, None, None
5177 return dest, dbranch, None, None
5175 else:
5178 else:
5176 dother = sother
5179 dother = sother
5177 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5180 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5178 common = None
5181 common = None
5179 else:
5182 else:
5180 common = commoninc
5183 common = commoninc
5181 if revs:
5184 if revs:
5182 revs = [repo.lookup(rev) for rev in revs]
5185 revs = [repo.lookup(rev) for rev in revs]
5183 repo.ui.pushbuffer()
5186 repo.ui.pushbuffer()
5184 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5187 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5185 commoninc=common)
5188 commoninc=common)
5186 repo.ui.popbuffer()
5189 repo.ui.popbuffer()
5187 return dest, dbranch, dother, outgoing
5190 return dest, dbranch, dother, outgoing
5188
5191
5189 if needsoutgoing:
5192 if needsoutgoing:
5190 dest, dbranch, dother, outgoing = getoutgoing()
5193 dest, dbranch, dother, outgoing = getoutgoing()
5191 else:
5194 else:
5192 dest = dbranch = dother = outgoing = None
5195 dest = dbranch = dother = outgoing = None
5193
5196
5194 if opts.get('remote'):
5197 if opts.get('remote'):
5195 t = []
5198 t = []
5196 if incoming:
5199 if incoming:
5197 t.append(_('1 or more incoming'))
5200 t.append(_('1 or more incoming'))
5198 o = outgoing.missing
5201 o = outgoing.missing
5199 if o:
5202 if o:
5200 t.append(_('%d outgoing') % len(o))
5203 t.append(_('%d outgoing') % len(o))
5201 other = dother or sother
5204 other = dother or sother
5202 if 'bookmarks' in other.listkeys('namespaces'):
5205 if 'bookmarks' in other.listkeys('namespaces'):
5203 counts = bookmarks.summary(repo, other)
5206 counts = bookmarks.summary(repo, other)
5204 if counts[0] > 0:
5207 if counts[0] > 0:
5205 t.append(_('%d incoming bookmarks') % counts[0])
5208 t.append(_('%d incoming bookmarks') % counts[0])
5206 if counts[1] > 0:
5209 if counts[1] > 0:
5207 t.append(_('%d outgoing bookmarks') % counts[1])
5210 t.append(_('%d outgoing bookmarks') % counts[1])
5208
5211
5209 if t:
5212 if t:
5210 # i18n: column positioning for "hg summary"
5213 # i18n: column positioning for "hg summary"
5211 ui.write(_('remote: %s\n') % (', '.join(t)))
5214 ui.write(_('remote: %s\n') % (', '.join(t)))
5212 else:
5215 else:
5213 # i18n: column positioning for "hg summary"
5216 # i18n: column positioning for "hg summary"
5214 ui.status(_('remote: (synced)\n'))
5217 ui.status(_('remote: (synced)\n'))
5215
5218
5216 cmdutil.summaryremotehooks(ui, repo, opts,
5219 cmdutil.summaryremotehooks(ui, repo, opts,
5217 ((source, sbranch, sother, commoninc),
5220 ((source, sbranch, sother, commoninc),
5218 (dest, dbranch, dother, outgoing)))
5221 (dest, dbranch, dother, outgoing)))
5219
5222
5220 @command('tag',
5223 @command('tag',
5221 [('f', 'force', None, _('force tag')),
5224 [('f', 'force', None, _('force tag')),
5222 ('l', 'local', None, _('make the tag local')),
5225 ('l', 'local', None, _('make the tag local')),
5223 ('r', 'rev', '', _('revision to tag'), _('REV')),
5226 ('r', 'rev', '', _('revision to tag'), _('REV')),
5224 ('', 'remove', None, _('remove a tag')),
5227 ('', 'remove', None, _('remove a tag')),
5225 # -l/--local is already there, commitopts cannot be used
5228 # -l/--local is already there, commitopts cannot be used
5226 ('e', 'edit', None, _('invoke editor on commit messages')),
5229 ('e', 'edit', None, _('invoke editor on commit messages')),
5227 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5230 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5228 ] + commitopts2,
5231 ] + commitopts2,
5229 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5232 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5230 def tag(ui, repo, name1, *names, **opts):
5233 def tag(ui, repo, name1, *names, **opts):
5231 """add one or more tags for the current or given revision
5234 """add one or more tags for the current or given revision
5232
5235
5233 Name a particular revision using <name>.
5236 Name a particular revision using <name>.
5234
5237
5235 Tags are used to name particular revisions of the repository and are
5238 Tags are used to name particular revisions of the repository and are
5236 very useful to compare different revisions, to go back to significant
5239 very useful to compare different revisions, to go back to significant
5237 earlier versions or to mark branch points as releases, etc. Changing
5240 earlier versions or to mark branch points as releases, etc. Changing
5238 an existing tag is normally disallowed; use -f/--force to override.
5241 an existing tag is normally disallowed; use -f/--force to override.
5239
5242
5240 If no revision is given, the parent of the working directory is
5243 If no revision is given, the parent of the working directory is
5241 used.
5244 used.
5242
5245
5243 To facilitate version control, distribution, and merging of tags,
5246 To facilitate version control, distribution, and merging of tags,
5244 they are stored as a file named ".hgtags" which is managed similarly
5247 they are stored as a file named ".hgtags" which is managed similarly
5245 to other project files and can be hand-edited if necessary. This
5248 to other project files and can be hand-edited if necessary. This
5246 also means that tagging creates a new commit. The file
5249 also means that tagging creates a new commit. The file
5247 ".hg/localtags" is used for local tags (not shared among
5250 ".hg/localtags" is used for local tags (not shared among
5248 repositories).
5251 repositories).
5249
5252
5250 Tag commits are usually made at the head of a branch. If the parent
5253 Tag commits are usually made at the head of a branch. If the parent
5251 of the working directory is not a branch head, :hg:`tag` aborts; use
5254 of the working directory is not a branch head, :hg:`tag` aborts; use
5252 -f/--force to force the tag commit to be based on a non-head
5255 -f/--force to force the tag commit to be based on a non-head
5253 changeset.
5256 changeset.
5254
5257
5255 See :hg:`help dates` for a list of formats valid for -d/--date.
5258 See :hg:`help dates` for a list of formats valid for -d/--date.
5256
5259
5257 Since tag names have priority over branch names during revision
5260 Since tag names have priority over branch names during revision
5258 lookup, using an existing branch name as a tag name is discouraged.
5261 lookup, using an existing branch name as a tag name is discouraged.
5259
5262
5260 Returns 0 on success.
5263 Returns 0 on success.
5261 """
5264 """
5262 opts = pycompat.byteskwargs(opts)
5265 opts = pycompat.byteskwargs(opts)
5263 wlock = lock = None
5266 wlock = lock = None
5264 try:
5267 try:
5265 wlock = repo.wlock()
5268 wlock = repo.wlock()
5266 lock = repo.lock()
5269 lock = repo.lock()
5267 rev_ = "."
5270 rev_ = "."
5268 names = [t.strip() for t in (name1,) + names]
5271 names = [t.strip() for t in (name1,) + names]
5269 if len(names) != len(set(names)):
5272 if len(names) != len(set(names)):
5270 raise error.Abort(_('tag names must be unique'))
5273 raise error.Abort(_('tag names must be unique'))
5271 for n in names:
5274 for n in names:
5272 scmutil.checknewlabel(repo, n, 'tag')
5275 scmutil.checknewlabel(repo, n, 'tag')
5273 if not n:
5276 if not n:
5274 raise error.Abort(_('tag names cannot consist entirely of '
5277 raise error.Abort(_('tag names cannot consist entirely of '
5275 'whitespace'))
5278 'whitespace'))
5276 if opts.get('rev') and opts.get('remove'):
5279 if opts.get('rev') and opts.get('remove'):
5277 raise error.Abort(_("--rev and --remove are incompatible"))
5280 raise error.Abort(_("--rev and --remove are incompatible"))
5278 if opts.get('rev'):
5281 if opts.get('rev'):
5279 rev_ = opts['rev']
5282 rev_ = opts['rev']
5280 message = opts.get('message')
5283 message = opts.get('message')
5281 if opts.get('remove'):
5284 if opts.get('remove'):
5282 if opts.get('local'):
5285 if opts.get('local'):
5283 expectedtype = 'local'
5286 expectedtype = 'local'
5284 else:
5287 else:
5285 expectedtype = 'global'
5288 expectedtype = 'global'
5286
5289
5287 for n in names:
5290 for n in names:
5288 if not repo.tagtype(n):
5291 if not repo.tagtype(n):
5289 raise error.Abort(_("tag '%s' does not exist") % n)
5292 raise error.Abort(_("tag '%s' does not exist") % n)
5290 if repo.tagtype(n) != expectedtype:
5293 if repo.tagtype(n) != expectedtype:
5291 if expectedtype == 'global':
5294 if expectedtype == 'global':
5292 raise error.Abort(_("tag '%s' is not a global tag") % n)
5295 raise error.Abort(_("tag '%s' is not a global tag") % n)
5293 else:
5296 else:
5294 raise error.Abort(_("tag '%s' is not a local tag") % n)
5297 raise error.Abort(_("tag '%s' is not a local tag") % n)
5295 rev_ = 'null'
5298 rev_ = 'null'
5296 if not message:
5299 if not message:
5297 # we don't translate commit messages
5300 # we don't translate commit messages
5298 message = 'Removed tag %s' % ', '.join(names)
5301 message = 'Removed tag %s' % ', '.join(names)
5299 elif not opts.get('force'):
5302 elif not opts.get('force'):
5300 for n in names:
5303 for n in names:
5301 if n in repo.tags():
5304 if n in repo.tags():
5302 raise error.Abort(_("tag '%s' already exists "
5305 raise error.Abort(_("tag '%s' already exists "
5303 "(use -f to force)") % n)
5306 "(use -f to force)") % n)
5304 if not opts.get('local'):
5307 if not opts.get('local'):
5305 p1, p2 = repo.dirstate.parents()
5308 p1, p2 = repo.dirstate.parents()
5306 if p2 != nullid:
5309 if p2 != nullid:
5307 raise error.Abort(_('uncommitted merge'))
5310 raise error.Abort(_('uncommitted merge'))
5308 bheads = repo.branchheads()
5311 bheads = repo.branchheads()
5309 if not opts.get('force') and bheads and p1 not in bheads:
5312 if not opts.get('force') and bheads and p1 not in bheads:
5310 raise error.Abort(_('working directory is not at a branch head '
5313 raise error.Abort(_('working directory is not at a branch head '
5311 '(use -f to force)'))
5314 '(use -f to force)'))
5312 r = scmutil.revsingle(repo, rev_).node()
5315 r = scmutil.revsingle(repo, rev_).node()
5313
5316
5314 if not message:
5317 if not message:
5315 # we don't translate commit messages
5318 # we don't translate commit messages
5316 message = ('Added tag %s for changeset %s' %
5319 message = ('Added tag %s for changeset %s' %
5317 (', '.join(names), short(r)))
5320 (', '.join(names), short(r)))
5318
5321
5319 date = opts.get('date')
5322 date = opts.get('date')
5320 if date:
5323 if date:
5321 date = util.parsedate(date)
5324 date = util.parsedate(date)
5322
5325
5323 if opts.get('remove'):
5326 if opts.get('remove'):
5324 editform = 'tag.remove'
5327 editform = 'tag.remove'
5325 else:
5328 else:
5326 editform = 'tag.add'
5329 editform = 'tag.add'
5327 editor = cmdutil.getcommiteditor(editform=editform,
5330 editor = cmdutil.getcommiteditor(editform=editform,
5328 **pycompat.strkwargs(opts))
5331 **pycompat.strkwargs(opts))
5329
5332
5330 # don't allow tagging the null rev
5333 # don't allow tagging the null rev
5331 if (not opts.get('remove') and
5334 if (not opts.get('remove') and
5332 scmutil.revsingle(repo, rev_).rev() == nullrev):
5335 scmutil.revsingle(repo, rev_).rev() == nullrev):
5333 raise error.Abort(_("cannot tag null revision"))
5336 raise error.Abort(_("cannot tag null revision"))
5334
5337
5335 tagsmod.tag(repo, names, r, message, opts.get('local'),
5338 tagsmod.tag(repo, names, r, message, opts.get('local'),
5336 opts.get('user'), date, editor=editor)
5339 opts.get('user'), date, editor=editor)
5337 finally:
5340 finally:
5338 release(lock, wlock)
5341 release(lock, wlock)
5339
5342
5340 @command('tags', formatteropts, '', cmdtype=readonly)
5343 @command('tags', formatteropts, '', cmdtype=readonly)
5341 def tags(ui, repo, **opts):
5344 def tags(ui, repo, **opts):
5342 """list repository tags
5345 """list repository tags
5343
5346
5344 This lists both regular and local tags. When the -v/--verbose
5347 This lists both regular and local tags. When the -v/--verbose
5345 switch is used, a third column "local" is printed for local tags.
5348 switch is used, a third column "local" is printed for local tags.
5346 When the -q/--quiet switch is used, only the tag name is printed.
5349 When the -q/--quiet switch is used, only the tag name is printed.
5347
5350
5348 Returns 0 on success.
5351 Returns 0 on success.
5349 """
5352 """
5350
5353
5351 opts = pycompat.byteskwargs(opts)
5354 opts = pycompat.byteskwargs(opts)
5352 ui.pager('tags')
5355 ui.pager('tags')
5353 fm = ui.formatter('tags', opts)
5356 fm = ui.formatter('tags', opts)
5354 hexfunc = fm.hexfunc
5357 hexfunc = fm.hexfunc
5355 tagtype = ""
5358 tagtype = ""
5356
5359
5357 for t, n in reversed(repo.tagslist()):
5360 for t, n in reversed(repo.tagslist()):
5358 hn = hexfunc(n)
5361 hn = hexfunc(n)
5359 label = 'tags.normal'
5362 label = 'tags.normal'
5360 tagtype = ''
5363 tagtype = ''
5361 if repo.tagtype(t) == 'local':
5364 if repo.tagtype(t) == 'local':
5362 label = 'tags.local'
5365 label = 'tags.local'
5363 tagtype = 'local'
5366 tagtype = 'local'
5364
5367
5365 fm.startitem()
5368 fm.startitem()
5366 fm.write('tag', '%s', t, label=label)
5369 fm.write('tag', '%s', t, label=label)
5367 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5370 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5368 fm.condwrite(not ui.quiet, 'rev node', fmt,
5371 fm.condwrite(not ui.quiet, 'rev node', fmt,
5369 repo.changelog.rev(n), hn, label=label)
5372 repo.changelog.rev(n), hn, label=label)
5370 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5373 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5371 tagtype, label=label)
5374 tagtype, label=label)
5372 fm.plain('\n')
5375 fm.plain('\n')
5373 fm.end()
5376 fm.end()
5374
5377
5375 @command('tip',
5378 @command('tip',
5376 [('p', 'patch', None, _('show patch')),
5379 [('p', 'patch', None, _('show patch')),
5377 ('g', 'git', None, _('use git extended diff format')),
5380 ('g', 'git', None, _('use git extended diff format')),
5378 ] + templateopts,
5381 ] + templateopts,
5379 _('[-p] [-g]'))
5382 _('[-p] [-g]'))
5380 def tip(ui, repo, **opts):
5383 def tip(ui, repo, **opts):
5381 """show the tip revision (DEPRECATED)
5384 """show the tip revision (DEPRECATED)
5382
5385
5383 The tip revision (usually just called the tip) is the changeset
5386 The tip revision (usually just called the tip) is the changeset
5384 most recently added to the repository (and therefore the most
5387 most recently added to the repository (and therefore the most
5385 recently changed head).
5388 recently changed head).
5386
5389
5387 If you have just made a commit, that commit will be the tip. If
5390 If you have just made a commit, that commit will be the tip. If
5388 you have just pulled changes from another repository, the tip of
5391 you have just pulled changes from another repository, the tip of
5389 that repository becomes the current tip. The "tip" tag is special
5392 that repository becomes the current tip. The "tip" tag is special
5390 and cannot be renamed or assigned to a different changeset.
5393 and cannot be renamed or assigned to a different changeset.
5391
5394
5392 This command is deprecated, please use :hg:`heads` instead.
5395 This command is deprecated, please use :hg:`heads` instead.
5393
5396
5394 Returns 0 on success.
5397 Returns 0 on success.
5395 """
5398 """
5396 opts = pycompat.byteskwargs(opts)
5399 opts = pycompat.byteskwargs(opts)
5397 displayer = cmdutil.show_changeset(ui, repo, opts)
5400 displayer = cmdutil.show_changeset(ui, repo, opts)
5398 displayer.show(repo['tip'])
5401 displayer.show(repo['tip'])
5399 displayer.close()
5402 displayer.close()
5400
5403
5401 @command('unbundle',
5404 @command('unbundle',
5402 [('u', 'update', None,
5405 [('u', 'update', None,
5403 _('update to new branch head if changesets were unbundled'))],
5406 _('update to new branch head if changesets were unbundled'))],
5404 _('[-u] FILE...'))
5407 _('[-u] FILE...'))
5405 def unbundle(ui, repo, fname1, *fnames, **opts):
5408 def unbundle(ui, repo, fname1, *fnames, **opts):
5406 """apply one or more bundle files
5409 """apply one or more bundle files
5407
5410
5408 Apply one or more bundle files generated by :hg:`bundle`.
5411 Apply one or more bundle files generated by :hg:`bundle`.
5409
5412
5410 Returns 0 on success, 1 if an update has unresolved files.
5413 Returns 0 on success, 1 if an update has unresolved files.
5411 """
5414 """
5412 fnames = (fname1,) + fnames
5415 fnames = (fname1,) + fnames
5413
5416
5414 with repo.lock():
5417 with repo.lock():
5415 for fname in fnames:
5418 for fname in fnames:
5416 f = hg.openpath(ui, fname)
5419 f = hg.openpath(ui, fname)
5417 gen = exchange.readbundle(ui, f, fname)
5420 gen = exchange.readbundle(ui, f, fname)
5418 if isinstance(gen, streamclone.streamcloneapplier):
5421 if isinstance(gen, streamclone.streamcloneapplier):
5419 raise error.Abort(
5422 raise error.Abort(
5420 _('packed bundles cannot be applied with '
5423 _('packed bundles cannot be applied with '
5421 '"hg unbundle"'),
5424 '"hg unbundle"'),
5422 hint=_('use "hg debugapplystreamclonebundle"'))
5425 hint=_('use "hg debugapplystreamclonebundle"'))
5423 url = 'bundle:' + fname
5426 url = 'bundle:' + fname
5424 try:
5427 try:
5425 txnname = 'unbundle'
5428 txnname = 'unbundle'
5426 if not isinstance(gen, bundle2.unbundle20):
5429 if not isinstance(gen, bundle2.unbundle20):
5427 txnname = 'unbundle\n%s' % util.hidepassword(url)
5430 txnname = 'unbundle\n%s' % util.hidepassword(url)
5428 with repo.transaction(txnname) as tr:
5431 with repo.transaction(txnname) as tr:
5429 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
5432 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
5430 url=url)
5433 url=url)
5431 except error.BundleUnknownFeatureError as exc:
5434 except error.BundleUnknownFeatureError as exc:
5432 raise error.Abort(
5435 raise error.Abort(
5433 _('%s: unknown bundle feature, %s') % (fname, exc),
5436 _('%s: unknown bundle feature, %s') % (fname, exc),
5434 hint=_("see https://mercurial-scm.org/"
5437 hint=_("see https://mercurial-scm.org/"
5435 "wiki/BundleFeature for more "
5438 "wiki/BundleFeature for more "
5436 "information"))
5439 "information"))
5437 modheads = bundle2.combinechangegroupresults(op)
5440 modheads = bundle2.combinechangegroupresults(op)
5438
5441
5439 return postincoming(ui, repo, modheads, opts.get(r'update'), None, None)
5442 return postincoming(ui, repo, modheads, opts.get(r'update'), None, None)
5440
5443
5441 @command('^update|up|checkout|co',
5444 @command('^update|up|checkout|co',
5442 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5445 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5443 ('c', 'check', None, _('require clean working directory')),
5446 ('c', 'check', None, _('require clean working directory')),
5444 ('m', 'merge', None, _('merge uncommitted changes')),
5447 ('m', 'merge', None, _('merge uncommitted changes')),
5445 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5448 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5446 ('r', 'rev', '', _('revision'), _('REV'))
5449 ('r', 'rev', '', _('revision'), _('REV'))
5447 ] + mergetoolopts,
5450 ] + mergetoolopts,
5448 _('[-C|-c|-m] [-d DATE] [[-r] REV]'))
5451 _('[-C|-c|-m] [-d DATE] [[-r] REV]'))
5449 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
5452 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
5450 merge=None, tool=None):
5453 merge=None, tool=None):
5451 """update working directory (or switch revisions)
5454 """update working directory (or switch revisions)
5452
5455
5453 Update the repository's working directory to the specified
5456 Update the repository's working directory to the specified
5454 changeset. If no changeset is specified, update to the tip of the
5457 changeset. If no changeset is specified, update to the tip of the
5455 current named branch and move the active bookmark (see :hg:`help
5458 current named branch and move the active bookmark (see :hg:`help
5456 bookmarks`).
5459 bookmarks`).
5457
5460
5458 Update sets the working directory's parent revision to the specified
5461 Update sets the working directory's parent revision to the specified
5459 changeset (see :hg:`help parents`).
5462 changeset (see :hg:`help parents`).
5460
5463
5461 If the changeset is not a descendant or ancestor of the working
5464 If the changeset is not a descendant or ancestor of the working
5462 directory's parent and there are uncommitted changes, the update is
5465 directory's parent and there are uncommitted changes, the update is
5463 aborted. With the -c/--check option, the working directory is checked
5466 aborted. With the -c/--check option, the working directory is checked
5464 for uncommitted changes; if none are found, the working directory is
5467 for uncommitted changes; if none are found, the working directory is
5465 updated to the specified changeset.
5468 updated to the specified changeset.
5466
5469
5467 .. container:: verbose
5470 .. container:: verbose
5468
5471
5469 The -C/--clean, -c/--check, and -m/--merge options control what
5472 The -C/--clean, -c/--check, and -m/--merge options control what
5470 happens if the working directory contains uncommitted changes.
5473 happens if the working directory contains uncommitted changes.
5471 At most of one of them can be specified.
5474 At most of one of them can be specified.
5472
5475
5473 1. If no option is specified, and if
5476 1. If no option is specified, and if
5474 the requested changeset is an ancestor or descendant of
5477 the requested changeset is an ancestor or descendant of
5475 the working directory's parent, the uncommitted changes
5478 the working directory's parent, the uncommitted changes
5476 are merged into the requested changeset and the merged
5479 are merged into the requested changeset and the merged
5477 result is left uncommitted. If the requested changeset is
5480 result is left uncommitted. If the requested changeset is
5478 not an ancestor or descendant (that is, it is on another
5481 not an ancestor or descendant (that is, it is on another
5479 branch), the update is aborted and the uncommitted changes
5482 branch), the update is aborted and the uncommitted changes
5480 are preserved.
5483 are preserved.
5481
5484
5482 2. With the -m/--merge option, the update is allowed even if the
5485 2. With the -m/--merge option, the update is allowed even if the
5483 requested changeset is not an ancestor or descendant of
5486 requested changeset is not an ancestor or descendant of
5484 the working directory's parent.
5487 the working directory's parent.
5485
5488
5486 3. With the -c/--check option, the update is aborted and the
5489 3. With the -c/--check option, the update is aborted and the
5487 uncommitted changes are preserved.
5490 uncommitted changes are preserved.
5488
5491
5489 4. With the -C/--clean option, uncommitted changes are discarded and
5492 4. With the -C/--clean option, uncommitted changes are discarded and
5490 the working directory is updated to the requested changeset.
5493 the working directory is updated to the requested changeset.
5491
5494
5492 To cancel an uncommitted merge (and lose your changes), use
5495 To cancel an uncommitted merge (and lose your changes), use
5493 :hg:`update --clean .`.
5496 :hg:`update --clean .`.
5494
5497
5495 Use null as the changeset to remove the working directory (like
5498 Use null as the changeset to remove the working directory (like
5496 :hg:`clone -U`).
5499 :hg:`clone -U`).
5497
5500
5498 If you want to revert just one file to an older revision, use
5501 If you want to revert just one file to an older revision, use
5499 :hg:`revert [-r REV] NAME`.
5502 :hg:`revert [-r REV] NAME`.
5500
5503
5501 See :hg:`help dates` for a list of formats valid for -d/--date.
5504 See :hg:`help dates` for a list of formats valid for -d/--date.
5502
5505
5503 Returns 0 on success, 1 if there are unresolved files.
5506 Returns 0 on success, 1 if there are unresolved files.
5504 """
5507 """
5505 if rev and node:
5508 if rev and node:
5506 raise error.Abort(_("please specify just one revision"))
5509 raise error.Abort(_("please specify just one revision"))
5507
5510
5508 if ui.configbool('commands', 'update.requiredest'):
5511 if ui.configbool('commands', 'update.requiredest'):
5509 if not node and not rev and not date:
5512 if not node and not rev and not date:
5510 raise error.Abort(_('you must specify a destination'),
5513 raise error.Abort(_('you must specify a destination'),
5511 hint=_('for example: hg update ".::"'))
5514 hint=_('for example: hg update ".::"'))
5512
5515
5513 if rev is None or rev == '':
5516 if rev is None or rev == '':
5514 rev = node
5517 rev = node
5515
5518
5516 if date and rev is not None:
5519 if date and rev is not None:
5517 raise error.Abort(_("you can't specify a revision and a date"))
5520 raise error.Abort(_("you can't specify a revision and a date"))
5518
5521
5519 if len([x for x in (clean, check, merge) if x]) > 1:
5522 if len([x for x in (clean, check, merge) if x]) > 1:
5520 raise error.Abort(_("can only specify one of -C/--clean, -c/--check, "
5523 raise error.Abort(_("can only specify one of -C/--clean, -c/--check, "
5521 "or -m/--merge"))
5524 "or -m/--merge"))
5522
5525
5523 updatecheck = None
5526 updatecheck = None
5524 if check:
5527 if check:
5525 updatecheck = 'abort'
5528 updatecheck = 'abort'
5526 elif merge:
5529 elif merge:
5527 updatecheck = 'none'
5530 updatecheck = 'none'
5528
5531
5529 with repo.wlock():
5532 with repo.wlock():
5530 cmdutil.clearunfinished(repo)
5533 cmdutil.clearunfinished(repo)
5531
5534
5532 if date:
5535 if date:
5533 rev = cmdutil.finddate(ui, repo, date)
5536 rev = cmdutil.finddate(ui, repo, date)
5534
5537
5535 # if we defined a bookmark, we have to remember the original name
5538 # if we defined a bookmark, we have to remember the original name
5536 brev = rev
5539 brev = rev
5537 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
5540 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
5538 ctx = scmutil.revsingle(repo, rev, rev)
5541 ctx = scmutil.revsingle(repo, rev, rev)
5539 rev = ctx.rev()
5542 rev = ctx.rev()
5540 if ctx.hidden():
5543 if ctx.hidden():
5541 ui.warn(_("updating to a hidden changeset %s\n") % ctx.hex()[:12])
5544 ui.warn(_("updating to a hidden changeset %s\n") % ctx.hex()[:12])
5542
5545
5543 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
5546 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
5544
5547
5545 return hg.updatetotally(ui, repo, rev, brev, clean=clean,
5548 return hg.updatetotally(ui, repo, rev, brev, clean=clean,
5546 updatecheck=updatecheck)
5549 updatecheck=updatecheck)
5547
5550
5548 @command('verify', [])
5551 @command('verify', [])
5549 def verify(ui, repo):
5552 def verify(ui, repo):
5550 """verify the integrity of the repository
5553 """verify the integrity of the repository
5551
5554
5552 Verify the integrity of the current repository.
5555 Verify the integrity of the current repository.
5553
5556
5554 This will perform an extensive check of the repository's
5557 This will perform an extensive check of the repository's
5555 integrity, validating the hashes and checksums of each entry in
5558 integrity, validating the hashes and checksums of each entry in
5556 the changelog, manifest, and tracked files, as well as the
5559 the changelog, manifest, and tracked files, as well as the
5557 integrity of their crosslinks and indices.
5560 integrity of their crosslinks and indices.
5558
5561
5559 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
5562 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
5560 for more information about recovery from corruption of the
5563 for more information about recovery from corruption of the
5561 repository.
5564 repository.
5562
5565
5563 Returns 0 on success, 1 if errors are encountered.
5566 Returns 0 on success, 1 if errors are encountered.
5564 """
5567 """
5565 return hg.verify(repo)
5568 return hg.verify(repo)
5566
5569
5567 @command('version', [] + formatteropts, norepo=True, cmdtype=readonly)
5570 @command('version', [] + formatteropts, norepo=True, cmdtype=readonly)
5568 def version_(ui, **opts):
5571 def version_(ui, **opts):
5569 """output version and copyright information"""
5572 """output version and copyright information"""
5570 opts = pycompat.byteskwargs(opts)
5573 opts = pycompat.byteskwargs(opts)
5571 if ui.verbose:
5574 if ui.verbose:
5572 ui.pager('version')
5575 ui.pager('version')
5573 fm = ui.formatter("version", opts)
5576 fm = ui.formatter("version", opts)
5574 fm.startitem()
5577 fm.startitem()
5575 fm.write("ver", _("Mercurial Distributed SCM (version %s)\n"),
5578 fm.write("ver", _("Mercurial Distributed SCM (version %s)\n"),
5576 util.version())
5579 util.version())
5577 license = _(
5580 license = _(
5578 "(see https://mercurial-scm.org for more information)\n"
5581 "(see https://mercurial-scm.org for more information)\n"
5579 "\nCopyright (C) 2005-2017 Matt Mackall and others\n"
5582 "\nCopyright (C) 2005-2017 Matt Mackall and others\n"
5580 "This is free software; see the source for copying conditions. "
5583 "This is free software; see the source for copying conditions. "
5581 "There is NO\nwarranty; "
5584 "There is NO\nwarranty; "
5582 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5585 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5583 )
5586 )
5584 if not ui.quiet:
5587 if not ui.quiet:
5585 fm.plain(license)
5588 fm.plain(license)
5586
5589
5587 if ui.verbose:
5590 if ui.verbose:
5588 fm.plain(_("\nEnabled extensions:\n\n"))
5591 fm.plain(_("\nEnabled extensions:\n\n"))
5589 # format names and versions into columns
5592 # format names and versions into columns
5590 names = []
5593 names = []
5591 vers = []
5594 vers = []
5592 isinternals = []
5595 isinternals = []
5593 for name, module in extensions.extensions():
5596 for name, module in extensions.extensions():
5594 names.append(name)
5597 names.append(name)
5595 vers.append(extensions.moduleversion(module) or None)
5598 vers.append(extensions.moduleversion(module) or None)
5596 isinternals.append(extensions.ismoduleinternal(module))
5599 isinternals.append(extensions.ismoduleinternal(module))
5597 fn = fm.nested("extensions")
5600 fn = fm.nested("extensions")
5598 if names:
5601 if names:
5599 namefmt = " %%-%ds " % max(len(n) for n in names)
5602 namefmt = " %%-%ds " % max(len(n) for n in names)
5600 places = [_("external"), _("internal")]
5603 places = [_("external"), _("internal")]
5601 for n, v, p in zip(names, vers, isinternals):
5604 for n, v, p in zip(names, vers, isinternals):
5602 fn.startitem()
5605 fn.startitem()
5603 fn.condwrite(ui.verbose, "name", namefmt, n)
5606 fn.condwrite(ui.verbose, "name", namefmt, n)
5604 if ui.verbose:
5607 if ui.verbose:
5605 fn.plain("%s " % places[p])
5608 fn.plain("%s " % places[p])
5606 fn.data(bundled=p)
5609 fn.data(bundled=p)
5607 fn.condwrite(ui.verbose and v, "ver", "%s", v)
5610 fn.condwrite(ui.verbose and v, "ver", "%s", v)
5608 if ui.verbose:
5611 if ui.verbose:
5609 fn.plain("\n")
5612 fn.plain("\n")
5610 fn.end()
5613 fn.end()
5611 fm.end()
5614 fm.end()
5612
5615
5613 def loadcmdtable(ui, name, cmdtable):
5616 def loadcmdtable(ui, name, cmdtable):
5614 """Load command functions from specified cmdtable
5617 """Load command functions from specified cmdtable
5615 """
5618 """
5616 overrides = [cmd for cmd in cmdtable if cmd in table]
5619 overrides = [cmd for cmd in cmdtable if cmd in table]
5617 if overrides:
5620 if overrides:
5618 ui.warn(_("extension '%s' overrides commands: %s\n")
5621 ui.warn(_("extension '%s' overrides commands: %s\n")
5619 % (name, " ".join(overrides)))
5622 % (name, " ".join(overrides)))
5620 table.update(cmdtable)
5623 table.update(cmdtable)
@@ -1,183 +1,188 b''
1 Tests for access level on hidden commits by various commands on based of their
1 Tests for access level on hidden commits by various commands on based of their
2 type.
2 type.
3
3
4 Setting the required config to start this
4 Setting the required config to start this
5
5
6 $ cat >> $HGRCPATH <<EOF
6 $ cat >> $HGRCPATH <<EOF
7 > [experimental]
7 > [experimental]
8 > evolution=createmarkers, allowunstable
8 > evolution=createmarkers, allowunstable
9 > directaccess=True
9 > directaccess=True
10 > directaccess.revnums=True
10 > directaccess.revnums=True
11 > [extensions]
11 > [extensions]
12 > amend =
12 > amend =
13 > EOF
13 > EOF
14
14
15 $ hg init repo
15 $ hg init repo
16 $ cd repo
16 $ cd repo
17 $ for ch in a b c; do touch $ch; echo "foo" >> $ch; hg ci -Aqm "Added "$ch; done
17 $ for ch in a b c; do touch $ch; echo "foo" >> $ch; hg ci -Aqm "Added "$ch; done
18
18
19 $ hg log -G -T '{rev}:{node} {desc}' --hidden
19 $ hg log -G -T '{rev}:{node} {desc}' --hidden
20 @ 2:28ad74487de9599d00d81085be739c61fc340652 Added c
20 @ 2:28ad74487de9599d00d81085be739c61fc340652 Added c
21 |
21 |
22 o 1:29becc82797a4bc11ec8880b58eaecd2ab3e7760 Added b
22 o 1:29becc82797a4bc11ec8880b58eaecd2ab3e7760 Added b
23 |
23 |
24 o 0:18d04c59bb5d2d4090ad9a5b59bd6274adb63add Added a
24 o 0:18d04c59bb5d2d4090ad9a5b59bd6274adb63add Added a
25
25
26 $ echo "bar" >> c
26 $ echo "bar" >> c
27 $ hg amend
27 $ hg amend
28
28
29 $ hg log -G -T '{rev}:{node} {desc}' --hidden
29 $ hg log -G -T '{rev}:{node} {desc}' --hidden
30 @ 3:2443a0e664694756d8b435d06b6ad84f941b6fc0 Added c
30 @ 3:2443a0e664694756d8b435d06b6ad84f941b6fc0 Added c
31 |
31 |
32 | x 2:28ad74487de9599d00d81085be739c61fc340652 Added c
32 | x 2:28ad74487de9599d00d81085be739c61fc340652 Added c
33 |/
33 |/
34 o 1:29becc82797a4bc11ec8880b58eaecd2ab3e7760 Added b
34 o 1:29becc82797a4bc11ec8880b58eaecd2ab3e7760 Added b
35 |
35 |
36 o 0:18d04c59bb5d2d4090ad9a5b59bd6274adb63add Added a
36 o 0:18d04c59bb5d2d4090ad9a5b59bd6274adb63add Added a
37
37
38 Testing read only commands on the hidden revision
38 Testing read only commands on the hidden revision
39
39
40 Testing with rev number
40 Testing with rev number
41
41
42 $ hg exp 2 --config experimental.directaccess.revnums=False
42 $ hg exp 2 --config experimental.directaccess.revnums=False
43 abort: hidden revision '2'!
43 abort: hidden revision '2'!
44 (use --hidden to access hidden revisions)
44 (use --hidden to access hidden revisions)
45 [255]
45 [255]
46
46
47 $ hg exp 2
47 $ hg exp 2
48 # HG changeset patch
48 # HG changeset patch
49 # User test
49 # User test
50 # Date 0 0
50 # Date 0 0
51 # Thu Jan 01 00:00:00 1970 +0000
51 # Thu Jan 01 00:00:00 1970 +0000
52 # Node ID 28ad74487de9599d00d81085be739c61fc340652
52 # Node ID 28ad74487de9599d00d81085be739c61fc340652
53 # Parent 29becc82797a4bc11ec8880b58eaecd2ab3e7760
53 # Parent 29becc82797a4bc11ec8880b58eaecd2ab3e7760
54 Added c
54 Added c
55
55
56 diff -r 29becc82797a -r 28ad74487de9 c
56 diff -r 29becc82797a -r 28ad74487de9 c
57 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
57 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
58 +++ b/c Thu Jan 01 00:00:00 1970 +0000
58 +++ b/c Thu Jan 01 00:00:00 1970 +0000
59 @@ -0,0 +1,1 @@
59 @@ -0,0 +1,1 @@
60 +foo
60 +foo
61
61
62 $ hg log -r 2
62 $ hg log -r 2
63 changeset: 2:28ad74487de9
63 changeset: 2:28ad74487de9
64 user: test
64 user: test
65 date: Thu Jan 01 00:00:00 1970 +0000
65 date: Thu Jan 01 00:00:00 1970 +0000
66 obsolete: rewritten using amend as 3:2443a0e66469
66 obsolete: rewritten using amend as 3:2443a0e66469
67 summary: Added c
67 summary: Added c
68
68
69 $ hg identify -r 2
69 $ hg identify -r 2
70 28ad74487de9
70 28ad74487de9
71
71
72 $ hg status --change 2
72 $ hg status --change 2
73 A c
73 A c
74
74
75 $ hg status --change 2 --config experimental.directaccess.revnums=False
75 $ hg status --change 2 --config experimental.directaccess.revnums=False
76 abort: hidden revision '2'!
76 abort: hidden revision '2'!
77 (use --hidden to access hidden revisions)
77 (use --hidden to access hidden revisions)
78 [255]
78 [255]
79
79
80 $ hg diff -c 2
80 $ hg diff -c 2
81 diff -r 29becc82797a -r 28ad74487de9 c
81 diff -r 29becc82797a -r 28ad74487de9 c
82 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
82 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
83 +++ b/c Thu Jan 01 00:00:00 1970 +0000
83 +++ b/c Thu Jan 01 00:00:00 1970 +0000
84 @@ -0,0 +1,1 @@
84 @@ -0,0 +1,1 @@
85 +foo
85 +foo
86
86
87 Testing with hash
87 Testing with hash
88
88
89 `hg export`
89 `hg export`
90
90
91 $ hg exp 28ad74
91 $ hg exp 28ad74
92 # HG changeset patch
92 # HG changeset patch
93 # User test
93 # User test
94 # Date 0 0
94 # Date 0 0
95 # Thu Jan 01 00:00:00 1970 +0000
95 # Thu Jan 01 00:00:00 1970 +0000
96 # Node ID 28ad74487de9599d00d81085be739c61fc340652
96 # Node ID 28ad74487de9599d00d81085be739c61fc340652
97 # Parent 29becc82797a4bc11ec8880b58eaecd2ab3e7760
97 # Parent 29becc82797a4bc11ec8880b58eaecd2ab3e7760
98 Added c
98 Added c
99
99
100 diff -r 29becc82797a -r 28ad74487de9 c
100 diff -r 29becc82797a -r 28ad74487de9 c
101 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
101 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
102 +++ b/c Thu Jan 01 00:00:00 1970 +0000
102 +++ b/c Thu Jan 01 00:00:00 1970 +0000
103 @@ -0,0 +1,1 @@
103 @@ -0,0 +1,1 @@
104 +foo
104 +foo
105
105
106 `hg log`
106 `hg log`
107
107
108 $ hg log -r 28ad74
108 $ hg log -r 28ad74
109 changeset: 2:28ad74487de9
109 changeset: 2:28ad74487de9
110 user: test
110 user: test
111 date: Thu Jan 01 00:00:00 1970 +0000
111 date: Thu Jan 01 00:00:00 1970 +0000
112 obsolete: rewritten using amend as 3:2443a0e66469
112 obsolete: rewritten using amend as 3:2443a0e66469
113 summary: Added c
113 summary: Added c
114
114
115 `hg cat`
115 `hg cat`
116
116
117 $ hg cat -r 28ad74 c
117 $ hg cat -r 28ad74 c
118 foo
118 foo
119
119
120 `hg diff`
120 `hg diff`
121
121
122 $ hg diff -c 28ad74
122 $ hg diff -c 28ad74
123 diff -r 29becc82797a -r 28ad74487de9 c
123 diff -r 29becc82797a -r 28ad74487de9 c
124 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
124 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
125 +++ b/c Thu Jan 01 00:00:00 1970 +0000
125 +++ b/c Thu Jan 01 00:00:00 1970 +0000
126 @@ -0,0 +1,1 @@
126 @@ -0,0 +1,1 @@
127 +foo
127 +foo
128
128
129 `hg files`
129 `hg files`
130
130
131 $ hg files -r 28ad74
131 $ hg files -r 28ad74
132 a
132 a
133 b
133 b
134 c
134 c
135
135
136 `hg identify`
136 `hg identify`
137
137
138 $ hg identify -r 28ad74
138 $ hg identify -r 28ad74
139 28ad74487de9
139 28ad74487de9
140
140
141 `hg annotate`
141 `hg annotate`
142
142
143 $ hg annotate -r 28ad74 a
143 $ hg annotate -r 28ad74 a
144 0: foo
144 0: foo
145
145
146 `hg status`
146 `hg status`
147
147
148 $ hg status --change 28ad74
148 $ hg status --change 28ad74
149 A c
149 A c
150
150
151 `hg archive`
152
153 This should not throw error
154 $ hg archive -r 28ad74 foo
155
151 `hg update`
156 `hg update`
152
157
153 $ hg up 28ad74
158 $ hg up 28ad74
154 updating to a hidden changeset 28ad74487de9
159 updating to a hidden changeset 28ad74487de9
155 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
160 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
156
161
157 $ hg up 3
162 $ hg up 3
158 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
163 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
159
164
160 `hg revert`
165 `hg revert`
161
166
162 $ hg revert -r 28ad74 --all
167 $ hg revert -r 28ad74 --all
163 reverting c
168 reverting c
164
169
165 $ hg diff
170 $ hg diff
166 diff -r 2443a0e66469 c
171 diff -r 2443a0e66469 c
167 --- a/c Thu Jan 01 00:00:00 1970 +0000
172 --- a/c Thu Jan 01 00:00:00 1970 +0000
168 +++ b/c Thu Jan 01 00:00:00 1970 +0000
173 +++ b/c Thu Jan 01 00:00:00 1970 +0000
169 @@ -1,2 +1,1 @@
174 @@ -1,2 +1,1 @@
170 foo
175 foo
171 -bar
176 -bar
172
177
173 Commands with undefined cmdtype should not work right now
178 Commands with undefined cmdtype should not work right now
174
179
175 $ hg phase -r 28ad74
180 $ hg phase -r 28ad74
176 abort: hidden revision '28ad74'!
181 abort: hidden revision '28ad74'!
177 (use --hidden to access hidden revisions)
182 (use --hidden to access hidden revisions)
178 [255]
183 [255]
179
184
180 $ hg phase -r 2
185 $ hg phase -r 2
181 abort: hidden revision '2'!
186 abort: hidden revision '2'!
182 (use --hidden to access hidden revisions)
187 (use --hidden to access hidden revisions)
183 [255]
188 [255]
General Comments 0
You need to be logged in to leave comments. Login now