##// END OF EJS Templates
bookmarks: fix check of hash-like name to not abort by ambiguous identifier...
Yuya Nishihara -
r32482:579df5aa default
parent child Browse files
Show More
@@ -1,5477 +1,5482
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
14
15 from .i18n import _
15 from .i18n import _
16 from .node import (
16 from .node import (
17 hex,
17 hex,
18 nullid,
18 nullid,
19 nullrev,
19 nullrev,
20 short,
20 short,
21 )
21 )
22 from . import (
22 from . import (
23 archival,
23 archival,
24 bookmarks,
24 bookmarks,
25 bundle2,
25 bundle2,
26 changegroup,
26 changegroup,
27 cmdutil,
27 cmdutil,
28 copies,
28 copies,
29 debugcommands as debugcommandsmod,
29 debugcommands as debugcommandsmod,
30 destutil,
30 destutil,
31 dirstateguard,
31 dirstateguard,
32 discovery,
32 discovery,
33 encoding,
33 encoding,
34 error,
34 error,
35 exchange,
35 exchange,
36 extensions,
36 extensions,
37 graphmod,
37 graphmod,
38 hbisect,
38 hbisect,
39 help,
39 help,
40 hg,
40 hg,
41 lock as lockmod,
41 lock as lockmod,
42 merge as mergemod,
42 merge as mergemod,
43 obsolete,
43 obsolete,
44 patch,
44 patch,
45 phases,
45 phases,
46 pycompat,
46 pycompat,
47 rcutil,
47 rcutil,
48 registrar,
48 registrar,
49 revsetlang,
49 revsetlang,
50 scmutil,
50 scmutil,
51 server,
51 server,
52 sshserver,
52 sshserver,
53 streamclone,
53 streamclone,
54 tags as tagsmod,
54 tags as tagsmod,
55 templatekw,
55 templatekw,
56 ui as uimod,
56 ui as uimod,
57 util,
57 util,
58 )
58 )
59
59
60 release = lockmod.release
60 release = lockmod.release
61
61
62 table = {}
62 table = {}
63 table.update(debugcommandsmod.command._table)
63 table.update(debugcommandsmod.command._table)
64
64
65 command = registrar.command(table)
65 command = registrar.command(table)
66
66
67 # label constants
67 # label constants
68 # until 3.5, bookmarks.current was the advertised name, not
68 # until 3.5, bookmarks.current was the advertised name, not
69 # bookmarks.active, so we must use both to avoid breaking old
69 # bookmarks.active, so we must use both to avoid breaking old
70 # custom styles
70 # custom styles
71 activebookmarklabel = 'bookmarks.active bookmarks.current'
71 activebookmarklabel = 'bookmarks.active bookmarks.current'
72
72
73 # common command options
73 # common command options
74
74
75 globalopts = [
75 globalopts = [
76 ('R', 'repository', '',
76 ('R', 'repository', '',
77 _('repository root directory or name of overlay bundle file'),
77 _('repository root directory or name of overlay bundle file'),
78 _('REPO')),
78 _('REPO')),
79 ('', 'cwd', '',
79 ('', 'cwd', '',
80 _('change working directory'), _('DIR')),
80 _('change working directory'), _('DIR')),
81 ('y', 'noninteractive', None,
81 ('y', 'noninteractive', None,
82 _('do not prompt, automatically pick the first choice for all prompts')),
82 _('do not prompt, automatically pick the first choice for all prompts')),
83 ('q', 'quiet', None, _('suppress output')),
83 ('q', 'quiet', None, _('suppress output')),
84 ('v', 'verbose', None, _('enable additional output')),
84 ('v', 'verbose', None, _('enable additional output')),
85 ('', 'color', '',
85 ('', 'color', '',
86 # i18n: 'always', 'auto', 'never', and 'debug' are keywords
86 # i18n: 'always', 'auto', 'never', and 'debug' are keywords
87 # and should not be translated
87 # and should not be translated
88 _("when to colorize (boolean, always, auto, never, or debug)"),
88 _("when to colorize (boolean, always, auto, never, or debug)"),
89 _('TYPE')),
89 _('TYPE')),
90 ('', 'config', [],
90 ('', 'config', [],
91 _('set/override config option (use \'section.name=value\')'),
91 _('set/override config option (use \'section.name=value\')'),
92 _('CONFIG')),
92 _('CONFIG')),
93 ('', 'debug', None, _('enable debugging output')),
93 ('', 'debug', None, _('enable debugging output')),
94 ('', 'debugger', None, _('start debugger')),
94 ('', 'debugger', None, _('start debugger')),
95 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
95 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
96 _('ENCODE')),
96 _('ENCODE')),
97 ('', 'encodingmode', encoding.encodingmode,
97 ('', 'encodingmode', encoding.encodingmode,
98 _('set the charset encoding mode'), _('MODE')),
98 _('set the charset encoding mode'), _('MODE')),
99 ('', 'traceback', None, _('always print a traceback on exception')),
99 ('', 'traceback', None, _('always print a traceback on exception')),
100 ('', 'time', None, _('time how long the command takes')),
100 ('', 'time', None, _('time how long the command takes')),
101 ('', 'profile', None, _('print command execution profile')),
101 ('', 'profile', None, _('print command execution profile')),
102 ('', 'version', None, _('output version information and exit')),
102 ('', 'version', None, _('output version information and exit')),
103 ('h', 'help', None, _('display help and exit')),
103 ('h', 'help', None, _('display help and exit')),
104 ('', 'hidden', False, _('consider hidden changesets')),
104 ('', 'hidden', False, _('consider hidden changesets')),
105 ('', 'pager', 'auto',
105 ('', 'pager', 'auto',
106 _("when to paginate (boolean, always, auto, or never)"), _('TYPE')),
106 _("when to paginate (boolean, always, auto, or never)"), _('TYPE')),
107 ]
107 ]
108
108
109 dryrunopts = cmdutil.dryrunopts
109 dryrunopts = cmdutil.dryrunopts
110 remoteopts = cmdutil.remoteopts
110 remoteopts = cmdutil.remoteopts
111 walkopts = cmdutil.walkopts
111 walkopts = cmdutil.walkopts
112 commitopts = cmdutil.commitopts
112 commitopts = cmdutil.commitopts
113 commitopts2 = cmdutil.commitopts2
113 commitopts2 = cmdutil.commitopts2
114 formatteropts = cmdutil.formatteropts
114 formatteropts = cmdutil.formatteropts
115 templateopts = cmdutil.templateopts
115 templateopts = cmdutil.templateopts
116 logopts = cmdutil.logopts
116 logopts = cmdutil.logopts
117 diffopts = cmdutil.diffopts
117 diffopts = cmdutil.diffopts
118 diffwsopts = cmdutil.diffwsopts
118 diffwsopts = cmdutil.diffwsopts
119 diffopts2 = cmdutil.diffopts2
119 diffopts2 = cmdutil.diffopts2
120 mergetoolopts = cmdutil.mergetoolopts
120 mergetoolopts = cmdutil.mergetoolopts
121 similarityopts = cmdutil.similarityopts
121 similarityopts = cmdutil.similarityopts
122 subrepoopts = cmdutil.subrepoopts
122 subrepoopts = cmdutil.subrepoopts
123 debugrevlogopts = cmdutil.debugrevlogopts
123 debugrevlogopts = cmdutil.debugrevlogopts
124
124
125 # Commands start here, listed alphabetically
125 # Commands start here, listed alphabetically
126
126
127 @command('^add',
127 @command('^add',
128 walkopts + subrepoopts + dryrunopts,
128 walkopts + subrepoopts + dryrunopts,
129 _('[OPTION]... [FILE]...'),
129 _('[OPTION]... [FILE]...'),
130 inferrepo=True)
130 inferrepo=True)
131 def add(ui, repo, *pats, **opts):
131 def add(ui, repo, *pats, **opts):
132 """add the specified files on the next commit
132 """add the specified files on the next commit
133
133
134 Schedule files to be version controlled and added to the
134 Schedule files to be version controlled and added to the
135 repository.
135 repository.
136
136
137 The files will be added to the repository at the next commit. To
137 The files will be added to the repository at the next commit. To
138 undo an add before that, see :hg:`forget`.
138 undo an add before that, see :hg:`forget`.
139
139
140 If no names are given, add all files to the repository (except
140 If no names are given, add all files to the repository (except
141 files matching ``.hgignore``).
141 files matching ``.hgignore``).
142
142
143 .. container:: verbose
143 .. container:: verbose
144
144
145 Examples:
145 Examples:
146
146
147 - New (unknown) files are added
147 - New (unknown) files are added
148 automatically by :hg:`add`::
148 automatically by :hg:`add`::
149
149
150 $ ls
150 $ ls
151 foo.c
151 foo.c
152 $ hg status
152 $ hg status
153 ? foo.c
153 ? foo.c
154 $ hg add
154 $ hg add
155 adding foo.c
155 adding foo.c
156 $ hg status
156 $ hg status
157 A foo.c
157 A foo.c
158
158
159 - Specific files to be added can be specified::
159 - Specific files to be added can be specified::
160
160
161 $ ls
161 $ ls
162 bar.c foo.c
162 bar.c foo.c
163 $ hg status
163 $ hg status
164 ? bar.c
164 ? bar.c
165 ? foo.c
165 ? foo.c
166 $ hg add bar.c
166 $ hg add bar.c
167 $ hg status
167 $ hg status
168 A bar.c
168 A bar.c
169 ? foo.c
169 ? foo.c
170
170
171 Returns 0 if all files are successfully added.
171 Returns 0 if all files are successfully added.
172 """
172 """
173
173
174 m = scmutil.match(repo[None], pats, pycompat.byteskwargs(opts))
174 m = scmutil.match(repo[None], pats, pycompat.byteskwargs(opts))
175 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
175 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
176 return rejected and 1 or 0
176 return rejected and 1 or 0
177
177
178 @command('addremove',
178 @command('addremove',
179 similarityopts + subrepoopts + walkopts + dryrunopts,
179 similarityopts + subrepoopts + walkopts + dryrunopts,
180 _('[OPTION]... [FILE]...'),
180 _('[OPTION]... [FILE]...'),
181 inferrepo=True)
181 inferrepo=True)
182 def addremove(ui, repo, *pats, **opts):
182 def addremove(ui, repo, *pats, **opts):
183 """add all new files, delete all missing files
183 """add all new files, delete all missing files
184
184
185 Add all new files and remove all missing files from the
185 Add all new files and remove all missing files from the
186 repository.
186 repository.
187
187
188 Unless names are given, new files are ignored if they match any of
188 Unless names are given, new files are ignored if they match any of
189 the patterns in ``.hgignore``. As with add, these changes take
189 the patterns in ``.hgignore``. As with add, these changes take
190 effect at the next commit.
190 effect at the next commit.
191
191
192 Use the -s/--similarity option to detect renamed files. This
192 Use the -s/--similarity option to detect renamed files. This
193 option takes a percentage between 0 (disabled) and 100 (files must
193 option takes a percentage between 0 (disabled) and 100 (files must
194 be identical) as its parameter. With a parameter greater than 0,
194 be identical) as its parameter. With a parameter greater than 0,
195 this compares every removed file with every added file and records
195 this compares every removed file with every added file and records
196 those similar enough as renames. Detecting renamed files this way
196 those similar enough as renames. Detecting renamed files this way
197 can be expensive. After using this option, :hg:`status -C` can be
197 can be expensive. After using this option, :hg:`status -C` can be
198 used to check which files were identified as moved or renamed. If
198 used to check which files were identified as moved or renamed. If
199 not specified, -s/--similarity defaults to 100 and only renames of
199 not specified, -s/--similarity defaults to 100 and only renames of
200 identical files are detected.
200 identical files are detected.
201
201
202 .. container:: verbose
202 .. container:: verbose
203
203
204 Examples:
204 Examples:
205
205
206 - A number of files (bar.c and foo.c) are new,
206 - A number of files (bar.c and foo.c) are new,
207 while foobar.c has been removed (without using :hg:`remove`)
207 while foobar.c has been removed (without using :hg:`remove`)
208 from the repository::
208 from the repository::
209
209
210 $ ls
210 $ ls
211 bar.c foo.c
211 bar.c foo.c
212 $ hg status
212 $ hg status
213 ! foobar.c
213 ! foobar.c
214 ? bar.c
214 ? bar.c
215 ? foo.c
215 ? foo.c
216 $ hg addremove
216 $ hg addremove
217 adding bar.c
217 adding bar.c
218 adding foo.c
218 adding foo.c
219 removing foobar.c
219 removing foobar.c
220 $ hg status
220 $ hg status
221 A bar.c
221 A bar.c
222 A foo.c
222 A foo.c
223 R foobar.c
223 R foobar.c
224
224
225 - A file foobar.c was moved to foo.c without using :hg:`rename`.
225 - A file foobar.c was moved to foo.c without using :hg:`rename`.
226 Afterwards, it was edited slightly::
226 Afterwards, it was edited slightly::
227
227
228 $ ls
228 $ ls
229 foo.c
229 foo.c
230 $ hg status
230 $ hg status
231 ! foobar.c
231 ! foobar.c
232 ? foo.c
232 ? foo.c
233 $ hg addremove --similarity 90
233 $ hg addremove --similarity 90
234 removing foobar.c
234 removing foobar.c
235 adding foo.c
235 adding foo.c
236 recording removal of foobar.c as rename to foo.c (94% similar)
236 recording removal of foobar.c as rename to foo.c (94% similar)
237 $ hg status -C
237 $ hg status -C
238 A foo.c
238 A foo.c
239 foobar.c
239 foobar.c
240 R foobar.c
240 R foobar.c
241
241
242 Returns 0 if all files are successfully added.
242 Returns 0 if all files are successfully added.
243 """
243 """
244 opts = pycompat.byteskwargs(opts)
244 opts = pycompat.byteskwargs(opts)
245 try:
245 try:
246 sim = float(opts.get('similarity') or 100)
246 sim = float(opts.get('similarity') or 100)
247 except ValueError:
247 except ValueError:
248 raise error.Abort(_('similarity must be a number'))
248 raise error.Abort(_('similarity must be a number'))
249 if sim < 0 or sim > 100:
249 if sim < 0 or sim > 100:
250 raise error.Abort(_('similarity must be between 0 and 100'))
250 raise error.Abort(_('similarity must be between 0 and 100'))
251 matcher = scmutil.match(repo[None], pats, opts)
251 matcher = scmutil.match(repo[None], pats, opts)
252 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
252 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
253
253
254 @command('^annotate|blame',
254 @command('^annotate|blame',
255 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
255 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
256 ('', 'follow', None,
256 ('', 'follow', None,
257 _('follow copies/renames and list the filename (DEPRECATED)')),
257 _('follow copies/renames and list the filename (DEPRECATED)')),
258 ('', 'no-follow', None, _("don't follow copies and renames")),
258 ('', 'no-follow', None, _("don't follow copies and renames")),
259 ('a', 'text', None, _('treat all files as text')),
259 ('a', 'text', None, _('treat all files as text')),
260 ('u', 'user', None, _('list the author (long with -v)')),
260 ('u', 'user', None, _('list the author (long with -v)')),
261 ('f', 'file', None, _('list the filename')),
261 ('f', 'file', None, _('list the filename')),
262 ('d', 'date', None, _('list the date (short with -q)')),
262 ('d', 'date', None, _('list the date (short with -q)')),
263 ('n', 'number', None, _('list the revision number (default)')),
263 ('n', 'number', None, _('list the revision number (default)')),
264 ('c', 'changeset', None, _('list the changeset')),
264 ('c', 'changeset', None, _('list the changeset')),
265 ('l', 'line-number', None, _('show line number at the first appearance'))
265 ('l', 'line-number', None, _('show line number at the first appearance'))
266 ] + diffwsopts + walkopts + formatteropts,
266 ] + diffwsopts + walkopts + formatteropts,
267 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
267 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
268 inferrepo=True)
268 inferrepo=True)
269 def annotate(ui, repo, *pats, **opts):
269 def annotate(ui, repo, *pats, **opts):
270 """show changeset information by line for each file
270 """show changeset information by line for each file
271
271
272 List changes in files, showing the revision id responsible for
272 List changes in files, showing the revision id responsible for
273 each line.
273 each line.
274
274
275 This command is useful for discovering when a change was made and
275 This command is useful for discovering when a change was made and
276 by whom.
276 by whom.
277
277
278 If you include --file, --user, or --date, the revision number is
278 If you include --file, --user, or --date, the revision number is
279 suppressed unless you also include --number.
279 suppressed unless you also include --number.
280
280
281 Without the -a/--text option, annotate will avoid processing files
281 Without the -a/--text option, annotate will avoid processing files
282 it detects as binary. With -a, annotate will annotate the file
282 it detects as binary. With -a, annotate will annotate the file
283 anyway, although the results will probably be neither useful
283 anyway, although the results will probably be neither useful
284 nor desirable.
284 nor desirable.
285
285
286 Returns 0 on success.
286 Returns 0 on success.
287 """
287 """
288 opts = pycompat.byteskwargs(opts)
288 opts = pycompat.byteskwargs(opts)
289 if not pats:
289 if not pats:
290 raise error.Abort(_('at least one filename or pattern is required'))
290 raise error.Abort(_('at least one filename or pattern is required'))
291
291
292 if opts.get('follow'):
292 if opts.get('follow'):
293 # --follow is deprecated and now just an alias for -f/--file
293 # --follow is deprecated and now just an alias for -f/--file
294 # to mimic the behavior of Mercurial before version 1.5
294 # to mimic the behavior of Mercurial before version 1.5
295 opts['file'] = True
295 opts['file'] = True
296
296
297 ctx = scmutil.revsingle(repo, opts.get('rev'))
297 ctx = scmutil.revsingle(repo, opts.get('rev'))
298
298
299 fm = ui.formatter('annotate', opts)
299 fm = ui.formatter('annotate', opts)
300 if ui.quiet:
300 if ui.quiet:
301 datefunc = util.shortdate
301 datefunc = util.shortdate
302 else:
302 else:
303 datefunc = util.datestr
303 datefunc = util.datestr
304 if ctx.rev() is None:
304 if ctx.rev() is None:
305 def hexfn(node):
305 def hexfn(node):
306 if node is None:
306 if node is None:
307 return None
307 return None
308 else:
308 else:
309 return fm.hexfunc(node)
309 return fm.hexfunc(node)
310 if opts.get('changeset'):
310 if opts.get('changeset'):
311 # omit "+" suffix which is appended to node hex
311 # omit "+" suffix which is appended to node hex
312 def formatrev(rev):
312 def formatrev(rev):
313 if rev is None:
313 if rev is None:
314 return '%d' % ctx.p1().rev()
314 return '%d' % ctx.p1().rev()
315 else:
315 else:
316 return '%d' % rev
316 return '%d' % rev
317 else:
317 else:
318 def formatrev(rev):
318 def formatrev(rev):
319 if rev is None:
319 if rev is None:
320 return '%d+' % ctx.p1().rev()
320 return '%d+' % ctx.p1().rev()
321 else:
321 else:
322 return '%d ' % rev
322 return '%d ' % rev
323 def formathex(hex):
323 def formathex(hex):
324 if hex is None:
324 if hex is None:
325 return '%s+' % fm.hexfunc(ctx.p1().node())
325 return '%s+' % fm.hexfunc(ctx.p1().node())
326 else:
326 else:
327 return '%s ' % hex
327 return '%s ' % hex
328 else:
328 else:
329 hexfn = fm.hexfunc
329 hexfn = fm.hexfunc
330 formatrev = formathex = str
330 formatrev = formathex = str
331
331
332 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
332 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
333 ('number', ' ', lambda x: x[0].rev(), formatrev),
333 ('number', ' ', lambda x: x[0].rev(), formatrev),
334 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
334 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
335 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
335 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
336 ('file', ' ', lambda x: x[0].path(), str),
336 ('file', ' ', lambda x: x[0].path(), str),
337 ('line_number', ':', lambda x: x[1], str),
337 ('line_number', ':', lambda x: x[1], str),
338 ]
338 ]
339 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
339 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
340
340
341 if (not opts.get('user') and not opts.get('changeset')
341 if (not opts.get('user') and not opts.get('changeset')
342 and not opts.get('date') and not opts.get('file')):
342 and not opts.get('date') and not opts.get('file')):
343 opts['number'] = True
343 opts['number'] = True
344
344
345 linenumber = opts.get('line_number') is not None
345 linenumber = opts.get('line_number') is not None
346 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
346 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
347 raise error.Abort(_('at least one of -n/-c is required for -l'))
347 raise error.Abort(_('at least one of -n/-c is required for -l'))
348
348
349 ui.pager('annotate')
349 ui.pager('annotate')
350
350
351 if fm.isplain():
351 if fm.isplain():
352 def makefunc(get, fmt):
352 def makefunc(get, fmt):
353 return lambda x: fmt(get(x))
353 return lambda x: fmt(get(x))
354 else:
354 else:
355 def makefunc(get, fmt):
355 def makefunc(get, fmt):
356 return get
356 return get
357 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
357 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
358 if opts.get(op)]
358 if opts.get(op)]
359 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
359 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
360 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
360 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
361 if opts.get(op))
361 if opts.get(op))
362
362
363 def bad(x, y):
363 def bad(x, y):
364 raise error.Abort("%s: %s" % (x, y))
364 raise error.Abort("%s: %s" % (x, y))
365
365
366 m = scmutil.match(ctx, pats, opts, badfn=bad)
366 m = scmutil.match(ctx, pats, opts, badfn=bad)
367
367
368 follow = not opts.get('no_follow')
368 follow = not opts.get('no_follow')
369 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
369 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
370 whitespace=True)
370 whitespace=True)
371 for abs in ctx.walk(m):
371 for abs in ctx.walk(m):
372 fctx = ctx[abs]
372 fctx = ctx[abs]
373 if not opts.get('text') and fctx.isbinary():
373 if not opts.get('text') and fctx.isbinary():
374 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
374 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
375 continue
375 continue
376
376
377 lines = fctx.annotate(follow=follow, linenumber=linenumber,
377 lines = fctx.annotate(follow=follow, linenumber=linenumber,
378 diffopts=diffopts)
378 diffopts=diffopts)
379 if not lines:
379 if not lines:
380 continue
380 continue
381 formats = []
381 formats = []
382 pieces = []
382 pieces = []
383
383
384 for f, sep in funcmap:
384 for f, sep in funcmap:
385 l = [f(n) for n, dummy in lines]
385 l = [f(n) for n, dummy in lines]
386 if fm.isplain():
386 if fm.isplain():
387 sizes = [encoding.colwidth(x) for x in l]
387 sizes = [encoding.colwidth(x) for x in l]
388 ml = max(sizes)
388 ml = max(sizes)
389 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
389 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
390 else:
390 else:
391 formats.append(['%s' for x in l])
391 formats.append(['%s' for x in l])
392 pieces.append(l)
392 pieces.append(l)
393
393
394 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
394 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
395 fm.startitem()
395 fm.startitem()
396 fm.write(fields, "".join(f), *p)
396 fm.write(fields, "".join(f), *p)
397 fm.write('line', ": %s", l[1])
397 fm.write('line', ": %s", l[1])
398
398
399 if not lines[-1][1].endswith('\n'):
399 if not lines[-1][1].endswith('\n'):
400 fm.plain('\n')
400 fm.plain('\n')
401
401
402 fm.end()
402 fm.end()
403
403
404 @command('archive',
404 @command('archive',
405 [('', 'no-decode', None, _('do not pass files through decoders')),
405 [('', 'no-decode', None, _('do not pass files through decoders')),
406 ('p', 'prefix', '', _('directory prefix for files in archive'),
406 ('p', 'prefix', '', _('directory prefix for files in archive'),
407 _('PREFIX')),
407 _('PREFIX')),
408 ('r', 'rev', '', _('revision to distribute'), _('REV')),
408 ('r', 'rev', '', _('revision to distribute'), _('REV')),
409 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
409 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
410 ] + subrepoopts + walkopts,
410 ] + subrepoopts + walkopts,
411 _('[OPTION]... DEST'))
411 _('[OPTION]... DEST'))
412 def archive(ui, repo, dest, **opts):
412 def archive(ui, repo, dest, **opts):
413 '''create an unversioned archive of a repository revision
413 '''create an unversioned archive of a repository revision
414
414
415 By default, the revision used is the parent of the working
415 By default, the revision used is the parent of the working
416 directory; use -r/--rev to specify a different revision.
416 directory; use -r/--rev to specify a different revision.
417
417
418 The archive type is automatically detected based on file
418 The archive type is automatically detected based on file
419 extension (to override, use -t/--type).
419 extension (to override, use -t/--type).
420
420
421 .. container:: verbose
421 .. container:: verbose
422
422
423 Examples:
423 Examples:
424
424
425 - create a zip file containing the 1.0 release::
425 - create a zip file containing the 1.0 release::
426
426
427 hg archive -r 1.0 project-1.0.zip
427 hg archive -r 1.0 project-1.0.zip
428
428
429 - create a tarball excluding .hg files::
429 - create a tarball excluding .hg files::
430
430
431 hg archive project.tar.gz -X ".hg*"
431 hg archive project.tar.gz -X ".hg*"
432
432
433 Valid types are:
433 Valid types are:
434
434
435 :``files``: a directory full of files (default)
435 :``files``: a directory full of files (default)
436 :``tar``: tar archive, uncompressed
436 :``tar``: tar archive, uncompressed
437 :``tbz2``: tar archive, compressed using bzip2
437 :``tbz2``: tar archive, compressed using bzip2
438 :``tgz``: tar archive, compressed using gzip
438 :``tgz``: tar archive, compressed using gzip
439 :``uzip``: zip archive, uncompressed
439 :``uzip``: zip archive, uncompressed
440 :``zip``: zip archive, compressed using deflate
440 :``zip``: zip archive, compressed using deflate
441
441
442 The exact name of the destination archive or directory is given
442 The exact name of the destination archive or directory is given
443 using a format string; see :hg:`help export` for details.
443 using a format string; see :hg:`help export` for details.
444
444
445 Each member added to an archive file has a directory prefix
445 Each member added to an archive file has a directory prefix
446 prepended. Use -p/--prefix to specify a format string for the
446 prepended. Use -p/--prefix to specify a format string for the
447 prefix. The default is the basename of the archive, with suffixes
447 prefix. The default is the basename of the archive, with suffixes
448 removed.
448 removed.
449
449
450 Returns 0 on success.
450 Returns 0 on success.
451 '''
451 '''
452
452
453 opts = pycompat.byteskwargs(opts)
453 opts = pycompat.byteskwargs(opts)
454 ctx = scmutil.revsingle(repo, opts.get('rev'))
454 ctx = scmutil.revsingle(repo, opts.get('rev'))
455 if not ctx:
455 if not ctx:
456 raise error.Abort(_('no working directory: please specify a revision'))
456 raise error.Abort(_('no working directory: please specify a revision'))
457 node = ctx.node()
457 node = ctx.node()
458 dest = cmdutil.makefilename(repo, dest, node)
458 dest = cmdutil.makefilename(repo, dest, node)
459 if os.path.realpath(dest) == repo.root:
459 if os.path.realpath(dest) == repo.root:
460 raise error.Abort(_('repository root cannot be destination'))
460 raise error.Abort(_('repository root cannot be destination'))
461
461
462 kind = opts.get('type') or archival.guesskind(dest) or 'files'
462 kind = opts.get('type') or archival.guesskind(dest) or 'files'
463 prefix = opts.get('prefix')
463 prefix = opts.get('prefix')
464
464
465 if dest == '-':
465 if dest == '-':
466 if kind == 'files':
466 if kind == 'files':
467 raise error.Abort(_('cannot archive plain files to stdout'))
467 raise error.Abort(_('cannot archive plain files to stdout'))
468 dest = cmdutil.makefileobj(repo, dest)
468 dest = cmdutil.makefileobj(repo, dest)
469 if not prefix:
469 if not prefix:
470 prefix = os.path.basename(repo.root) + '-%h'
470 prefix = os.path.basename(repo.root) + '-%h'
471
471
472 prefix = cmdutil.makefilename(repo, prefix, node)
472 prefix = cmdutil.makefilename(repo, prefix, node)
473 matchfn = scmutil.match(ctx, [], opts)
473 matchfn = scmutil.match(ctx, [], opts)
474 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
474 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
475 matchfn, prefix, subrepos=opts.get('subrepos'))
475 matchfn, prefix, subrepos=opts.get('subrepos'))
476
476
477 @command('backout',
477 @command('backout',
478 [('', 'merge', None, _('merge with old dirstate parent after backout')),
478 [('', 'merge', None, _('merge with old dirstate parent after backout')),
479 ('', 'commit', None,
479 ('', 'commit', None,
480 _('commit if no conflicts were encountered (DEPRECATED)')),
480 _('commit if no conflicts were encountered (DEPRECATED)')),
481 ('', 'no-commit', None, _('do not commit')),
481 ('', 'no-commit', None, _('do not commit')),
482 ('', 'parent', '',
482 ('', 'parent', '',
483 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
483 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
484 ('r', 'rev', '', _('revision to backout'), _('REV')),
484 ('r', 'rev', '', _('revision to backout'), _('REV')),
485 ('e', 'edit', False, _('invoke editor on commit messages')),
485 ('e', 'edit', False, _('invoke editor on commit messages')),
486 ] + mergetoolopts + walkopts + commitopts + commitopts2,
486 ] + mergetoolopts + walkopts + commitopts + commitopts2,
487 _('[OPTION]... [-r] REV'))
487 _('[OPTION]... [-r] REV'))
488 def backout(ui, repo, node=None, rev=None, **opts):
488 def backout(ui, repo, node=None, rev=None, **opts):
489 '''reverse effect of earlier changeset
489 '''reverse effect of earlier changeset
490
490
491 Prepare a new changeset with the effect of REV undone in the
491 Prepare a new changeset with the effect of REV undone in the
492 current working directory. If no conflicts were encountered,
492 current working directory. If no conflicts were encountered,
493 it will be committed immediately.
493 it will be committed immediately.
494
494
495 If REV is the parent of the working directory, then this new changeset
495 If REV is the parent of the working directory, then this new changeset
496 is committed automatically (unless --no-commit is specified).
496 is committed automatically (unless --no-commit is specified).
497
497
498 .. note::
498 .. note::
499
499
500 :hg:`backout` cannot be used to fix either an unwanted or
500 :hg:`backout` cannot be used to fix either an unwanted or
501 incorrect merge.
501 incorrect merge.
502
502
503 .. container:: verbose
503 .. container:: verbose
504
504
505 Examples:
505 Examples:
506
506
507 - Reverse the effect of the parent of the working directory.
507 - Reverse the effect of the parent of the working directory.
508 This backout will be committed immediately::
508 This backout will be committed immediately::
509
509
510 hg backout -r .
510 hg backout -r .
511
511
512 - Reverse the effect of previous bad revision 23::
512 - Reverse the effect of previous bad revision 23::
513
513
514 hg backout -r 23
514 hg backout -r 23
515
515
516 - Reverse the effect of previous bad revision 23 and
516 - Reverse the effect of previous bad revision 23 and
517 leave changes uncommitted::
517 leave changes uncommitted::
518
518
519 hg backout -r 23 --no-commit
519 hg backout -r 23 --no-commit
520 hg commit -m "Backout revision 23"
520 hg commit -m "Backout revision 23"
521
521
522 By default, the pending changeset will have one parent,
522 By default, the pending changeset will have one parent,
523 maintaining a linear history. With --merge, the pending
523 maintaining a linear history. With --merge, the pending
524 changeset will instead have two parents: the old parent of the
524 changeset will instead have two parents: the old parent of the
525 working directory and a new child of REV that simply undoes REV.
525 working directory and a new child of REV that simply undoes REV.
526
526
527 Before version 1.7, the behavior without --merge was equivalent
527 Before version 1.7, the behavior without --merge was equivalent
528 to specifying --merge followed by :hg:`update --clean .` to
528 to specifying --merge followed by :hg:`update --clean .` to
529 cancel the merge and leave the child of REV as a head to be
529 cancel the merge and leave the child of REV as a head to be
530 merged separately.
530 merged separately.
531
531
532 See :hg:`help dates` for a list of formats valid for -d/--date.
532 See :hg:`help dates` for a list of formats valid for -d/--date.
533
533
534 See :hg:`help revert` for a way to restore files to the state
534 See :hg:`help revert` for a way to restore files to the state
535 of another revision.
535 of another revision.
536
536
537 Returns 0 on success, 1 if nothing to backout or there are unresolved
537 Returns 0 on success, 1 if nothing to backout or there are unresolved
538 files.
538 files.
539 '''
539 '''
540 wlock = lock = None
540 wlock = lock = None
541 try:
541 try:
542 wlock = repo.wlock()
542 wlock = repo.wlock()
543 lock = repo.lock()
543 lock = repo.lock()
544 return _dobackout(ui, repo, node, rev, **opts)
544 return _dobackout(ui, repo, node, rev, **opts)
545 finally:
545 finally:
546 release(lock, wlock)
546 release(lock, wlock)
547
547
548 def _dobackout(ui, repo, node=None, rev=None, **opts):
548 def _dobackout(ui, repo, node=None, rev=None, **opts):
549 opts = pycompat.byteskwargs(opts)
549 opts = pycompat.byteskwargs(opts)
550 if opts.get('commit') and opts.get('no_commit'):
550 if opts.get('commit') and opts.get('no_commit'):
551 raise error.Abort(_("cannot use --commit with --no-commit"))
551 raise error.Abort(_("cannot use --commit with --no-commit"))
552 if opts.get('merge') and opts.get('no_commit'):
552 if opts.get('merge') and opts.get('no_commit'):
553 raise error.Abort(_("cannot use --merge with --no-commit"))
553 raise error.Abort(_("cannot use --merge with --no-commit"))
554
554
555 if rev and node:
555 if rev and node:
556 raise error.Abort(_("please specify just one revision"))
556 raise error.Abort(_("please specify just one revision"))
557
557
558 if not rev:
558 if not rev:
559 rev = node
559 rev = node
560
560
561 if not rev:
561 if not rev:
562 raise error.Abort(_("please specify a revision to backout"))
562 raise error.Abort(_("please specify a revision to backout"))
563
563
564 date = opts.get('date')
564 date = opts.get('date')
565 if date:
565 if date:
566 opts['date'] = util.parsedate(date)
566 opts['date'] = util.parsedate(date)
567
567
568 cmdutil.checkunfinished(repo)
568 cmdutil.checkunfinished(repo)
569 cmdutil.bailifchanged(repo)
569 cmdutil.bailifchanged(repo)
570 node = scmutil.revsingle(repo, rev).node()
570 node = scmutil.revsingle(repo, rev).node()
571
571
572 op1, op2 = repo.dirstate.parents()
572 op1, op2 = repo.dirstate.parents()
573 if not repo.changelog.isancestor(node, op1):
573 if not repo.changelog.isancestor(node, op1):
574 raise error.Abort(_('cannot backout change that is not an ancestor'))
574 raise error.Abort(_('cannot backout change that is not an ancestor'))
575
575
576 p1, p2 = repo.changelog.parents(node)
576 p1, p2 = repo.changelog.parents(node)
577 if p1 == nullid:
577 if p1 == nullid:
578 raise error.Abort(_('cannot backout a change with no parents'))
578 raise error.Abort(_('cannot backout a change with no parents'))
579 if p2 != nullid:
579 if p2 != nullid:
580 if not opts.get('parent'):
580 if not opts.get('parent'):
581 raise error.Abort(_('cannot backout a merge changeset'))
581 raise error.Abort(_('cannot backout a merge changeset'))
582 p = repo.lookup(opts['parent'])
582 p = repo.lookup(opts['parent'])
583 if p not in (p1, p2):
583 if p not in (p1, p2):
584 raise error.Abort(_('%s is not a parent of %s') %
584 raise error.Abort(_('%s is not a parent of %s') %
585 (short(p), short(node)))
585 (short(p), short(node)))
586 parent = p
586 parent = p
587 else:
587 else:
588 if opts.get('parent'):
588 if opts.get('parent'):
589 raise error.Abort(_('cannot use --parent on non-merge changeset'))
589 raise error.Abort(_('cannot use --parent on non-merge changeset'))
590 parent = p1
590 parent = p1
591
591
592 # the backout should appear on the same branch
592 # the backout should appear on the same branch
593 branch = repo.dirstate.branch()
593 branch = repo.dirstate.branch()
594 bheads = repo.branchheads(branch)
594 bheads = repo.branchheads(branch)
595 rctx = scmutil.revsingle(repo, hex(parent))
595 rctx = scmutil.revsingle(repo, hex(parent))
596 if not opts.get('merge') and op1 != node:
596 if not opts.get('merge') and op1 != node:
597 dsguard = dirstateguard.dirstateguard(repo, 'backout')
597 dsguard = dirstateguard.dirstateguard(repo, 'backout')
598 try:
598 try:
599 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
599 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
600 'backout')
600 'backout')
601 stats = mergemod.update(repo, parent, True, True, node, False)
601 stats = mergemod.update(repo, parent, True, True, node, False)
602 repo.setparents(op1, op2)
602 repo.setparents(op1, op2)
603 dsguard.close()
603 dsguard.close()
604 hg._showstats(repo, stats)
604 hg._showstats(repo, stats)
605 if stats[3]:
605 if stats[3]:
606 repo.ui.status(_("use 'hg resolve' to retry unresolved "
606 repo.ui.status(_("use 'hg resolve' to retry unresolved "
607 "file merges\n"))
607 "file merges\n"))
608 return 1
608 return 1
609 finally:
609 finally:
610 ui.setconfig('ui', 'forcemerge', '', '')
610 ui.setconfig('ui', 'forcemerge', '', '')
611 lockmod.release(dsguard)
611 lockmod.release(dsguard)
612 else:
612 else:
613 hg.clean(repo, node, show_stats=False)
613 hg.clean(repo, node, show_stats=False)
614 repo.dirstate.setbranch(branch)
614 repo.dirstate.setbranch(branch)
615 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
615 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
616
616
617 if opts.get('no_commit'):
617 if opts.get('no_commit'):
618 msg = _("changeset %s backed out, "
618 msg = _("changeset %s backed out, "
619 "don't forget to commit.\n")
619 "don't forget to commit.\n")
620 ui.status(msg % short(node))
620 ui.status(msg % short(node))
621 return 0
621 return 0
622
622
623 def commitfunc(ui, repo, message, match, opts):
623 def commitfunc(ui, repo, message, match, opts):
624 editform = 'backout'
624 editform = 'backout'
625 e = cmdutil.getcommiteditor(editform=editform,
625 e = cmdutil.getcommiteditor(editform=editform,
626 **pycompat.strkwargs(opts))
626 **pycompat.strkwargs(opts))
627 if not message:
627 if not message:
628 # we don't translate commit messages
628 # we don't translate commit messages
629 message = "Backed out changeset %s" % short(node)
629 message = "Backed out changeset %s" % short(node)
630 e = cmdutil.getcommiteditor(edit=True, editform=editform)
630 e = cmdutil.getcommiteditor(edit=True, editform=editform)
631 return repo.commit(message, opts.get('user'), opts.get('date'),
631 return repo.commit(message, opts.get('user'), opts.get('date'),
632 match, editor=e)
632 match, editor=e)
633 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
633 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
634 if not newnode:
634 if not newnode:
635 ui.status(_("nothing changed\n"))
635 ui.status(_("nothing changed\n"))
636 return 1
636 return 1
637 cmdutil.commitstatus(repo, newnode, branch, bheads)
637 cmdutil.commitstatus(repo, newnode, branch, bheads)
638
638
639 def nice(node):
639 def nice(node):
640 return '%d:%s' % (repo.changelog.rev(node), short(node))
640 return '%d:%s' % (repo.changelog.rev(node), short(node))
641 ui.status(_('changeset %s backs out changeset %s\n') %
641 ui.status(_('changeset %s backs out changeset %s\n') %
642 (nice(repo.changelog.tip()), nice(node)))
642 (nice(repo.changelog.tip()), nice(node)))
643 if opts.get('merge') and op1 != node:
643 if opts.get('merge') and op1 != node:
644 hg.clean(repo, op1, show_stats=False)
644 hg.clean(repo, op1, show_stats=False)
645 ui.status(_('merging with changeset %s\n')
645 ui.status(_('merging with changeset %s\n')
646 % nice(repo.changelog.tip()))
646 % nice(repo.changelog.tip()))
647 try:
647 try:
648 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
648 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
649 'backout')
649 'backout')
650 return hg.merge(repo, hex(repo.changelog.tip()))
650 return hg.merge(repo, hex(repo.changelog.tip()))
651 finally:
651 finally:
652 ui.setconfig('ui', 'forcemerge', '', '')
652 ui.setconfig('ui', 'forcemerge', '', '')
653 return 0
653 return 0
654
654
655 @command('bisect',
655 @command('bisect',
656 [('r', 'reset', False, _('reset bisect state')),
656 [('r', 'reset', False, _('reset bisect state')),
657 ('g', 'good', False, _('mark changeset good')),
657 ('g', 'good', False, _('mark changeset good')),
658 ('b', 'bad', False, _('mark changeset bad')),
658 ('b', 'bad', False, _('mark changeset bad')),
659 ('s', 'skip', False, _('skip testing changeset')),
659 ('s', 'skip', False, _('skip testing changeset')),
660 ('e', 'extend', False, _('extend the bisect range')),
660 ('e', 'extend', False, _('extend the bisect range')),
661 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
661 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
662 ('U', 'noupdate', False, _('do not update to target'))],
662 ('U', 'noupdate', False, _('do not update to target'))],
663 _("[-gbsr] [-U] [-c CMD] [REV]"))
663 _("[-gbsr] [-U] [-c CMD] [REV]"))
664 def bisect(ui, repo, rev=None, extra=None, command=None,
664 def bisect(ui, repo, rev=None, extra=None, command=None,
665 reset=None, good=None, bad=None, skip=None, extend=None,
665 reset=None, good=None, bad=None, skip=None, extend=None,
666 noupdate=None):
666 noupdate=None):
667 """subdivision search of changesets
667 """subdivision search of changesets
668
668
669 This command helps to find changesets which introduce problems. To
669 This command helps to find changesets which introduce problems. To
670 use, mark the earliest changeset you know exhibits the problem as
670 use, mark the earliest changeset you know exhibits the problem as
671 bad, then mark the latest changeset which is free from the problem
671 bad, then mark the latest changeset which is free from the problem
672 as good. Bisect will update your working directory to a revision
672 as good. Bisect will update your working directory to a revision
673 for testing (unless the -U/--noupdate option is specified). Once
673 for testing (unless the -U/--noupdate option is specified). Once
674 you have performed tests, mark the working directory as good or
674 you have performed tests, mark the working directory as good or
675 bad, and bisect will either update to another candidate changeset
675 bad, and bisect will either update to another candidate changeset
676 or announce that it has found the bad revision.
676 or announce that it has found the bad revision.
677
677
678 As a shortcut, you can also use the revision argument to mark a
678 As a shortcut, you can also use the revision argument to mark a
679 revision as good or bad without checking it out first.
679 revision as good or bad without checking it out first.
680
680
681 If you supply a command, it will be used for automatic bisection.
681 If you supply a command, it will be used for automatic bisection.
682 The environment variable HG_NODE will contain the ID of the
682 The environment variable HG_NODE will contain the ID of the
683 changeset being tested. The exit status of the command will be
683 changeset being tested. The exit status of the command will be
684 used to mark revisions as good or bad: status 0 means good, 125
684 used to mark revisions as good or bad: status 0 means good, 125
685 means to skip the revision, 127 (command not found) will abort the
685 means to skip the revision, 127 (command not found) will abort the
686 bisection, and any other non-zero exit status means the revision
686 bisection, and any other non-zero exit status means the revision
687 is bad.
687 is bad.
688
688
689 .. container:: verbose
689 .. container:: verbose
690
690
691 Some examples:
691 Some examples:
692
692
693 - start a bisection with known bad revision 34, and good revision 12::
693 - start a bisection with known bad revision 34, and good revision 12::
694
694
695 hg bisect --bad 34
695 hg bisect --bad 34
696 hg bisect --good 12
696 hg bisect --good 12
697
697
698 - advance the current bisection by marking current revision as good or
698 - advance the current bisection by marking current revision as good or
699 bad::
699 bad::
700
700
701 hg bisect --good
701 hg bisect --good
702 hg bisect --bad
702 hg bisect --bad
703
703
704 - mark the current revision, or a known revision, to be skipped (e.g. if
704 - mark the current revision, or a known revision, to be skipped (e.g. if
705 that revision is not usable because of another issue)::
705 that revision is not usable because of another issue)::
706
706
707 hg bisect --skip
707 hg bisect --skip
708 hg bisect --skip 23
708 hg bisect --skip 23
709
709
710 - skip all revisions that do not touch directories ``foo`` or ``bar``::
710 - skip all revisions that do not touch directories ``foo`` or ``bar``::
711
711
712 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
712 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
713
713
714 - forget the current bisection::
714 - forget the current bisection::
715
715
716 hg bisect --reset
716 hg bisect --reset
717
717
718 - use 'make && make tests' to automatically find the first broken
718 - use 'make && make tests' to automatically find the first broken
719 revision::
719 revision::
720
720
721 hg bisect --reset
721 hg bisect --reset
722 hg bisect --bad 34
722 hg bisect --bad 34
723 hg bisect --good 12
723 hg bisect --good 12
724 hg bisect --command "make && make tests"
724 hg bisect --command "make && make tests"
725
725
726 - see all changesets whose states are already known in the current
726 - see all changesets whose states are already known in the current
727 bisection::
727 bisection::
728
728
729 hg log -r "bisect(pruned)"
729 hg log -r "bisect(pruned)"
730
730
731 - see the changeset currently being bisected (especially useful
731 - see the changeset currently being bisected (especially useful
732 if running with -U/--noupdate)::
732 if running with -U/--noupdate)::
733
733
734 hg log -r "bisect(current)"
734 hg log -r "bisect(current)"
735
735
736 - see all changesets that took part in the current bisection::
736 - see all changesets that took part in the current bisection::
737
737
738 hg log -r "bisect(range)"
738 hg log -r "bisect(range)"
739
739
740 - you can even get a nice graph::
740 - you can even get a nice graph::
741
741
742 hg log --graph -r "bisect(range)"
742 hg log --graph -r "bisect(range)"
743
743
744 See :hg:`help revisions.bisect` for more about the `bisect()` predicate.
744 See :hg:`help revisions.bisect` for more about the `bisect()` predicate.
745
745
746 Returns 0 on success.
746 Returns 0 on success.
747 """
747 """
748 # backward compatibility
748 # backward compatibility
749 if rev in "good bad reset init".split():
749 if rev in "good bad reset init".split():
750 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
750 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
751 cmd, rev, extra = rev, extra, None
751 cmd, rev, extra = rev, extra, None
752 if cmd == "good":
752 if cmd == "good":
753 good = True
753 good = True
754 elif cmd == "bad":
754 elif cmd == "bad":
755 bad = True
755 bad = True
756 else:
756 else:
757 reset = True
757 reset = True
758 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
758 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
759 raise error.Abort(_('incompatible arguments'))
759 raise error.Abort(_('incompatible arguments'))
760
760
761 if reset:
761 if reset:
762 hbisect.resetstate(repo)
762 hbisect.resetstate(repo)
763 return
763 return
764
764
765 state = hbisect.load_state(repo)
765 state = hbisect.load_state(repo)
766
766
767 # update state
767 # update state
768 if good or bad or skip:
768 if good or bad or skip:
769 if rev:
769 if rev:
770 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
770 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
771 else:
771 else:
772 nodes = [repo.lookup('.')]
772 nodes = [repo.lookup('.')]
773 if good:
773 if good:
774 state['good'] += nodes
774 state['good'] += nodes
775 elif bad:
775 elif bad:
776 state['bad'] += nodes
776 state['bad'] += nodes
777 elif skip:
777 elif skip:
778 state['skip'] += nodes
778 state['skip'] += nodes
779 hbisect.save_state(repo, state)
779 hbisect.save_state(repo, state)
780 if not (state['good'] and state['bad']):
780 if not (state['good'] and state['bad']):
781 return
781 return
782
782
783 def mayupdate(repo, node, show_stats=True):
783 def mayupdate(repo, node, show_stats=True):
784 """common used update sequence"""
784 """common used update sequence"""
785 if noupdate:
785 if noupdate:
786 return
786 return
787 cmdutil.checkunfinished(repo)
787 cmdutil.checkunfinished(repo)
788 cmdutil.bailifchanged(repo)
788 cmdutil.bailifchanged(repo)
789 return hg.clean(repo, node, show_stats=show_stats)
789 return hg.clean(repo, node, show_stats=show_stats)
790
790
791 displayer = cmdutil.show_changeset(ui, repo, {})
791 displayer = cmdutil.show_changeset(ui, repo, {})
792
792
793 if command:
793 if command:
794 changesets = 1
794 changesets = 1
795 if noupdate:
795 if noupdate:
796 try:
796 try:
797 node = state['current'][0]
797 node = state['current'][0]
798 except LookupError:
798 except LookupError:
799 raise error.Abort(_('current bisect revision is unknown - '
799 raise error.Abort(_('current bisect revision is unknown - '
800 'start a new bisect to fix'))
800 'start a new bisect to fix'))
801 else:
801 else:
802 node, p2 = repo.dirstate.parents()
802 node, p2 = repo.dirstate.parents()
803 if p2 != nullid:
803 if p2 != nullid:
804 raise error.Abort(_('current bisect revision is a merge'))
804 raise error.Abort(_('current bisect revision is a merge'))
805 if rev:
805 if rev:
806 node = repo[scmutil.revsingle(repo, rev, node)].node()
806 node = repo[scmutil.revsingle(repo, rev, node)].node()
807 try:
807 try:
808 while changesets:
808 while changesets:
809 # update state
809 # update state
810 state['current'] = [node]
810 state['current'] = [node]
811 hbisect.save_state(repo, state)
811 hbisect.save_state(repo, state)
812 status = ui.system(command, environ={'HG_NODE': hex(node)},
812 status = ui.system(command, environ={'HG_NODE': hex(node)},
813 blockedtag='bisect_check')
813 blockedtag='bisect_check')
814 if status == 125:
814 if status == 125:
815 transition = "skip"
815 transition = "skip"
816 elif status == 0:
816 elif status == 0:
817 transition = "good"
817 transition = "good"
818 # status < 0 means process was killed
818 # status < 0 means process was killed
819 elif status == 127:
819 elif status == 127:
820 raise error.Abort(_("failed to execute %s") % command)
820 raise error.Abort(_("failed to execute %s") % command)
821 elif status < 0:
821 elif status < 0:
822 raise error.Abort(_("%s killed") % command)
822 raise error.Abort(_("%s killed") % command)
823 else:
823 else:
824 transition = "bad"
824 transition = "bad"
825 state[transition].append(node)
825 state[transition].append(node)
826 ctx = repo[node]
826 ctx = repo[node]
827 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
827 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
828 hbisect.checkstate(state)
828 hbisect.checkstate(state)
829 # bisect
829 # bisect
830 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
830 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
831 # update to next check
831 # update to next check
832 node = nodes[0]
832 node = nodes[0]
833 mayupdate(repo, node, show_stats=False)
833 mayupdate(repo, node, show_stats=False)
834 finally:
834 finally:
835 state['current'] = [node]
835 state['current'] = [node]
836 hbisect.save_state(repo, state)
836 hbisect.save_state(repo, state)
837 hbisect.printresult(ui, repo, state, displayer, nodes, bgood)
837 hbisect.printresult(ui, repo, state, displayer, nodes, bgood)
838 return
838 return
839
839
840 hbisect.checkstate(state)
840 hbisect.checkstate(state)
841
841
842 # actually bisect
842 # actually bisect
843 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
843 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
844 if extend:
844 if extend:
845 if not changesets:
845 if not changesets:
846 extendnode = hbisect.extendrange(repo, state, nodes, good)
846 extendnode = hbisect.extendrange(repo, state, nodes, good)
847 if extendnode is not None:
847 if extendnode is not None:
848 ui.write(_("Extending search to changeset %d:%s\n")
848 ui.write(_("Extending search to changeset %d:%s\n")
849 % (extendnode.rev(), extendnode))
849 % (extendnode.rev(), extendnode))
850 state['current'] = [extendnode.node()]
850 state['current'] = [extendnode.node()]
851 hbisect.save_state(repo, state)
851 hbisect.save_state(repo, state)
852 return mayupdate(repo, extendnode.node())
852 return mayupdate(repo, extendnode.node())
853 raise error.Abort(_("nothing to extend"))
853 raise error.Abort(_("nothing to extend"))
854
854
855 if changesets == 0:
855 if changesets == 0:
856 hbisect.printresult(ui, repo, state, displayer, nodes, good)
856 hbisect.printresult(ui, repo, state, displayer, nodes, good)
857 else:
857 else:
858 assert len(nodes) == 1 # only a single node can be tested next
858 assert len(nodes) == 1 # only a single node can be tested next
859 node = nodes[0]
859 node = nodes[0]
860 # compute the approximate number of remaining tests
860 # compute the approximate number of remaining tests
861 tests, size = 0, 2
861 tests, size = 0, 2
862 while size <= changesets:
862 while size <= changesets:
863 tests, size = tests + 1, size * 2
863 tests, size = tests + 1, size * 2
864 rev = repo.changelog.rev(node)
864 rev = repo.changelog.rev(node)
865 ui.write(_("Testing changeset %d:%s "
865 ui.write(_("Testing changeset %d:%s "
866 "(%d changesets remaining, ~%d tests)\n")
866 "(%d changesets remaining, ~%d tests)\n")
867 % (rev, short(node), changesets, tests))
867 % (rev, short(node), changesets, tests))
868 state['current'] = [node]
868 state['current'] = [node]
869 hbisect.save_state(repo, state)
869 hbisect.save_state(repo, state)
870 return mayupdate(repo, node)
870 return mayupdate(repo, node)
871
871
872 @command('bookmarks|bookmark',
872 @command('bookmarks|bookmark',
873 [('f', 'force', False, _('force')),
873 [('f', 'force', False, _('force')),
874 ('r', 'rev', '', _('revision for bookmark action'), _('REV')),
874 ('r', 'rev', '', _('revision for bookmark action'), _('REV')),
875 ('d', 'delete', False, _('delete a given bookmark')),
875 ('d', 'delete', False, _('delete a given bookmark')),
876 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
876 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
877 ('i', 'inactive', False, _('mark a bookmark inactive')),
877 ('i', 'inactive', False, _('mark a bookmark inactive')),
878 ] + formatteropts,
878 ] + formatteropts,
879 _('hg bookmarks [OPTIONS]... [NAME]...'))
879 _('hg bookmarks [OPTIONS]... [NAME]...'))
880 def bookmark(ui, repo, *names, **opts):
880 def bookmark(ui, repo, *names, **opts):
881 '''create a new bookmark or list existing bookmarks
881 '''create a new bookmark or list existing bookmarks
882
882
883 Bookmarks are labels on changesets to help track lines of development.
883 Bookmarks are labels on changesets to help track lines of development.
884 Bookmarks are unversioned and can be moved, renamed and deleted.
884 Bookmarks are unversioned and can be moved, renamed and deleted.
885 Deleting or moving a bookmark has no effect on the associated changesets.
885 Deleting or moving a bookmark has no effect on the associated changesets.
886
886
887 Creating or updating to a bookmark causes it to be marked as 'active'.
887 Creating or updating to a bookmark causes it to be marked as 'active'.
888 The active bookmark is indicated with a '*'.
888 The active bookmark is indicated with a '*'.
889 When a commit is made, the active bookmark will advance to the new commit.
889 When a commit is made, the active bookmark will advance to the new commit.
890 A plain :hg:`update` will also advance an active bookmark, if possible.
890 A plain :hg:`update` will also advance an active bookmark, if possible.
891 Updating away from a bookmark will cause it to be deactivated.
891 Updating away from a bookmark will cause it to be deactivated.
892
892
893 Bookmarks can be pushed and pulled between repositories (see
893 Bookmarks can be pushed and pulled between repositories (see
894 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
894 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
895 diverged, a new 'divergent bookmark' of the form 'name@path' will
895 diverged, a new 'divergent bookmark' of the form 'name@path' will
896 be created. Using :hg:`merge` will resolve the divergence.
896 be created. Using :hg:`merge` will resolve the divergence.
897
897
898 A bookmark named '@' has the special property that :hg:`clone` will
898 A bookmark named '@' has the special property that :hg:`clone` will
899 check it out by default if it exists.
899 check it out by default if it exists.
900
900
901 .. container:: verbose
901 .. container:: verbose
902
902
903 Examples:
903 Examples:
904
904
905 - create an active bookmark for a new line of development::
905 - create an active bookmark for a new line of development::
906
906
907 hg book new-feature
907 hg book new-feature
908
908
909 - create an inactive bookmark as a place marker::
909 - create an inactive bookmark as a place marker::
910
910
911 hg book -i reviewed
911 hg book -i reviewed
912
912
913 - create an inactive bookmark on another changeset::
913 - create an inactive bookmark on another changeset::
914
914
915 hg book -r .^ tested
915 hg book -r .^ tested
916
916
917 - rename bookmark turkey to dinner::
917 - rename bookmark turkey to dinner::
918
918
919 hg book -m turkey dinner
919 hg book -m turkey dinner
920
920
921 - move the '@' bookmark from another branch::
921 - move the '@' bookmark from another branch::
922
922
923 hg book -f @
923 hg book -f @
924 '''
924 '''
925 opts = pycompat.byteskwargs(opts)
925 opts = pycompat.byteskwargs(opts)
926 force = opts.get('force')
926 force = opts.get('force')
927 rev = opts.get('rev')
927 rev = opts.get('rev')
928 delete = opts.get('delete')
928 delete = opts.get('delete')
929 rename = opts.get('rename')
929 rename = opts.get('rename')
930 inactive = opts.get('inactive')
930 inactive = opts.get('inactive')
931
931
932 def checkformat(mark):
932 def checkformat(mark):
933 mark = mark.strip()
933 mark = mark.strip()
934 if not mark:
934 if not mark:
935 raise error.Abort(_("bookmark names cannot consist entirely of "
935 raise error.Abort(_("bookmark names cannot consist entirely of "
936 "whitespace"))
936 "whitespace"))
937 scmutil.checknewlabel(repo, mark, 'bookmark')
937 scmutil.checknewlabel(repo, mark, 'bookmark')
938 return mark
938 return mark
939
939
940 def checkconflict(repo, mark, cur, force=False, target=None):
940 def checkconflict(repo, mark, cur, force=False, target=None):
941 if mark in marks and not force:
941 if mark in marks and not force:
942 if target:
942 if target:
943 if marks[mark] == target and target == cur:
943 if marks[mark] == target and target == cur:
944 # re-activating a bookmark
944 # re-activating a bookmark
945 return
945 return
946 anc = repo.changelog.ancestors([repo[target].rev()])
946 anc = repo.changelog.ancestors([repo[target].rev()])
947 bmctx = repo[marks[mark]]
947 bmctx = repo[marks[mark]]
948 divs = [repo[b].node() for b in marks
948 divs = [repo[b].node() for b in marks
949 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
949 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
950
950
951 # allow resolving a single divergent bookmark even if moving
951 # allow resolving a single divergent bookmark even if moving
952 # the bookmark across branches when a revision is specified
952 # the bookmark across branches when a revision is specified
953 # that contains a divergent bookmark
953 # that contains a divergent bookmark
954 if bmctx.rev() not in anc and target in divs:
954 if bmctx.rev() not in anc and target in divs:
955 bookmarks.deletedivergent(repo, [target], mark)
955 bookmarks.deletedivergent(repo, [target], mark)
956 return
956 return
957
957
958 deletefrom = [b for b in divs
958 deletefrom = [b for b in divs
959 if repo[b].rev() in anc or b == target]
959 if repo[b].rev() in anc or b == target]
960 bookmarks.deletedivergent(repo, deletefrom, mark)
960 bookmarks.deletedivergent(repo, deletefrom, mark)
961 if bookmarks.validdest(repo, bmctx, repo[target]):
961 if bookmarks.validdest(repo, bmctx, repo[target]):
962 ui.status(_("moving bookmark '%s' forward from %s\n") %
962 ui.status(_("moving bookmark '%s' forward from %s\n") %
963 (mark, short(bmctx.node())))
963 (mark, short(bmctx.node())))
964 return
964 return
965 raise error.Abort(_("bookmark '%s' already exists "
965 raise error.Abort(_("bookmark '%s' already exists "
966 "(use -f to force)") % mark)
966 "(use -f to force)") % mark)
967 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
967 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
968 and not force):
968 and not force):
969 raise error.Abort(
969 raise error.Abort(
970 _("a bookmark cannot have the name of an existing branch"))
970 _("a bookmark cannot have the name of an existing branch"))
971 if len(mark) > 3 and mark in repo and not force:
971 if len(mark) > 3 and not force:
972 repo.ui.warn(
972 try:
973 _("bookmark %s matches a changeset hash\n"
973 shadowhash = (mark in repo)
974 "(did you leave a -r out of an 'hg bookmark' command?)\n") %
974 except error.LookupError: # ambiguous identifier
975 mark)
975 shadowhash = False
976 if shadowhash:
977 repo.ui.warn(
978 _("bookmark %s matches a changeset hash\n"
979 "(did you leave a -r out of an 'hg bookmark' command?)\n")
980 % mark)
976
981
977 if delete and rename:
982 if delete and rename:
978 raise error.Abort(_("--delete and --rename are incompatible"))
983 raise error.Abort(_("--delete and --rename are incompatible"))
979 if delete and rev:
984 if delete and rev:
980 raise error.Abort(_("--rev is incompatible with --delete"))
985 raise error.Abort(_("--rev is incompatible with --delete"))
981 if rename and rev:
986 if rename and rev:
982 raise error.Abort(_("--rev is incompatible with --rename"))
987 raise error.Abort(_("--rev is incompatible with --rename"))
983 if not names and (delete or rev):
988 if not names and (delete or rev):
984 raise error.Abort(_("bookmark name required"))
989 raise error.Abort(_("bookmark name required"))
985
990
986 if delete or rename or names or inactive:
991 if delete or rename or names or inactive:
987 wlock = lock = tr = None
992 wlock = lock = tr = None
988 try:
993 try:
989 wlock = repo.wlock()
994 wlock = repo.wlock()
990 lock = repo.lock()
995 lock = repo.lock()
991 cur = repo.changectx('.').node()
996 cur = repo.changectx('.').node()
992 marks = repo._bookmarks
997 marks = repo._bookmarks
993 if delete:
998 if delete:
994 tr = repo.transaction('bookmark')
999 tr = repo.transaction('bookmark')
995 for mark in names:
1000 for mark in names:
996 if mark not in marks:
1001 if mark not in marks:
997 raise error.Abort(_("bookmark '%s' does not exist") %
1002 raise error.Abort(_("bookmark '%s' does not exist") %
998 mark)
1003 mark)
999 if mark == repo._activebookmark:
1004 if mark == repo._activebookmark:
1000 bookmarks.deactivate(repo)
1005 bookmarks.deactivate(repo)
1001 del marks[mark]
1006 del marks[mark]
1002
1007
1003 elif rename:
1008 elif rename:
1004 tr = repo.transaction('bookmark')
1009 tr = repo.transaction('bookmark')
1005 if not names:
1010 if not names:
1006 raise error.Abort(_("new bookmark name required"))
1011 raise error.Abort(_("new bookmark name required"))
1007 elif len(names) > 1:
1012 elif len(names) > 1:
1008 raise error.Abort(_("only one new bookmark name allowed"))
1013 raise error.Abort(_("only one new bookmark name allowed"))
1009 mark = checkformat(names[0])
1014 mark = checkformat(names[0])
1010 if rename not in marks:
1015 if rename not in marks:
1011 raise error.Abort(_("bookmark '%s' does not exist")
1016 raise error.Abort(_("bookmark '%s' does not exist")
1012 % rename)
1017 % rename)
1013 checkconflict(repo, mark, cur, force)
1018 checkconflict(repo, mark, cur, force)
1014 marks[mark] = marks[rename]
1019 marks[mark] = marks[rename]
1015 if repo._activebookmark == rename and not inactive:
1020 if repo._activebookmark == rename and not inactive:
1016 bookmarks.activate(repo, mark)
1021 bookmarks.activate(repo, mark)
1017 del marks[rename]
1022 del marks[rename]
1018 elif names:
1023 elif names:
1019 tr = repo.transaction('bookmark')
1024 tr = repo.transaction('bookmark')
1020 newact = None
1025 newact = None
1021 for mark in names:
1026 for mark in names:
1022 mark = checkformat(mark)
1027 mark = checkformat(mark)
1023 if newact is None:
1028 if newact is None:
1024 newact = mark
1029 newact = mark
1025 if inactive and mark == repo._activebookmark:
1030 if inactive and mark == repo._activebookmark:
1026 bookmarks.deactivate(repo)
1031 bookmarks.deactivate(repo)
1027 return
1032 return
1028 tgt = cur
1033 tgt = cur
1029 if rev:
1034 if rev:
1030 tgt = scmutil.revsingle(repo, rev).node()
1035 tgt = scmutil.revsingle(repo, rev).node()
1031 checkconflict(repo, mark, cur, force, tgt)
1036 checkconflict(repo, mark, cur, force, tgt)
1032 marks[mark] = tgt
1037 marks[mark] = tgt
1033 if not inactive and cur == marks[newact] and not rev:
1038 if not inactive and cur == marks[newact] and not rev:
1034 bookmarks.activate(repo, newact)
1039 bookmarks.activate(repo, newact)
1035 elif cur != tgt and newact == repo._activebookmark:
1040 elif cur != tgt and newact == repo._activebookmark:
1036 bookmarks.deactivate(repo)
1041 bookmarks.deactivate(repo)
1037 elif inactive:
1042 elif inactive:
1038 if len(marks) == 0:
1043 if len(marks) == 0:
1039 ui.status(_("no bookmarks set\n"))
1044 ui.status(_("no bookmarks set\n"))
1040 elif not repo._activebookmark:
1045 elif not repo._activebookmark:
1041 ui.status(_("no active bookmark\n"))
1046 ui.status(_("no active bookmark\n"))
1042 else:
1047 else:
1043 bookmarks.deactivate(repo)
1048 bookmarks.deactivate(repo)
1044 if tr is not None:
1049 if tr is not None:
1045 marks.recordchange(tr)
1050 marks.recordchange(tr)
1046 tr.close()
1051 tr.close()
1047 finally:
1052 finally:
1048 lockmod.release(tr, lock, wlock)
1053 lockmod.release(tr, lock, wlock)
1049 else: # show bookmarks
1054 else: # show bookmarks
1050 fm = ui.formatter('bookmarks', opts)
1055 fm = ui.formatter('bookmarks', opts)
1051 hexfn = fm.hexfunc
1056 hexfn = fm.hexfunc
1052 marks = repo._bookmarks
1057 marks = repo._bookmarks
1053 if len(marks) == 0 and fm.isplain():
1058 if len(marks) == 0 and fm.isplain():
1054 ui.status(_("no bookmarks set\n"))
1059 ui.status(_("no bookmarks set\n"))
1055 for bmark, n in sorted(marks.iteritems()):
1060 for bmark, n in sorted(marks.iteritems()):
1056 active = repo._activebookmark
1061 active = repo._activebookmark
1057 if bmark == active:
1062 if bmark == active:
1058 prefix, label = '*', activebookmarklabel
1063 prefix, label = '*', activebookmarklabel
1059 else:
1064 else:
1060 prefix, label = ' ', ''
1065 prefix, label = ' ', ''
1061
1066
1062 fm.startitem()
1067 fm.startitem()
1063 if not ui.quiet:
1068 if not ui.quiet:
1064 fm.plain(' %s ' % prefix, label=label)
1069 fm.plain(' %s ' % prefix, label=label)
1065 fm.write('bookmark', '%s', bmark, label=label)
1070 fm.write('bookmark', '%s', bmark, label=label)
1066 pad = " " * (25 - encoding.colwidth(bmark))
1071 pad = " " * (25 - encoding.colwidth(bmark))
1067 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1072 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1068 repo.changelog.rev(n), hexfn(n), label=label)
1073 repo.changelog.rev(n), hexfn(n), label=label)
1069 fm.data(active=(bmark == active))
1074 fm.data(active=(bmark == active))
1070 fm.plain('\n')
1075 fm.plain('\n')
1071 fm.end()
1076 fm.end()
1072
1077
1073 @command('branch',
1078 @command('branch',
1074 [('f', 'force', None,
1079 [('f', 'force', None,
1075 _('set branch name even if it shadows an existing branch')),
1080 _('set branch name even if it shadows an existing branch')),
1076 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1081 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1077 _('[-fC] [NAME]'))
1082 _('[-fC] [NAME]'))
1078 def branch(ui, repo, label=None, **opts):
1083 def branch(ui, repo, label=None, **opts):
1079 """set or show the current branch name
1084 """set or show the current branch name
1080
1085
1081 .. note::
1086 .. note::
1082
1087
1083 Branch names are permanent and global. Use :hg:`bookmark` to create a
1088 Branch names are permanent and global. Use :hg:`bookmark` to create a
1084 light-weight bookmark instead. See :hg:`help glossary` for more
1089 light-weight bookmark instead. See :hg:`help glossary` for more
1085 information about named branches and bookmarks.
1090 information about named branches and bookmarks.
1086
1091
1087 With no argument, show the current branch name. With one argument,
1092 With no argument, show the current branch name. With one argument,
1088 set the working directory branch name (the branch will not exist
1093 set the working directory branch name (the branch will not exist
1089 in the repository until the next commit). Standard practice
1094 in the repository until the next commit). Standard practice
1090 recommends that primary development take place on the 'default'
1095 recommends that primary development take place on the 'default'
1091 branch.
1096 branch.
1092
1097
1093 Unless -f/--force is specified, branch will not let you set a
1098 Unless -f/--force is specified, branch will not let you set a
1094 branch name that already exists.
1099 branch name that already exists.
1095
1100
1096 Use -C/--clean to reset the working directory branch to that of
1101 Use -C/--clean to reset the working directory branch to that of
1097 the parent of the working directory, negating a previous branch
1102 the parent of the working directory, negating a previous branch
1098 change.
1103 change.
1099
1104
1100 Use the command :hg:`update` to switch to an existing branch. Use
1105 Use the command :hg:`update` to switch to an existing branch. Use
1101 :hg:`commit --close-branch` to mark this branch head as closed.
1106 :hg:`commit --close-branch` to mark this branch head as closed.
1102 When all heads of a branch are closed, the branch will be
1107 When all heads of a branch are closed, the branch will be
1103 considered closed.
1108 considered closed.
1104
1109
1105 Returns 0 on success.
1110 Returns 0 on success.
1106 """
1111 """
1107 opts = pycompat.byteskwargs(opts)
1112 opts = pycompat.byteskwargs(opts)
1108 if label:
1113 if label:
1109 label = label.strip()
1114 label = label.strip()
1110
1115
1111 if not opts.get('clean') and not label:
1116 if not opts.get('clean') and not label:
1112 ui.write("%s\n" % repo.dirstate.branch())
1117 ui.write("%s\n" % repo.dirstate.branch())
1113 return
1118 return
1114
1119
1115 with repo.wlock():
1120 with repo.wlock():
1116 if opts.get('clean'):
1121 if opts.get('clean'):
1117 label = repo[None].p1().branch()
1122 label = repo[None].p1().branch()
1118 repo.dirstate.setbranch(label)
1123 repo.dirstate.setbranch(label)
1119 ui.status(_('reset working directory to branch %s\n') % label)
1124 ui.status(_('reset working directory to branch %s\n') % label)
1120 elif label:
1125 elif label:
1121 if not opts.get('force') and label in repo.branchmap():
1126 if not opts.get('force') and label in repo.branchmap():
1122 if label not in [p.branch() for p in repo[None].parents()]:
1127 if label not in [p.branch() for p in repo[None].parents()]:
1123 raise error.Abort(_('a branch of the same name already'
1128 raise error.Abort(_('a branch of the same name already'
1124 ' exists'),
1129 ' exists'),
1125 # i18n: "it" refers to an existing branch
1130 # i18n: "it" refers to an existing branch
1126 hint=_("use 'hg update' to switch to it"))
1131 hint=_("use 'hg update' to switch to it"))
1127 scmutil.checknewlabel(repo, label, 'branch')
1132 scmutil.checknewlabel(repo, label, 'branch')
1128 repo.dirstate.setbranch(label)
1133 repo.dirstate.setbranch(label)
1129 ui.status(_('marked working directory as branch %s\n') % label)
1134 ui.status(_('marked working directory as branch %s\n') % label)
1130
1135
1131 # find any open named branches aside from default
1136 # find any open named branches aside from default
1132 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1137 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1133 if n != "default" and not c]
1138 if n != "default" and not c]
1134 if not others:
1139 if not others:
1135 ui.status(_('(branches are permanent and global, '
1140 ui.status(_('(branches are permanent and global, '
1136 'did you want a bookmark?)\n'))
1141 'did you want a bookmark?)\n'))
1137
1142
1138 @command('branches',
1143 @command('branches',
1139 [('a', 'active', False,
1144 [('a', 'active', False,
1140 _('show only branches that have unmerged heads (DEPRECATED)')),
1145 _('show only branches that have unmerged heads (DEPRECATED)')),
1141 ('c', 'closed', False, _('show normal and closed branches')),
1146 ('c', 'closed', False, _('show normal and closed branches')),
1142 ] + formatteropts,
1147 ] + formatteropts,
1143 _('[-c]'))
1148 _('[-c]'))
1144 def branches(ui, repo, active=False, closed=False, **opts):
1149 def branches(ui, repo, active=False, closed=False, **opts):
1145 """list repository named branches
1150 """list repository named branches
1146
1151
1147 List the repository's named branches, indicating which ones are
1152 List the repository's named branches, indicating which ones are
1148 inactive. If -c/--closed is specified, also list branches which have
1153 inactive. If -c/--closed is specified, also list branches which have
1149 been marked closed (see :hg:`commit --close-branch`).
1154 been marked closed (see :hg:`commit --close-branch`).
1150
1155
1151 Use the command :hg:`update` to switch to an existing branch.
1156 Use the command :hg:`update` to switch to an existing branch.
1152
1157
1153 Returns 0.
1158 Returns 0.
1154 """
1159 """
1155
1160
1156 opts = pycompat.byteskwargs(opts)
1161 opts = pycompat.byteskwargs(opts)
1157 ui.pager('branches')
1162 ui.pager('branches')
1158 fm = ui.formatter('branches', opts)
1163 fm = ui.formatter('branches', opts)
1159 hexfunc = fm.hexfunc
1164 hexfunc = fm.hexfunc
1160
1165
1161 allheads = set(repo.heads())
1166 allheads = set(repo.heads())
1162 branches = []
1167 branches = []
1163 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1168 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1164 isactive = not isclosed and bool(set(heads) & allheads)
1169 isactive = not isclosed and bool(set(heads) & allheads)
1165 branches.append((tag, repo[tip], isactive, not isclosed))
1170 branches.append((tag, repo[tip], isactive, not isclosed))
1166 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1171 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1167 reverse=True)
1172 reverse=True)
1168
1173
1169 for tag, ctx, isactive, isopen in branches:
1174 for tag, ctx, isactive, isopen in branches:
1170 if active and not isactive:
1175 if active and not isactive:
1171 continue
1176 continue
1172 if isactive:
1177 if isactive:
1173 label = 'branches.active'
1178 label = 'branches.active'
1174 notice = ''
1179 notice = ''
1175 elif not isopen:
1180 elif not isopen:
1176 if not closed:
1181 if not closed:
1177 continue
1182 continue
1178 label = 'branches.closed'
1183 label = 'branches.closed'
1179 notice = _(' (closed)')
1184 notice = _(' (closed)')
1180 else:
1185 else:
1181 label = 'branches.inactive'
1186 label = 'branches.inactive'
1182 notice = _(' (inactive)')
1187 notice = _(' (inactive)')
1183 current = (tag == repo.dirstate.branch())
1188 current = (tag == repo.dirstate.branch())
1184 if current:
1189 if current:
1185 label = 'branches.current'
1190 label = 'branches.current'
1186
1191
1187 fm.startitem()
1192 fm.startitem()
1188 fm.write('branch', '%s', tag, label=label)
1193 fm.write('branch', '%s', tag, label=label)
1189 rev = ctx.rev()
1194 rev = ctx.rev()
1190 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1195 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1191 fmt = ' ' * padsize + ' %d:%s'
1196 fmt = ' ' * padsize + ' %d:%s'
1192 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1197 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1193 label='log.changeset changeset.%s' % ctx.phasestr())
1198 label='log.changeset changeset.%s' % ctx.phasestr())
1194 fm.context(ctx=ctx)
1199 fm.context(ctx=ctx)
1195 fm.data(active=isactive, closed=not isopen, current=current)
1200 fm.data(active=isactive, closed=not isopen, current=current)
1196 if not ui.quiet:
1201 if not ui.quiet:
1197 fm.plain(notice)
1202 fm.plain(notice)
1198 fm.plain('\n')
1203 fm.plain('\n')
1199 fm.end()
1204 fm.end()
1200
1205
1201 @command('bundle',
1206 @command('bundle',
1202 [('f', 'force', None, _('run even when the destination is unrelated')),
1207 [('f', 'force', None, _('run even when the destination is unrelated')),
1203 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1208 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1204 _('REV')),
1209 _('REV')),
1205 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1210 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1206 _('BRANCH')),
1211 _('BRANCH')),
1207 ('', 'base', [],
1212 ('', 'base', [],
1208 _('a base changeset assumed to be available at the destination'),
1213 _('a base changeset assumed to be available at the destination'),
1209 _('REV')),
1214 _('REV')),
1210 ('a', 'all', None, _('bundle all changesets in the repository')),
1215 ('a', 'all', None, _('bundle all changesets in the repository')),
1211 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1216 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1212 ] + remoteopts,
1217 ] + remoteopts,
1213 _('[-f] [-t BUNDLESPEC] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1218 _('[-f] [-t BUNDLESPEC] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1214 def bundle(ui, repo, fname, dest=None, **opts):
1219 def bundle(ui, repo, fname, dest=None, **opts):
1215 """create a bundle file
1220 """create a bundle file
1216
1221
1217 Generate a bundle file containing data to be added to a repository.
1222 Generate a bundle file containing data to be added to a repository.
1218
1223
1219 To create a bundle containing all changesets, use -a/--all
1224 To create a bundle containing all changesets, use -a/--all
1220 (or --base null). Otherwise, hg assumes the destination will have
1225 (or --base null). Otherwise, hg assumes the destination will have
1221 all the nodes you specify with --base parameters. Otherwise, hg
1226 all the nodes you specify with --base parameters. Otherwise, hg
1222 will assume the repository has all the nodes in destination, or
1227 will assume the repository has all the nodes in destination, or
1223 default-push/default if no destination is specified.
1228 default-push/default if no destination is specified.
1224
1229
1225 You can change bundle format with the -t/--type option. See
1230 You can change bundle format with the -t/--type option. See
1226 :hg:`help bundlespec` for documentation on this format. By default,
1231 :hg:`help bundlespec` for documentation on this format. By default,
1227 the most appropriate format is used and compression defaults to
1232 the most appropriate format is used and compression defaults to
1228 bzip2.
1233 bzip2.
1229
1234
1230 The bundle file can then be transferred using conventional means
1235 The bundle file can then be transferred using conventional means
1231 and applied to another repository with the unbundle or pull
1236 and applied to another repository with the unbundle or pull
1232 command. This is useful when direct push and pull are not
1237 command. This is useful when direct push and pull are not
1233 available or when exporting an entire repository is undesirable.
1238 available or when exporting an entire repository is undesirable.
1234
1239
1235 Applying bundles preserves all changeset contents including
1240 Applying bundles preserves all changeset contents including
1236 permissions, copy/rename information, and revision history.
1241 permissions, copy/rename information, and revision history.
1237
1242
1238 Returns 0 on success, 1 if no changes found.
1243 Returns 0 on success, 1 if no changes found.
1239 """
1244 """
1240 opts = pycompat.byteskwargs(opts)
1245 opts = pycompat.byteskwargs(opts)
1241 revs = None
1246 revs = None
1242 if 'rev' in opts:
1247 if 'rev' in opts:
1243 revstrings = opts['rev']
1248 revstrings = opts['rev']
1244 revs = scmutil.revrange(repo, revstrings)
1249 revs = scmutil.revrange(repo, revstrings)
1245 if revstrings and not revs:
1250 if revstrings and not revs:
1246 raise error.Abort(_('no commits to bundle'))
1251 raise error.Abort(_('no commits to bundle'))
1247
1252
1248 bundletype = opts.get('type', 'bzip2').lower()
1253 bundletype = opts.get('type', 'bzip2').lower()
1249 try:
1254 try:
1250 bcompression, cgversion, params = exchange.parsebundlespec(
1255 bcompression, cgversion, params = exchange.parsebundlespec(
1251 repo, bundletype, strict=False)
1256 repo, bundletype, strict=False)
1252 except error.UnsupportedBundleSpecification as e:
1257 except error.UnsupportedBundleSpecification as e:
1253 raise error.Abort(str(e),
1258 raise error.Abort(str(e),
1254 hint=_("see 'hg help bundlespec' for supported "
1259 hint=_("see 'hg help bundlespec' for supported "
1255 "values for --type"))
1260 "values for --type"))
1256
1261
1257 # Packed bundles are a pseudo bundle format for now.
1262 # Packed bundles are a pseudo bundle format for now.
1258 if cgversion == 's1':
1263 if cgversion == 's1':
1259 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1264 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1260 hint=_("use 'hg debugcreatestreamclonebundle'"))
1265 hint=_("use 'hg debugcreatestreamclonebundle'"))
1261
1266
1262 if opts.get('all'):
1267 if opts.get('all'):
1263 if dest:
1268 if dest:
1264 raise error.Abort(_("--all is incompatible with specifying "
1269 raise error.Abort(_("--all is incompatible with specifying "
1265 "a destination"))
1270 "a destination"))
1266 if opts.get('base'):
1271 if opts.get('base'):
1267 ui.warn(_("ignoring --base because --all was specified\n"))
1272 ui.warn(_("ignoring --base because --all was specified\n"))
1268 base = ['null']
1273 base = ['null']
1269 else:
1274 else:
1270 base = scmutil.revrange(repo, opts.get('base'))
1275 base = scmutil.revrange(repo, opts.get('base'))
1271 if cgversion not in changegroup.supportedoutgoingversions(repo):
1276 if cgversion not in changegroup.supportedoutgoingversions(repo):
1272 raise error.Abort(_("repository does not support bundle version %s") %
1277 raise error.Abort(_("repository does not support bundle version %s") %
1273 cgversion)
1278 cgversion)
1274
1279
1275 if base:
1280 if base:
1276 if dest:
1281 if dest:
1277 raise error.Abort(_("--base is incompatible with specifying "
1282 raise error.Abort(_("--base is incompatible with specifying "
1278 "a destination"))
1283 "a destination"))
1279 common = [repo.lookup(rev) for rev in base]
1284 common = [repo.lookup(rev) for rev in base]
1280 heads = revs and map(repo.lookup, revs) or None
1285 heads = revs and map(repo.lookup, revs) or None
1281 outgoing = discovery.outgoing(repo, common, heads)
1286 outgoing = discovery.outgoing(repo, common, heads)
1282 else:
1287 else:
1283 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1288 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1284 dest, branches = hg.parseurl(dest, opts.get('branch'))
1289 dest, branches = hg.parseurl(dest, opts.get('branch'))
1285 other = hg.peer(repo, opts, dest)
1290 other = hg.peer(repo, opts, dest)
1286 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1291 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1287 heads = revs and map(repo.lookup, revs) or revs
1292 heads = revs and map(repo.lookup, revs) or revs
1288 outgoing = discovery.findcommonoutgoing(repo, other,
1293 outgoing = discovery.findcommonoutgoing(repo, other,
1289 onlyheads=heads,
1294 onlyheads=heads,
1290 force=opts.get('force'),
1295 force=opts.get('force'),
1291 portable=True)
1296 portable=True)
1292
1297
1293 if not outgoing.missing:
1298 if not outgoing.missing:
1294 scmutil.nochangesfound(ui, repo, not base and outgoing.excluded)
1299 scmutil.nochangesfound(ui, repo, not base and outgoing.excluded)
1295 return 1
1300 return 1
1296
1301
1297 if cgversion == '01': #bundle1
1302 if cgversion == '01': #bundle1
1298 if bcompression is None:
1303 if bcompression is None:
1299 bcompression = 'UN'
1304 bcompression = 'UN'
1300 bversion = 'HG10' + bcompression
1305 bversion = 'HG10' + bcompression
1301 bcompression = None
1306 bcompression = None
1302 elif cgversion in ('02', '03'):
1307 elif cgversion in ('02', '03'):
1303 bversion = 'HG20'
1308 bversion = 'HG20'
1304 else:
1309 else:
1305 raise error.ProgrammingError(
1310 raise error.ProgrammingError(
1306 'bundle: unexpected changegroup version %s' % cgversion)
1311 'bundle: unexpected changegroup version %s' % cgversion)
1307
1312
1308 # TODO compression options should be derived from bundlespec parsing.
1313 # TODO compression options should be derived from bundlespec parsing.
1309 # This is a temporary hack to allow adjusting bundle compression
1314 # This is a temporary hack to allow adjusting bundle compression
1310 # level without a) formalizing the bundlespec changes to declare it
1315 # level without a) formalizing the bundlespec changes to declare it
1311 # b) introducing a command flag.
1316 # b) introducing a command flag.
1312 compopts = {}
1317 compopts = {}
1313 complevel = ui.configint('experimental', 'bundlecomplevel')
1318 complevel = ui.configint('experimental', 'bundlecomplevel')
1314 if complevel is not None:
1319 if complevel is not None:
1315 compopts['level'] = complevel
1320 compopts['level'] = complevel
1316
1321
1317
1322
1318 contentopts = {'cg.version': cgversion}
1323 contentopts = {'cg.version': cgversion}
1319 bundle2.writenewbundle(ui, repo, 'bundle', fname, bversion, outgoing,
1324 bundle2.writenewbundle(ui, repo, 'bundle', fname, bversion, outgoing,
1320 contentopts, compression=bcompression,
1325 contentopts, compression=bcompression,
1321 compopts=compopts)
1326 compopts=compopts)
1322
1327
1323 @command('cat',
1328 @command('cat',
1324 [('o', 'output', '',
1329 [('o', 'output', '',
1325 _('print output to file with formatted name'), _('FORMAT')),
1330 _('print output to file with formatted name'), _('FORMAT')),
1326 ('r', 'rev', '', _('print the given revision'), _('REV')),
1331 ('r', 'rev', '', _('print the given revision'), _('REV')),
1327 ('', 'decode', None, _('apply any matching decode filter')),
1332 ('', 'decode', None, _('apply any matching decode filter')),
1328 ] + walkopts,
1333 ] + walkopts,
1329 _('[OPTION]... FILE...'),
1334 _('[OPTION]... FILE...'),
1330 inferrepo=True)
1335 inferrepo=True)
1331 def cat(ui, repo, file1, *pats, **opts):
1336 def cat(ui, repo, file1, *pats, **opts):
1332 """output the current or given revision of files
1337 """output the current or given revision of files
1333
1338
1334 Print the specified files as they were at the given revision. If
1339 Print the specified files as they were at the given revision. If
1335 no revision is given, the parent of the working directory is used.
1340 no revision is given, the parent of the working directory is used.
1336
1341
1337 Output may be to a file, in which case the name of the file is
1342 Output may be to a file, in which case the name of the file is
1338 given using a format string. The formatting rules as follows:
1343 given using a format string. The formatting rules as follows:
1339
1344
1340 :``%%``: literal "%" character
1345 :``%%``: literal "%" character
1341 :``%s``: basename of file being printed
1346 :``%s``: basename of file being printed
1342 :``%d``: dirname of file being printed, or '.' if in repository root
1347 :``%d``: dirname of file being printed, or '.' if in repository root
1343 :``%p``: root-relative path name of file being printed
1348 :``%p``: root-relative path name of file being printed
1344 :``%H``: changeset hash (40 hexadecimal digits)
1349 :``%H``: changeset hash (40 hexadecimal digits)
1345 :``%R``: changeset revision number
1350 :``%R``: changeset revision number
1346 :``%h``: short-form changeset hash (12 hexadecimal digits)
1351 :``%h``: short-form changeset hash (12 hexadecimal digits)
1347 :``%r``: zero-padded changeset revision number
1352 :``%r``: zero-padded changeset revision number
1348 :``%b``: basename of the exporting repository
1353 :``%b``: basename of the exporting repository
1349
1354
1350 Returns 0 on success.
1355 Returns 0 on success.
1351 """
1356 """
1352 ctx = scmutil.revsingle(repo, opts.get('rev'))
1357 ctx = scmutil.revsingle(repo, opts.get('rev'))
1353 m = scmutil.match(ctx, (file1,) + pats, opts)
1358 m = scmutil.match(ctx, (file1,) + pats, opts)
1354
1359
1355 ui.pager('cat')
1360 ui.pager('cat')
1356 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1361 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1357
1362
1358 @command('^clone',
1363 @command('^clone',
1359 [('U', 'noupdate', None, _('the clone will include an empty working '
1364 [('U', 'noupdate', None, _('the clone will include an empty working '
1360 'directory (only a repository)')),
1365 'directory (only a repository)')),
1361 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1366 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1362 _('REV')),
1367 _('REV')),
1363 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1368 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1364 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1369 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1365 ('', 'pull', None, _('use pull protocol to copy metadata')),
1370 ('', 'pull', None, _('use pull protocol to copy metadata')),
1366 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1371 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1367 ] + remoteopts,
1372 ] + remoteopts,
1368 _('[OPTION]... SOURCE [DEST]'),
1373 _('[OPTION]... SOURCE [DEST]'),
1369 norepo=True)
1374 norepo=True)
1370 def clone(ui, source, dest=None, **opts):
1375 def clone(ui, source, dest=None, **opts):
1371 """make a copy of an existing repository
1376 """make a copy of an existing repository
1372
1377
1373 Create a copy of an existing repository in a new directory.
1378 Create a copy of an existing repository in a new directory.
1374
1379
1375 If no destination directory name is specified, it defaults to the
1380 If no destination directory name is specified, it defaults to the
1376 basename of the source.
1381 basename of the source.
1377
1382
1378 The location of the source is added to the new repository's
1383 The location of the source is added to the new repository's
1379 ``.hg/hgrc`` file, as the default to be used for future pulls.
1384 ``.hg/hgrc`` file, as the default to be used for future pulls.
1380
1385
1381 Only local paths and ``ssh://`` URLs are supported as
1386 Only local paths and ``ssh://`` URLs are supported as
1382 destinations. For ``ssh://`` destinations, no working directory or
1387 destinations. For ``ssh://`` destinations, no working directory or
1383 ``.hg/hgrc`` will be created on the remote side.
1388 ``.hg/hgrc`` will be created on the remote side.
1384
1389
1385 If the source repository has a bookmark called '@' set, that
1390 If the source repository has a bookmark called '@' set, that
1386 revision will be checked out in the new repository by default.
1391 revision will be checked out in the new repository by default.
1387
1392
1388 To check out a particular version, use -u/--update, or
1393 To check out a particular version, use -u/--update, or
1389 -U/--noupdate to create a clone with no working directory.
1394 -U/--noupdate to create a clone with no working directory.
1390
1395
1391 To pull only a subset of changesets, specify one or more revisions
1396 To pull only a subset of changesets, specify one or more revisions
1392 identifiers with -r/--rev or branches with -b/--branch. The
1397 identifiers with -r/--rev or branches with -b/--branch. The
1393 resulting clone will contain only the specified changesets and
1398 resulting clone will contain only the specified changesets and
1394 their ancestors. These options (or 'clone src#rev dest') imply
1399 their ancestors. These options (or 'clone src#rev dest') imply
1395 --pull, even for local source repositories.
1400 --pull, even for local source repositories.
1396
1401
1397 .. note::
1402 .. note::
1398
1403
1399 Specifying a tag will include the tagged changeset but not the
1404 Specifying a tag will include the tagged changeset but not the
1400 changeset containing the tag.
1405 changeset containing the tag.
1401
1406
1402 .. container:: verbose
1407 .. container:: verbose
1403
1408
1404 For efficiency, hardlinks are used for cloning whenever the
1409 For efficiency, hardlinks are used for cloning whenever the
1405 source and destination are on the same filesystem (note this
1410 source and destination are on the same filesystem (note this
1406 applies only to the repository data, not to the working
1411 applies only to the repository data, not to the working
1407 directory). Some filesystems, such as AFS, implement hardlinking
1412 directory). Some filesystems, such as AFS, implement hardlinking
1408 incorrectly, but do not report errors. In these cases, use the
1413 incorrectly, but do not report errors. In these cases, use the
1409 --pull option to avoid hardlinking.
1414 --pull option to avoid hardlinking.
1410
1415
1411 In some cases, you can clone repositories and the working
1416 In some cases, you can clone repositories and the working
1412 directory using full hardlinks with ::
1417 directory using full hardlinks with ::
1413
1418
1414 $ cp -al REPO REPOCLONE
1419 $ cp -al REPO REPOCLONE
1415
1420
1416 This is the fastest way to clone, but it is not always safe. The
1421 This is the fastest way to clone, but it is not always safe. The
1417 operation is not atomic (making sure REPO is not modified during
1422 operation is not atomic (making sure REPO is not modified during
1418 the operation is up to you) and you have to make sure your
1423 the operation is up to you) and you have to make sure your
1419 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1424 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1420 so). Also, this is not compatible with certain extensions that
1425 so). Also, this is not compatible with certain extensions that
1421 place their metadata under the .hg directory, such as mq.
1426 place their metadata under the .hg directory, such as mq.
1422
1427
1423 Mercurial will update the working directory to the first applicable
1428 Mercurial will update the working directory to the first applicable
1424 revision from this list:
1429 revision from this list:
1425
1430
1426 a) null if -U or the source repository has no changesets
1431 a) null if -U or the source repository has no changesets
1427 b) if -u . and the source repository is local, the first parent of
1432 b) if -u . and the source repository is local, the first parent of
1428 the source repository's working directory
1433 the source repository's working directory
1429 c) the changeset specified with -u (if a branch name, this means the
1434 c) the changeset specified with -u (if a branch name, this means the
1430 latest head of that branch)
1435 latest head of that branch)
1431 d) the changeset specified with -r
1436 d) the changeset specified with -r
1432 e) the tipmost head specified with -b
1437 e) the tipmost head specified with -b
1433 f) the tipmost head specified with the url#branch source syntax
1438 f) the tipmost head specified with the url#branch source syntax
1434 g) the revision marked with the '@' bookmark, if present
1439 g) the revision marked with the '@' bookmark, if present
1435 h) the tipmost head of the default branch
1440 h) the tipmost head of the default branch
1436 i) tip
1441 i) tip
1437
1442
1438 When cloning from servers that support it, Mercurial may fetch
1443 When cloning from servers that support it, Mercurial may fetch
1439 pre-generated data from a server-advertised URL. When this is done,
1444 pre-generated data from a server-advertised URL. When this is done,
1440 hooks operating on incoming changesets and changegroups may fire twice,
1445 hooks operating on incoming changesets and changegroups may fire twice,
1441 once for the bundle fetched from the URL and another for any additional
1446 once for the bundle fetched from the URL and another for any additional
1442 data not fetched from this URL. In addition, if an error occurs, the
1447 data not fetched from this URL. In addition, if an error occurs, the
1443 repository may be rolled back to a partial clone. This behavior may
1448 repository may be rolled back to a partial clone. This behavior may
1444 change in future releases. See :hg:`help -e clonebundles` for more.
1449 change in future releases. See :hg:`help -e clonebundles` for more.
1445
1450
1446 Examples:
1451 Examples:
1447
1452
1448 - clone a remote repository to a new directory named hg/::
1453 - clone a remote repository to a new directory named hg/::
1449
1454
1450 hg clone https://www.mercurial-scm.org/repo/hg/
1455 hg clone https://www.mercurial-scm.org/repo/hg/
1451
1456
1452 - create a lightweight local clone::
1457 - create a lightweight local clone::
1453
1458
1454 hg clone project/ project-feature/
1459 hg clone project/ project-feature/
1455
1460
1456 - clone from an absolute path on an ssh server (note double-slash)::
1461 - clone from an absolute path on an ssh server (note double-slash)::
1457
1462
1458 hg clone ssh://user@server//home/projects/alpha/
1463 hg clone ssh://user@server//home/projects/alpha/
1459
1464
1460 - do a high-speed clone over a LAN while checking out a
1465 - do a high-speed clone over a LAN while checking out a
1461 specified version::
1466 specified version::
1462
1467
1463 hg clone --uncompressed http://server/repo -u 1.5
1468 hg clone --uncompressed http://server/repo -u 1.5
1464
1469
1465 - create a repository without changesets after a particular revision::
1470 - create a repository without changesets after a particular revision::
1466
1471
1467 hg clone -r 04e544 experimental/ good/
1472 hg clone -r 04e544 experimental/ good/
1468
1473
1469 - clone (and track) a particular named branch::
1474 - clone (and track) a particular named branch::
1470
1475
1471 hg clone https://www.mercurial-scm.org/repo/hg/#stable
1476 hg clone https://www.mercurial-scm.org/repo/hg/#stable
1472
1477
1473 See :hg:`help urls` for details on specifying URLs.
1478 See :hg:`help urls` for details on specifying URLs.
1474
1479
1475 Returns 0 on success.
1480 Returns 0 on success.
1476 """
1481 """
1477 opts = pycompat.byteskwargs(opts)
1482 opts = pycompat.byteskwargs(opts)
1478 if opts.get('noupdate') and opts.get('updaterev'):
1483 if opts.get('noupdate') and opts.get('updaterev'):
1479 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1484 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1480
1485
1481 r = hg.clone(ui, opts, source, dest,
1486 r = hg.clone(ui, opts, source, dest,
1482 pull=opts.get('pull'),
1487 pull=opts.get('pull'),
1483 stream=opts.get('uncompressed'),
1488 stream=opts.get('uncompressed'),
1484 rev=opts.get('rev'),
1489 rev=opts.get('rev'),
1485 update=opts.get('updaterev') or not opts.get('noupdate'),
1490 update=opts.get('updaterev') or not opts.get('noupdate'),
1486 branch=opts.get('branch'),
1491 branch=opts.get('branch'),
1487 shareopts=opts.get('shareopts'))
1492 shareopts=opts.get('shareopts'))
1488
1493
1489 return r is None
1494 return r is None
1490
1495
1491 @command('^commit|ci',
1496 @command('^commit|ci',
1492 [('A', 'addremove', None,
1497 [('A', 'addremove', None,
1493 _('mark new/missing files as added/removed before committing')),
1498 _('mark new/missing files as added/removed before committing')),
1494 ('', 'close-branch', None,
1499 ('', 'close-branch', None,
1495 _('mark a branch head as closed')),
1500 _('mark a branch head as closed')),
1496 ('', 'amend', None, _('amend the parent of the working directory')),
1501 ('', 'amend', None, _('amend the parent of the working directory')),
1497 ('s', 'secret', None, _('use the secret phase for committing')),
1502 ('s', 'secret', None, _('use the secret phase for committing')),
1498 ('e', 'edit', None, _('invoke editor on commit messages')),
1503 ('e', 'edit', None, _('invoke editor on commit messages')),
1499 ('i', 'interactive', None, _('use interactive mode')),
1504 ('i', 'interactive', None, _('use interactive mode')),
1500 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1505 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1501 _('[OPTION]... [FILE]...'),
1506 _('[OPTION]... [FILE]...'),
1502 inferrepo=True)
1507 inferrepo=True)
1503 def commit(ui, repo, *pats, **opts):
1508 def commit(ui, repo, *pats, **opts):
1504 """commit the specified files or all outstanding changes
1509 """commit the specified files or all outstanding changes
1505
1510
1506 Commit changes to the given files into the repository. Unlike a
1511 Commit changes to the given files into the repository. Unlike a
1507 centralized SCM, this operation is a local operation. See
1512 centralized SCM, this operation is a local operation. See
1508 :hg:`push` for a way to actively distribute your changes.
1513 :hg:`push` for a way to actively distribute your changes.
1509
1514
1510 If a list of files is omitted, all changes reported by :hg:`status`
1515 If a list of files is omitted, all changes reported by :hg:`status`
1511 will be committed.
1516 will be committed.
1512
1517
1513 If you are committing the result of a merge, do not provide any
1518 If you are committing the result of a merge, do not provide any
1514 filenames or -I/-X filters.
1519 filenames or -I/-X filters.
1515
1520
1516 If no commit message is specified, Mercurial starts your
1521 If no commit message is specified, Mercurial starts your
1517 configured editor where you can enter a message. In case your
1522 configured editor where you can enter a message. In case your
1518 commit fails, you will find a backup of your message in
1523 commit fails, you will find a backup of your message in
1519 ``.hg/last-message.txt``.
1524 ``.hg/last-message.txt``.
1520
1525
1521 The --close-branch flag can be used to mark the current branch
1526 The --close-branch flag can be used to mark the current branch
1522 head closed. When all heads of a branch are closed, the branch
1527 head closed. When all heads of a branch are closed, the branch
1523 will be considered closed and no longer listed.
1528 will be considered closed and no longer listed.
1524
1529
1525 The --amend flag can be used to amend the parent of the
1530 The --amend flag can be used to amend the parent of the
1526 working directory with a new commit that contains the changes
1531 working directory with a new commit that contains the changes
1527 in the parent in addition to those currently reported by :hg:`status`,
1532 in the parent in addition to those currently reported by :hg:`status`,
1528 if there are any. The old commit is stored in a backup bundle in
1533 if there are any. The old commit is stored in a backup bundle in
1529 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1534 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1530 on how to restore it).
1535 on how to restore it).
1531
1536
1532 Message, user and date are taken from the amended commit unless
1537 Message, user and date are taken from the amended commit unless
1533 specified. When a message isn't specified on the command line,
1538 specified. When a message isn't specified on the command line,
1534 the editor will open with the message of the amended commit.
1539 the editor will open with the message of the amended commit.
1535
1540
1536 It is not possible to amend public changesets (see :hg:`help phases`)
1541 It is not possible to amend public changesets (see :hg:`help phases`)
1537 or changesets that have children.
1542 or changesets that have children.
1538
1543
1539 See :hg:`help dates` for a list of formats valid for -d/--date.
1544 See :hg:`help dates` for a list of formats valid for -d/--date.
1540
1545
1541 Returns 0 on success, 1 if nothing changed.
1546 Returns 0 on success, 1 if nothing changed.
1542
1547
1543 .. container:: verbose
1548 .. container:: verbose
1544
1549
1545 Examples:
1550 Examples:
1546
1551
1547 - commit all files ending in .py::
1552 - commit all files ending in .py::
1548
1553
1549 hg commit --include "set:**.py"
1554 hg commit --include "set:**.py"
1550
1555
1551 - commit all non-binary files::
1556 - commit all non-binary files::
1552
1557
1553 hg commit --exclude "set:binary()"
1558 hg commit --exclude "set:binary()"
1554
1559
1555 - amend the current commit and set the date to now::
1560 - amend the current commit and set the date to now::
1556
1561
1557 hg commit --amend --date now
1562 hg commit --amend --date now
1558 """
1563 """
1559 wlock = lock = None
1564 wlock = lock = None
1560 try:
1565 try:
1561 wlock = repo.wlock()
1566 wlock = repo.wlock()
1562 lock = repo.lock()
1567 lock = repo.lock()
1563 return _docommit(ui, repo, *pats, **opts)
1568 return _docommit(ui, repo, *pats, **opts)
1564 finally:
1569 finally:
1565 release(lock, wlock)
1570 release(lock, wlock)
1566
1571
1567 def _docommit(ui, repo, *pats, **opts):
1572 def _docommit(ui, repo, *pats, **opts):
1568 if opts.get(r'interactive'):
1573 if opts.get(r'interactive'):
1569 opts.pop(r'interactive')
1574 opts.pop(r'interactive')
1570 ret = cmdutil.dorecord(ui, repo, commit, None, False,
1575 ret = cmdutil.dorecord(ui, repo, commit, None, False,
1571 cmdutil.recordfilter, *pats,
1576 cmdutil.recordfilter, *pats,
1572 **opts)
1577 **opts)
1573 # ret can be 0 (no changes to record) or the value returned by
1578 # ret can be 0 (no changes to record) or the value returned by
1574 # commit(), 1 if nothing changed or None on success.
1579 # commit(), 1 if nothing changed or None on success.
1575 return 1 if ret == 0 else ret
1580 return 1 if ret == 0 else ret
1576
1581
1577 opts = pycompat.byteskwargs(opts)
1582 opts = pycompat.byteskwargs(opts)
1578 if opts.get('subrepos'):
1583 if opts.get('subrepos'):
1579 if opts.get('amend'):
1584 if opts.get('amend'):
1580 raise error.Abort(_('cannot amend with --subrepos'))
1585 raise error.Abort(_('cannot amend with --subrepos'))
1581 # Let --subrepos on the command line override config setting.
1586 # Let --subrepos on the command line override config setting.
1582 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1587 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1583
1588
1584 cmdutil.checkunfinished(repo, commit=True)
1589 cmdutil.checkunfinished(repo, commit=True)
1585
1590
1586 branch = repo[None].branch()
1591 branch = repo[None].branch()
1587 bheads = repo.branchheads(branch)
1592 bheads = repo.branchheads(branch)
1588
1593
1589 extra = {}
1594 extra = {}
1590 if opts.get('close_branch'):
1595 if opts.get('close_branch'):
1591 extra['close'] = 1
1596 extra['close'] = 1
1592
1597
1593 if not bheads:
1598 if not bheads:
1594 raise error.Abort(_('can only close branch heads'))
1599 raise error.Abort(_('can only close branch heads'))
1595 elif opts.get('amend'):
1600 elif opts.get('amend'):
1596 if repo[None].parents()[0].p1().branch() != branch and \
1601 if repo[None].parents()[0].p1().branch() != branch and \
1597 repo[None].parents()[0].p2().branch() != branch:
1602 repo[None].parents()[0].p2().branch() != branch:
1598 raise error.Abort(_('can only close branch heads'))
1603 raise error.Abort(_('can only close branch heads'))
1599
1604
1600 if opts.get('amend'):
1605 if opts.get('amend'):
1601 if ui.configbool('ui', 'commitsubrepos'):
1606 if ui.configbool('ui', 'commitsubrepos'):
1602 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1607 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1603
1608
1604 old = repo['.']
1609 old = repo['.']
1605 if not old.mutable():
1610 if not old.mutable():
1606 raise error.Abort(_('cannot amend public changesets'))
1611 raise error.Abort(_('cannot amend public changesets'))
1607 if len(repo[None].parents()) > 1:
1612 if len(repo[None].parents()) > 1:
1608 raise error.Abort(_('cannot amend while merging'))
1613 raise error.Abort(_('cannot amend while merging'))
1609 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1614 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1610 if not allowunstable and old.children():
1615 if not allowunstable and old.children():
1611 raise error.Abort(_('cannot amend changeset with children'))
1616 raise error.Abort(_('cannot amend changeset with children'))
1612
1617
1613 # Currently histedit gets confused if an amend happens while histedit
1618 # Currently histedit gets confused if an amend happens while histedit
1614 # is in progress. Since we have a checkunfinished command, we are
1619 # is in progress. Since we have a checkunfinished command, we are
1615 # temporarily honoring it.
1620 # temporarily honoring it.
1616 #
1621 #
1617 # Note: eventually this guard will be removed. Please do not expect
1622 # Note: eventually this guard will be removed. Please do not expect
1618 # this behavior to remain.
1623 # this behavior to remain.
1619 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
1624 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
1620 cmdutil.checkunfinished(repo)
1625 cmdutil.checkunfinished(repo)
1621
1626
1622 # commitfunc is used only for temporary amend commit by cmdutil.amend
1627 # commitfunc is used only for temporary amend commit by cmdutil.amend
1623 def commitfunc(ui, repo, message, match, opts):
1628 def commitfunc(ui, repo, message, match, opts):
1624 return repo.commit(message,
1629 return repo.commit(message,
1625 opts.get('user') or old.user(),
1630 opts.get('user') or old.user(),
1626 opts.get('date') or old.date(),
1631 opts.get('date') or old.date(),
1627 match,
1632 match,
1628 extra=extra)
1633 extra=extra)
1629
1634
1630 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1635 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1631 if node == old.node():
1636 if node == old.node():
1632 ui.status(_("nothing changed\n"))
1637 ui.status(_("nothing changed\n"))
1633 return 1
1638 return 1
1634 else:
1639 else:
1635 def commitfunc(ui, repo, message, match, opts):
1640 def commitfunc(ui, repo, message, match, opts):
1636 overrides = {}
1641 overrides = {}
1637 if opts.get('secret'):
1642 if opts.get('secret'):
1638 overrides[('phases', 'new-commit')] = 'secret'
1643 overrides[('phases', 'new-commit')] = 'secret'
1639
1644
1640 baseui = repo.baseui
1645 baseui = repo.baseui
1641 with baseui.configoverride(overrides, 'commit'):
1646 with baseui.configoverride(overrides, 'commit'):
1642 with ui.configoverride(overrides, 'commit'):
1647 with ui.configoverride(overrides, 'commit'):
1643 editform = cmdutil.mergeeditform(repo[None],
1648 editform = cmdutil.mergeeditform(repo[None],
1644 'commit.normal')
1649 'commit.normal')
1645 editor = cmdutil.getcommiteditor(
1650 editor = cmdutil.getcommiteditor(
1646 editform=editform, **pycompat.strkwargs(opts))
1651 editform=editform, **pycompat.strkwargs(opts))
1647 return repo.commit(message,
1652 return repo.commit(message,
1648 opts.get('user'),
1653 opts.get('user'),
1649 opts.get('date'),
1654 opts.get('date'),
1650 match,
1655 match,
1651 editor=editor,
1656 editor=editor,
1652 extra=extra)
1657 extra=extra)
1653
1658
1654 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1659 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1655
1660
1656 if not node:
1661 if not node:
1657 stat = cmdutil.postcommitstatus(repo, pats, opts)
1662 stat = cmdutil.postcommitstatus(repo, pats, opts)
1658 if stat[3]:
1663 if stat[3]:
1659 ui.status(_("nothing changed (%d missing files, see "
1664 ui.status(_("nothing changed (%d missing files, see "
1660 "'hg status')\n") % len(stat[3]))
1665 "'hg status')\n") % len(stat[3]))
1661 else:
1666 else:
1662 ui.status(_("nothing changed\n"))
1667 ui.status(_("nothing changed\n"))
1663 return 1
1668 return 1
1664
1669
1665 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1670 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1666
1671
1667 @command('config|showconfig|debugconfig',
1672 @command('config|showconfig|debugconfig',
1668 [('u', 'untrusted', None, _('show untrusted configuration options')),
1673 [('u', 'untrusted', None, _('show untrusted configuration options')),
1669 ('e', 'edit', None, _('edit user config')),
1674 ('e', 'edit', None, _('edit user config')),
1670 ('l', 'local', None, _('edit repository config')),
1675 ('l', 'local', None, _('edit repository config')),
1671 ('g', 'global', None, _('edit global config'))] + formatteropts,
1676 ('g', 'global', None, _('edit global config'))] + formatteropts,
1672 _('[-u] [NAME]...'),
1677 _('[-u] [NAME]...'),
1673 optionalrepo=True)
1678 optionalrepo=True)
1674 def config(ui, repo, *values, **opts):
1679 def config(ui, repo, *values, **opts):
1675 """show combined config settings from all hgrc files
1680 """show combined config settings from all hgrc files
1676
1681
1677 With no arguments, print names and values of all config items.
1682 With no arguments, print names and values of all config items.
1678
1683
1679 With one argument of the form section.name, print just the value
1684 With one argument of the form section.name, print just the value
1680 of that config item.
1685 of that config item.
1681
1686
1682 With multiple arguments, print names and values of all config
1687 With multiple arguments, print names and values of all config
1683 items with matching section names.
1688 items with matching section names.
1684
1689
1685 With --edit, start an editor on the user-level config file. With
1690 With --edit, start an editor on the user-level config file. With
1686 --global, edit the system-wide config file. With --local, edit the
1691 --global, edit the system-wide config file. With --local, edit the
1687 repository-level config file.
1692 repository-level config file.
1688
1693
1689 With --debug, the source (filename and line number) is printed
1694 With --debug, the source (filename and line number) is printed
1690 for each config item.
1695 for each config item.
1691
1696
1692 See :hg:`help config` for more information about config files.
1697 See :hg:`help config` for more information about config files.
1693
1698
1694 Returns 0 on success, 1 if NAME does not exist.
1699 Returns 0 on success, 1 if NAME does not exist.
1695
1700
1696 """
1701 """
1697
1702
1698 opts = pycompat.byteskwargs(opts)
1703 opts = pycompat.byteskwargs(opts)
1699 if opts.get('edit') or opts.get('local') or opts.get('global'):
1704 if opts.get('edit') or opts.get('local') or opts.get('global'):
1700 if opts.get('local') and opts.get('global'):
1705 if opts.get('local') and opts.get('global'):
1701 raise error.Abort(_("can't use --local and --global together"))
1706 raise error.Abort(_("can't use --local and --global together"))
1702
1707
1703 if opts.get('local'):
1708 if opts.get('local'):
1704 if not repo:
1709 if not repo:
1705 raise error.Abort(_("can't use --local outside a repository"))
1710 raise error.Abort(_("can't use --local outside a repository"))
1706 paths = [repo.vfs.join('hgrc')]
1711 paths = [repo.vfs.join('hgrc')]
1707 elif opts.get('global'):
1712 elif opts.get('global'):
1708 paths = rcutil.systemrcpath()
1713 paths = rcutil.systemrcpath()
1709 else:
1714 else:
1710 paths = rcutil.userrcpath()
1715 paths = rcutil.userrcpath()
1711
1716
1712 for f in paths:
1717 for f in paths:
1713 if os.path.exists(f):
1718 if os.path.exists(f):
1714 break
1719 break
1715 else:
1720 else:
1716 if opts.get('global'):
1721 if opts.get('global'):
1717 samplehgrc = uimod.samplehgrcs['global']
1722 samplehgrc = uimod.samplehgrcs['global']
1718 elif opts.get('local'):
1723 elif opts.get('local'):
1719 samplehgrc = uimod.samplehgrcs['local']
1724 samplehgrc = uimod.samplehgrcs['local']
1720 else:
1725 else:
1721 samplehgrc = uimod.samplehgrcs['user']
1726 samplehgrc = uimod.samplehgrcs['user']
1722
1727
1723 f = paths[0]
1728 f = paths[0]
1724 fp = open(f, "w")
1729 fp = open(f, "w")
1725 fp.write(samplehgrc)
1730 fp.write(samplehgrc)
1726 fp.close()
1731 fp.close()
1727
1732
1728 editor = ui.geteditor()
1733 editor = ui.geteditor()
1729 ui.system("%s \"%s\"" % (editor, f),
1734 ui.system("%s \"%s\"" % (editor, f),
1730 onerr=error.Abort, errprefix=_("edit failed"),
1735 onerr=error.Abort, errprefix=_("edit failed"),
1731 blockedtag='config_edit')
1736 blockedtag='config_edit')
1732 return
1737 return
1733 ui.pager('config')
1738 ui.pager('config')
1734 fm = ui.formatter('config', opts)
1739 fm = ui.formatter('config', opts)
1735 for t, f in rcutil.rccomponents():
1740 for t, f in rcutil.rccomponents():
1736 if t == 'path':
1741 if t == 'path':
1737 ui.debug('read config from: %s\n' % f)
1742 ui.debug('read config from: %s\n' % f)
1738 elif t == 'items':
1743 elif t == 'items':
1739 for section, name, value, source in f:
1744 for section, name, value, source in f:
1740 ui.debug('set config by: %s\n' % source)
1745 ui.debug('set config by: %s\n' % source)
1741 else:
1746 else:
1742 raise error.ProgrammingError('unknown rctype: %s' % t)
1747 raise error.ProgrammingError('unknown rctype: %s' % t)
1743 untrusted = bool(opts.get('untrusted'))
1748 untrusted = bool(opts.get('untrusted'))
1744 if values:
1749 if values:
1745 sections = [v for v in values if '.' not in v]
1750 sections = [v for v in values if '.' not in v]
1746 items = [v for v in values if '.' in v]
1751 items = [v for v in values if '.' in v]
1747 if len(items) > 1 or items and sections:
1752 if len(items) > 1 or items and sections:
1748 raise error.Abort(_('only one config item permitted'))
1753 raise error.Abort(_('only one config item permitted'))
1749 matched = False
1754 matched = False
1750 for section, name, value in ui.walkconfig(untrusted=untrusted):
1755 for section, name, value in ui.walkconfig(untrusted=untrusted):
1751 source = ui.configsource(section, name, untrusted)
1756 source = ui.configsource(section, name, untrusted)
1752 value = pycompat.bytestr(value)
1757 value = pycompat.bytestr(value)
1753 if fm.isplain():
1758 if fm.isplain():
1754 source = source or 'none'
1759 source = source or 'none'
1755 value = value.replace('\n', '\\n')
1760 value = value.replace('\n', '\\n')
1756 entryname = section + '.' + name
1761 entryname = section + '.' + name
1757 if values:
1762 if values:
1758 for v in values:
1763 for v in values:
1759 if v == section:
1764 if v == section:
1760 fm.startitem()
1765 fm.startitem()
1761 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1766 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1762 fm.write('name value', '%s=%s\n', entryname, value)
1767 fm.write('name value', '%s=%s\n', entryname, value)
1763 matched = True
1768 matched = True
1764 elif v == entryname:
1769 elif v == entryname:
1765 fm.startitem()
1770 fm.startitem()
1766 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1771 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1767 fm.write('value', '%s\n', value)
1772 fm.write('value', '%s\n', value)
1768 fm.data(name=entryname)
1773 fm.data(name=entryname)
1769 matched = True
1774 matched = True
1770 else:
1775 else:
1771 fm.startitem()
1776 fm.startitem()
1772 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1777 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1773 fm.write('name value', '%s=%s\n', entryname, value)
1778 fm.write('name value', '%s=%s\n', entryname, value)
1774 matched = True
1779 matched = True
1775 fm.end()
1780 fm.end()
1776 if matched:
1781 if matched:
1777 return 0
1782 return 0
1778 return 1
1783 return 1
1779
1784
1780 @command('copy|cp',
1785 @command('copy|cp',
1781 [('A', 'after', None, _('record a copy that has already occurred')),
1786 [('A', 'after', None, _('record a copy that has already occurred')),
1782 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1787 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1783 ] + walkopts + dryrunopts,
1788 ] + walkopts + dryrunopts,
1784 _('[OPTION]... [SOURCE]... DEST'))
1789 _('[OPTION]... [SOURCE]... DEST'))
1785 def copy(ui, repo, *pats, **opts):
1790 def copy(ui, repo, *pats, **opts):
1786 """mark files as copied for the next commit
1791 """mark files as copied for the next commit
1787
1792
1788 Mark dest as having copies of source files. If dest is a
1793 Mark dest as having copies of source files. If dest is a
1789 directory, copies are put in that directory. If dest is a file,
1794 directory, copies are put in that directory. If dest is a file,
1790 the source must be a single file.
1795 the source must be a single file.
1791
1796
1792 By default, this command copies the contents of files as they
1797 By default, this command copies the contents of files as they
1793 exist in the working directory. If invoked with -A/--after, the
1798 exist in the working directory. If invoked with -A/--after, the
1794 operation is recorded, but no copying is performed.
1799 operation is recorded, but no copying is performed.
1795
1800
1796 This command takes effect with the next commit. To undo a copy
1801 This command takes effect with the next commit. To undo a copy
1797 before that, see :hg:`revert`.
1802 before that, see :hg:`revert`.
1798
1803
1799 Returns 0 on success, 1 if errors are encountered.
1804 Returns 0 on success, 1 if errors are encountered.
1800 """
1805 """
1801 opts = pycompat.byteskwargs(opts)
1806 opts = pycompat.byteskwargs(opts)
1802 with repo.wlock(False):
1807 with repo.wlock(False):
1803 return cmdutil.copy(ui, repo, pats, opts)
1808 return cmdutil.copy(ui, repo, pats, opts)
1804
1809
1805 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1810 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1806 def debugcommands(ui, cmd='', *args):
1811 def debugcommands(ui, cmd='', *args):
1807 """list all available commands and options"""
1812 """list all available commands and options"""
1808 for cmd, vals in sorted(table.iteritems()):
1813 for cmd, vals in sorted(table.iteritems()):
1809 cmd = cmd.split('|')[0].strip('^')
1814 cmd = cmd.split('|')[0].strip('^')
1810 opts = ', '.join([i[1] for i in vals[1]])
1815 opts = ', '.join([i[1] for i in vals[1]])
1811 ui.write('%s: %s\n' % (cmd, opts))
1816 ui.write('%s: %s\n' % (cmd, opts))
1812
1817
1813 @command('debugcomplete',
1818 @command('debugcomplete',
1814 [('o', 'options', None, _('show the command options'))],
1819 [('o', 'options', None, _('show the command options'))],
1815 _('[-o] CMD'),
1820 _('[-o] CMD'),
1816 norepo=True)
1821 norepo=True)
1817 def debugcomplete(ui, cmd='', **opts):
1822 def debugcomplete(ui, cmd='', **opts):
1818 """returns the completion list associated with the given command"""
1823 """returns the completion list associated with the given command"""
1819
1824
1820 if opts.get('options'):
1825 if opts.get('options'):
1821 options = []
1826 options = []
1822 otables = [globalopts]
1827 otables = [globalopts]
1823 if cmd:
1828 if cmd:
1824 aliases, entry = cmdutil.findcmd(cmd, table, False)
1829 aliases, entry = cmdutil.findcmd(cmd, table, False)
1825 otables.append(entry[1])
1830 otables.append(entry[1])
1826 for t in otables:
1831 for t in otables:
1827 for o in t:
1832 for o in t:
1828 if "(DEPRECATED)" in o[3]:
1833 if "(DEPRECATED)" in o[3]:
1829 continue
1834 continue
1830 if o[0]:
1835 if o[0]:
1831 options.append('-%s' % o[0])
1836 options.append('-%s' % o[0])
1832 options.append('--%s' % o[1])
1837 options.append('--%s' % o[1])
1833 ui.write("%s\n" % "\n".join(options))
1838 ui.write("%s\n" % "\n".join(options))
1834 return
1839 return
1835
1840
1836 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
1841 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
1837 if ui.verbose:
1842 if ui.verbose:
1838 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1843 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1839 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1844 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1840
1845
1841 @command('^diff',
1846 @command('^diff',
1842 [('r', 'rev', [], _('revision'), _('REV')),
1847 [('r', 'rev', [], _('revision'), _('REV')),
1843 ('c', 'change', '', _('change made by revision'), _('REV'))
1848 ('c', 'change', '', _('change made by revision'), _('REV'))
1844 ] + diffopts + diffopts2 + walkopts + subrepoopts,
1849 ] + diffopts + diffopts2 + walkopts + subrepoopts,
1845 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
1850 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
1846 inferrepo=True)
1851 inferrepo=True)
1847 def diff(ui, repo, *pats, **opts):
1852 def diff(ui, repo, *pats, **opts):
1848 """diff repository (or selected files)
1853 """diff repository (or selected files)
1849
1854
1850 Show differences between revisions for the specified files.
1855 Show differences between revisions for the specified files.
1851
1856
1852 Differences between files are shown using the unified diff format.
1857 Differences between files are shown using the unified diff format.
1853
1858
1854 .. note::
1859 .. note::
1855
1860
1856 :hg:`diff` may generate unexpected results for merges, as it will
1861 :hg:`diff` may generate unexpected results for merges, as it will
1857 default to comparing against the working directory's first
1862 default to comparing against the working directory's first
1858 parent changeset if no revisions are specified.
1863 parent changeset if no revisions are specified.
1859
1864
1860 When two revision arguments are given, then changes are shown
1865 When two revision arguments are given, then changes are shown
1861 between those revisions. If only one revision is specified then
1866 between those revisions. If only one revision is specified then
1862 that revision is compared to the working directory, and, when no
1867 that revision is compared to the working directory, and, when no
1863 revisions are specified, the working directory files are compared
1868 revisions are specified, the working directory files are compared
1864 to its first parent.
1869 to its first parent.
1865
1870
1866 Alternatively you can specify -c/--change with a revision to see
1871 Alternatively you can specify -c/--change with a revision to see
1867 the changes in that changeset relative to its first parent.
1872 the changes in that changeset relative to its first parent.
1868
1873
1869 Without the -a/--text option, diff will avoid generating diffs of
1874 Without the -a/--text option, diff will avoid generating diffs of
1870 files it detects as binary. With -a, diff will generate a diff
1875 files it detects as binary. With -a, diff will generate a diff
1871 anyway, probably with undesirable results.
1876 anyway, probably with undesirable results.
1872
1877
1873 Use the -g/--git option to generate diffs in the git extended diff
1878 Use the -g/--git option to generate diffs in the git extended diff
1874 format. For more information, read :hg:`help diffs`.
1879 format. For more information, read :hg:`help diffs`.
1875
1880
1876 .. container:: verbose
1881 .. container:: verbose
1877
1882
1878 Examples:
1883 Examples:
1879
1884
1880 - compare a file in the current working directory to its parent::
1885 - compare a file in the current working directory to its parent::
1881
1886
1882 hg diff foo.c
1887 hg diff foo.c
1883
1888
1884 - compare two historical versions of a directory, with rename info::
1889 - compare two historical versions of a directory, with rename info::
1885
1890
1886 hg diff --git -r 1.0:1.2 lib/
1891 hg diff --git -r 1.0:1.2 lib/
1887
1892
1888 - get change stats relative to the last change on some date::
1893 - get change stats relative to the last change on some date::
1889
1894
1890 hg diff --stat -r "date('may 2')"
1895 hg diff --stat -r "date('may 2')"
1891
1896
1892 - diff all newly-added files that contain a keyword::
1897 - diff all newly-added files that contain a keyword::
1893
1898
1894 hg diff "set:added() and grep(GNU)"
1899 hg diff "set:added() and grep(GNU)"
1895
1900
1896 - compare a revision and its parents::
1901 - compare a revision and its parents::
1897
1902
1898 hg diff -c 9353 # compare against first parent
1903 hg diff -c 9353 # compare against first parent
1899 hg diff -r 9353^:9353 # same using revset syntax
1904 hg diff -r 9353^:9353 # same using revset syntax
1900 hg diff -r 9353^2:9353 # compare against the second parent
1905 hg diff -r 9353^2:9353 # compare against the second parent
1901
1906
1902 Returns 0 on success.
1907 Returns 0 on success.
1903 """
1908 """
1904
1909
1905 opts = pycompat.byteskwargs(opts)
1910 opts = pycompat.byteskwargs(opts)
1906 revs = opts.get('rev')
1911 revs = opts.get('rev')
1907 change = opts.get('change')
1912 change = opts.get('change')
1908 stat = opts.get('stat')
1913 stat = opts.get('stat')
1909 reverse = opts.get('reverse')
1914 reverse = opts.get('reverse')
1910
1915
1911 if revs and change:
1916 if revs and change:
1912 msg = _('cannot specify --rev and --change at the same time')
1917 msg = _('cannot specify --rev and --change at the same time')
1913 raise error.Abort(msg)
1918 raise error.Abort(msg)
1914 elif change:
1919 elif change:
1915 node2 = scmutil.revsingle(repo, change, None).node()
1920 node2 = scmutil.revsingle(repo, change, None).node()
1916 node1 = repo[node2].p1().node()
1921 node1 = repo[node2].p1().node()
1917 else:
1922 else:
1918 node1, node2 = scmutil.revpair(repo, revs)
1923 node1, node2 = scmutil.revpair(repo, revs)
1919
1924
1920 if reverse:
1925 if reverse:
1921 node1, node2 = node2, node1
1926 node1, node2 = node2, node1
1922
1927
1923 diffopts = patch.diffallopts(ui, opts)
1928 diffopts = patch.diffallopts(ui, opts)
1924 m = scmutil.match(repo[node2], pats, opts)
1929 m = scmutil.match(repo[node2], pats, opts)
1925 ui.pager('diff')
1930 ui.pager('diff')
1926 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
1931 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
1927 listsubrepos=opts.get('subrepos'),
1932 listsubrepos=opts.get('subrepos'),
1928 root=opts.get('root'))
1933 root=opts.get('root'))
1929
1934
1930 @command('^export',
1935 @command('^export',
1931 [('o', 'output', '',
1936 [('o', 'output', '',
1932 _('print output to file with formatted name'), _('FORMAT')),
1937 _('print output to file with formatted name'), _('FORMAT')),
1933 ('', 'switch-parent', None, _('diff against the second parent')),
1938 ('', 'switch-parent', None, _('diff against the second parent')),
1934 ('r', 'rev', [], _('revisions to export'), _('REV')),
1939 ('r', 'rev', [], _('revisions to export'), _('REV')),
1935 ] + diffopts,
1940 ] + diffopts,
1936 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
1941 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
1937 def export(ui, repo, *changesets, **opts):
1942 def export(ui, repo, *changesets, **opts):
1938 """dump the header and diffs for one or more changesets
1943 """dump the header and diffs for one or more changesets
1939
1944
1940 Print the changeset header and diffs for one or more revisions.
1945 Print the changeset header and diffs for one or more revisions.
1941 If no revision is given, the parent of the working directory is used.
1946 If no revision is given, the parent of the working directory is used.
1942
1947
1943 The information shown in the changeset header is: author, date,
1948 The information shown in the changeset header is: author, date,
1944 branch name (if non-default), changeset hash, parent(s) and commit
1949 branch name (if non-default), changeset hash, parent(s) and commit
1945 comment.
1950 comment.
1946
1951
1947 .. note::
1952 .. note::
1948
1953
1949 :hg:`export` may generate unexpected diff output for merge
1954 :hg:`export` may generate unexpected diff output for merge
1950 changesets, as it will compare the merge changeset against its
1955 changesets, as it will compare the merge changeset against its
1951 first parent only.
1956 first parent only.
1952
1957
1953 Output may be to a file, in which case the name of the file is
1958 Output may be to a file, in which case the name of the file is
1954 given using a format string. The formatting rules are as follows:
1959 given using a format string. The formatting rules are as follows:
1955
1960
1956 :``%%``: literal "%" character
1961 :``%%``: literal "%" character
1957 :``%H``: changeset hash (40 hexadecimal digits)
1962 :``%H``: changeset hash (40 hexadecimal digits)
1958 :``%N``: number of patches being generated
1963 :``%N``: number of patches being generated
1959 :``%R``: changeset revision number
1964 :``%R``: changeset revision number
1960 :``%b``: basename of the exporting repository
1965 :``%b``: basename of the exporting repository
1961 :``%h``: short-form changeset hash (12 hexadecimal digits)
1966 :``%h``: short-form changeset hash (12 hexadecimal digits)
1962 :``%m``: first line of the commit message (only alphanumeric characters)
1967 :``%m``: first line of the commit message (only alphanumeric characters)
1963 :``%n``: zero-padded sequence number, starting at 1
1968 :``%n``: zero-padded sequence number, starting at 1
1964 :``%r``: zero-padded changeset revision number
1969 :``%r``: zero-padded changeset revision number
1965
1970
1966 Without the -a/--text option, export will avoid generating diffs
1971 Without the -a/--text option, export will avoid generating diffs
1967 of files it detects as binary. With -a, export will generate a
1972 of files it detects as binary. With -a, export will generate a
1968 diff anyway, probably with undesirable results.
1973 diff anyway, probably with undesirable results.
1969
1974
1970 Use the -g/--git option to generate diffs in the git extended diff
1975 Use the -g/--git option to generate diffs in the git extended diff
1971 format. See :hg:`help diffs` for more information.
1976 format. See :hg:`help diffs` for more information.
1972
1977
1973 With the --switch-parent option, the diff will be against the
1978 With the --switch-parent option, the diff will be against the
1974 second parent. It can be useful to review a merge.
1979 second parent. It can be useful to review a merge.
1975
1980
1976 .. container:: verbose
1981 .. container:: verbose
1977
1982
1978 Examples:
1983 Examples:
1979
1984
1980 - use export and import to transplant a bugfix to the current
1985 - use export and import to transplant a bugfix to the current
1981 branch::
1986 branch::
1982
1987
1983 hg export -r 9353 | hg import -
1988 hg export -r 9353 | hg import -
1984
1989
1985 - export all the changesets between two revisions to a file with
1990 - export all the changesets between two revisions to a file with
1986 rename information::
1991 rename information::
1987
1992
1988 hg export --git -r 123:150 > changes.txt
1993 hg export --git -r 123:150 > changes.txt
1989
1994
1990 - split outgoing changes into a series of patches with
1995 - split outgoing changes into a series of patches with
1991 descriptive names::
1996 descriptive names::
1992
1997
1993 hg export -r "outgoing()" -o "%n-%m.patch"
1998 hg export -r "outgoing()" -o "%n-%m.patch"
1994
1999
1995 Returns 0 on success.
2000 Returns 0 on success.
1996 """
2001 """
1997 opts = pycompat.byteskwargs(opts)
2002 opts = pycompat.byteskwargs(opts)
1998 changesets += tuple(opts.get('rev', []))
2003 changesets += tuple(opts.get('rev', []))
1999 if not changesets:
2004 if not changesets:
2000 changesets = ['.']
2005 changesets = ['.']
2001 revs = scmutil.revrange(repo, changesets)
2006 revs = scmutil.revrange(repo, changesets)
2002 if not revs:
2007 if not revs:
2003 raise error.Abort(_("export requires at least one changeset"))
2008 raise error.Abort(_("export requires at least one changeset"))
2004 if len(revs) > 1:
2009 if len(revs) > 1:
2005 ui.note(_('exporting patches:\n'))
2010 ui.note(_('exporting patches:\n'))
2006 else:
2011 else:
2007 ui.note(_('exporting patch:\n'))
2012 ui.note(_('exporting patch:\n'))
2008 ui.pager('export')
2013 ui.pager('export')
2009 cmdutil.export(repo, revs, fntemplate=opts.get('output'),
2014 cmdutil.export(repo, revs, fntemplate=opts.get('output'),
2010 switch_parent=opts.get('switch_parent'),
2015 switch_parent=opts.get('switch_parent'),
2011 opts=patch.diffallopts(ui, opts))
2016 opts=patch.diffallopts(ui, opts))
2012
2017
2013 @command('files',
2018 @command('files',
2014 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
2019 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
2015 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
2020 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
2016 ] + walkopts + formatteropts + subrepoopts,
2021 ] + walkopts + formatteropts + subrepoopts,
2017 _('[OPTION]... [FILE]...'))
2022 _('[OPTION]... [FILE]...'))
2018 def files(ui, repo, *pats, **opts):
2023 def files(ui, repo, *pats, **opts):
2019 """list tracked files
2024 """list tracked files
2020
2025
2021 Print files under Mercurial control in the working directory or
2026 Print files under Mercurial control in the working directory or
2022 specified revision for given files (excluding removed files).
2027 specified revision for given files (excluding removed files).
2023 Files can be specified as filenames or filesets.
2028 Files can be specified as filenames or filesets.
2024
2029
2025 If no files are given to match, this command prints the names
2030 If no files are given to match, this command prints the names
2026 of all files under Mercurial control.
2031 of all files under Mercurial control.
2027
2032
2028 .. container:: verbose
2033 .. container:: verbose
2029
2034
2030 Examples:
2035 Examples:
2031
2036
2032 - list all files under the current directory::
2037 - list all files under the current directory::
2033
2038
2034 hg files .
2039 hg files .
2035
2040
2036 - shows sizes and flags for current revision::
2041 - shows sizes and flags for current revision::
2037
2042
2038 hg files -vr .
2043 hg files -vr .
2039
2044
2040 - list all files named README::
2045 - list all files named README::
2041
2046
2042 hg files -I "**/README"
2047 hg files -I "**/README"
2043
2048
2044 - list all binary files::
2049 - list all binary files::
2045
2050
2046 hg files "set:binary()"
2051 hg files "set:binary()"
2047
2052
2048 - find files containing a regular expression::
2053 - find files containing a regular expression::
2049
2054
2050 hg files "set:grep('bob')"
2055 hg files "set:grep('bob')"
2051
2056
2052 - search tracked file contents with xargs and grep::
2057 - search tracked file contents with xargs and grep::
2053
2058
2054 hg files -0 | xargs -0 grep foo
2059 hg files -0 | xargs -0 grep foo
2055
2060
2056 See :hg:`help patterns` and :hg:`help filesets` for more information
2061 See :hg:`help patterns` and :hg:`help filesets` for more information
2057 on specifying file patterns.
2062 on specifying file patterns.
2058
2063
2059 Returns 0 if a match is found, 1 otherwise.
2064 Returns 0 if a match is found, 1 otherwise.
2060
2065
2061 """
2066 """
2062
2067
2063 opts = pycompat.byteskwargs(opts)
2068 opts = pycompat.byteskwargs(opts)
2064 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2069 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2065
2070
2066 end = '\n'
2071 end = '\n'
2067 if opts.get('print0'):
2072 if opts.get('print0'):
2068 end = '\0'
2073 end = '\0'
2069 fmt = '%s' + end
2074 fmt = '%s' + end
2070
2075
2071 m = scmutil.match(ctx, pats, opts)
2076 m = scmutil.match(ctx, pats, opts)
2072 ui.pager('files')
2077 ui.pager('files')
2073 with ui.formatter('files', opts) as fm:
2078 with ui.formatter('files', opts) as fm:
2074 return cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
2079 return cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
2075
2080
2076 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
2081 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
2077 def forget(ui, repo, *pats, **opts):
2082 def forget(ui, repo, *pats, **opts):
2078 """forget the specified files on the next commit
2083 """forget the specified files on the next commit
2079
2084
2080 Mark the specified files so they will no longer be tracked
2085 Mark the specified files so they will no longer be tracked
2081 after the next commit.
2086 after the next commit.
2082
2087
2083 This only removes files from the current branch, not from the
2088 This only removes files from the current branch, not from the
2084 entire project history, and it does not delete them from the
2089 entire project history, and it does not delete them from the
2085 working directory.
2090 working directory.
2086
2091
2087 To delete the file from the working directory, see :hg:`remove`.
2092 To delete the file from the working directory, see :hg:`remove`.
2088
2093
2089 To undo a forget before the next commit, see :hg:`add`.
2094 To undo a forget before the next commit, see :hg:`add`.
2090
2095
2091 .. container:: verbose
2096 .. container:: verbose
2092
2097
2093 Examples:
2098 Examples:
2094
2099
2095 - forget newly-added binary files::
2100 - forget newly-added binary files::
2096
2101
2097 hg forget "set:added() and binary()"
2102 hg forget "set:added() and binary()"
2098
2103
2099 - forget files that would be excluded by .hgignore::
2104 - forget files that would be excluded by .hgignore::
2100
2105
2101 hg forget "set:hgignore()"
2106 hg forget "set:hgignore()"
2102
2107
2103 Returns 0 on success.
2108 Returns 0 on success.
2104 """
2109 """
2105
2110
2106 opts = pycompat.byteskwargs(opts)
2111 opts = pycompat.byteskwargs(opts)
2107 if not pats:
2112 if not pats:
2108 raise error.Abort(_('no files specified'))
2113 raise error.Abort(_('no files specified'))
2109
2114
2110 m = scmutil.match(repo[None], pats, opts)
2115 m = scmutil.match(repo[None], pats, opts)
2111 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2116 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2112 return rejected and 1 or 0
2117 return rejected and 1 or 0
2113
2118
2114 @command(
2119 @command(
2115 'graft',
2120 'graft',
2116 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2121 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2117 ('c', 'continue', False, _('resume interrupted graft')),
2122 ('c', 'continue', False, _('resume interrupted graft')),
2118 ('e', 'edit', False, _('invoke editor on commit messages')),
2123 ('e', 'edit', False, _('invoke editor on commit messages')),
2119 ('', 'log', None, _('append graft info to log message')),
2124 ('', 'log', None, _('append graft info to log message')),
2120 ('f', 'force', False, _('force graft')),
2125 ('f', 'force', False, _('force graft')),
2121 ('D', 'currentdate', False,
2126 ('D', 'currentdate', False,
2122 _('record the current date as commit date')),
2127 _('record the current date as commit date')),
2123 ('U', 'currentuser', False,
2128 ('U', 'currentuser', False,
2124 _('record the current user as committer'), _('DATE'))]
2129 _('record the current user as committer'), _('DATE'))]
2125 + commitopts2 + mergetoolopts + dryrunopts,
2130 + commitopts2 + mergetoolopts + dryrunopts,
2126 _('[OPTION]... [-r REV]... REV...'))
2131 _('[OPTION]... [-r REV]... REV...'))
2127 def graft(ui, repo, *revs, **opts):
2132 def graft(ui, repo, *revs, **opts):
2128 '''copy changes from other branches onto the current branch
2133 '''copy changes from other branches onto the current branch
2129
2134
2130 This command uses Mercurial's merge logic to copy individual
2135 This command uses Mercurial's merge logic to copy individual
2131 changes from other branches without merging branches in the
2136 changes from other branches without merging branches in the
2132 history graph. This is sometimes known as 'backporting' or
2137 history graph. This is sometimes known as 'backporting' or
2133 'cherry-picking'. By default, graft will copy user, date, and
2138 'cherry-picking'. By default, graft will copy user, date, and
2134 description from the source changesets.
2139 description from the source changesets.
2135
2140
2136 Changesets that are ancestors of the current revision, that have
2141 Changesets that are ancestors of the current revision, that have
2137 already been grafted, or that are merges will be skipped.
2142 already been grafted, or that are merges will be skipped.
2138
2143
2139 If --log is specified, log messages will have a comment appended
2144 If --log is specified, log messages will have a comment appended
2140 of the form::
2145 of the form::
2141
2146
2142 (grafted from CHANGESETHASH)
2147 (grafted from CHANGESETHASH)
2143
2148
2144 If --force is specified, revisions will be grafted even if they
2149 If --force is specified, revisions will be grafted even if they
2145 are already ancestors of or have been grafted to the destination.
2150 are already ancestors of or have been grafted to the destination.
2146 This is useful when the revisions have since been backed out.
2151 This is useful when the revisions have since been backed out.
2147
2152
2148 If a graft merge results in conflicts, the graft process is
2153 If a graft merge results in conflicts, the graft process is
2149 interrupted so that the current merge can be manually resolved.
2154 interrupted so that the current merge can be manually resolved.
2150 Once all conflicts are addressed, the graft process can be
2155 Once all conflicts are addressed, the graft process can be
2151 continued with the -c/--continue option.
2156 continued with the -c/--continue option.
2152
2157
2153 .. note::
2158 .. note::
2154
2159
2155 The -c/--continue option does not reapply earlier options, except
2160 The -c/--continue option does not reapply earlier options, except
2156 for --force.
2161 for --force.
2157
2162
2158 .. container:: verbose
2163 .. container:: verbose
2159
2164
2160 Examples:
2165 Examples:
2161
2166
2162 - copy a single change to the stable branch and edit its description::
2167 - copy a single change to the stable branch and edit its description::
2163
2168
2164 hg update stable
2169 hg update stable
2165 hg graft --edit 9393
2170 hg graft --edit 9393
2166
2171
2167 - graft a range of changesets with one exception, updating dates::
2172 - graft a range of changesets with one exception, updating dates::
2168
2173
2169 hg graft -D "2085::2093 and not 2091"
2174 hg graft -D "2085::2093 and not 2091"
2170
2175
2171 - continue a graft after resolving conflicts::
2176 - continue a graft after resolving conflicts::
2172
2177
2173 hg graft -c
2178 hg graft -c
2174
2179
2175 - show the source of a grafted changeset::
2180 - show the source of a grafted changeset::
2176
2181
2177 hg log --debug -r .
2182 hg log --debug -r .
2178
2183
2179 - show revisions sorted by date::
2184 - show revisions sorted by date::
2180
2185
2181 hg log -r "sort(all(), date)"
2186 hg log -r "sort(all(), date)"
2182
2187
2183 See :hg:`help revisions` for more about specifying revisions.
2188 See :hg:`help revisions` for more about specifying revisions.
2184
2189
2185 Returns 0 on successful completion.
2190 Returns 0 on successful completion.
2186 '''
2191 '''
2187 with repo.wlock():
2192 with repo.wlock():
2188 return _dograft(ui, repo, *revs, **opts)
2193 return _dograft(ui, repo, *revs, **opts)
2189
2194
2190 def _dograft(ui, repo, *revs, **opts):
2195 def _dograft(ui, repo, *revs, **opts):
2191 opts = pycompat.byteskwargs(opts)
2196 opts = pycompat.byteskwargs(opts)
2192 if revs and opts.get('rev'):
2197 if revs and opts.get('rev'):
2193 ui.warn(_('warning: inconsistent use of --rev might give unexpected '
2198 ui.warn(_('warning: inconsistent use of --rev might give unexpected '
2194 'revision ordering!\n'))
2199 'revision ordering!\n'))
2195
2200
2196 revs = list(revs)
2201 revs = list(revs)
2197 revs.extend(opts.get('rev'))
2202 revs.extend(opts.get('rev'))
2198
2203
2199 if not opts.get('user') and opts.get('currentuser'):
2204 if not opts.get('user') and opts.get('currentuser'):
2200 opts['user'] = ui.username()
2205 opts['user'] = ui.username()
2201 if not opts.get('date') and opts.get('currentdate'):
2206 if not opts.get('date') and opts.get('currentdate'):
2202 opts['date'] = "%d %d" % util.makedate()
2207 opts['date'] = "%d %d" % util.makedate()
2203
2208
2204 editor = cmdutil.getcommiteditor(editform='graft',
2209 editor = cmdutil.getcommiteditor(editform='graft',
2205 **pycompat.strkwargs(opts))
2210 **pycompat.strkwargs(opts))
2206
2211
2207 cont = False
2212 cont = False
2208 if opts.get('continue'):
2213 if opts.get('continue'):
2209 cont = True
2214 cont = True
2210 if revs:
2215 if revs:
2211 raise error.Abort(_("can't specify --continue and revisions"))
2216 raise error.Abort(_("can't specify --continue and revisions"))
2212 # read in unfinished revisions
2217 # read in unfinished revisions
2213 try:
2218 try:
2214 nodes = repo.vfs.read('graftstate').splitlines()
2219 nodes = repo.vfs.read('graftstate').splitlines()
2215 revs = [repo[node].rev() for node in nodes]
2220 revs = [repo[node].rev() for node in nodes]
2216 except IOError as inst:
2221 except IOError as inst:
2217 if inst.errno != errno.ENOENT:
2222 if inst.errno != errno.ENOENT:
2218 raise
2223 raise
2219 cmdutil.wrongtooltocontinue(repo, _('graft'))
2224 cmdutil.wrongtooltocontinue(repo, _('graft'))
2220 else:
2225 else:
2221 cmdutil.checkunfinished(repo)
2226 cmdutil.checkunfinished(repo)
2222 cmdutil.bailifchanged(repo)
2227 cmdutil.bailifchanged(repo)
2223 if not revs:
2228 if not revs:
2224 raise error.Abort(_('no revisions specified'))
2229 raise error.Abort(_('no revisions specified'))
2225 revs = scmutil.revrange(repo, revs)
2230 revs = scmutil.revrange(repo, revs)
2226
2231
2227 skipped = set()
2232 skipped = set()
2228 # check for merges
2233 # check for merges
2229 for rev in repo.revs('%ld and merge()', revs):
2234 for rev in repo.revs('%ld and merge()', revs):
2230 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2235 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2231 skipped.add(rev)
2236 skipped.add(rev)
2232 revs = [r for r in revs if r not in skipped]
2237 revs = [r for r in revs if r not in skipped]
2233 if not revs:
2238 if not revs:
2234 return -1
2239 return -1
2235
2240
2236 # Don't check in the --continue case, in effect retaining --force across
2241 # Don't check in the --continue case, in effect retaining --force across
2237 # --continues. That's because without --force, any revisions we decided to
2242 # --continues. That's because without --force, any revisions we decided to
2238 # skip would have been filtered out here, so they wouldn't have made their
2243 # skip would have been filtered out here, so they wouldn't have made their
2239 # way to the graftstate. With --force, any revisions we would have otherwise
2244 # way to the graftstate. With --force, any revisions we would have otherwise
2240 # skipped would not have been filtered out, and if they hadn't been applied
2245 # skipped would not have been filtered out, and if they hadn't been applied
2241 # already, they'd have been in the graftstate.
2246 # already, they'd have been in the graftstate.
2242 if not (cont or opts.get('force')):
2247 if not (cont or opts.get('force')):
2243 # check for ancestors of dest branch
2248 # check for ancestors of dest branch
2244 crev = repo['.'].rev()
2249 crev = repo['.'].rev()
2245 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2250 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2246 # XXX make this lazy in the future
2251 # XXX make this lazy in the future
2247 # don't mutate while iterating, create a copy
2252 # don't mutate while iterating, create a copy
2248 for rev in list(revs):
2253 for rev in list(revs):
2249 if rev in ancestors:
2254 if rev in ancestors:
2250 ui.warn(_('skipping ancestor revision %d:%s\n') %
2255 ui.warn(_('skipping ancestor revision %d:%s\n') %
2251 (rev, repo[rev]))
2256 (rev, repo[rev]))
2252 # XXX remove on list is slow
2257 # XXX remove on list is slow
2253 revs.remove(rev)
2258 revs.remove(rev)
2254 if not revs:
2259 if not revs:
2255 return -1
2260 return -1
2256
2261
2257 # analyze revs for earlier grafts
2262 # analyze revs for earlier grafts
2258 ids = {}
2263 ids = {}
2259 for ctx in repo.set("%ld", revs):
2264 for ctx in repo.set("%ld", revs):
2260 ids[ctx.hex()] = ctx.rev()
2265 ids[ctx.hex()] = ctx.rev()
2261 n = ctx.extra().get('source')
2266 n = ctx.extra().get('source')
2262 if n:
2267 if n:
2263 ids[n] = ctx.rev()
2268 ids[n] = ctx.rev()
2264
2269
2265 # check ancestors for earlier grafts
2270 # check ancestors for earlier grafts
2266 ui.debug('scanning for duplicate grafts\n')
2271 ui.debug('scanning for duplicate grafts\n')
2267
2272
2268 # The only changesets we can be sure doesn't contain grafts of any
2273 # The only changesets we can be sure doesn't contain grafts of any
2269 # revs, are the ones that are common ancestors of *all* revs:
2274 # revs, are the ones that are common ancestors of *all* revs:
2270 for rev in repo.revs('only(%d,ancestor(%ld))', crev, revs):
2275 for rev in repo.revs('only(%d,ancestor(%ld))', crev, revs):
2271 ctx = repo[rev]
2276 ctx = repo[rev]
2272 n = ctx.extra().get('source')
2277 n = ctx.extra().get('source')
2273 if n in ids:
2278 if n in ids:
2274 try:
2279 try:
2275 r = repo[n].rev()
2280 r = repo[n].rev()
2276 except error.RepoLookupError:
2281 except error.RepoLookupError:
2277 r = None
2282 r = None
2278 if r in revs:
2283 if r in revs:
2279 ui.warn(_('skipping revision %d:%s '
2284 ui.warn(_('skipping revision %d:%s '
2280 '(already grafted to %d:%s)\n')
2285 '(already grafted to %d:%s)\n')
2281 % (r, repo[r], rev, ctx))
2286 % (r, repo[r], rev, ctx))
2282 revs.remove(r)
2287 revs.remove(r)
2283 elif ids[n] in revs:
2288 elif ids[n] in revs:
2284 if r is None:
2289 if r is None:
2285 ui.warn(_('skipping already grafted revision %d:%s '
2290 ui.warn(_('skipping already grafted revision %d:%s '
2286 '(%d:%s also has unknown origin %s)\n')
2291 '(%d:%s also has unknown origin %s)\n')
2287 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
2292 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
2288 else:
2293 else:
2289 ui.warn(_('skipping already grafted revision %d:%s '
2294 ui.warn(_('skipping already grafted revision %d:%s '
2290 '(%d:%s also has origin %d:%s)\n')
2295 '(%d:%s also has origin %d:%s)\n')
2291 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
2296 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
2292 revs.remove(ids[n])
2297 revs.remove(ids[n])
2293 elif ctx.hex() in ids:
2298 elif ctx.hex() in ids:
2294 r = ids[ctx.hex()]
2299 r = ids[ctx.hex()]
2295 ui.warn(_('skipping already grafted revision %d:%s '
2300 ui.warn(_('skipping already grafted revision %d:%s '
2296 '(was grafted from %d:%s)\n') %
2301 '(was grafted from %d:%s)\n') %
2297 (r, repo[r], rev, ctx))
2302 (r, repo[r], rev, ctx))
2298 revs.remove(r)
2303 revs.remove(r)
2299 if not revs:
2304 if not revs:
2300 return -1
2305 return -1
2301
2306
2302 for pos, ctx in enumerate(repo.set("%ld", revs)):
2307 for pos, ctx in enumerate(repo.set("%ld", revs)):
2303 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
2308 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
2304 ctx.description().split('\n', 1)[0])
2309 ctx.description().split('\n', 1)[0])
2305 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
2310 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
2306 if names:
2311 if names:
2307 desc += ' (%s)' % ' '.join(names)
2312 desc += ' (%s)' % ' '.join(names)
2308 ui.status(_('grafting %s\n') % desc)
2313 ui.status(_('grafting %s\n') % desc)
2309 if opts.get('dry_run'):
2314 if opts.get('dry_run'):
2310 continue
2315 continue
2311
2316
2312 source = ctx.extra().get('source')
2317 source = ctx.extra().get('source')
2313 extra = {}
2318 extra = {}
2314 if source:
2319 if source:
2315 extra['source'] = source
2320 extra['source'] = source
2316 extra['intermediate-source'] = ctx.hex()
2321 extra['intermediate-source'] = ctx.hex()
2317 else:
2322 else:
2318 extra['source'] = ctx.hex()
2323 extra['source'] = ctx.hex()
2319 user = ctx.user()
2324 user = ctx.user()
2320 if opts.get('user'):
2325 if opts.get('user'):
2321 user = opts['user']
2326 user = opts['user']
2322 date = ctx.date()
2327 date = ctx.date()
2323 if opts.get('date'):
2328 if opts.get('date'):
2324 date = opts['date']
2329 date = opts['date']
2325 message = ctx.description()
2330 message = ctx.description()
2326 if opts.get('log'):
2331 if opts.get('log'):
2327 message += '\n(grafted from %s)' % ctx.hex()
2332 message += '\n(grafted from %s)' % ctx.hex()
2328
2333
2329 # we don't merge the first commit when continuing
2334 # we don't merge the first commit when continuing
2330 if not cont:
2335 if not cont:
2331 # perform the graft merge with p1(rev) as 'ancestor'
2336 # perform the graft merge with p1(rev) as 'ancestor'
2332 try:
2337 try:
2333 # ui.forcemerge is an internal variable, do not document
2338 # ui.forcemerge is an internal variable, do not document
2334 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
2339 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
2335 'graft')
2340 'graft')
2336 stats = mergemod.graft(repo, ctx, ctx.p1(),
2341 stats = mergemod.graft(repo, ctx, ctx.p1(),
2337 ['local', 'graft'])
2342 ['local', 'graft'])
2338 finally:
2343 finally:
2339 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
2344 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
2340 # report any conflicts
2345 # report any conflicts
2341 if stats and stats[3] > 0:
2346 if stats and stats[3] > 0:
2342 # write out state for --continue
2347 # write out state for --continue
2343 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2348 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2344 repo.vfs.write('graftstate', ''.join(nodelines))
2349 repo.vfs.write('graftstate', ''.join(nodelines))
2345 extra = ''
2350 extra = ''
2346 if opts.get('user'):
2351 if opts.get('user'):
2347 extra += ' --user %s' % util.shellquote(opts['user'])
2352 extra += ' --user %s' % util.shellquote(opts['user'])
2348 if opts.get('date'):
2353 if opts.get('date'):
2349 extra += ' --date %s' % util.shellquote(opts['date'])
2354 extra += ' --date %s' % util.shellquote(opts['date'])
2350 if opts.get('log'):
2355 if opts.get('log'):
2351 extra += ' --log'
2356 extra += ' --log'
2352 hint=_("use 'hg resolve' and 'hg graft --continue%s'") % extra
2357 hint=_("use 'hg resolve' and 'hg graft --continue%s'") % extra
2353 raise error.Abort(
2358 raise error.Abort(
2354 _("unresolved conflicts, can't continue"),
2359 _("unresolved conflicts, can't continue"),
2355 hint=hint)
2360 hint=hint)
2356 else:
2361 else:
2357 cont = False
2362 cont = False
2358
2363
2359 # commit
2364 # commit
2360 node = repo.commit(text=message, user=user,
2365 node = repo.commit(text=message, user=user,
2361 date=date, extra=extra, editor=editor)
2366 date=date, extra=extra, editor=editor)
2362 if node is None:
2367 if node is None:
2363 ui.warn(
2368 ui.warn(
2364 _('note: graft of %d:%s created no changes to commit\n') %
2369 _('note: graft of %d:%s created no changes to commit\n') %
2365 (ctx.rev(), ctx))
2370 (ctx.rev(), ctx))
2366
2371
2367 # remove state when we complete successfully
2372 # remove state when we complete successfully
2368 if not opts.get('dry_run'):
2373 if not opts.get('dry_run'):
2369 repo.vfs.unlinkpath('graftstate', ignoremissing=True)
2374 repo.vfs.unlinkpath('graftstate', ignoremissing=True)
2370
2375
2371 return 0
2376 return 0
2372
2377
2373 @command('grep',
2378 @command('grep',
2374 [('0', 'print0', None, _('end fields with NUL')),
2379 [('0', 'print0', None, _('end fields with NUL')),
2375 ('', 'all', None, _('print all revisions that match')),
2380 ('', 'all', None, _('print all revisions that match')),
2376 ('a', 'text', None, _('treat all files as text')),
2381 ('a', 'text', None, _('treat all files as text')),
2377 ('f', 'follow', None,
2382 ('f', 'follow', None,
2378 _('follow changeset history,'
2383 _('follow changeset history,'
2379 ' or file history across copies and renames')),
2384 ' or file history across copies and renames')),
2380 ('i', 'ignore-case', None, _('ignore case when matching')),
2385 ('i', 'ignore-case', None, _('ignore case when matching')),
2381 ('l', 'files-with-matches', None,
2386 ('l', 'files-with-matches', None,
2382 _('print only filenames and revisions that match')),
2387 _('print only filenames and revisions that match')),
2383 ('n', 'line-number', None, _('print matching line numbers')),
2388 ('n', 'line-number', None, _('print matching line numbers')),
2384 ('r', 'rev', [],
2389 ('r', 'rev', [],
2385 _('only search files changed within revision range'), _('REV')),
2390 _('only search files changed within revision range'), _('REV')),
2386 ('u', 'user', None, _('list the author (long with -v)')),
2391 ('u', 'user', None, _('list the author (long with -v)')),
2387 ('d', 'date', None, _('list the date (short with -q)')),
2392 ('d', 'date', None, _('list the date (short with -q)')),
2388 ] + formatteropts + walkopts,
2393 ] + formatteropts + walkopts,
2389 _('[OPTION]... PATTERN [FILE]...'),
2394 _('[OPTION]... PATTERN [FILE]...'),
2390 inferrepo=True)
2395 inferrepo=True)
2391 def grep(ui, repo, pattern, *pats, **opts):
2396 def grep(ui, repo, pattern, *pats, **opts):
2392 """search revision history for a pattern in specified files
2397 """search revision history for a pattern in specified files
2393
2398
2394 Search revision history for a regular expression in the specified
2399 Search revision history for a regular expression in the specified
2395 files or the entire project.
2400 files or the entire project.
2396
2401
2397 By default, grep prints the most recent revision number for each
2402 By default, grep prints the most recent revision number for each
2398 file in which it finds a match. To get it to print every revision
2403 file in which it finds a match. To get it to print every revision
2399 that contains a change in match status ("-" for a match that becomes
2404 that contains a change in match status ("-" for a match that becomes
2400 a non-match, or "+" for a non-match that becomes a match), use the
2405 a non-match, or "+" for a non-match that becomes a match), use the
2401 --all flag.
2406 --all flag.
2402
2407
2403 PATTERN can be any Python (roughly Perl-compatible) regular
2408 PATTERN can be any Python (roughly Perl-compatible) regular
2404 expression.
2409 expression.
2405
2410
2406 If no FILEs are specified (and -f/--follow isn't set), all files in
2411 If no FILEs are specified (and -f/--follow isn't set), all files in
2407 the repository are searched, including those that don't exist in the
2412 the repository are searched, including those that don't exist in the
2408 current branch or have been deleted in a prior changeset.
2413 current branch or have been deleted in a prior changeset.
2409
2414
2410 Returns 0 if a match is found, 1 otherwise.
2415 Returns 0 if a match is found, 1 otherwise.
2411 """
2416 """
2412 opts = pycompat.byteskwargs(opts)
2417 opts = pycompat.byteskwargs(opts)
2413 reflags = re.M
2418 reflags = re.M
2414 if opts.get('ignore_case'):
2419 if opts.get('ignore_case'):
2415 reflags |= re.I
2420 reflags |= re.I
2416 try:
2421 try:
2417 regexp = util.re.compile(pattern, reflags)
2422 regexp = util.re.compile(pattern, reflags)
2418 except re.error as inst:
2423 except re.error as inst:
2419 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2424 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2420 return 1
2425 return 1
2421 sep, eol = ':', '\n'
2426 sep, eol = ':', '\n'
2422 if opts.get('print0'):
2427 if opts.get('print0'):
2423 sep = eol = '\0'
2428 sep = eol = '\0'
2424
2429
2425 getfile = util.lrucachefunc(repo.file)
2430 getfile = util.lrucachefunc(repo.file)
2426
2431
2427 def matchlines(body):
2432 def matchlines(body):
2428 begin = 0
2433 begin = 0
2429 linenum = 0
2434 linenum = 0
2430 while begin < len(body):
2435 while begin < len(body):
2431 match = regexp.search(body, begin)
2436 match = regexp.search(body, begin)
2432 if not match:
2437 if not match:
2433 break
2438 break
2434 mstart, mend = match.span()
2439 mstart, mend = match.span()
2435 linenum += body.count('\n', begin, mstart) + 1
2440 linenum += body.count('\n', begin, mstart) + 1
2436 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2441 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2437 begin = body.find('\n', mend) + 1 or len(body) + 1
2442 begin = body.find('\n', mend) + 1 or len(body) + 1
2438 lend = begin - 1
2443 lend = begin - 1
2439 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2444 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2440
2445
2441 class linestate(object):
2446 class linestate(object):
2442 def __init__(self, line, linenum, colstart, colend):
2447 def __init__(self, line, linenum, colstart, colend):
2443 self.line = line
2448 self.line = line
2444 self.linenum = linenum
2449 self.linenum = linenum
2445 self.colstart = colstart
2450 self.colstart = colstart
2446 self.colend = colend
2451 self.colend = colend
2447
2452
2448 def __hash__(self):
2453 def __hash__(self):
2449 return hash((self.linenum, self.line))
2454 return hash((self.linenum, self.line))
2450
2455
2451 def __eq__(self, other):
2456 def __eq__(self, other):
2452 return self.line == other.line
2457 return self.line == other.line
2453
2458
2454 def findpos(self):
2459 def findpos(self):
2455 """Iterate all (start, end) indices of matches"""
2460 """Iterate all (start, end) indices of matches"""
2456 yield self.colstart, self.colend
2461 yield self.colstart, self.colend
2457 p = self.colend
2462 p = self.colend
2458 while p < len(self.line):
2463 while p < len(self.line):
2459 m = regexp.search(self.line, p)
2464 m = regexp.search(self.line, p)
2460 if not m:
2465 if not m:
2461 break
2466 break
2462 yield m.span()
2467 yield m.span()
2463 p = m.end()
2468 p = m.end()
2464
2469
2465 matches = {}
2470 matches = {}
2466 copies = {}
2471 copies = {}
2467 def grepbody(fn, rev, body):
2472 def grepbody(fn, rev, body):
2468 matches[rev].setdefault(fn, [])
2473 matches[rev].setdefault(fn, [])
2469 m = matches[rev][fn]
2474 m = matches[rev][fn]
2470 for lnum, cstart, cend, line in matchlines(body):
2475 for lnum, cstart, cend, line in matchlines(body):
2471 s = linestate(line, lnum, cstart, cend)
2476 s = linestate(line, lnum, cstart, cend)
2472 m.append(s)
2477 m.append(s)
2473
2478
2474 def difflinestates(a, b):
2479 def difflinestates(a, b):
2475 sm = difflib.SequenceMatcher(None, a, b)
2480 sm = difflib.SequenceMatcher(None, a, b)
2476 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2481 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2477 if tag == 'insert':
2482 if tag == 'insert':
2478 for i in xrange(blo, bhi):
2483 for i in xrange(blo, bhi):
2479 yield ('+', b[i])
2484 yield ('+', b[i])
2480 elif tag == 'delete':
2485 elif tag == 'delete':
2481 for i in xrange(alo, ahi):
2486 for i in xrange(alo, ahi):
2482 yield ('-', a[i])
2487 yield ('-', a[i])
2483 elif tag == 'replace':
2488 elif tag == 'replace':
2484 for i in xrange(alo, ahi):
2489 for i in xrange(alo, ahi):
2485 yield ('-', a[i])
2490 yield ('-', a[i])
2486 for i in xrange(blo, bhi):
2491 for i in xrange(blo, bhi):
2487 yield ('+', b[i])
2492 yield ('+', b[i])
2488
2493
2489 def display(fm, fn, ctx, pstates, states):
2494 def display(fm, fn, ctx, pstates, states):
2490 rev = ctx.rev()
2495 rev = ctx.rev()
2491 if fm.isplain():
2496 if fm.isplain():
2492 formatuser = ui.shortuser
2497 formatuser = ui.shortuser
2493 else:
2498 else:
2494 formatuser = str
2499 formatuser = str
2495 if ui.quiet:
2500 if ui.quiet:
2496 datefmt = '%Y-%m-%d'
2501 datefmt = '%Y-%m-%d'
2497 else:
2502 else:
2498 datefmt = '%a %b %d %H:%M:%S %Y %1%2'
2503 datefmt = '%a %b %d %H:%M:%S %Y %1%2'
2499 found = False
2504 found = False
2500 @util.cachefunc
2505 @util.cachefunc
2501 def binary():
2506 def binary():
2502 flog = getfile(fn)
2507 flog = getfile(fn)
2503 return util.binary(flog.read(ctx.filenode(fn)))
2508 return util.binary(flog.read(ctx.filenode(fn)))
2504
2509
2505 fieldnamemap = {'filename': 'file', 'linenumber': 'line_number'}
2510 fieldnamemap = {'filename': 'file', 'linenumber': 'line_number'}
2506 if opts.get('all'):
2511 if opts.get('all'):
2507 iter = difflinestates(pstates, states)
2512 iter = difflinestates(pstates, states)
2508 else:
2513 else:
2509 iter = [('', l) for l in states]
2514 iter = [('', l) for l in states]
2510 for change, l in iter:
2515 for change, l in iter:
2511 fm.startitem()
2516 fm.startitem()
2512 fm.data(node=fm.hexfunc(ctx.node()))
2517 fm.data(node=fm.hexfunc(ctx.node()))
2513 cols = [
2518 cols = [
2514 ('filename', fn, True),
2519 ('filename', fn, True),
2515 ('rev', rev, True),
2520 ('rev', rev, True),
2516 ('linenumber', l.linenum, opts.get('line_number')),
2521 ('linenumber', l.linenum, opts.get('line_number')),
2517 ]
2522 ]
2518 if opts.get('all'):
2523 if opts.get('all'):
2519 cols.append(('change', change, True))
2524 cols.append(('change', change, True))
2520 cols.extend([
2525 cols.extend([
2521 ('user', formatuser(ctx.user()), opts.get('user')),
2526 ('user', formatuser(ctx.user()), opts.get('user')),
2522 ('date', fm.formatdate(ctx.date(), datefmt), opts.get('date')),
2527 ('date', fm.formatdate(ctx.date(), datefmt), opts.get('date')),
2523 ])
2528 ])
2524 lastcol = next(name for name, data, cond in reversed(cols) if cond)
2529 lastcol = next(name for name, data, cond in reversed(cols) if cond)
2525 for name, data, cond in cols:
2530 for name, data, cond in cols:
2526 field = fieldnamemap.get(name, name)
2531 field = fieldnamemap.get(name, name)
2527 fm.condwrite(cond, field, '%s', data, label='grep.%s' % name)
2532 fm.condwrite(cond, field, '%s', data, label='grep.%s' % name)
2528 if cond and name != lastcol:
2533 if cond and name != lastcol:
2529 fm.plain(sep, label='grep.sep')
2534 fm.plain(sep, label='grep.sep')
2530 if not opts.get('files_with_matches'):
2535 if not opts.get('files_with_matches'):
2531 fm.plain(sep, label='grep.sep')
2536 fm.plain(sep, label='grep.sep')
2532 if not opts.get('text') and binary():
2537 if not opts.get('text') and binary():
2533 fm.plain(_(" Binary file matches"))
2538 fm.plain(_(" Binary file matches"))
2534 else:
2539 else:
2535 displaymatches(fm.nested('texts'), l)
2540 displaymatches(fm.nested('texts'), l)
2536 fm.plain(eol)
2541 fm.plain(eol)
2537 found = True
2542 found = True
2538 if opts.get('files_with_matches'):
2543 if opts.get('files_with_matches'):
2539 break
2544 break
2540 return found
2545 return found
2541
2546
2542 def displaymatches(fm, l):
2547 def displaymatches(fm, l):
2543 p = 0
2548 p = 0
2544 for s, e in l.findpos():
2549 for s, e in l.findpos():
2545 if p < s:
2550 if p < s:
2546 fm.startitem()
2551 fm.startitem()
2547 fm.write('text', '%s', l.line[p:s])
2552 fm.write('text', '%s', l.line[p:s])
2548 fm.data(matched=False)
2553 fm.data(matched=False)
2549 fm.startitem()
2554 fm.startitem()
2550 fm.write('text', '%s', l.line[s:e], label='grep.match')
2555 fm.write('text', '%s', l.line[s:e], label='grep.match')
2551 fm.data(matched=True)
2556 fm.data(matched=True)
2552 p = e
2557 p = e
2553 if p < len(l.line):
2558 if p < len(l.line):
2554 fm.startitem()
2559 fm.startitem()
2555 fm.write('text', '%s', l.line[p:])
2560 fm.write('text', '%s', l.line[p:])
2556 fm.data(matched=False)
2561 fm.data(matched=False)
2557 fm.end()
2562 fm.end()
2558
2563
2559 skip = {}
2564 skip = {}
2560 revfiles = {}
2565 revfiles = {}
2561 matchfn = scmutil.match(repo[None], pats, opts)
2566 matchfn = scmutil.match(repo[None], pats, opts)
2562 found = False
2567 found = False
2563 follow = opts.get('follow')
2568 follow = opts.get('follow')
2564
2569
2565 def prep(ctx, fns):
2570 def prep(ctx, fns):
2566 rev = ctx.rev()
2571 rev = ctx.rev()
2567 pctx = ctx.p1()
2572 pctx = ctx.p1()
2568 parent = pctx.rev()
2573 parent = pctx.rev()
2569 matches.setdefault(rev, {})
2574 matches.setdefault(rev, {})
2570 matches.setdefault(parent, {})
2575 matches.setdefault(parent, {})
2571 files = revfiles.setdefault(rev, [])
2576 files = revfiles.setdefault(rev, [])
2572 for fn in fns:
2577 for fn in fns:
2573 flog = getfile(fn)
2578 flog = getfile(fn)
2574 try:
2579 try:
2575 fnode = ctx.filenode(fn)
2580 fnode = ctx.filenode(fn)
2576 except error.LookupError:
2581 except error.LookupError:
2577 continue
2582 continue
2578
2583
2579 copied = flog.renamed(fnode)
2584 copied = flog.renamed(fnode)
2580 copy = follow and copied and copied[0]
2585 copy = follow and copied and copied[0]
2581 if copy:
2586 if copy:
2582 copies.setdefault(rev, {})[fn] = copy
2587 copies.setdefault(rev, {})[fn] = copy
2583 if fn in skip:
2588 if fn in skip:
2584 if copy:
2589 if copy:
2585 skip[copy] = True
2590 skip[copy] = True
2586 continue
2591 continue
2587 files.append(fn)
2592 files.append(fn)
2588
2593
2589 if fn not in matches[rev]:
2594 if fn not in matches[rev]:
2590 grepbody(fn, rev, flog.read(fnode))
2595 grepbody(fn, rev, flog.read(fnode))
2591
2596
2592 pfn = copy or fn
2597 pfn = copy or fn
2593 if pfn not in matches[parent]:
2598 if pfn not in matches[parent]:
2594 try:
2599 try:
2595 fnode = pctx.filenode(pfn)
2600 fnode = pctx.filenode(pfn)
2596 grepbody(pfn, parent, flog.read(fnode))
2601 grepbody(pfn, parent, flog.read(fnode))
2597 except error.LookupError:
2602 except error.LookupError:
2598 pass
2603 pass
2599
2604
2600 ui.pager('grep')
2605 ui.pager('grep')
2601 fm = ui.formatter('grep', opts)
2606 fm = ui.formatter('grep', opts)
2602 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2607 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2603 rev = ctx.rev()
2608 rev = ctx.rev()
2604 parent = ctx.p1().rev()
2609 parent = ctx.p1().rev()
2605 for fn in sorted(revfiles.get(rev, [])):
2610 for fn in sorted(revfiles.get(rev, [])):
2606 states = matches[rev][fn]
2611 states = matches[rev][fn]
2607 copy = copies.get(rev, {}).get(fn)
2612 copy = copies.get(rev, {}).get(fn)
2608 if fn in skip:
2613 if fn in skip:
2609 if copy:
2614 if copy:
2610 skip[copy] = True
2615 skip[copy] = True
2611 continue
2616 continue
2612 pstates = matches.get(parent, {}).get(copy or fn, [])
2617 pstates = matches.get(parent, {}).get(copy or fn, [])
2613 if pstates or states:
2618 if pstates or states:
2614 r = display(fm, fn, ctx, pstates, states)
2619 r = display(fm, fn, ctx, pstates, states)
2615 found = found or r
2620 found = found or r
2616 if r and not opts.get('all'):
2621 if r and not opts.get('all'):
2617 skip[fn] = True
2622 skip[fn] = True
2618 if copy:
2623 if copy:
2619 skip[copy] = True
2624 skip[copy] = True
2620 del matches[rev]
2625 del matches[rev]
2621 del revfiles[rev]
2626 del revfiles[rev]
2622 fm.end()
2627 fm.end()
2623
2628
2624 return not found
2629 return not found
2625
2630
2626 @command('heads',
2631 @command('heads',
2627 [('r', 'rev', '',
2632 [('r', 'rev', '',
2628 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2633 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2629 ('t', 'topo', False, _('show topological heads only')),
2634 ('t', 'topo', False, _('show topological heads only')),
2630 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2635 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2631 ('c', 'closed', False, _('show normal and closed branch heads')),
2636 ('c', 'closed', False, _('show normal and closed branch heads')),
2632 ] + templateopts,
2637 ] + templateopts,
2633 _('[-ct] [-r STARTREV] [REV]...'))
2638 _('[-ct] [-r STARTREV] [REV]...'))
2634 def heads(ui, repo, *branchrevs, **opts):
2639 def heads(ui, repo, *branchrevs, **opts):
2635 """show branch heads
2640 """show branch heads
2636
2641
2637 With no arguments, show all open branch heads in the repository.
2642 With no arguments, show all open branch heads in the repository.
2638 Branch heads are changesets that have no descendants on the
2643 Branch heads are changesets that have no descendants on the
2639 same branch. They are where development generally takes place and
2644 same branch. They are where development generally takes place and
2640 are the usual targets for update and merge operations.
2645 are the usual targets for update and merge operations.
2641
2646
2642 If one or more REVs are given, only open branch heads on the
2647 If one or more REVs are given, only open branch heads on the
2643 branches associated with the specified changesets are shown. This
2648 branches associated with the specified changesets are shown. This
2644 means that you can use :hg:`heads .` to see the heads on the
2649 means that you can use :hg:`heads .` to see the heads on the
2645 currently checked-out branch.
2650 currently checked-out branch.
2646
2651
2647 If -c/--closed is specified, also show branch heads marked closed
2652 If -c/--closed is specified, also show branch heads marked closed
2648 (see :hg:`commit --close-branch`).
2653 (see :hg:`commit --close-branch`).
2649
2654
2650 If STARTREV is specified, only those heads that are descendants of
2655 If STARTREV is specified, only those heads that are descendants of
2651 STARTREV will be displayed.
2656 STARTREV will be displayed.
2652
2657
2653 If -t/--topo is specified, named branch mechanics will be ignored and only
2658 If -t/--topo is specified, named branch mechanics will be ignored and only
2654 topological heads (changesets with no children) will be shown.
2659 topological heads (changesets with no children) will be shown.
2655
2660
2656 Returns 0 if matching heads are found, 1 if not.
2661 Returns 0 if matching heads are found, 1 if not.
2657 """
2662 """
2658
2663
2659 opts = pycompat.byteskwargs(opts)
2664 opts = pycompat.byteskwargs(opts)
2660 start = None
2665 start = None
2661 if 'rev' in opts:
2666 if 'rev' in opts:
2662 start = scmutil.revsingle(repo, opts['rev'], None).node()
2667 start = scmutil.revsingle(repo, opts['rev'], None).node()
2663
2668
2664 if opts.get('topo'):
2669 if opts.get('topo'):
2665 heads = [repo[h] for h in repo.heads(start)]
2670 heads = [repo[h] for h in repo.heads(start)]
2666 else:
2671 else:
2667 heads = []
2672 heads = []
2668 for branch in repo.branchmap():
2673 for branch in repo.branchmap():
2669 heads += repo.branchheads(branch, start, opts.get('closed'))
2674 heads += repo.branchheads(branch, start, opts.get('closed'))
2670 heads = [repo[h] for h in heads]
2675 heads = [repo[h] for h in heads]
2671
2676
2672 if branchrevs:
2677 if branchrevs:
2673 branches = set(repo[br].branch() for br in branchrevs)
2678 branches = set(repo[br].branch() for br in branchrevs)
2674 heads = [h for h in heads if h.branch() in branches]
2679 heads = [h for h in heads if h.branch() in branches]
2675
2680
2676 if opts.get('active') and branchrevs:
2681 if opts.get('active') and branchrevs:
2677 dagheads = repo.heads(start)
2682 dagheads = repo.heads(start)
2678 heads = [h for h in heads if h.node() in dagheads]
2683 heads = [h for h in heads if h.node() in dagheads]
2679
2684
2680 if branchrevs:
2685 if branchrevs:
2681 haveheads = set(h.branch() for h in heads)
2686 haveheads = set(h.branch() for h in heads)
2682 if branches - haveheads:
2687 if branches - haveheads:
2683 headless = ', '.join(b for b in branches - haveheads)
2688 headless = ', '.join(b for b in branches - haveheads)
2684 msg = _('no open branch heads found on branches %s')
2689 msg = _('no open branch heads found on branches %s')
2685 if opts.get('rev'):
2690 if opts.get('rev'):
2686 msg += _(' (started at %s)') % opts['rev']
2691 msg += _(' (started at %s)') % opts['rev']
2687 ui.warn((msg + '\n') % headless)
2692 ui.warn((msg + '\n') % headless)
2688
2693
2689 if not heads:
2694 if not heads:
2690 return 1
2695 return 1
2691
2696
2692 ui.pager('heads')
2697 ui.pager('heads')
2693 heads = sorted(heads, key=lambda x: -x.rev())
2698 heads = sorted(heads, key=lambda x: -x.rev())
2694 displayer = cmdutil.show_changeset(ui, repo, opts)
2699 displayer = cmdutil.show_changeset(ui, repo, opts)
2695 for ctx in heads:
2700 for ctx in heads:
2696 displayer.show(ctx)
2701 displayer.show(ctx)
2697 displayer.close()
2702 displayer.close()
2698
2703
2699 @command('help',
2704 @command('help',
2700 [('e', 'extension', None, _('show only help for extensions')),
2705 [('e', 'extension', None, _('show only help for extensions')),
2701 ('c', 'command', None, _('show only help for commands')),
2706 ('c', 'command', None, _('show only help for commands')),
2702 ('k', 'keyword', None, _('show topics matching keyword')),
2707 ('k', 'keyword', None, _('show topics matching keyword')),
2703 ('s', 'system', [], _('show help for specific platform(s)')),
2708 ('s', 'system', [], _('show help for specific platform(s)')),
2704 ],
2709 ],
2705 _('[-ecks] [TOPIC]'),
2710 _('[-ecks] [TOPIC]'),
2706 norepo=True)
2711 norepo=True)
2707 def help_(ui, name=None, **opts):
2712 def help_(ui, name=None, **opts):
2708 """show help for a given topic or a help overview
2713 """show help for a given topic or a help overview
2709
2714
2710 With no arguments, print a list of commands with short help messages.
2715 With no arguments, print a list of commands with short help messages.
2711
2716
2712 Given a topic, extension, or command name, print help for that
2717 Given a topic, extension, or command name, print help for that
2713 topic.
2718 topic.
2714
2719
2715 Returns 0 if successful.
2720 Returns 0 if successful.
2716 """
2721 """
2717
2722
2718 keep = opts.get(r'system') or []
2723 keep = opts.get(r'system') or []
2719 if len(keep) == 0:
2724 if len(keep) == 0:
2720 if pycompat.sysplatform.startswith('win'):
2725 if pycompat.sysplatform.startswith('win'):
2721 keep.append('windows')
2726 keep.append('windows')
2722 elif pycompat.sysplatform == 'OpenVMS':
2727 elif pycompat.sysplatform == 'OpenVMS':
2723 keep.append('vms')
2728 keep.append('vms')
2724 elif pycompat.sysplatform == 'plan9':
2729 elif pycompat.sysplatform == 'plan9':
2725 keep.append('plan9')
2730 keep.append('plan9')
2726 else:
2731 else:
2727 keep.append('unix')
2732 keep.append('unix')
2728 keep.append(pycompat.sysplatform.lower())
2733 keep.append(pycompat.sysplatform.lower())
2729 if ui.verbose:
2734 if ui.verbose:
2730 keep.append('verbose')
2735 keep.append('verbose')
2731
2736
2732 formatted = help.formattedhelp(ui, name, keep=keep, **opts)
2737 formatted = help.formattedhelp(ui, name, keep=keep, **opts)
2733 ui.pager('help')
2738 ui.pager('help')
2734 ui.write(formatted)
2739 ui.write(formatted)
2735
2740
2736
2741
2737 @command('identify|id',
2742 @command('identify|id',
2738 [('r', 'rev', '',
2743 [('r', 'rev', '',
2739 _('identify the specified revision'), _('REV')),
2744 _('identify the specified revision'), _('REV')),
2740 ('n', 'num', None, _('show local revision number')),
2745 ('n', 'num', None, _('show local revision number')),
2741 ('i', 'id', None, _('show global revision id')),
2746 ('i', 'id', None, _('show global revision id')),
2742 ('b', 'branch', None, _('show branch')),
2747 ('b', 'branch', None, _('show branch')),
2743 ('t', 'tags', None, _('show tags')),
2748 ('t', 'tags', None, _('show tags')),
2744 ('B', 'bookmarks', None, _('show bookmarks')),
2749 ('B', 'bookmarks', None, _('show bookmarks')),
2745 ] + remoteopts,
2750 ] + remoteopts,
2746 _('[-nibtB] [-r REV] [SOURCE]'),
2751 _('[-nibtB] [-r REV] [SOURCE]'),
2747 optionalrepo=True)
2752 optionalrepo=True)
2748 def identify(ui, repo, source=None, rev=None,
2753 def identify(ui, repo, source=None, rev=None,
2749 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
2754 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
2750 """identify the working directory or specified revision
2755 """identify the working directory or specified revision
2751
2756
2752 Print a summary identifying the repository state at REV using one or
2757 Print a summary identifying the repository state at REV using one or
2753 two parent hash identifiers, followed by a "+" if the working
2758 two parent hash identifiers, followed by a "+" if the working
2754 directory has uncommitted changes, the branch name (if not default),
2759 directory has uncommitted changes, the branch name (if not default),
2755 a list of tags, and a list of bookmarks.
2760 a list of tags, and a list of bookmarks.
2756
2761
2757 When REV is not given, print a summary of the current state of the
2762 When REV is not given, print a summary of the current state of the
2758 repository.
2763 repository.
2759
2764
2760 Specifying a path to a repository root or Mercurial bundle will
2765 Specifying a path to a repository root or Mercurial bundle will
2761 cause lookup to operate on that repository/bundle.
2766 cause lookup to operate on that repository/bundle.
2762
2767
2763 .. container:: verbose
2768 .. container:: verbose
2764
2769
2765 Examples:
2770 Examples:
2766
2771
2767 - generate a build identifier for the working directory::
2772 - generate a build identifier for the working directory::
2768
2773
2769 hg id --id > build-id.dat
2774 hg id --id > build-id.dat
2770
2775
2771 - find the revision corresponding to a tag::
2776 - find the revision corresponding to a tag::
2772
2777
2773 hg id -n -r 1.3
2778 hg id -n -r 1.3
2774
2779
2775 - check the most recent revision of a remote repository::
2780 - check the most recent revision of a remote repository::
2776
2781
2777 hg id -r tip https://www.mercurial-scm.org/repo/hg/
2782 hg id -r tip https://www.mercurial-scm.org/repo/hg/
2778
2783
2779 See :hg:`log` for generating more information about specific revisions,
2784 See :hg:`log` for generating more information about specific revisions,
2780 including full hash identifiers.
2785 including full hash identifiers.
2781
2786
2782 Returns 0 if successful.
2787 Returns 0 if successful.
2783 """
2788 """
2784
2789
2785 opts = pycompat.byteskwargs(opts)
2790 opts = pycompat.byteskwargs(opts)
2786 if not repo and not source:
2791 if not repo and not source:
2787 raise error.Abort(_("there is no Mercurial repository here "
2792 raise error.Abort(_("there is no Mercurial repository here "
2788 "(.hg not found)"))
2793 "(.hg not found)"))
2789
2794
2790 if ui.debugflag:
2795 if ui.debugflag:
2791 hexfunc = hex
2796 hexfunc = hex
2792 else:
2797 else:
2793 hexfunc = short
2798 hexfunc = short
2794 default = not (num or id or branch or tags or bookmarks)
2799 default = not (num or id or branch or tags or bookmarks)
2795 output = []
2800 output = []
2796 revs = []
2801 revs = []
2797
2802
2798 if source:
2803 if source:
2799 source, branches = hg.parseurl(ui.expandpath(source))
2804 source, branches = hg.parseurl(ui.expandpath(source))
2800 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
2805 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
2801 repo = peer.local()
2806 repo = peer.local()
2802 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
2807 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
2803
2808
2804 if not repo:
2809 if not repo:
2805 if num or branch or tags:
2810 if num or branch or tags:
2806 raise error.Abort(
2811 raise error.Abort(
2807 _("can't query remote revision number, branch, or tags"))
2812 _("can't query remote revision number, branch, or tags"))
2808 if not rev and revs:
2813 if not rev and revs:
2809 rev = revs[0]
2814 rev = revs[0]
2810 if not rev:
2815 if not rev:
2811 rev = "tip"
2816 rev = "tip"
2812
2817
2813 remoterev = peer.lookup(rev)
2818 remoterev = peer.lookup(rev)
2814 if default or id:
2819 if default or id:
2815 output = [hexfunc(remoterev)]
2820 output = [hexfunc(remoterev)]
2816
2821
2817 def getbms():
2822 def getbms():
2818 bms = []
2823 bms = []
2819
2824
2820 if 'bookmarks' in peer.listkeys('namespaces'):
2825 if 'bookmarks' in peer.listkeys('namespaces'):
2821 hexremoterev = hex(remoterev)
2826 hexremoterev = hex(remoterev)
2822 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
2827 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
2823 if bmr == hexremoterev]
2828 if bmr == hexremoterev]
2824
2829
2825 return sorted(bms)
2830 return sorted(bms)
2826
2831
2827 if bookmarks:
2832 if bookmarks:
2828 output.extend(getbms())
2833 output.extend(getbms())
2829 elif default and not ui.quiet:
2834 elif default and not ui.quiet:
2830 # multiple bookmarks for a single parent separated by '/'
2835 # multiple bookmarks for a single parent separated by '/'
2831 bm = '/'.join(getbms())
2836 bm = '/'.join(getbms())
2832 if bm:
2837 if bm:
2833 output.append(bm)
2838 output.append(bm)
2834 else:
2839 else:
2835 ctx = scmutil.revsingle(repo, rev, None)
2840 ctx = scmutil.revsingle(repo, rev, None)
2836
2841
2837 if ctx.rev() is None:
2842 if ctx.rev() is None:
2838 ctx = repo[None]
2843 ctx = repo[None]
2839 parents = ctx.parents()
2844 parents = ctx.parents()
2840 taglist = []
2845 taglist = []
2841 for p in parents:
2846 for p in parents:
2842 taglist.extend(p.tags())
2847 taglist.extend(p.tags())
2843
2848
2844 changed = ""
2849 changed = ""
2845 if default or id or num:
2850 if default or id or num:
2846 if (any(repo.status())
2851 if (any(repo.status())
2847 or any(ctx.sub(s).dirty() for s in ctx.substate)):
2852 or any(ctx.sub(s).dirty() for s in ctx.substate)):
2848 changed = '+'
2853 changed = '+'
2849 if default or id:
2854 if default or id:
2850 output = ["%s%s" %
2855 output = ["%s%s" %
2851 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
2856 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
2852 if num:
2857 if num:
2853 output.append("%s%s" %
2858 output.append("%s%s" %
2854 ('+'.join([str(p.rev()) for p in parents]), changed))
2859 ('+'.join([str(p.rev()) for p in parents]), changed))
2855 else:
2860 else:
2856 if default or id:
2861 if default or id:
2857 output = [hexfunc(ctx.node())]
2862 output = [hexfunc(ctx.node())]
2858 if num:
2863 if num:
2859 output.append(str(ctx.rev()))
2864 output.append(str(ctx.rev()))
2860 taglist = ctx.tags()
2865 taglist = ctx.tags()
2861
2866
2862 if default and not ui.quiet:
2867 if default and not ui.quiet:
2863 b = ctx.branch()
2868 b = ctx.branch()
2864 if b != 'default':
2869 if b != 'default':
2865 output.append("(%s)" % b)
2870 output.append("(%s)" % b)
2866
2871
2867 # multiple tags for a single parent separated by '/'
2872 # multiple tags for a single parent separated by '/'
2868 t = '/'.join(taglist)
2873 t = '/'.join(taglist)
2869 if t:
2874 if t:
2870 output.append(t)
2875 output.append(t)
2871
2876
2872 # multiple bookmarks for a single parent separated by '/'
2877 # multiple bookmarks for a single parent separated by '/'
2873 bm = '/'.join(ctx.bookmarks())
2878 bm = '/'.join(ctx.bookmarks())
2874 if bm:
2879 if bm:
2875 output.append(bm)
2880 output.append(bm)
2876 else:
2881 else:
2877 if branch:
2882 if branch:
2878 output.append(ctx.branch())
2883 output.append(ctx.branch())
2879
2884
2880 if tags:
2885 if tags:
2881 output.extend(taglist)
2886 output.extend(taglist)
2882
2887
2883 if bookmarks:
2888 if bookmarks:
2884 output.extend(ctx.bookmarks())
2889 output.extend(ctx.bookmarks())
2885
2890
2886 ui.write("%s\n" % ' '.join(output))
2891 ui.write("%s\n" % ' '.join(output))
2887
2892
2888 @command('import|patch',
2893 @command('import|patch',
2889 [('p', 'strip', 1,
2894 [('p', 'strip', 1,
2890 _('directory strip option for patch. This has the same '
2895 _('directory strip option for patch. This has the same '
2891 'meaning as the corresponding patch option'), _('NUM')),
2896 'meaning as the corresponding patch option'), _('NUM')),
2892 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
2897 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
2893 ('e', 'edit', False, _('invoke editor on commit messages')),
2898 ('e', 'edit', False, _('invoke editor on commit messages')),
2894 ('f', 'force', None,
2899 ('f', 'force', None,
2895 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
2900 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
2896 ('', 'no-commit', None,
2901 ('', 'no-commit', None,
2897 _("don't commit, just update the working directory")),
2902 _("don't commit, just update the working directory")),
2898 ('', 'bypass', None,
2903 ('', 'bypass', None,
2899 _("apply patch without touching the working directory")),
2904 _("apply patch without touching the working directory")),
2900 ('', 'partial', None,
2905 ('', 'partial', None,
2901 _('commit even if some hunks fail')),
2906 _('commit even if some hunks fail')),
2902 ('', 'exact', None,
2907 ('', 'exact', None,
2903 _('abort if patch would apply lossily')),
2908 _('abort if patch would apply lossily')),
2904 ('', 'prefix', '',
2909 ('', 'prefix', '',
2905 _('apply patch to subdirectory'), _('DIR')),
2910 _('apply patch to subdirectory'), _('DIR')),
2906 ('', 'import-branch', None,
2911 ('', 'import-branch', None,
2907 _('use any branch information in patch (implied by --exact)'))] +
2912 _('use any branch information in patch (implied by --exact)'))] +
2908 commitopts + commitopts2 + similarityopts,
2913 commitopts + commitopts2 + similarityopts,
2909 _('[OPTION]... PATCH...'))
2914 _('[OPTION]... PATCH...'))
2910 def import_(ui, repo, patch1=None, *patches, **opts):
2915 def import_(ui, repo, patch1=None, *patches, **opts):
2911 """import an ordered set of patches
2916 """import an ordered set of patches
2912
2917
2913 Import a list of patches and commit them individually (unless
2918 Import a list of patches and commit them individually (unless
2914 --no-commit is specified).
2919 --no-commit is specified).
2915
2920
2916 To read a patch from standard input (stdin), use "-" as the patch
2921 To read a patch from standard input (stdin), use "-" as the patch
2917 name. If a URL is specified, the patch will be downloaded from
2922 name. If a URL is specified, the patch will be downloaded from
2918 there.
2923 there.
2919
2924
2920 Import first applies changes to the working directory (unless
2925 Import first applies changes to the working directory (unless
2921 --bypass is specified), import will abort if there are outstanding
2926 --bypass is specified), import will abort if there are outstanding
2922 changes.
2927 changes.
2923
2928
2924 Use --bypass to apply and commit patches directly to the
2929 Use --bypass to apply and commit patches directly to the
2925 repository, without affecting the working directory. Without
2930 repository, without affecting the working directory. Without
2926 --exact, patches will be applied on top of the working directory
2931 --exact, patches will be applied on top of the working directory
2927 parent revision.
2932 parent revision.
2928
2933
2929 You can import a patch straight from a mail message. Even patches
2934 You can import a patch straight from a mail message. Even patches
2930 as attachments work (to use the body part, it must have type
2935 as attachments work (to use the body part, it must have type
2931 text/plain or text/x-patch). From and Subject headers of email
2936 text/plain or text/x-patch). From and Subject headers of email
2932 message are used as default committer and commit message. All
2937 message are used as default committer and commit message. All
2933 text/plain body parts before first diff are added to the commit
2938 text/plain body parts before first diff are added to the commit
2934 message.
2939 message.
2935
2940
2936 If the imported patch was generated by :hg:`export`, user and
2941 If the imported patch was generated by :hg:`export`, user and
2937 description from patch override values from message headers and
2942 description from patch override values from message headers and
2938 body. Values given on command line with -m/--message and -u/--user
2943 body. Values given on command line with -m/--message and -u/--user
2939 override these.
2944 override these.
2940
2945
2941 If --exact is specified, import will set the working directory to
2946 If --exact is specified, import will set the working directory to
2942 the parent of each patch before applying it, and will abort if the
2947 the parent of each patch before applying it, and will abort if the
2943 resulting changeset has a different ID than the one recorded in
2948 resulting changeset has a different ID than the one recorded in
2944 the patch. This will guard against various ways that portable
2949 the patch. This will guard against various ways that portable
2945 patch formats and mail systems might fail to transfer Mercurial
2950 patch formats and mail systems might fail to transfer Mercurial
2946 data or metadata. See :hg:`bundle` for lossless transmission.
2951 data or metadata. See :hg:`bundle` for lossless transmission.
2947
2952
2948 Use --partial to ensure a changeset will be created from the patch
2953 Use --partial to ensure a changeset will be created from the patch
2949 even if some hunks fail to apply. Hunks that fail to apply will be
2954 even if some hunks fail to apply. Hunks that fail to apply will be
2950 written to a <target-file>.rej file. Conflicts can then be resolved
2955 written to a <target-file>.rej file. Conflicts can then be resolved
2951 by hand before :hg:`commit --amend` is run to update the created
2956 by hand before :hg:`commit --amend` is run to update the created
2952 changeset. This flag exists to let people import patches that
2957 changeset. This flag exists to let people import patches that
2953 partially apply without losing the associated metadata (author,
2958 partially apply without losing the associated metadata (author,
2954 date, description, ...).
2959 date, description, ...).
2955
2960
2956 .. note::
2961 .. note::
2957
2962
2958 When no hunks apply cleanly, :hg:`import --partial` will create
2963 When no hunks apply cleanly, :hg:`import --partial` will create
2959 an empty changeset, importing only the patch metadata.
2964 an empty changeset, importing only the patch metadata.
2960
2965
2961 With -s/--similarity, hg will attempt to discover renames and
2966 With -s/--similarity, hg will attempt to discover renames and
2962 copies in the patch in the same way as :hg:`addremove`.
2967 copies in the patch in the same way as :hg:`addremove`.
2963
2968
2964 It is possible to use external patch programs to perform the patch
2969 It is possible to use external patch programs to perform the patch
2965 by setting the ``ui.patch`` configuration option. For the default
2970 by setting the ``ui.patch`` configuration option. For the default
2966 internal tool, the fuzz can also be configured via ``patch.fuzz``.
2971 internal tool, the fuzz can also be configured via ``patch.fuzz``.
2967 See :hg:`help config` for more information about configuration
2972 See :hg:`help config` for more information about configuration
2968 files and how to use these options.
2973 files and how to use these options.
2969
2974
2970 See :hg:`help dates` for a list of formats valid for -d/--date.
2975 See :hg:`help dates` for a list of formats valid for -d/--date.
2971
2976
2972 .. container:: verbose
2977 .. container:: verbose
2973
2978
2974 Examples:
2979 Examples:
2975
2980
2976 - import a traditional patch from a website and detect renames::
2981 - import a traditional patch from a website and detect renames::
2977
2982
2978 hg import -s 80 http://example.com/bugfix.patch
2983 hg import -s 80 http://example.com/bugfix.patch
2979
2984
2980 - import a changeset from an hgweb server::
2985 - import a changeset from an hgweb server::
2981
2986
2982 hg import https://www.mercurial-scm.org/repo/hg/rev/5ca8c111e9aa
2987 hg import https://www.mercurial-scm.org/repo/hg/rev/5ca8c111e9aa
2983
2988
2984 - import all the patches in an Unix-style mbox::
2989 - import all the patches in an Unix-style mbox::
2985
2990
2986 hg import incoming-patches.mbox
2991 hg import incoming-patches.mbox
2987
2992
2988 - import patches from stdin::
2993 - import patches from stdin::
2989
2994
2990 hg import -
2995 hg import -
2991
2996
2992 - attempt to exactly restore an exported changeset (not always
2997 - attempt to exactly restore an exported changeset (not always
2993 possible)::
2998 possible)::
2994
2999
2995 hg import --exact proposed-fix.patch
3000 hg import --exact proposed-fix.patch
2996
3001
2997 - use an external tool to apply a patch which is too fuzzy for
3002 - use an external tool to apply a patch which is too fuzzy for
2998 the default internal tool.
3003 the default internal tool.
2999
3004
3000 hg import --config ui.patch="patch --merge" fuzzy.patch
3005 hg import --config ui.patch="patch --merge" fuzzy.patch
3001
3006
3002 - change the default fuzzing from 2 to a less strict 7
3007 - change the default fuzzing from 2 to a less strict 7
3003
3008
3004 hg import --config ui.fuzz=7 fuzz.patch
3009 hg import --config ui.fuzz=7 fuzz.patch
3005
3010
3006 Returns 0 on success, 1 on partial success (see --partial).
3011 Returns 0 on success, 1 on partial success (see --partial).
3007 """
3012 """
3008
3013
3009 opts = pycompat.byteskwargs(opts)
3014 opts = pycompat.byteskwargs(opts)
3010 if not patch1:
3015 if not patch1:
3011 raise error.Abort(_('need at least one patch to import'))
3016 raise error.Abort(_('need at least one patch to import'))
3012
3017
3013 patches = (patch1,) + patches
3018 patches = (patch1,) + patches
3014
3019
3015 date = opts.get('date')
3020 date = opts.get('date')
3016 if date:
3021 if date:
3017 opts['date'] = util.parsedate(date)
3022 opts['date'] = util.parsedate(date)
3018
3023
3019 exact = opts.get('exact')
3024 exact = opts.get('exact')
3020 update = not opts.get('bypass')
3025 update = not opts.get('bypass')
3021 if not update and opts.get('no_commit'):
3026 if not update and opts.get('no_commit'):
3022 raise error.Abort(_('cannot use --no-commit with --bypass'))
3027 raise error.Abort(_('cannot use --no-commit with --bypass'))
3023 try:
3028 try:
3024 sim = float(opts.get('similarity') or 0)
3029 sim = float(opts.get('similarity') or 0)
3025 except ValueError:
3030 except ValueError:
3026 raise error.Abort(_('similarity must be a number'))
3031 raise error.Abort(_('similarity must be a number'))
3027 if sim < 0 or sim > 100:
3032 if sim < 0 or sim > 100:
3028 raise error.Abort(_('similarity must be between 0 and 100'))
3033 raise error.Abort(_('similarity must be between 0 and 100'))
3029 if sim and not update:
3034 if sim and not update:
3030 raise error.Abort(_('cannot use --similarity with --bypass'))
3035 raise error.Abort(_('cannot use --similarity with --bypass'))
3031 if exact:
3036 if exact:
3032 if opts.get('edit'):
3037 if opts.get('edit'):
3033 raise error.Abort(_('cannot use --exact with --edit'))
3038 raise error.Abort(_('cannot use --exact with --edit'))
3034 if opts.get('prefix'):
3039 if opts.get('prefix'):
3035 raise error.Abort(_('cannot use --exact with --prefix'))
3040 raise error.Abort(_('cannot use --exact with --prefix'))
3036
3041
3037 base = opts["base"]
3042 base = opts["base"]
3038 wlock = dsguard = lock = tr = None
3043 wlock = dsguard = lock = tr = None
3039 msgs = []
3044 msgs = []
3040 ret = 0
3045 ret = 0
3041
3046
3042
3047
3043 try:
3048 try:
3044 wlock = repo.wlock()
3049 wlock = repo.wlock()
3045
3050
3046 if update:
3051 if update:
3047 cmdutil.checkunfinished(repo)
3052 cmdutil.checkunfinished(repo)
3048 if (exact or not opts.get('force')):
3053 if (exact or not opts.get('force')):
3049 cmdutil.bailifchanged(repo)
3054 cmdutil.bailifchanged(repo)
3050
3055
3051 if not opts.get('no_commit'):
3056 if not opts.get('no_commit'):
3052 lock = repo.lock()
3057 lock = repo.lock()
3053 tr = repo.transaction('import')
3058 tr = repo.transaction('import')
3054 else:
3059 else:
3055 dsguard = dirstateguard.dirstateguard(repo, 'import')
3060 dsguard = dirstateguard.dirstateguard(repo, 'import')
3056 parents = repo[None].parents()
3061 parents = repo[None].parents()
3057 for patchurl in patches:
3062 for patchurl in patches:
3058 if patchurl == '-':
3063 if patchurl == '-':
3059 ui.status(_('applying patch from stdin\n'))
3064 ui.status(_('applying patch from stdin\n'))
3060 patchfile = ui.fin
3065 patchfile = ui.fin
3061 patchurl = 'stdin' # for error message
3066 patchurl = 'stdin' # for error message
3062 else:
3067 else:
3063 patchurl = os.path.join(base, patchurl)
3068 patchurl = os.path.join(base, patchurl)
3064 ui.status(_('applying %s\n') % patchurl)
3069 ui.status(_('applying %s\n') % patchurl)
3065 patchfile = hg.openpath(ui, patchurl)
3070 patchfile = hg.openpath(ui, patchurl)
3066
3071
3067 haspatch = False
3072 haspatch = False
3068 for hunk in patch.split(patchfile):
3073 for hunk in patch.split(patchfile):
3069 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
3074 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
3070 parents, opts,
3075 parents, opts,
3071 msgs, hg.clean)
3076 msgs, hg.clean)
3072 if msg:
3077 if msg:
3073 haspatch = True
3078 haspatch = True
3074 ui.note(msg + '\n')
3079 ui.note(msg + '\n')
3075 if update or exact:
3080 if update or exact:
3076 parents = repo[None].parents()
3081 parents = repo[None].parents()
3077 else:
3082 else:
3078 parents = [repo[node]]
3083 parents = [repo[node]]
3079 if rej:
3084 if rej:
3080 ui.write_err(_("patch applied partially\n"))
3085 ui.write_err(_("patch applied partially\n"))
3081 ui.write_err(_("(fix the .rej files and run "
3086 ui.write_err(_("(fix the .rej files and run "
3082 "`hg commit --amend`)\n"))
3087 "`hg commit --amend`)\n"))
3083 ret = 1
3088 ret = 1
3084 break
3089 break
3085
3090
3086 if not haspatch:
3091 if not haspatch:
3087 raise error.Abort(_('%s: no diffs found') % patchurl)
3092 raise error.Abort(_('%s: no diffs found') % patchurl)
3088
3093
3089 if tr:
3094 if tr:
3090 tr.close()
3095 tr.close()
3091 if msgs:
3096 if msgs:
3092 repo.savecommitmessage('\n* * *\n'.join(msgs))
3097 repo.savecommitmessage('\n* * *\n'.join(msgs))
3093 if dsguard:
3098 if dsguard:
3094 dsguard.close()
3099 dsguard.close()
3095 return ret
3100 return ret
3096 finally:
3101 finally:
3097 if tr:
3102 if tr:
3098 tr.release()
3103 tr.release()
3099 release(lock, dsguard, wlock)
3104 release(lock, dsguard, wlock)
3100
3105
3101 @command('incoming|in',
3106 @command('incoming|in',
3102 [('f', 'force', None,
3107 [('f', 'force', None,
3103 _('run even if remote repository is unrelated')),
3108 _('run even if remote repository is unrelated')),
3104 ('n', 'newest-first', None, _('show newest record first')),
3109 ('n', 'newest-first', None, _('show newest record first')),
3105 ('', 'bundle', '',
3110 ('', 'bundle', '',
3106 _('file to store the bundles into'), _('FILE')),
3111 _('file to store the bundles into'), _('FILE')),
3107 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3112 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3108 ('B', 'bookmarks', False, _("compare bookmarks")),
3113 ('B', 'bookmarks', False, _("compare bookmarks")),
3109 ('b', 'branch', [],
3114 ('b', 'branch', [],
3110 _('a specific branch you would like to pull'), _('BRANCH')),
3115 _('a specific branch you would like to pull'), _('BRANCH')),
3111 ] + logopts + remoteopts + subrepoopts,
3116 ] + logopts + remoteopts + subrepoopts,
3112 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3117 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3113 def incoming(ui, repo, source="default", **opts):
3118 def incoming(ui, repo, source="default", **opts):
3114 """show new changesets found in source
3119 """show new changesets found in source
3115
3120
3116 Show new changesets found in the specified path/URL or the default
3121 Show new changesets found in the specified path/URL or the default
3117 pull location. These are the changesets that would have been pulled
3122 pull location. These are the changesets that would have been pulled
3118 if a pull at the time you issued this command.
3123 if a pull at the time you issued this command.
3119
3124
3120 See pull for valid source format details.
3125 See pull for valid source format details.
3121
3126
3122 .. container:: verbose
3127 .. container:: verbose
3123
3128
3124 With -B/--bookmarks, the result of bookmark comparison between
3129 With -B/--bookmarks, the result of bookmark comparison between
3125 local and remote repositories is displayed. With -v/--verbose,
3130 local and remote repositories is displayed. With -v/--verbose,
3126 status is also displayed for each bookmark like below::
3131 status is also displayed for each bookmark like below::
3127
3132
3128 BM1 01234567890a added
3133 BM1 01234567890a added
3129 BM2 1234567890ab advanced
3134 BM2 1234567890ab advanced
3130 BM3 234567890abc diverged
3135 BM3 234567890abc diverged
3131 BM4 34567890abcd changed
3136 BM4 34567890abcd changed
3132
3137
3133 The action taken locally when pulling depends on the
3138 The action taken locally when pulling depends on the
3134 status of each bookmark:
3139 status of each bookmark:
3135
3140
3136 :``added``: pull will create it
3141 :``added``: pull will create it
3137 :``advanced``: pull will update it
3142 :``advanced``: pull will update it
3138 :``diverged``: pull will create a divergent bookmark
3143 :``diverged``: pull will create a divergent bookmark
3139 :``changed``: result depends on remote changesets
3144 :``changed``: result depends on remote changesets
3140
3145
3141 From the point of view of pulling behavior, bookmark
3146 From the point of view of pulling behavior, bookmark
3142 existing only in the remote repository are treated as ``added``,
3147 existing only in the remote repository are treated as ``added``,
3143 even if it is in fact locally deleted.
3148 even if it is in fact locally deleted.
3144
3149
3145 .. container:: verbose
3150 .. container:: verbose
3146
3151
3147 For remote repository, using --bundle avoids downloading the
3152 For remote repository, using --bundle avoids downloading the
3148 changesets twice if the incoming is followed by a pull.
3153 changesets twice if the incoming is followed by a pull.
3149
3154
3150 Examples:
3155 Examples:
3151
3156
3152 - show incoming changes with patches and full description::
3157 - show incoming changes with patches and full description::
3153
3158
3154 hg incoming -vp
3159 hg incoming -vp
3155
3160
3156 - show incoming changes excluding merges, store a bundle::
3161 - show incoming changes excluding merges, store a bundle::
3157
3162
3158 hg in -vpM --bundle incoming.hg
3163 hg in -vpM --bundle incoming.hg
3159 hg pull incoming.hg
3164 hg pull incoming.hg
3160
3165
3161 - briefly list changes inside a bundle::
3166 - briefly list changes inside a bundle::
3162
3167
3163 hg in changes.hg -T "{desc|firstline}\\n"
3168 hg in changes.hg -T "{desc|firstline}\\n"
3164
3169
3165 Returns 0 if there are incoming changes, 1 otherwise.
3170 Returns 0 if there are incoming changes, 1 otherwise.
3166 """
3171 """
3167 opts = pycompat.byteskwargs(opts)
3172 opts = pycompat.byteskwargs(opts)
3168 if opts.get('graph'):
3173 if opts.get('graph'):
3169 cmdutil.checkunsupportedgraphflags([], opts)
3174 cmdutil.checkunsupportedgraphflags([], opts)
3170 def display(other, chlist, displayer):
3175 def display(other, chlist, displayer):
3171 revdag = cmdutil.graphrevs(other, chlist, opts)
3176 revdag = cmdutil.graphrevs(other, chlist, opts)
3172 cmdutil.displaygraph(ui, repo, revdag, displayer,
3177 cmdutil.displaygraph(ui, repo, revdag, displayer,
3173 graphmod.asciiedges)
3178 graphmod.asciiedges)
3174
3179
3175 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3180 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3176 return 0
3181 return 0
3177
3182
3178 if opts.get('bundle') and opts.get('subrepos'):
3183 if opts.get('bundle') and opts.get('subrepos'):
3179 raise error.Abort(_('cannot combine --bundle and --subrepos'))
3184 raise error.Abort(_('cannot combine --bundle and --subrepos'))
3180
3185
3181 if opts.get('bookmarks'):
3186 if opts.get('bookmarks'):
3182 source, branches = hg.parseurl(ui.expandpath(source),
3187 source, branches = hg.parseurl(ui.expandpath(source),
3183 opts.get('branch'))
3188 opts.get('branch'))
3184 other = hg.peer(repo, opts, source)
3189 other = hg.peer(repo, opts, source)
3185 if 'bookmarks' not in other.listkeys('namespaces'):
3190 if 'bookmarks' not in other.listkeys('namespaces'):
3186 ui.warn(_("remote doesn't support bookmarks\n"))
3191 ui.warn(_("remote doesn't support bookmarks\n"))
3187 return 0
3192 return 0
3188 ui.pager('incoming')
3193 ui.pager('incoming')
3189 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3194 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3190 return bookmarks.incoming(ui, repo, other)
3195 return bookmarks.incoming(ui, repo, other)
3191
3196
3192 repo._subtoppath = ui.expandpath(source)
3197 repo._subtoppath = ui.expandpath(source)
3193 try:
3198 try:
3194 return hg.incoming(ui, repo, source, opts)
3199 return hg.incoming(ui, repo, source, opts)
3195 finally:
3200 finally:
3196 del repo._subtoppath
3201 del repo._subtoppath
3197
3202
3198
3203
3199 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
3204 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
3200 norepo=True)
3205 norepo=True)
3201 def init(ui, dest=".", **opts):
3206 def init(ui, dest=".", **opts):
3202 """create a new repository in the given directory
3207 """create a new repository in the given directory
3203
3208
3204 Initialize a new repository in the given directory. If the given
3209 Initialize a new repository in the given directory. If the given
3205 directory does not exist, it will be created.
3210 directory does not exist, it will be created.
3206
3211
3207 If no directory is given, the current directory is used.
3212 If no directory is given, the current directory is used.
3208
3213
3209 It is possible to specify an ``ssh://`` URL as the destination.
3214 It is possible to specify an ``ssh://`` URL as the destination.
3210 See :hg:`help urls` for more information.
3215 See :hg:`help urls` for more information.
3211
3216
3212 Returns 0 on success.
3217 Returns 0 on success.
3213 """
3218 """
3214 opts = pycompat.byteskwargs(opts)
3219 opts = pycompat.byteskwargs(opts)
3215 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3220 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3216
3221
3217 @command('locate',
3222 @command('locate',
3218 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3223 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3219 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3224 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3220 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3225 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3221 ] + walkopts,
3226 ] + walkopts,
3222 _('[OPTION]... [PATTERN]...'))
3227 _('[OPTION]... [PATTERN]...'))
3223 def locate(ui, repo, *pats, **opts):
3228 def locate(ui, repo, *pats, **opts):
3224 """locate files matching specific patterns (DEPRECATED)
3229 """locate files matching specific patterns (DEPRECATED)
3225
3230
3226 Print files under Mercurial control in the working directory whose
3231 Print files under Mercurial control in the working directory whose
3227 names match the given patterns.
3232 names match the given patterns.
3228
3233
3229 By default, this command searches all directories in the working
3234 By default, this command searches all directories in the working
3230 directory. To search just the current directory and its
3235 directory. To search just the current directory and its
3231 subdirectories, use "--include .".
3236 subdirectories, use "--include .".
3232
3237
3233 If no patterns are given to match, this command prints the names
3238 If no patterns are given to match, this command prints the names
3234 of all files under Mercurial control in the working directory.
3239 of all files under Mercurial control in the working directory.
3235
3240
3236 If you want to feed the output of this command into the "xargs"
3241 If you want to feed the output of this command into the "xargs"
3237 command, use the -0 option to both this command and "xargs". This
3242 command, use the -0 option to both this command and "xargs". This
3238 will avoid the problem of "xargs" treating single filenames that
3243 will avoid the problem of "xargs" treating single filenames that
3239 contain whitespace as multiple filenames.
3244 contain whitespace as multiple filenames.
3240
3245
3241 See :hg:`help files` for a more versatile command.
3246 See :hg:`help files` for a more versatile command.
3242
3247
3243 Returns 0 if a match is found, 1 otherwise.
3248 Returns 0 if a match is found, 1 otherwise.
3244 """
3249 """
3245 opts = pycompat.byteskwargs(opts)
3250 opts = pycompat.byteskwargs(opts)
3246 if opts.get('print0'):
3251 if opts.get('print0'):
3247 end = '\0'
3252 end = '\0'
3248 else:
3253 else:
3249 end = '\n'
3254 end = '\n'
3250 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3255 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3251
3256
3252 ret = 1
3257 ret = 1
3253 ctx = repo[rev]
3258 ctx = repo[rev]
3254 m = scmutil.match(ctx, pats, opts, default='relglob',
3259 m = scmutil.match(ctx, pats, opts, default='relglob',
3255 badfn=lambda x, y: False)
3260 badfn=lambda x, y: False)
3256
3261
3257 ui.pager('locate')
3262 ui.pager('locate')
3258 for abs in ctx.matches(m):
3263 for abs in ctx.matches(m):
3259 if opts.get('fullpath'):
3264 if opts.get('fullpath'):
3260 ui.write(repo.wjoin(abs), end)
3265 ui.write(repo.wjoin(abs), end)
3261 else:
3266 else:
3262 ui.write(((pats and m.rel(abs)) or abs), end)
3267 ui.write(((pats and m.rel(abs)) or abs), end)
3263 ret = 0
3268 ret = 0
3264
3269
3265 return ret
3270 return ret
3266
3271
3267 @command('^log|history',
3272 @command('^log|history',
3268 [('f', 'follow', None,
3273 [('f', 'follow', None,
3269 _('follow changeset history, or file history across copies and renames')),
3274 _('follow changeset history, or file history across copies and renames')),
3270 ('', 'follow-first', None,
3275 ('', 'follow-first', None,
3271 _('only follow the first parent of merge changesets (DEPRECATED)')),
3276 _('only follow the first parent of merge changesets (DEPRECATED)')),
3272 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3277 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3273 ('C', 'copies', None, _('show copied files')),
3278 ('C', 'copies', None, _('show copied files')),
3274 ('k', 'keyword', [],
3279 ('k', 'keyword', [],
3275 _('do case-insensitive search for a given text'), _('TEXT')),
3280 _('do case-insensitive search for a given text'), _('TEXT')),
3276 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
3281 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
3277 ('', 'removed', None, _('include revisions where files were removed')),
3282 ('', 'removed', None, _('include revisions where files were removed')),
3278 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3283 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3279 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3284 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3280 ('', 'only-branch', [],
3285 ('', 'only-branch', [],
3281 _('show only changesets within the given named branch (DEPRECATED)'),
3286 _('show only changesets within the given named branch (DEPRECATED)'),
3282 _('BRANCH')),
3287 _('BRANCH')),
3283 ('b', 'branch', [],
3288 ('b', 'branch', [],
3284 _('show changesets within the given named branch'), _('BRANCH')),
3289 _('show changesets within the given named branch'), _('BRANCH')),
3285 ('P', 'prune', [],
3290 ('P', 'prune', [],
3286 _('do not display revision or any of its ancestors'), _('REV')),
3291 _('do not display revision or any of its ancestors'), _('REV')),
3287 ] + logopts + walkopts,
3292 ] + logopts + walkopts,
3288 _('[OPTION]... [FILE]'),
3293 _('[OPTION]... [FILE]'),
3289 inferrepo=True)
3294 inferrepo=True)
3290 def log(ui, repo, *pats, **opts):
3295 def log(ui, repo, *pats, **opts):
3291 """show revision history of entire repository or files
3296 """show revision history of entire repository or files
3292
3297
3293 Print the revision history of the specified files or the entire
3298 Print the revision history of the specified files or the entire
3294 project.
3299 project.
3295
3300
3296 If no revision range is specified, the default is ``tip:0`` unless
3301 If no revision range is specified, the default is ``tip:0`` unless
3297 --follow is set, in which case the working directory parent is
3302 --follow is set, in which case the working directory parent is
3298 used as the starting revision.
3303 used as the starting revision.
3299
3304
3300 File history is shown without following rename or copy history of
3305 File history is shown without following rename or copy history of
3301 files. Use -f/--follow with a filename to follow history across
3306 files. Use -f/--follow with a filename to follow history across
3302 renames and copies. --follow without a filename will only show
3307 renames and copies. --follow without a filename will only show
3303 ancestors or descendants of the starting revision.
3308 ancestors or descendants of the starting revision.
3304
3309
3305 By default this command prints revision number and changeset id,
3310 By default this command prints revision number and changeset id,
3306 tags, non-trivial parents, user, date and time, and a summary for
3311 tags, non-trivial parents, user, date and time, and a summary for
3307 each commit. When the -v/--verbose switch is used, the list of
3312 each commit. When the -v/--verbose switch is used, the list of
3308 changed files and full commit message are shown.
3313 changed files and full commit message are shown.
3309
3314
3310 With --graph the revisions are shown as an ASCII art DAG with the most
3315 With --graph the revisions are shown as an ASCII art DAG with the most
3311 recent changeset at the top.
3316 recent changeset at the top.
3312 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
3317 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
3313 and '+' represents a fork where the changeset from the lines below is a
3318 and '+' represents a fork where the changeset from the lines below is a
3314 parent of the 'o' merge on the same line.
3319 parent of the 'o' merge on the same line.
3315 Paths in the DAG are represented with '|', '/' and so forth. ':' in place
3320 Paths in the DAG are represented with '|', '/' and so forth. ':' in place
3316 of a '|' indicates one or more revisions in a path are omitted.
3321 of a '|' indicates one or more revisions in a path are omitted.
3317
3322
3318 .. note::
3323 .. note::
3319
3324
3320 :hg:`log --patch` may generate unexpected diff output for merge
3325 :hg:`log --patch` may generate unexpected diff output for merge
3321 changesets, as it will only compare the merge changeset against
3326 changesets, as it will only compare the merge changeset against
3322 its first parent. Also, only files different from BOTH parents
3327 its first parent. Also, only files different from BOTH parents
3323 will appear in files:.
3328 will appear in files:.
3324
3329
3325 .. note::
3330 .. note::
3326
3331
3327 For performance reasons, :hg:`log FILE` may omit duplicate changes
3332 For performance reasons, :hg:`log FILE` may omit duplicate changes
3328 made on branches and will not show removals or mode changes. To
3333 made on branches and will not show removals or mode changes. To
3329 see all such changes, use the --removed switch.
3334 see all such changes, use the --removed switch.
3330
3335
3331 .. container:: verbose
3336 .. container:: verbose
3332
3337
3333 Some examples:
3338 Some examples:
3334
3339
3335 - changesets with full descriptions and file lists::
3340 - changesets with full descriptions and file lists::
3336
3341
3337 hg log -v
3342 hg log -v
3338
3343
3339 - changesets ancestral to the working directory::
3344 - changesets ancestral to the working directory::
3340
3345
3341 hg log -f
3346 hg log -f
3342
3347
3343 - last 10 commits on the current branch::
3348 - last 10 commits on the current branch::
3344
3349
3345 hg log -l 10 -b .
3350 hg log -l 10 -b .
3346
3351
3347 - changesets showing all modifications of a file, including removals::
3352 - changesets showing all modifications of a file, including removals::
3348
3353
3349 hg log --removed file.c
3354 hg log --removed file.c
3350
3355
3351 - all changesets that touch a directory, with diffs, excluding merges::
3356 - all changesets that touch a directory, with diffs, excluding merges::
3352
3357
3353 hg log -Mp lib/
3358 hg log -Mp lib/
3354
3359
3355 - all revision numbers that match a keyword::
3360 - all revision numbers that match a keyword::
3356
3361
3357 hg log -k bug --template "{rev}\\n"
3362 hg log -k bug --template "{rev}\\n"
3358
3363
3359 - the full hash identifier of the working directory parent::
3364 - the full hash identifier of the working directory parent::
3360
3365
3361 hg log -r . --template "{node}\\n"
3366 hg log -r . --template "{node}\\n"
3362
3367
3363 - list available log templates::
3368 - list available log templates::
3364
3369
3365 hg log -T list
3370 hg log -T list
3366
3371
3367 - check if a given changeset is included in a tagged release::
3372 - check if a given changeset is included in a tagged release::
3368
3373
3369 hg log -r "a21ccf and ancestor(1.9)"
3374 hg log -r "a21ccf and ancestor(1.9)"
3370
3375
3371 - find all changesets by some user in a date range::
3376 - find all changesets by some user in a date range::
3372
3377
3373 hg log -k alice -d "may 2008 to jul 2008"
3378 hg log -k alice -d "may 2008 to jul 2008"
3374
3379
3375 - summary of all changesets after the last tag::
3380 - summary of all changesets after the last tag::
3376
3381
3377 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3382 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3378
3383
3379 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.
3380
3385
3381 See :hg:`help revisions` for more about specifying and ordering
3386 See :hg:`help revisions` for more about specifying and ordering
3382 revisions.
3387 revisions.
3383
3388
3384 See :hg:`help templates` for more about pre-packaged styles and
3389 See :hg:`help templates` for more about pre-packaged styles and
3385 specifying custom templates.
3390 specifying custom templates.
3386
3391
3387 Returns 0 on success.
3392 Returns 0 on success.
3388
3393
3389 """
3394 """
3390 opts = pycompat.byteskwargs(opts)
3395 opts = pycompat.byteskwargs(opts)
3391 if opts.get('follow') and opts.get('rev'):
3396 if opts.get('follow') and opts.get('rev'):
3392 opts['rev'] = [revsetlang.formatspec('reverse(::%lr)', opts.get('rev'))]
3397 opts['rev'] = [revsetlang.formatspec('reverse(::%lr)', opts.get('rev'))]
3393 del opts['follow']
3398 del opts['follow']
3394
3399
3395 if opts.get('graph'):
3400 if opts.get('graph'):
3396 return cmdutil.graphlog(ui, repo, pats, opts)
3401 return cmdutil.graphlog(ui, repo, pats, opts)
3397
3402
3398 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
3403 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
3399 limit = cmdutil.loglimit(opts)
3404 limit = cmdutil.loglimit(opts)
3400 count = 0
3405 count = 0
3401
3406
3402 getrenamed = None
3407 getrenamed = None
3403 if opts.get('copies'):
3408 if opts.get('copies'):
3404 endrev = None
3409 endrev = None
3405 if opts.get('rev'):
3410 if opts.get('rev'):
3406 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
3411 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
3407 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3412 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3408
3413
3409 ui.pager('log')
3414 ui.pager('log')
3410 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
3415 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
3411 for rev in revs:
3416 for rev in revs:
3412 if count == limit:
3417 if count == limit:
3413 break
3418 break
3414 ctx = repo[rev]
3419 ctx = repo[rev]
3415 copies = None
3420 copies = None
3416 if getrenamed is not None and rev:
3421 if getrenamed is not None and rev:
3417 copies = []
3422 copies = []
3418 for fn in ctx.files():
3423 for fn in ctx.files():
3419 rename = getrenamed(fn, rev)
3424 rename = getrenamed(fn, rev)
3420 if rename:
3425 if rename:
3421 copies.append((fn, rename[0]))
3426 copies.append((fn, rename[0]))
3422 if filematcher:
3427 if filematcher:
3423 revmatchfn = filematcher(ctx.rev())
3428 revmatchfn = filematcher(ctx.rev())
3424 else:
3429 else:
3425 revmatchfn = None
3430 revmatchfn = None
3426 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
3431 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
3427 if displayer.flush(ctx):
3432 if displayer.flush(ctx):
3428 count += 1
3433 count += 1
3429
3434
3430 displayer.close()
3435 displayer.close()
3431
3436
3432 @command('manifest',
3437 @command('manifest',
3433 [('r', 'rev', '', _('revision to display'), _('REV')),
3438 [('r', 'rev', '', _('revision to display'), _('REV')),
3434 ('', 'all', False, _("list files from all revisions"))]
3439 ('', 'all', False, _("list files from all revisions"))]
3435 + formatteropts,
3440 + formatteropts,
3436 _('[-r REV]'))
3441 _('[-r REV]'))
3437 def manifest(ui, repo, node=None, rev=None, **opts):
3442 def manifest(ui, repo, node=None, rev=None, **opts):
3438 """output the current or given revision of the project manifest
3443 """output the current or given revision of the project manifest
3439
3444
3440 Print a list of version controlled files for the given revision.
3445 Print a list of version controlled files for the given revision.
3441 If no revision is given, the first parent of the working directory
3446 If no revision is given, the first parent of the working directory
3442 is used, or the null revision if no revision is checked out.
3447 is used, or the null revision if no revision is checked out.
3443
3448
3444 With -v, print file permissions, symlink and executable bits.
3449 With -v, print file permissions, symlink and executable bits.
3445 With --debug, print file revision hashes.
3450 With --debug, print file revision hashes.
3446
3451
3447 If option --all is specified, the list of all files from all revisions
3452 If option --all is specified, the list of all files from all revisions
3448 is printed. This includes deleted and renamed files.
3453 is printed. This includes deleted and renamed files.
3449
3454
3450 Returns 0 on success.
3455 Returns 0 on success.
3451 """
3456 """
3452 opts = pycompat.byteskwargs(opts)
3457 opts = pycompat.byteskwargs(opts)
3453 fm = ui.formatter('manifest', opts)
3458 fm = ui.formatter('manifest', opts)
3454
3459
3455 if opts.get('all'):
3460 if opts.get('all'):
3456 if rev or node:
3461 if rev or node:
3457 raise error.Abort(_("can't specify a revision with --all"))
3462 raise error.Abort(_("can't specify a revision with --all"))
3458
3463
3459 res = []
3464 res = []
3460 prefix = "data/"
3465 prefix = "data/"
3461 suffix = ".i"
3466 suffix = ".i"
3462 plen = len(prefix)
3467 plen = len(prefix)
3463 slen = len(suffix)
3468 slen = len(suffix)
3464 with repo.lock():
3469 with repo.lock():
3465 for fn, b, size in repo.store.datafiles():
3470 for fn, b, size in repo.store.datafiles():
3466 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
3471 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
3467 res.append(fn[plen:-slen])
3472 res.append(fn[plen:-slen])
3468 ui.pager('manifest')
3473 ui.pager('manifest')
3469 for f in res:
3474 for f in res:
3470 fm.startitem()
3475 fm.startitem()
3471 fm.write("path", '%s\n', f)
3476 fm.write("path", '%s\n', f)
3472 fm.end()
3477 fm.end()
3473 return
3478 return
3474
3479
3475 if rev and node:
3480 if rev and node:
3476 raise error.Abort(_("please specify just one revision"))
3481 raise error.Abort(_("please specify just one revision"))
3477
3482
3478 if not node:
3483 if not node:
3479 node = rev
3484 node = rev
3480
3485
3481 char = {'l': '@', 'x': '*', '': ''}
3486 char = {'l': '@', 'x': '*', '': ''}
3482 mode = {'l': '644', 'x': '755', '': '644'}
3487 mode = {'l': '644', 'x': '755', '': '644'}
3483 ctx = scmutil.revsingle(repo, node)
3488 ctx = scmutil.revsingle(repo, node)
3484 mf = ctx.manifest()
3489 mf = ctx.manifest()
3485 ui.pager('manifest')
3490 ui.pager('manifest')
3486 for f in ctx:
3491 for f in ctx:
3487 fm.startitem()
3492 fm.startitem()
3488 fl = ctx[f].flags()
3493 fl = ctx[f].flags()
3489 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
3494 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
3490 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
3495 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
3491 fm.write('path', '%s\n', f)
3496 fm.write('path', '%s\n', f)
3492 fm.end()
3497 fm.end()
3493
3498
3494 @command('^merge',
3499 @command('^merge',
3495 [('f', 'force', None,
3500 [('f', 'force', None,
3496 _('force a merge including outstanding changes (DEPRECATED)')),
3501 _('force a merge including outstanding changes (DEPRECATED)')),
3497 ('r', 'rev', '', _('revision to merge'), _('REV')),
3502 ('r', 'rev', '', _('revision to merge'), _('REV')),
3498 ('P', 'preview', None,
3503 ('P', 'preview', None,
3499 _('review revisions to merge (no merge is performed)'))
3504 _('review revisions to merge (no merge is performed)'))
3500 ] + mergetoolopts,
3505 ] + mergetoolopts,
3501 _('[-P] [[-r] REV]'))
3506 _('[-P] [[-r] REV]'))
3502 def merge(ui, repo, node=None, **opts):
3507 def merge(ui, repo, node=None, **opts):
3503 """merge another revision into working directory
3508 """merge another revision into working directory
3504
3509
3505 The current working directory is updated with all changes made in
3510 The current working directory is updated with all changes made in
3506 the requested revision since the last common predecessor revision.
3511 the requested revision since the last common predecessor revision.
3507
3512
3508 Files that changed between either parent are marked as changed for
3513 Files that changed between either parent are marked as changed for
3509 the next commit and a commit must be performed before any further
3514 the next commit and a commit must be performed before any further
3510 updates to the repository are allowed. The next commit will have
3515 updates to the repository are allowed. The next commit will have
3511 two parents.
3516 two parents.
3512
3517
3513 ``--tool`` can be used to specify the merge tool used for file
3518 ``--tool`` can be used to specify the merge tool used for file
3514 merges. It overrides the HGMERGE environment variable and your
3519 merges. It overrides the HGMERGE environment variable and your
3515 configuration files. See :hg:`help merge-tools` for options.
3520 configuration files. See :hg:`help merge-tools` for options.
3516
3521
3517 If no revision is specified, the working directory's parent is a
3522 If no revision is specified, the working directory's parent is a
3518 head revision, and the current branch contains exactly one other
3523 head revision, and the current branch contains exactly one other
3519 head, the other head is merged with by default. Otherwise, an
3524 head, the other head is merged with by default. Otherwise, an
3520 explicit revision with which to merge with must be provided.
3525 explicit revision with which to merge with must be provided.
3521
3526
3522 See :hg:`help resolve` for information on handling file conflicts.
3527 See :hg:`help resolve` for information on handling file conflicts.
3523
3528
3524 To undo an uncommitted merge, use :hg:`update --clean .` which
3529 To undo an uncommitted merge, use :hg:`update --clean .` which
3525 will check out a clean copy of the original merge parent, losing
3530 will check out a clean copy of the original merge parent, losing
3526 all changes.
3531 all changes.
3527
3532
3528 Returns 0 on success, 1 if there are unresolved files.
3533 Returns 0 on success, 1 if there are unresolved files.
3529 """
3534 """
3530
3535
3531 opts = pycompat.byteskwargs(opts)
3536 opts = pycompat.byteskwargs(opts)
3532 if opts.get('rev') and node:
3537 if opts.get('rev') and node:
3533 raise error.Abort(_("please specify just one revision"))
3538 raise error.Abort(_("please specify just one revision"))
3534 if not node:
3539 if not node:
3535 node = opts.get('rev')
3540 node = opts.get('rev')
3536
3541
3537 if node:
3542 if node:
3538 node = scmutil.revsingle(repo, node).node()
3543 node = scmutil.revsingle(repo, node).node()
3539
3544
3540 if not node:
3545 if not node:
3541 node = repo[destutil.destmerge(repo)].node()
3546 node = repo[destutil.destmerge(repo)].node()
3542
3547
3543 if opts.get('preview'):
3548 if opts.get('preview'):
3544 # find nodes that are ancestors of p2 but not of p1
3549 # find nodes that are ancestors of p2 but not of p1
3545 p1 = repo.lookup('.')
3550 p1 = repo.lookup('.')
3546 p2 = repo.lookup(node)
3551 p2 = repo.lookup(node)
3547 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
3552 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
3548
3553
3549 displayer = cmdutil.show_changeset(ui, repo, opts)
3554 displayer = cmdutil.show_changeset(ui, repo, opts)
3550 for node in nodes:
3555 for node in nodes:
3551 displayer.show(repo[node])
3556 displayer.show(repo[node])
3552 displayer.close()
3557 displayer.close()
3553 return 0
3558 return 0
3554
3559
3555 try:
3560 try:
3556 # ui.forcemerge is an internal variable, do not document
3561 # ui.forcemerge is an internal variable, do not document
3557 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
3562 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
3558 force = opts.get('force')
3563 force = opts.get('force')
3559 labels = ['working copy', 'merge rev']
3564 labels = ['working copy', 'merge rev']
3560 return hg.merge(repo, node, force=force, mergeforce=force,
3565 return hg.merge(repo, node, force=force, mergeforce=force,
3561 labels=labels)
3566 labels=labels)
3562 finally:
3567 finally:
3563 ui.setconfig('ui', 'forcemerge', '', 'merge')
3568 ui.setconfig('ui', 'forcemerge', '', 'merge')
3564
3569
3565 @command('outgoing|out',
3570 @command('outgoing|out',
3566 [('f', 'force', None, _('run even when the destination is unrelated')),
3571 [('f', 'force', None, _('run even when the destination is unrelated')),
3567 ('r', 'rev', [],
3572 ('r', 'rev', [],
3568 _('a changeset intended to be included in the destination'), _('REV')),
3573 _('a changeset intended to be included in the destination'), _('REV')),
3569 ('n', 'newest-first', None, _('show newest record first')),
3574 ('n', 'newest-first', None, _('show newest record first')),
3570 ('B', 'bookmarks', False, _('compare bookmarks')),
3575 ('B', 'bookmarks', False, _('compare bookmarks')),
3571 ('b', 'branch', [], _('a specific branch you would like to push'),
3576 ('b', 'branch', [], _('a specific branch you would like to push'),
3572 _('BRANCH')),
3577 _('BRANCH')),
3573 ] + logopts + remoteopts + subrepoopts,
3578 ] + logopts + remoteopts + subrepoopts,
3574 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
3579 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
3575 def outgoing(ui, repo, dest=None, **opts):
3580 def outgoing(ui, repo, dest=None, **opts):
3576 """show changesets not found in the destination
3581 """show changesets not found in the destination
3577
3582
3578 Show changesets not found in the specified destination repository
3583 Show changesets not found in the specified destination repository
3579 or the default push location. These are the changesets that would
3584 or the default push location. These are the changesets that would
3580 be pushed if a push was requested.
3585 be pushed if a push was requested.
3581
3586
3582 See pull for details of valid destination formats.
3587 See pull for details of valid destination formats.
3583
3588
3584 .. container:: verbose
3589 .. container:: verbose
3585
3590
3586 With -B/--bookmarks, the result of bookmark comparison between
3591 With -B/--bookmarks, the result of bookmark comparison between
3587 local and remote repositories is displayed. With -v/--verbose,
3592 local and remote repositories is displayed. With -v/--verbose,
3588 status is also displayed for each bookmark like below::
3593 status is also displayed for each bookmark like below::
3589
3594
3590 BM1 01234567890a added
3595 BM1 01234567890a added
3591 BM2 deleted
3596 BM2 deleted
3592 BM3 234567890abc advanced
3597 BM3 234567890abc advanced
3593 BM4 34567890abcd diverged
3598 BM4 34567890abcd diverged
3594 BM5 4567890abcde changed
3599 BM5 4567890abcde changed
3595
3600
3596 The action taken when pushing depends on the
3601 The action taken when pushing depends on the
3597 status of each bookmark:
3602 status of each bookmark:
3598
3603
3599 :``added``: push with ``-B`` will create it
3604 :``added``: push with ``-B`` will create it
3600 :``deleted``: push with ``-B`` will delete it
3605 :``deleted``: push with ``-B`` will delete it
3601 :``advanced``: push will update it
3606 :``advanced``: push will update it
3602 :``diverged``: push with ``-B`` will update it
3607 :``diverged``: push with ``-B`` will update it
3603 :``changed``: push with ``-B`` will update it
3608 :``changed``: push with ``-B`` will update it
3604
3609
3605 From the point of view of pushing behavior, bookmarks
3610 From the point of view of pushing behavior, bookmarks
3606 existing only in the remote repository are treated as
3611 existing only in the remote repository are treated as
3607 ``deleted``, even if it is in fact added remotely.
3612 ``deleted``, even if it is in fact added remotely.
3608
3613
3609 Returns 0 if there are outgoing changes, 1 otherwise.
3614 Returns 0 if there are outgoing changes, 1 otherwise.
3610 """
3615 """
3611 opts = pycompat.byteskwargs(opts)
3616 opts = pycompat.byteskwargs(opts)
3612 if opts.get('graph'):
3617 if opts.get('graph'):
3613 cmdutil.checkunsupportedgraphflags([], opts)
3618 cmdutil.checkunsupportedgraphflags([], opts)
3614 o, other = hg._outgoing(ui, repo, dest, opts)
3619 o, other = hg._outgoing(ui, repo, dest, opts)
3615 if not o:
3620 if not o:
3616 cmdutil.outgoinghooks(ui, repo, other, opts, o)
3621 cmdutil.outgoinghooks(ui, repo, other, opts, o)
3617 return
3622 return
3618
3623
3619 revdag = cmdutil.graphrevs(repo, o, opts)
3624 revdag = cmdutil.graphrevs(repo, o, opts)
3620 ui.pager('outgoing')
3625 ui.pager('outgoing')
3621 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
3626 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
3622 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
3627 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
3623 cmdutil.outgoinghooks(ui, repo, other, opts, o)
3628 cmdutil.outgoinghooks(ui, repo, other, opts, o)
3624 return 0
3629 return 0
3625
3630
3626 if opts.get('bookmarks'):
3631 if opts.get('bookmarks'):
3627 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3632 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3628 dest, branches = hg.parseurl(dest, opts.get('branch'))
3633 dest, branches = hg.parseurl(dest, opts.get('branch'))
3629 other = hg.peer(repo, opts, dest)
3634 other = hg.peer(repo, opts, dest)
3630 if 'bookmarks' not in other.listkeys('namespaces'):
3635 if 'bookmarks' not in other.listkeys('namespaces'):
3631 ui.warn(_("remote doesn't support bookmarks\n"))
3636 ui.warn(_("remote doesn't support bookmarks\n"))
3632 return 0
3637 return 0
3633 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
3638 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
3634 ui.pager('outgoing')
3639 ui.pager('outgoing')
3635 return bookmarks.outgoing(ui, repo, other)
3640 return bookmarks.outgoing(ui, repo, other)
3636
3641
3637 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
3642 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
3638 try:
3643 try:
3639 return hg.outgoing(ui, repo, dest, opts)
3644 return hg.outgoing(ui, repo, dest, opts)
3640 finally:
3645 finally:
3641 del repo._subtoppath
3646 del repo._subtoppath
3642
3647
3643 @command('parents',
3648 @command('parents',
3644 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
3649 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
3645 ] + templateopts,
3650 ] + templateopts,
3646 _('[-r REV] [FILE]'),
3651 _('[-r REV] [FILE]'),
3647 inferrepo=True)
3652 inferrepo=True)
3648 def parents(ui, repo, file_=None, **opts):
3653 def parents(ui, repo, file_=None, **opts):
3649 """show the parents of the working directory or revision (DEPRECATED)
3654 """show the parents of the working directory or revision (DEPRECATED)
3650
3655
3651 Print the working directory's parent revisions. If a revision is
3656 Print the working directory's parent revisions. If a revision is
3652 given via -r/--rev, the parent of that revision will be printed.
3657 given via -r/--rev, the parent of that revision will be printed.
3653 If a file argument is given, the revision in which the file was
3658 If a file argument is given, the revision in which the file was
3654 last changed (before the working directory revision or the
3659 last changed (before the working directory revision or the
3655 argument to --rev if given) is printed.
3660 argument to --rev if given) is printed.
3656
3661
3657 This command is equivalent to::
3662 This command is equivalent to::
3658
3663
3659 hg log -r "p1()+p2()" or
3664 hg log -r "p1()+p2()" or
3660 hg log -r "p1(REV)+p2(REV)" or
3665 hg log -r "p1(REV)+p2(REV)" or
3661 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
3666 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
3662 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
3667 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
3663
3668
3664 See :hg:`summary` and :hg:`help revsets` for related information.
3669 See :hg:`summary` and :hg:`help revsets` for related information.
3665
3670
3666 Returns 0 on success.
3671 Returns 0 on success.
3667 """
3672 """
3668
3673
3669 opts = pycompat.byteskwargs(opts)
3674 opts = pycompat.byteskwargs(opts)
3670 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3675 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3671
3676
3672 if file_:
3677 if file_:
3673 m = scmutil.match(ctx, (file_,), opts)
3678 m = scmutil.match(ctx, (file_,), opts)
3674 if m.anypats() or len(m.files()) != 1:
3679 if m.anypats() or len(m.files()) != 1:
3675 raise error.Abort(_('can only specify an explicit filename'))
3680 raise error.Abort(_('can only specify an explicit filename'))
3676 file_ = m.files()[0]
3681 file_ = m.files()[0]
3677 filenodes = []
3682 filenodes = []
3678 for cp in ctx.parents():
3683 for cp in ctx.parents():
3679 if not cp:
3684 if not cp:
3680 continue
3685 continue
3681 try:
3686 try:
3682 filenodes.append(cp.filenode(file_))
3687 filenodes.append(cp.filenode(file_))
3683 except error.LookupError:
3688 except error.LookupError:
3684 pass
3689 pass
3685 if not filenodes:
3690 if not filenodes:
3686 raise error.Abort(_("'%s' not found in manifest!") % file_)
3691 raise error.Abort(_("'%s' not found in manifest!") % file_)
3687 p = []
3692 p = []
3688 for fn in filenodes:
3693 for fn in filenodes:
3689 fctx = repo.filectx(file_, fileid=fn)
3694 fctx = repo.filectx(file_, fileid=fn)
3690 p.append(fctx.node())
3695 p.append(fctx.node())
3691 else:
3696 else:
3692 p = [cp.node() for cp in ctx.parents()]
3697 p = [cp.node() for cp in ctx.parents()]
3693
3698
3694 displayer = cmdutil.show_changeset(ui, repo, opts)
3699 displayer = cmdutil.show_changeset(ui, repo, opts)
3695 for n in p:
3700 for n in p:
3696 if n != nullid:
3701 if n != nullid:
3697 displayer.show(repo[n])
3702 displayer.show(repo[n])
3698 displayer.close()
3703 displayer.close()
3699
3704
3700 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True)
3705 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True)
3701 def paths(ui, repo, search=None, **opts):
3706 def paths(ui, repo, search=None, **opts):
3702 """show aliases for remote repositories
3707 """show aliases for remote repositories
3703
3708
3704 Show definition of symbolic path name NAME. If no name is given,
3709 Show definition of symbolic path name NAME. If no name is given,
3705 show definition of all available names.
3710 show definition of all available names.
3706
3711
3707 Option -q/--quiet suppresses all output when searching for NAME
3712 Option -q/--quiet suppresses all output when searching for NAME
3708 and shows only the path names when listing all definitions.
3713 and shows only the path names when listing all definitions.
3709
3714
3710 Path names are defined in the [paths] section of your
3715 Path names are defined in the [paths] section of your
3711 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
3716 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
3712 repository, ``.hg/hgrc`` is used, too.
3717 repository, ``.hg/hgrc`` is used, too.
3713
3718
3714 The path names ``default`` and ``default-push`` have a special
3719 The path names ``default`` and ``default-push`` have a special
3715 meaning. When performing a push or pull operation, they are used
3720 meaning. When performing a push or pull operation, they are used
3716 as fallbacks if no location is specified on the command-line.
3721 as fallbacks if no location is specified on the command-line.
3717 When ``default-push`` is set, it will be used for push and
3722 When ``default-push`` is set, it will be used for push and
3718 ``default`` will be used for pull; otherwise ``default`` is used
3723 ``default`` will be used for pull; otherwise ``default`` is used
3719 as the fallback for both. When cloning a repository, the clone
3724 as the fallback for both. When cloning a repository, the clone
3720 source is written as ``default`` in ``.hg/hgrc``.
3725 source is written as ``default`` in ``.hg/hgrc``.
3721
3726
3722 .. note::
3727 .. note::
3723
3728
3724 ``default`` and ``default-push`` apply to all inbound (e.g.
3729 ``default`` and ``default-push`` apply to all inbound (e.g.
3725 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
3730 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
3726 and :hg:`bundle`) operations.
3731 and :hg:`bundle`) operations.
3727
3732
3728 See :hg:`help urls` for more information.
3733 See :hg:`help urls` for more information.
3729
3734
3730 Returns 0 on success.
3735 Returns 0 on success.
3731 """
3736 """
3732
3737
3733 opts = pycompat.byteskwargs(opts)
3738 opts = pycompat.byteskwargs(opts)
3734 ui.pager('paths')
3739 ui.pager('paths')
3735 if search:
3740 if search:
3736 pathitems = [(name, path) for name, path in ui.paths.iteritems()
3741 pathitems = [(name, path) for name, path in ui.paths.iteritems()
3737 if name == search]
3742 if name == search]
3738 else:
3743 else:
3739 pathitems = sorted(ui.paths.iteritems())
3744 pathitems = sorted(ui.paths.iteritems())
3740
3745
3741 fm = ui.formatter('paths', opts)
3746 fm = ui.formatter('paths', opts)
3742 if fm.isplain():
3747 if fm.isplain():
3743 hidepassword = util.hidepassword
3748 hidepassword = util.hidepassword
3744 else:
3749 else:
3745 hidepassword = str
3750 hidepassword = str
3746 if ui.quiet:
3751 if ui.quiet:
3747 namefmt = '%s\n'
3752 namefmt = '%s\n'
3748 else:
3753 else:
3749 namefmt = '%s = '
3754 namefmt = '%s = '
3750 showsubopts = not search and not ui.quiet
3755 showsubopts = not search and not ui.quiet
3751
3756
3752 for name, path in pathitems:
3757 for name, path in pathitems:
3753 fm.startitem()
3758 fm.startitem()
3754 fm.condwrite(not search, 'name', namefmt, name)
3759 fm.condwrite(not search, 'name', namefmt, name)
3755 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
3760 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
3756 for subopt, value in sorted(path.suboptions.items()):
3761 for subopt, value in sorted(path.suboptions.items()):
3757 assert subopt not in ('name', 'url')
3762 assert subopt not in ('name', 'url')
3758 if showsubopts:
3763 if showsubopts:
3759 fm.plain('%s:%s = ' % (name, subopt))
3764 fm.plain('%s:%s = ' % (name, subopt))
3760 fm.condwrite(showsubopts, subopt, '%s\n', value)
3765 fm.condwrite(showsubopts, subopt, '%s\n', value)
3761
3766
3762 fm.end()
3767 fm.end()
3763
3768
3764 if search and not pathitems:
3769 if search and not pathitems:
3765 if not ui.quiet:
3770 if not ui.quiet:
3766 ui.warn(_("not found!\n"))
3771 ui.warn(_("not found!\n"))
3767 return 1
3772 return 1
3768 else:
3773 else:
3769 return 0
3774 return 0
3770
3775
3771 @command('phase',
3776 @command('phase',
3772 [('p', 'public', False, _('set changeset phase to public')),
3777 [('p', 'public', False, _('set changeset phase to public')),
3773 ('d', 'draft', False, _('set changeset phase to draft')),
3778 ('d', 'draft', False, _('set changeset phase to draft')),
3774 ('s', 'secret', False, _('set changeset phase to secret')),
3779 ('s', 'secret', False, _('set changeset phase to secret')),
3775 ('f', 'force', False, _('allow to move boundary backward')),
3780 ('f', 'force', False, _('allow to move boundary backward')),
3776 ('r', 'rev', [], _('target revision'), _('REV')),
3781 ('r', 'rev', [], _('target revision'), _('REV')),
3777 ],
3782 ],
3778 _('[-p|-d|-s] [-f] [-r] [REV...]'))
3783 _('[-p|-d|-s] [-f] [-r] [REV...]'))
3779 def phase(ui, repo, *revs, **opts):
3784 def phase(ui, repo, *revs, **opts):
3780 """set or show the current phase name
3785 """set or show the current phase name
3781
3786
3782 With no argument, show the phase name of the current revision(s).
3787 With no argument, show the phase name of the current revision(s).
3783
3788
3784 With one of -p/--public, -d/--draft or -s/--secret, change the
3789 With one of -p/--public, -d/--draft or -s/--secret, change the
3785 phase value of the specified revisions.
3790 phase value of the specified revisions.
3786
3791
3787 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
3792 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
3788 lower phase to an higher phase. Phases are ordered as follows::
3793 lower phase to an higher phase. Phases are ordered as follows::
3789
3794
3790 public < draft < secret
3795 public < draft < secret
3791
3796
3792 Returns 0 on success, 1 if some phases could not be changed.
3797 Returns 0 on success, 1 if some phases could not be changed.
3793
3798
3794 (For more information about the phases concept, see :hg:`help phases`.)
3799 (For more information about the phases concept, see :hg:`help phases`.)
3795 """
3800 """
3796 opts = pycompat.byteskwargs(opts)
3801 opts = pycompat.byteskwargs(opts)
3797 # search for a unique phase argument
3802 # search for a unique phase argument
3798 targetphase = None
3803 targetphase = None
3799 for idx, name in enumerate(phases.phasenames):
3804 for idx, name in enumerate(phases.phasenames):
3800 if opts[name]:
3805 if opts[name]:
3801 if targetphase is not None:
3806 if targetphase is not None:
3802 raise error.Abort(_('only one phase can be specified'))
3807 raise error.Abort(_('only one phase can be specified'))
3803 targetphase = idx
3808 targetphase = idx
3804
3809
3805 # look for specified revision
3810 # look for specified revision
3806 revs = list(revs)
3811 revs = list(revs)
3807 revs.extend(opts['rev'])
3812 revs.extend(opts['rev'])
3808 if not revs:
3813 if not revs:
3809 # display both parents as the second parent phase can influence
3814 # display both parents as the second parent phase can influence
3810 # the phase of a merge commit
3815 # the phase of a merge commit
3811 revs = [c.rev() for c in repo[None].parents()]
3816 revs = [c.rev() for c in repo[None].parents()]
3812
3817
3813 revs = scmutil.revrange(repo, revs)
3818 revs = scmutil.revrange(repo, revs)
3814
3819
3815 lock = None
3820 lock = None
3816 ret = 0
3821 ret = 0
3817 if targetphase is None:
3822 if targetphase is None:
3818 # display
3823 # display
3819 for r in revs:
3824 for r in revs:
3820 ctx = repo[r]
3825 ctx = repo[r]
3821 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
3826 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
3822 else:
3827 else:
3823 tr = None
3828 tr = None
3824 lock = repo.lock()
3829 lock = repo.lock()
3825 try:
3830 try:
3826 tr = repo.transaction("phase")
3831 tr = repo.transaction("phase")
3827 # set phase
3832 # set phase
3828 if not revs:
3833 if not revs:
3829 raise error.Abort(_('empty revision set'))
3834 raise error.Abort(_('empty revision set'))
3830 nodes = [repo[r].node() for r in revs]
3835 nodes = [repo[r].node() for r in revs]
3831 # moving revision from public to draft may hide them
3836 # moving revision from public to draft may hide them
3832 # We have to check result on an unfiltered repository
3837 # We have to check result on an unfiltered repository
3833 unfi = repo.unfiltered()
3838 unfi = repo.unfiltered()
3834 getphase = unfi._phasecache.phase
3839 getphase = unfi._phasecache.phase
3835 olddata = [getphase(unfi, r) for r in unfi]
3840 olddata = [getphase(unfi, r) for r in unfi]
3836 phases.advanceboundary(repo, tr, targetphase, nodes)
3841 phases.advanceboundary(repo, tr, targetphase, nodes)
3837 if opts['force']:
3842 if opts['force']:
3838 phases.retractboundary(repo, tr, targetphase, nodes)
3843 phases.retractboundary(repo, tr, targetphase, nodes)
3839 tr.close()
3844 tr.close()
3840 finally:
3845 finally:
3841 if tr is not None:
3846 if tr is not None:
3842 tr.release()
3847 tr.release()
3843 lock.release()
3848 lock.release()
3844 getphase = unfi._phasecache.phase
3849 getphase = unfi._phasecache.phase
3845 newdata = [getphase(unfi, r) for r in unfi]
3850 newdata = [getphase(unfi, r) for r in unfi]
3846 changes = sum(newdata[r] != olddata[r] for r in unfi)
3851 changes = sum(newdata[r] != olddata[r] for r in unfi)
3847 cl = unfi.changelog
3852 cl = unfi.changelog
3848 rejected = [n for n in nodes
3853 rejected = [n for n in nodes
3849 if newdata[cl.rev(n)] < targetphase]
3854 if newdata[cl.rev(n)] < targetphase]
3850 if rejected:
3855 if rejected:
3851 ui.warn(_('cannot move %i changesets to a higher '
3856 ui.warn(_('cannot move %i changesets to a higher '
3852 'phase, use --force\n') % len(rejected))
3857 'phase, use --force\n') % len(rejected))
3853 ret = 1
3858 ret = 1
3854 if changes:
3859 if changes:
3855 msg = _('phase changed for %i changesets\n') % changes
3860 msg = _('phase changed for %i changesets\n') % changes
3856 if ret:
3861 if ret:
3857 ui.status(msg)
3862 ui.status(msg)
3858 else:
3863 else:
3859 ui.note(msg)
3864 ui.note(msg)
3860 else:
3865 else:
3861 ui.warn(_('no phases changed\n'))
3866 ui.warn(_('no phases changed\n'))
3862 return ret
3867 return ret
3863
3868
3864 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
3869 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
3865 """Run after a changegroup has been added via pull/unbundle
3870 """Run after a changegroup has been added via pull/unbundle
3866
3871
3867 This takes arguments below:
3872 This takes arguments below:
3868
3873
3869 :modheads: change of heads by pull/unbundle
3874 :modheads: change of heads by pull/unbundle
3870 :optupdate: updating working directory is needed or not
3875 :optupdate: updating working directory is needed or not
3871 :checkout: update destination revision (or None to default destination)
3876 :checkout: update destination revision (or None to default destination)
3872 :brev: a name, which might be a bookmark to be activated after updating
3877 :brev: a name, which might be a bookmark to be activated after updating
3873 """
3878 """
3874 if modheads == 0:
3879 if modheads == 0:
3875 return
3880 return
3876 if optupdate:
3881 if optupdate:
3877 try:
3882 try:
3878 return hg.updatetotally(ui, repo, checkout, brev)
3883 return hg.updatetotally(ui, repo, checkout, brev)
3879 except error.UpdateAbort as inst:
3884 except error.UpdateAbort as inst:
3880 msg = _("not updating: %s") % str(inst)
3885 msg = _("not updating: %s") % str(inst)
3881 hint = inst.hint
3886 hint = inst.hint
3882 raise error.UpdateAbort(msg, hint=hint)
3887 raise error.UpdateAbort(msg, hint=hint)
3883 if modheads > 1:
3888 if modheads > 1:
3884 currentbranchheads = len(repo.branchheads())
3889 currentbranchheads = len(repo.branchheads())
3885 if currentbranchheads == modheads:
3890 if currentbranchheads == modheads:
3886 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
3891 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
3887 elif currentbranchheads > 1:
3892 elif currentbranchheads > 1:
3888 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
3893 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
3889 "merge)\n"))
3894 "merge)\n"))
3890 else:
3895 else:
3891 ui.status(_("(run 'hg heads' to see heads)\n"))
3896 ui.status(_("(run 'hg heads' to see heads)\n"))
3892 else:
3897 else:
3893 ui.status(_("(run 'hg update' to get a working copy)\n"))
3898 ui.status(_("(run 'hg update' to get a working copy)\n"))
3894
3899
3895 @command('^pull',
3900 @command('^pull',
3896 [('u', 'update', None,
3901 [('u', 'update', None,
3897 _('update to new branch head if changesets were pulled')),
3902 _('update to new branch head if changesets were pulled')),
3898 ('f', 'force', None, _('run even when remote repository is unrelated')),
3903 ('f', 'force', None, _('run even when remote repository is unrelated')),
3899 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3904 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3900 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
3905 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
3901 ('b', 'branch', [], _('a specific branch you would like to pull'),
3906 ('b', 'branch', [], _('a specific branch you would like to pull'),
3902 _('BRANCH')),
3907 _('BRANCH')),
3903 ] + remoteopts,
3908 ] + remoteopts,
3904 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
3909 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
3905 def pull(ui, repo, source="default", **opts):
3910 def pull(ui, repo, source="default", **opts):
3906 """pull changes from the specified source
3911 """pull changes from the specified source
3907
3912
3908 Pull changes from a remote repository to a local one.
3913 Pull changes from a remote repository to a local one.
3909
3914
3910 This finds all changes from the repository at the specified path
3915 This finds all changes from the repository at the specified path
3911 or URL and adds them to a local repository (the current one unless
3916 or URL and adds them to a local repository (the current one unless
3912 -R is specified). By default, this does not update the copy of the
3917 -R is specified). By default, this does not update the copy of the
3913 project in the working directory.
3918 project in the working directory.
3914
3919
3915 Use :hg:`incoming` if you want to see what would have been added
3920 Use :hg:`incoming` if you want to see what would have been added
3916 by a pull at the time you issued this command. If you then decide
3921 by a pull at the time you issued this command. If you then decide
3917 to add those changes to the repository, you should use :hg:`pull
3922 to add those changes to the repository, you should use :hg:`pull
3918 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
3923 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
3919
3924
3920 If SOURCE is omitted, the 'default' path will be used.
3925 If SOURCE is omitted, the 'default' path will be used.
3921 See :hg:`help urls` for more information.
3926 See :hg:`help urls` for more information.
3922
3927
3923 Specifying bookmark as ``.`` is equivalent to specifying the active
3928 Specifying bookmark as ``.`` is equivalent to specifying the active
3924 bookmark's name.
3929 bookmark's name.
3925
3930
3926 Returns 0 on success, 1 if an update had unresolved files.
3931 Returns 0 on success, 1 if an update had unresolved files.
3927 """
3932 """
3928
3933
3929 opts = pycompat.byteskwargs(opts)
3934 opts = pycompat.byteskwargs(opts)
3930 if ui.configbool('commands', 'update.requiredest') and opts.get('update'):
3935 if ui.configbool('commands', 'update.requiredest') and opts.get('update'):
3931 msg = _('update destination required by configuration')
3936 msg = _('update destination required by configuration')
3932 hint = _('use hg pull followed by hg update DEST')
3937 hint = _('use hg pull followed by hg update DEST')
3933 raise error.Abort(msg, hint=hint)
3938 raise error.Abort(msg, hint=hint)
3934
3939
3935 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
3940 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
3936 ui.status(_('pulling from %s\n') % util.hidepassword(source))
3941 ui.status(_('pulling from %s\n') % util.hidepassword(source))
3937 other = hg.peer(repo, opts, source)
3942 other = hg.peer(repo, opts, source)
3938 try:
3943 try:
3939 revs, checkout = hg.addbranchrevs(repo, other, branches,
3944 revs, checkout = hg.addbranchrevs(repo, other, branches,
3940 opts.get('rev'))
3945 opts.get('rev'))
3941
3946
3942
3947
3943 pullopargs = {}
3948 pullopargs = {}
3944 if opts.get('bookmark'):
3949 if opts.get('bookmark'):
3945 if not revs:
3950 if not revs:
3946 revs = []
3951 revs = []
3947 # The list of bookmark used here is not the one used to actually
3952 # The list of bookmark used here is not the one used to actually
3948 # update the bookmark name. This can result in the revision pulled
3953 # update the bookmark name. This can result in the revision pulled
3949 # not ending up with the name of the bookmark because of a race
3954 # not ending up with the name of the bookmark because of a race
3950 # condition on the server. (See issue 4689 for details)
3955 # condition on the server. (See issue 4689 for details)
3951 remotebookmarks = other.listkeys('bookmarks')
3956 remotebookmarks = other.listkeys('bookmarks')
3952 pullopargs['remotebookmarks'] = remotebookmarks
3957 pullopargs['remotebookmarks'] = remotebookmarks
3953 for b in opts['bookmark']:
3958 for b in opts['bookmark']:
3954 b = repo._bookmarks.expandname(b)
3959 b = repo._bookmarks.expandname(b)
3955 if b not in remotebookmarks:
3960 if b not in remotebookmarks:
3956 raise error.Abort(_('remote bookmark %s not found!') % b)
3961 raise error.Abort(_('remote bookmark %s not found!') % b)
3957 revs.append(remotebookmarks[b])
3962 revs.append(remotebookmarks[b])
3958
3963
3959 if revs:
3964 if revs:
3960 try:
3965 try:
3961 # When 'rev' is a bookmark name, we cannot guarantee that it
3966 # When 'rev' is a bookmark name, we cannot guarantee that it
3962 # will be updated with that name because of a race condition
3967 # will be updated with that name because of a race condition
3963 # server side. (See issue 4689 for details)
3968 # server side. (See issue 4689 for details)
3964 oldrevs = revs
3969 oldrevs = revs
3965 revs = [] # actually, nodes
3970 revs = [] # actually, nodes
3966 for r in oldrevs:
3971 for r in oldrevs:
3967 node = other.lookup(r)
3972 node = other.lookup(r)
3968 revs.append(node)
3973 revs.append(node)
3969 if r == checkout:
3974 if r == checkout:
3970 checkout = node
3975 checkout = node
3971 except error.CapabilityError:
3976 except error.CapabilityError:
3972 err = _("other repository doesn't support revision lookup, "
3977 err = _("other repository doesn't support revision lookup, "
3973 "so a rev cannot be specified.")
3978 "so a rev cannot be specified.")
3974 raise error.Abort(err)
3979 raise error.Abort(err)
3975
3980
3976 pullopargs.update(opts.get('opargs', {}))
3981 pullopargs.update(opts.get('opargs', {}))
3977 modheads = exchange.pull(repo, other, heads=revs,
3982 modheads = exchange.pull(repo, other, heads=revs,
3978 force=opts.get('force'),
3983 force=opts.get('force'),
3979 bookmarks=opts.get('bookmark', ()),
3984 bookmarks=opts.get('bookmark', ()),
3980 opargs=pullopargs).cgresult
3985 opargs=pullopargs).cgresult
3981
3986
3982 # brev is a name, which might be a bookmark to be activated at
3987 # brev is a name, which might be a bookmark to be activated at
3983 # the end of the update. In other words, it is an explicit
3988 # the end of the update. In other words, it is an explicit
3984 # destination of the update
3989 # destination of the update
3985 brev = None
3990 brev = None
3986
3991
3987 if checkout:
3992 if checkout:
3988 checkout = str(repo.changelog.rev(checkout))
3993 checkout = str(repo.changelog.rev(checkout))
3989
3994
3990 # order below depends on implementation of
3995 # order below depends on implementation of
3991 # hg.addbranchrevs(). opts['bookmark'] is ignored,
3996 # hg.addbranchrevs(). opts['bookmark'] is ignored,
3992 # because 'checkout' is determined without it.
3997 # because 'checkout' is determined without it.
3993 if opts.get('rev'):
3998 if opts.get('rev'):
3994 brev = opts['rev'][0]
3999 brev = opts['rev'][0]
3995 elif opts.get('branch'):
4000 elif opts.get('branch'):
3996 brev = opts['branch'][0]
4001 brev = opts['branch'][0]
3997 else:
4002 else:
3998 brev = branches[0]
4003 brev = branches[0]
3999 repo._subtoppath = source
4004 repo._subtoppath = source
4000 try:
4005 try:
4001 ret = postincoming(ui, repo, modheads, opts.get('update'),
4006 ret = postincoming(ui, repo, modheads, opts.get('update'),
4002 checkout, brev)
4007 checkout, brev)
4003
4008
4004 finally:
4009 finally:
4005 del repo._subtoppath
4010 del repo._subtoppath
4006
4011
4007 finally:
4012 finally:
4008 other.close()
4013 other.close()
4009 return ret
4014 return ret
4010
4015
4011 @command('^push',
4016 @command('^push',
4012 [('f', 'force', None, _('force push')),
4017 [('f', 'force', None, _('force push')),
4013 ('r', 'rev', [],
4018 ('r', 'rev', [],
4014 _('a changeset intended to be included in the destination'),
4019 _('a changeset intended to be included in the destination'),
4015 _('REV')),
4020 _('REV')),
4016 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4021 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4017 ('b', 'branch', [],
4022 ('b', 'branch', [],
4018 _('a specific branch you would like to push'), _('BRANCH')),
4023 _('a specific branch you would like to push'), _('BRANCH')),
4019 ('', 'new-branch', False, _('allow pushing a new branch')),
4024 ('', 'new-branch', False, _('allow pushing a new branch')),
4020 ] + remoteopts,
4025 ] + remoteopts,
4021 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4026 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4022 def push(ui, repo, dest=None, **opts):
4027 def push(ui, repo, dest=None, **opts):
4023 """push changes to the specified destination
4028 """push changes to the specified destination
4024
4029
4025 Push changesets from the local repository to the specified
4030 Push changesets from the local repository to the specified
4026 destination.
4031 destination.
4027
4032
4028 This operation is symmetrical to pull: it is identical to a pull
4033 This operation is symmetrical to pull: it is identical to a pull
4029 in the destination repository from the current one.
4034 in the destination repository from the current one.
4030
4035
4031 By default, push will not allow creation of new heads at the
4036 By default, push will not allow creation of new heads at the
4032 destination, since multiple heads would make it unclear which head
4037 destination, since multiple heads would make it unclear which head
4033 to use. In this situation, it is recommended to pull and merge
4038 to use. In this situation, it is recommended to pull and merge
4034 before pushing.
4039 before pushing.
4035
4040
4036 Use --new-branch if you want to allow push to create a new named
4041 Use --new-branch if you want to allow push to create a new named
4037 branch that is not present at the destination. This allows you to
4042 branch that is not present at the destination. This allows you to
4038 only create a new branch without forcing other changes.
4043 only create a new branch without forcing other changes.
4039
4044
4040 .. note::
4045 .. note::
4041
4046
4042 Extra care should be taken with the -f/--force option,
4047 Extra care should be taken with the -f/--force option,
4043 which will push all new heads on all branches, an action which will
4048 which will push all new heads on all branches, an action which will
4044 almost always cause confusion for collaborators.
4049 almost always cause confusion for collaborators.
4045
4050
4046 If -r/--rev is used, the specified revision and all its ancestors
4051 If -r/--rev is used, the specified revision and all its ancestors
4047 will be pushed to the remote repository.
4052 will be pushed to the remote repository.
4048
4053
4049 If -B/--bookmark is used, the specified bookmarked revision, its
4054 If -B/--bookmark is used, the specified bookmarked revision, its
4050 ancestors, and the bookmark will be pushed to the remote
4055 ancestors, and the bookmark will be pushed to the remote
4051 repository. Specifying ``.`` is equivalent to specifying the active
4056 repository. Specifying ``.`` is equivalent to specifying the active
4052 bookmark's name.
4057 bookmark's name.
4053
4058
4054 Please see :hg:`help urls` for important details about ``ssh://``
4059 Please see :hg:`help urls` for important details about ``ssh://``
4055 URLs. If DESTINATION is omitted, a default path will be used.
4060 URLs. If DESTINATION is omitted, a default path will be used.
4056
4061
4057 Returns 0 if push was successful, 1 if nothing to push.
4062 Returns 0 if push was successful, 1 if nothing to push.
4058 """
4063 """
4059
4064
4060 opts = pycompat.byteskwargs(opts)
4065 opts = pycompat.byteskwargs(opts)
4061 if opts.get('bookmark'):
4066 if opts.get('bookmark'):
4062 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
4067 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
4063 for b in opts['bookmark']:
4068 for b in opts['bookmark']:
4064 # translate -B options to -r so changesets get pushed
4069 # translate -B options to -r so changesets get pushed
4065 b = repo._bookmarks.expandname(b)
4070 b = repo._bookmarks.expandname(b)
4066 if b in repo._bookmarks:
4071 if b in repo._bookmarks:
4067 opts.setdefault('rev', []).append(b)
4072 opts.setdefault('rev', []).append(b)
4068 else:
4073 else:
4069 # if we try to push a deleted bookmark, translate it to null
4074 # if we try to push a deleted bookmark, translate it to null
4070 # this lets simultaneous -r, -b options continue working
4075 # this lets simultaneous -r, -b options continue working
4071 opts.setdefault('rev', []).append("null")
4076 opts.setdefault('rev', []).append("null")
4072
4077
4073 path = ui.paths.getpath(dest, default=('default-push', 'default'))
4078 path = ui.paths.getpath(dest, default=('default-push', 'default'))
4074 if not path:
4079 if not path:
4075 raise error.Abort(_('default repository not configured!'),
4080 raise error.Abort(_('default repository not configured!'),
4076 hint=_("see 'hg help config.paths'"))
4081 hint=_("see 'hg help config.paths'"))
4077 dest = path.pushloc or path.loc
4082 dest = path.pushloc or path.loc
4078 branches = (path.branch, opts.get('branch') or [])
4083 branches = (path.branch, opts.get('branch') or [])
4079 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4084 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4080 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4085 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4081 other = hg.peer(repo, opts, dest)
4086 other = hg.peer(repo, opts, dest)
4082
4087
4083 if revs:
4088 if revs:
4084 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4089 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4085 if not revs:
4090 if not revs:
4086 raise error.Abort(_("specified revisions evaluate to an empty set"),
4091 raise error.Abort(_("specified revisions evaluate to an empty set"),
4087 hint=_("use different revision arguments"))
4092 hint=_("use different revision arguments"))
4088 elif path.pushrev:
4093 elif path.pushrev:
4089 # It doesn't make any sense to specify ancestor revisions. So limit
4094 # It doesn't make any sense to specify ancestor revisions. So limit
4090 # to DAG heads to make discovery simpler.
4095 # to DAG heads to make discovery simpler.
4091 expr = revsetlang.formatspec('heads(%r)', path.pushrev)
4096 expr = revsetlang.formatspec('heads(%r)', path.pushrev)
4092 revs = scmutil.revrange(repo, [expr])
4097 revs = scmutil.revrange(repo, [expr])
4093 revs = [repo[rev].node() for rev in revs]
4098 revs = [repo[rev].node() for rev in revs]
4094 if not revs:
4099 if not revs:
4095 raise error.Abort(_('default push revset for path evaluates to an '
4100 raise error.Abort(_('default push revset for path evaluates to an '
4096 'empty set'))
4101 'empty set'))
4097
4102
4098 repo._subtoppath = dest
4103 repo._subtoppath = dest
4099 try:
4104 try:
4100 # push subrepos depth-first for coherent ordering
4105 # push subrepos depth-first for coherent ordering
4101 c = repo['']
4106 c = repo['']
4102 subs = c.substate # only repos that are committed
4107 subs = c.substate # only repos that are committed
4103 for s in sorted(subs):
4108 for s in sorted(subs):
4104 result = c.sub(s).push(opts)
4109 result = c.sub(s).push(opts)
4105 if result == 0:
4110 if result == 0:
4106 return not result
4111 return not result
4107 finally:
4112 finally:
4108 del repo._subtoppath
4113 del repo._subtoppath
4109 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
4114 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
4110 newbranch=opts.get('new_branch'),
4115 newbranch=opts.get('new_branch'),
4111 bookmarks=opts.get('bookmark', ()),
4116 bookmarks=opts.get('bookmark', ()),
4112 opargs=opts.get('opargs'))
4117 opargs=opts.get('opargs'))
4113
4118
4114 result = not pushop.cgresult
4119 result = not pushop.cgresult
4115
4120
4116 if pushop.bkresult is not None:
4121 if pushop.bkresult is not None:
4117 if pushop.bkresult == 2:
4122 if pushop.bkresult == 2:
4118 result = 2
4123 result = 2
4119 elif not result and pushop.bkresult:
4124 elif not result and pushop.bkresult:
4120 result = 2
4125 result = 2
4121
4126
4122 return result
4127 return result
4123
4128
4124 @command('recover', [])
4129 @command('recover', [])
4125 def recover(ui, repo):
4130 def recover(ui, repo):
4126 """roll back an interrupted transaction
4131 """roll back an interrupted transaction
4127
4132
4128 Recover from an interrupted commit or pull.
4133 Recover from an interrupted commit or pull.
4129
4134
4130 This command tries to fix the repository status after an
4135 This command tries to fix the repository status after an
4131 interrupted operation. It should only be necessary when Mercurial
4136 interrupted operation. It should only be necessary when Mercurial
4132 suggests it.
4137 suggests it.
4133
4138
4134 Returns 0 if successful, 1 if nothing to recover or verify fails.
4139 Returns 0 if successful, 1 if nothing to recover or verify fails.
4135 """
4140 """
4136 if repo.recover():
4141 if repo.recover():
4137 return hg.verify(repo)
4142 return hg.verify(repo)
4138 return 1
4143 return 1
4139
4144
4140 @command('^remove|rm',
4145 @command('^remove|rm',
4141 [('A', 'after', None, _('record delete for missing files')),
4146 [('A', 'after', None, _('record delete for missing files')),
4142 ('f', 'force', None,
4147 ('f', 'force', None,
4143 _('forget added files, delete modified files')),
4148 _('forget added files, delete modified files')),
4144 ] + subrepoopts + walkopts,
4149 ] + subrepoopts + walkopts,
4145 _('[OPTION]... FILE...'),
4150 _('[OPTION]... FILE...'),
4146 inferrepo=True)
4151 inferrepo=True)
4147 def remove(ui, repo, *pats, **opts):
4152 def remove(ui, repo, *pats, **opts):
4148 """remove the specified files on the next commit
4153 """remove the specified files on the next commit
4149
4154
4150 Schedule the indicated files for removal from the current branch.
4155 Schedule the indicated files for removal from the current branch.
4151
4156
4152 This command schedules the files to be removed at the next commit.
4157 This command schedules the files to be removed at the next commit.
4153 To undo a remove before that, see :hg:`revert`. To undo added
4158 To undo a remove before that, see :hg:`revert`. To undo added
4154 files, see :hg:`forget`.
4159 files, see :hg:`forget`.
4155
4160
4156 .. container:: verbose
4161 .. container:: verbose
4157
4162
4158 -A/--after can be used to remove only files that have already
4163 -A/--after can be used to remove only files that have already
4159 been deleted, -f/--force can be used to force deletion, and -Af
4164 been deleted, -f/--force can be used to force deletion, and -Af
4160 can be used to remove files from the next revision without
4165 can be used to remove files from the next revision without
4161 deleting them from the working directory.
4166 deleting them from the working directory.
4162
4167
4163 The following table details the behavior of remove for different
4168 The following table details the behavior of remove for different
4164 file states (columns) and option combinations (rows). The file
4169 file states (columns) and option combinations (rows). The file
4165 states are Added [A], Clean [C], Modified [M] and Missing [!]
4170 states are Added [A], Clean [C], Modified [M] and Missing [!]
4166 (as reported by :hg:`status`). The actions are Warn, Remove
4171 (as reported by :hg:`status`). The actions are Warn, Remove
4167 (from branch) and Delete (from disk):
4172 (from branch) and Delete (from disk):
4168
4173
4169 ========= == == == ==
4174 ========= == == == ==
4170 opt/state A C M !
4175 opt/state A C M !
4171 ========= == == == ==
4176 ========= == == == ==
4172 none W RD W R
4177 none W RD W R
4173 -f R RD RD R
4178 -f R RD RD R
4174 -A W W W R
4179 -A W W W R
4175 -Af R R R R
4180 -Af R R R R
4176 ========= == == == ==
4181 ========= == == == ==
4177
4182
4178 .. note::
4183 .. note::
4179
4184
4180 :hg:`remove` never deletes files in Added [A] state from the
4185 :hg:`remove` never deletes files in Added [A] state from the
4181 working directory, not even if ``--force`` is specified.
4186 working directory, not even if ``--force`` is specified.
4182
4187
4183 Returns 0 on success, 1 if any warnings encountered.
4188 Returns 0 on success, 1 if any warnings encountered.
4184 """
4189 """
4185
4190
4186 opts = pycompat.byteskwargs(opts)
4191 opts = pycompat.byteskwargs(opts)
4187 after, force = opts.get('after'), opts.get('force')
4192 after, force = opts.get('after'), opts.get('force')
4188 if not pats and not after:
4193 if not pats and not after:
4189 raise error.Abort(_('no files specified'))
4194 raise error.Abort(_('no files specified'))
4190
4195
4191 m = scmutil.match(repo[None], pats, opts)
4196 m = scmutil.match(repo[None], pats, opts)
4192 subrepos = opts.get('subrepos')
4197 subrepos = opts.get('subrepos')
4193 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
4198 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
4194
4199
4195 @command('rename|move|mv',
4200 @command('rename|move|mv',
4196 [('A', 'after', None, _('record a rename that has already occurred')),
4201 [('A', 'after', None, _('record a rename that has already occurred')),
4197 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4202 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4198 ] + walkopts + dryrunopts,
4203 ] + walkopts + dryrunopts,
4199 _('[OPTION]... SOURCE... DEST'))
4204 _('[OPTION]... SOURCE... DEST'))
4200 def rename(ui, repo, *pats, **opts):
4205 def rename(ui, repo, *pats, **opts):
4201 """rename files; equivalent of copy + remove
4206 """rename files; equivalent of copy + remove
4202
4207
4203 Mark dest as copies of sources; mark sources for deletion. If dest
4208 Mark dest as copies of sources; mark sources for deletion. If dest
4204 is a directory, copies are put in that directory. If dest is a
4209 is a directory, copies are put in that directory. If dest is a
4205 file, there can only be one source.
4210 file, there can only be one source.
4206
4211
4207 By default, this command copies the contents of files as they
4212 By default, this command copies the contents of files as they
4208 exist in the working directory. If invoked with -A/--after, the
4213 exist in the working directory. If invoked with -A/--after, the
4209 operation is recorded, but no copying is performed.
4214 operation is recorded, but no copying is performed.
4210
4215
4211 This command takes effect at the next commit. To undo a rename
4216 This command takes effect at the next commit. To undo a rename
4212 before that, see :hg:`revert`.
4217 before that, see :hg:`revert`.
4213
4218
4214 Returns 0 on success, 1 if errors are encountered.
4219 Returns 0 on success, 1 if errors are encountered.
4215 """
4220 """
4216 opts = pycompat.byteskwargs(opts)
4221 opts = pycompat.byteskwargs(opts)
4217 with repo.wlock(False):
4222 with repo.wlock(False):
4218 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4223 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4219
4224
4220 @command('resolve',
4225 @command('resolve',
4221 [('a', 'all', None, _('select all unresolved files')),
4226 [('a', 'all', None, _('select all unresolved files')),
4222 ('l', 'list', None, _('list state of files needing merge')),
4227 ('l', 'list', None, _('list state of files needing merge')),
4223 ('m', 'mark', None, _('mark files as resolved')),
4228 ('m', 'mark', None, _('mark files as resolved')),
4224 ('u', 'unmark', None, _('mark files as unresolved')),
4229 ('u', 'unmark', None, _('mark files as unresolved')),
4225 ('n', 'no-status', None, _('hide status prefix'))]
4230 ('n', 'no-status', None, _('hide status prefix'))]
4226 + mergetoolopts + walkopts + formatteropts,
4231 + mergetoolopts + walkopts + formatteropts,
4227 _('[OPTION]... [FILE]...'),
4232 _('[OPTION]... [FILE]...'),
4228 inferrepo=True)
4233 inferrepo=True)
4229 def resolve(ui, repo, *pats, **opts):
4234 def resolve(ui, repo, *pats, **opts):
4230 """redo merges or set/view the merge status of files
4235 """redo merges or set/view the merge status of files
4231
4236
4232 Merges with unresolved conflicts are often the result of
4237 Merges with unresolved conflicts are often the result of
4233 non-interactive merging using the ``internal:merge`` configuration
4238 non-interactive merging using the ``internal:merge`` configuration
4234 setting, or a command-line merge tool like ``diff3``. The resolve
4239 setting, or a command-line merge tool like ``diff3``. The resolve
4235 command is used to manage the files involved in a merge, after
4240 command is used to manage the files involved in a merge, after
4236 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4241 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4237 working directory must have two parents). See :hg:`help
4242 working directory must have two parents). See :hg:`help
4238 merge-tools` for information on configuring merge tools.
4243 merge-tools` for information on configuring merge tools.
4239
4244
4240 The resolve command can be used in the following ways:
4245 The resolve command can be used in the following ways:
4241
4246
4242 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4247 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4243 files, discarding any previous merge attempts. Re-merging is not
4248 files, discarding any previous merge attempts. Re-merging is not
4244 performed for files already marked as resolved. Use ``--all/-a``
4249 performed for files already marked as resolved. Use ``--all/-a``
4245 to select all unresolved files. ``--tool`` can be used to specify
4250 to select all unresolved files. ``--tool`` can be used to specify
4246 the merge tool used for the given files. It overrides the HGMERGE
4251 the merge tool used for the given files. It overrides the HGMERGE
4247 environment variable and your configuration files. Previous file
4252 environment variable and your configuration files. Previous file
4248 contents are saved with a ``.orig`` suffix.
4253 contents are saved with a ``.orig`` suffix.
4249
4254
4250 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4255 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4251 (e.g. after having manually fixed-up the files). The default is
4256 (e.g. after having manually fixed-up the files). The default is
4252 to mark all unresolved files.
4257 to mark all unresolved files.
4253
4258
4254 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4259 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4255 default is to mark all resolved files.
4260 default is to mark all resolved files.
4256
4261
4257 - :hg:`resolve -l`: list files which had or still have conflicts.
4262 - :hg:`resolve -l`: list files which had or still have conflicts.
4258 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4263 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4259 You can use ``set:unresolved()`` or ``set:resolved()`` to filter
4264 You can use ``set:unresolved()`` or ``set:resolved()`` to filter
4260 the list. See :hg:`help filesets` for details.
4265 the list. See :hg:`help filesets` for details.
4261
4266
4262 .. note::
4267 .. note::
4263
4268
4264 Mercurial will not let you commit files with unresolved merge
4269 Mercurial will not let you commit files with unresolved merge
4265 conflicts. You must use :hg:`resolve -m ...` before you can
4270 conflicts. You must use :hg:`resolve -m ...` before you can
4266 commit after a conflicting merge.
4271 commit after a conflicting merge.
4267
4272
4268 Returns 0 on success, 1 if any files fail a resolve attempt.
4273 Returns 0 on success, 1 if any files fail a resolve attempt.
4269 """
4274 """
4270
4275
4271 opts = pycompat.byteskwargs(opts)
4276 opts = pycompat.byteskwargs(opts)
4272 flaglist = 'all mark unmark list no_status'.split()
4277 flaglist = 'all mark unmark list no_status'.split()
4273 all, mark, unmark, show, nostatus = \
4278 all, mark, unmark, show, nostatus = \
4274 [opts.get(o) for o in flaglist]
4279 [opts.get(o) for o in flaglist]
4275
4280
4276 if (show and (mark or unmark)) or (mark and unmark):
4281 if (show and (mark or unmark)) or (mark and unmark):
4277 raise error.Abort(_("too many options specified"))
4282 raise error.Abort(_("too many options specified"))
4278 if pats and all:
4283 if pats and all:
4279 raise error.Abort(_("can't specify --all and patterns"))
4284 raise error.Abort(_("can't specify --all and patterns"))
4280 if not (all or pats or show or mark or unmark):
4285 if not (all or pats or show or mark or unmark):
4281 raise error.Abort(_('no files or directories specified'),
4286 raise error.Abort(_('no files or directories specified'),
4282 hint=('use --all to re-merge all unresolved files'))
4287 hint=('use --all to re-merge all unresolved files'))
4283
4288
4284 if show:
4289 if show:
4285 ui.pager('resolve')
4290 ui.pager('resolve')
4286 fm = ui.formatter('resolve', opts)
4291 fm = ui.formatter('resolve', opts)
4287 ms = mergemod.mergestate.read(repo)
4292 ms = mergemod.mergestate.read(repo)
4288 m = scmutil.match(repo[None], pats, opts)
4293 m = scmutil.match(repo[None], pats, opts)
4289 for f in ms:
4294 for f in ms:
4290 if not m(f):
4295 if not m(f):
4291 continue
4296 continue
4292 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
4297 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
4293 'd': 'driverresolved'}[ms[f]]
4298 'd': 'driverresolved'}[ms[f]]
4294 fm.startitem()
4299 fm.startitem()
4295 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
4300 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
4296 fm.write('path', '%s\n', f, label=l)
4301 fm.write('path', '%s\n', f, label=l)
4297 fm.end()
4302 fm.end()
4298 return 0
4303 return 0
4299
4304
4300 with repo.wlock():
4305 with repo.wlock():
4301 ms = mergemod.mergestate.read(repo)
4306 ms = mergemod.mergestate.read(repo)
4302
4307
4303 if not (ms.active() or repo.dirstate.p2() != nullid):
4308 if not (ms.active() or repo.dirstate.p2() != nullid):
4304 raise error.Abort(
4309 raise error.Abort(
4305 _('resolve command not applicable when not merging'))
4310 _('resolve command not applicable when not merging'))
4306
4311
4307 wctx = repo[None]
4312 wctx = repo[None]
4308
4313
4309 if ms.mergedriver and ms.mdstate() == 'u':
4314 if ms.mergedriver and ms.mdstate() == 'u':
4310 proceed = mergemod.driverpreprocess(repo, ms, wctx)
4315 proceed = mergemod.driverpreprocess(repo, ms, wctx)
4311 ms.commit()
4316 ms.commit()
4312 # allow mark and unmark to go through
4317 # allow mark and unmark to go through
4313 if not mark and not unmark and not proceed:
4318 if not mark and not unmark and not proceed:
4314 return 1
4319 return 1
4315
4320
4316 m = scmutil.match(wctx, pats, opts)
4321 m = scmutil.match(wctx, pats, opts)
4317 ret = 0
4322 ret = 0
4318 didwork = False
4323 didwork = False
4319 runconclude = False
4324 runconclude = False
4320
4325
4321 tocomplete = []
4326 tocomplete = []
4322 for f in ms:
4327 for f in ms:
4323 if not m(f):
4328 if not m(f):
4324 continue
4329 continue
4325
4330
4326 didwork = True
4331 didwork = True
4327
4332
4328 # don't let driver-resolved files be marked, and run the conclude
4333 # don't let driver-resolved files be marked, and run the conclude
4329 # step if asked to resolve
4334 # step if asked to resolve
4330 if ms[f] == "d":
4335 if ms[f] == "d":
4331 exact = m.exact(f)
4336 exact = m.exact(f)
4332 if mark:
4337 if mark:
4333 if exact:
4338 if exact:
4334 ui.warn(_('not marking %s as it is driver-resolved\n')
4339 ui.warn(_('not marking %s as it is driver-resolved\n')
4335 % f)
4340 % f)
4336 elif unmark:
4341 elif unmark:
4337 if exact:
4342 if exact:
4338 ui.warn(_('not unmarking %s as it is driver-resolved\n')
4343 ui.warn(_('not unmarking %s as it is driver-resolved\n')
4339 % f)
4344 % f)
4340 else:
4345 else:
4341 runconclude = True
4346 runconclude = True
4342 continue
4347 continue
4343
4348
4344 if mark:
4349 if mark:
4345 ms.mark(f, "r")
4350 ms.mark(f, "r")
4346 elif unmark:
4351 elif unmark:
4347 ms.mark(f, "u")
4352 ms.mark(f, "u")
4348 else:
4353 else:
4349 # backup pre-resolve (merge uses .orig for its own purposes)
4354 # backup pre-resolve (merge uses .orig for its own purposes)
4350 a = repo.wjoin(f)
4355 a = repo.wjoin(f)
4351 try:
4356 try:
4352 util.copyfile(a, a + ".resolve")
4357 util.copyfile(a, a + ".resolve")
4353 except (IOError, OSError) as inst:
4358 except (IOError, OSError) as inst:
4354 if inst.errno != errno.ENOENT:
4359 if inst.errno != errno.ENOENT:
4355 raise
4360 raise
4356
4361
4357 try:
4362 try:
4358 # preresolve file
4363 # preresolve file
4359 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4364 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4360 'resolve')
4365 'resolve')
4361 complete, r = ms.preresolve(f, wctx)
4366 complete, r = ms.preresolve(f, wctx)
4362 if not complete:
4367 if not complete:
4363 tocomplete.append(f)
4368 tocomplete.append(f)
4364 elif r:
4369 elif r:
4365 ret = 1
4370 ret = 1
4366 finally:
4371 finally:
4367 ui.setconfig('ui', 'forcemerge', '', 'resolve')
4372 ui.setconfig('ui', 'forcemerge', '', 'resolve')
4368 ms.commit()
4373 ms.commit()
4369
4374
4370 # replace filemerge's .orig file with our resolve file, but only
4375 # replace filemerge's .orig file with our resolve file, but only
4371 # for merges that are complete
4376 # for merges that are complete
4372 if complete:
4377 if complete:
4373 try:
4378 try:
4374 util.rename(a + ".resolve",
4379 util.rename(a + ".resolve",
4375 scmutil.origpath(ui, repo, a))
4380 scmutil.origpath(ui, repo, a))
4376 except OSError as inst:
4381 except OSError as inst:
4377 if inst.errno != errno.ENOENT:
4382 if inst.errno != errno.ENOENT:
4378 raise
4383 raise
4379
4384
4380 for f in tocomplete:
4385 for f in tocomplete:
4381 try:
4386 try:
4382 # resolve file
4387 # resolve file
4383 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4388 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4384 'resolve')
4389 'resolve')
4385 r = ms.resolve(f, wctx)
4390 r = ms.resolve(f, wctx)
4386 if r:
4391 if r:
4387 ret = 1
4392 ret = 1
4388 finally:
4393 finally:
4389 ui.setconfig('ui', 'forcemerge', '', 'resolve')
4394 ui.setconfig('ui', 'forcemerge', '', 'resolve')
4390 ms.commit()
4395 ms.commit()
4391
4396
4392 # replace filemerge's .orig file with our resolve file
4397 # replace filemerge's .orig file with our resolve file
4393 a = repo.wjoin(f)
4398 a = repo.wjoin(f)
4394 try:
4399 try:
4395 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
4400 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
4396 except OSError as inst:
4401 except OSError as inst:
4397 if inst.errno != errno.ENOENT:
4402 if inst.errno != errno.ENOENT:
4398 raise
4403 raise
4399
4404
4400 ms.commit()
4405 ms.commit()
4401 ms.recordactions()
4406 ms.recordactions()
4402
4407
4403 if not didwork and pats:
4408 if not didwork and pats:
4404 hint = None
4409 hint = None
4405 if not any([p for p in pats if p.find(':') >= 0]):
4410 if not any([p for p in pats if p.find(':') >= 0]):
4406 pats = ['path:%s' % p for p in pats]
4411 pats = ['path:%s' % p for p in pats]
4407 m = scmutil.match(wctx, pats, opts)
4412 m = scmutil.match(wctx, pats, opts)
4408 for f in ms:
4413 for f in ms:
4409 if not m(f):
4414 if not m(f):
4410 continue
4415 continue
4411 flags = ''.join(['-%s ' % o[0] for o in flaglist
4416 flags = ''.join(['-%s ' % o[0] for o in flaglist
4412 if opts.get(o)])
4417 if opts.get(o)])
4413 hint = _("(try: hg resolve %s%s)\n") % (
4418 hint = _("(try: hg resolve %s%s)\n") % (
4414 flags,
4419 flags,
4415 ' '.join(pats))
4420 ' '.join(pats))
4416 break
4421 break
4417 ui.warn(_("arguments do not match paths that need resolving\n"))
4422 ui.warn(_("arguments do not match paths that need resolving\n"))
4418 if hint:
4423 if hint:
4419 ui.warn(hint)
4424 ui.warn(hint)
4420 elif ms.mergedriver and ms.mdstate() != 's':
4425 elif ms.mergedriver and ms.mdstate() != 's':
4421 # run conclude step when either a driver-resolved file is requested
4426 # run conclude step when either a driver-resolved file is requested
4422 # or there are no driver-resolved files
4427 # or there are no driver-resolved files
4423 # we can't use 'ret' to determine whether any files are unresolved
4428 # we can't use 'ret' to determine whether any files are unresolved
4424 # because we might not have tried to resolve some
4429 # because we might not have tried to resolve some
4425 if ((runconclude or not list(ms.driverresolved()))
4430 if ((runconclude or not list(ms.driverresolved()))
4426 and not list(ms.unresolved())):
4431 and not list(ms.unresolved())):
4427 proceed = mergemod.driverconclude(repo, ms, wctx)
4432 proceed = mergemod.driverconclude(repo, ms, wctx)
4428 ms.commit()
4433 ms.commit()
4429 if not proceed:
4434 if not proceed:
4430 return 1
4435 return 1
4431
4436
4432 # Nudge users into finishing an unfinished operation
4437 # Nudge users into finishing an unfinished operation
4433 unresolvedf = list(ms.unresolved())
4438 unresolvedf = list(ms.unresolved())
4434 driverresolvedf = list(ms.driverresolved())
4439 driverresolvedf = list(ms.driverresolved())
4435 if not unresolvedf and not driverresolvedf:
4440 if not unresolvedf and not driverresolvedf:
4436 ui.status(_('(no more unresolved files)\n'))
4441 ui.status(_('(no more unresolved files)\n'))
4437 cmdutil.checkafterresolved(repo)
4442 cmdutil.checkafterresolved(repo)
4438 elif not unresolvedf:
4443 elif not unresolvedf:
4439 ui.status(_('(no more unresolved files -- '
4444 ui.status(_('(no more unresolved files -- '
4440 'run "hg resolve --all" to conclude)\n'))
4445 'run "hg resolve --all" to conclude)\n'))
4441
4446
4442 return ret
4447 return ret
4443
4448
4444 @command('revert',
4449 @command('revert',
4445 [('a', 'all', None, _('revert all changes when no arguments given')),
4450 [('a', 'all', None, _('revert all changes when no arguments given')),
4446 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4451 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4447 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4452 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4448 ('C', 'no-backup', None, _('do not save backup copies of files')),
4453 ('C', 'no-backup', None, _('do not save backup copies of files')),
4449 ('i', 'interactive', None,
4454 ('i', 'interactive', None,
4450 _('interactively select the changes (EXPERIMENTAL)')),
4455 _('interactively select the changes (EXPERIMENTAL)')),
4451 ] + walkopts + dryrunopts,
4456 ] + walkopts + dryrunopts,
4452 _('[OPTION]... [-r REV] [NAME]...'))
4457 _('[OPTION]... [-r REV] [NAME]...'))
4453 def revert(ui, repo, *pats, **opts):
4458 def revert(ui, repo, *pats, **opts):
4454 """restore files to their checkout state
4459 """restore files to their checkout state
4455
4460
4456 .. note::
4461 .. note::
4457
4462
4458 To check out earlier revisions, you should use :hg:`update REV`.
4463 To check out earlier revisions, you should use :hg:`update REV`.
4459 To cancel an uncommitted merge (and lose your changes),
4464 To cancel an uncommitted merge (and lose your changes),
4460 use :hg:`update --clean .`.
4465 use :hg:`update --clean .`.
4461
4466
4462 With no revision specified, revert the specified files or directories
4467 With no revision specified, revert the specified files or directories
4463 to the contents they had in the parent of the working directory.
4468 to the contents they had in the parent of the working directory.
4464 This restores the contents of files to an unmodified
4469 This restores the contents of files to an unmodified
4465 state and unschedules adds, removes, copies, and renames. If the
4470 state and unschedules adds, removes, copies, and renames. If the
4466 working directory has two parents, you must explicitly specify a
4471 working directory has two parents, you must explicitly specify a
4467 revision.
4472 revision.
4468
4473
4469 Using the -r/--rev or -d/--date options, revert the given files or
4474 Using the -r/--rev or -d/--date options, revert the given files or
4470 directories to their states as of a specific revision. Because
4475 directories to their states as of a specific revision. Because
4471 revert does not change the working directory parents, this will
4476 revert does not change the working directory parents, this will
4472 cause these files to appear modified. This can be helpful to "back
4477 cause these files to appear modified. This can be helpful to "back
4473 out" some or all of an earlier change. See :hg:`backout` for a
4478 out" some or all of an earlier change. See :hg:`backout` for a
4474 related method.
4479 related method.
4475
4480
4476 Modified files are saved with a .orig suffix before reverting.
4481 Modified files are saved with a .orig suffix before reverting.
4477 To disable these backups, use --no-backup. It is possible to store
4482 To disable these backups, use --no-backup. It is possible to store
4478 the backup files in a custom directory relative to the root of the
4483 the backup files in a custom directory relative to the root of the
4479 repository by setting the ``ui.origbackuppath`` configuration
4484 repository by setting the ``ui.origbackuppath`` configuration
4480 option.
4485 option.
4481
4486
4482 See :hg:`help dates` for a list of formats valid for -d/--date.
4487 See :hg:`help dates` for a list of formats valid for -d/--date.
4483
4488
4484 See :hg:`help backout` for a way to reverse the effect of an
4489 See :hg:`help backout` for a way to reverse the effect of an
4485 earlier changeset.
4490 earlier changeset.
4486
4491
4487 Returns 0 on success.
4492 Returns 0 on success.
4488 """
4493 """
4489
4494
4490 if opts.get("date"):
4495 if opts.get("date"):
4491 if opts.get("rev"):
4496 if opts.get("rev"):
4492 raise error.Abort(_("you can't specify a revision and a date"))
4497 raise error.Abort(_("you can't specify a revision and a date"))
4493 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4498 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4494
4499
4495 parent, p2 = repo.dirstate.parents()
4500 parent, p2 = repo.dirstate.parents()
4496 if not opts.get('rev') and p2 != nullid:
4501 if not opts.get('rev') and p2 != nullid:
4497 # revert after merge is a trap for new users (issue2915)
4502 # revert after merge is a trap for new users (issue2915)
4498 raise error.Abort(_('uncommitted merge with no revision specified'),
4503 raise error.Abort(_('uncommitted merge with no revision specified'),
4499 hint=_("use 'hg update' or see 'hg help revert'"))
4504 hint=_("use 'hg update' or see 'hg help revert'"))
4500
4505
4501 ctx = scmutil.revsingle(repo, opts.get('rev'))
4506 ctx = scmutil.revsingle(repo, opts.get('rev'))
4502
4507
4503 if (not (pats or opts.get('include') or opts.get('exclude') or
4508 if (not (pats or opts.get('include') or opts.get('exclude') or
4504 opts.get('all') or opts.get('interactive'))):
4509 opts.get('all') or opts.get('interactive'))):
4505 msg = _("no files or directories specified")
4510 msg = _("no files or directories specified")
4506 if p2 != nullid:
4511 if p2 != nullid:
4507 hint = _("uncommitted merge, use --all to discard all changes,"
4512 hint = _("uncommitted merge, use --all to discard all changes,"
4508 " or 'hg update -C .' to abort the merge")
4513 " or 'hg update -C .' to abort the merge")
4509 raise error.Abort(msg, hint=hint)
4514 raise error.Abort(msg, hint=hint)
4510 dirty = any(repo.status())
4515 dirty = any(repo.status())
4511 node = ctx.node()
4516 node = ctx.node()
4512 if node != parent:
4517 if node != parent:
4513 if dirty:
4518 if dirty:
4514 hint = _("uncommitted changes, use --all to discard all"
4519 hint = _("uncommitted changes, use --all to discard all"
4515 " changes, or 'hg update %s' to update") % ctx.rev()
4520 " changes, or 'hg update %s' to update") % ctx.rev()
4516 else:
4521 else:
4517 hint = _("use --all to revert all files,"
4522 hint = _("use --all to revert all files,"
4518 " or 'hg update %s' to update") % ctx.rev()
4523 " or 'hg update %s' to update") % ctx.rev()
4519 elif dirty:
4524 elif dirty:
4520 hint = _("uncommitted changes, use --all to discard all changes")
4525 hint = _("uncommitted changes, use --all to discard all changes")
4521 else:
4526 else:
4522 hint = _("use --all to revert all files")
4527 hint = _("use --all to revert all files")
4523 raise error.Abort(msg, hint=hint)
4528 raise error.Abort(msg, hint=hint)
4524
4529
4525 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
4530 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
4526
4531
4527 @command('rollback', dryrunopts +
4532 @command('rollback', dryrunopts +
4528 [('f', 'force', False, _('ignore safety measures'))])
4533 [('f', 'force', False, _('ignore safety measures'))])
4529 def rollback(ui, repo, **opts):
4534 def rollback(ui, repo, **opts):
4530 """roll back the last transaction (DANGEROUS) (DEPRECATED)
4535 """roll back the last transaction (DANGEROUS) (DEPRECATED)
4531
4536
4532 Please use :hg:`commit --amend` instead of rollback to correct
4537 Please use :hg:`commit --amend` instead of rollback to correct
4533 mistakes in the last commit.
4538 mistakes in the last commit.
4534
4539
4535 This command should be used with care. There is only one level of
4540 This command should be used with care. There is only one level of
4536 rollback, and there is no way to undo a rollback. It will also
4541 rollback, and there is no way to undo a rollback. It will also
4537 restore the dirstate at the time of the last transaction, losing
4542 restore the dirstate at the time of the last transaction, losing
4538 any dirstate changes since that time. This command does not alter
4543 any dirstate changes since that time. This command does not alter
4539 the working directory.
4544 the working directory.
4540
4545
4541 Transactions are used to encapsulate the effects of all commands
4546 Transactions are used to encapsulate the effects of all commands
4542 that create new changesets or propagate existing changesets into a
4547 that create new changesets or propagate existing changesets into a
4543 repository.
4548 repository.
4544
4549
4545 .. container:: verbose
4550 .. container:: verbose
4546
4551
4547 For example, the following commands are transactional, and their
4552 For example, the following commands are transactional, and their
4548 effects can be rolled back:
4553 effects can be rolled back:
4549
4554
4550 - commit
4555 - commit
4551 - import
4556 - import
4552 - pull
4557 - pull
4553 - push (with this repository as the destination)
4558 - push (with this repository as the destination)
4554 - unbundle
4559 - unbundle
4555
4560
4556 To avoid permanent data loss, rollback will refuse to rollback a
4561 To avoid permanent data loss, rollback will refuse to rollback a
4557 commit transaction if it isn't checked out. Use --force to
4562 commit transaction if it isn't checked out. Use --force to
4558 override this protection.
4563 override this protection.
4559
4564
4560 The rollback command can be entirely disabled by setting the
4565 The rollback command can be entirely disabled by setting the
4561 ``ui.rollback`` configuration setting to false. If you're here
4566 ``ui.rollback`` configuration setting to false. If you're here
4562 because you want to use rollback and it's disabled, you can
4567 because you want to use rollback and it's disabled, you can
4563 re-enable the command by setting ``ui.rollback`` to true.
4568 re-enable the command by setting ``ui.rollback`` to true.
4564
4569
4565 This command is not intended for use on public repositories. Once
4570 This command is not intended for use on public repositories. Once
4566 changes are visible for pull by other users, rolling a transaction
4571 changes are visible for pull by other users, rolling a transaction
4567 back locally is ineffective (someone else may already have pulled
4572 back locally is ineffective (someone else may already have pulled
4568 the changes). Furthermore, a race is possible with readers of the
4573 the changes). Furthermore, a race is possible with readers of the
4569 repository; for example an in-progress pull from the repository
4574 repository; for example an in-progress pull from the repository
4570 may fail if a rollback is performed.
4575 may fail if a rollback is performed.
4571
4576
4572 Returns 0 on success, 1 if no rollback data is available.
4577 Returns 0 on success, 1 if no rollback data is available.
4573 """
4578 """
4574 if not ui.configbool('ui', 'rollback', True):
4579 if not ui.configbool('ui', 'rollback', True):
4575 raise error.Abort(_('rollback is disabled because it is unsafe'),
4580 raise error.Abort(_('rollback is disabled because it is unsafe'),
4576 hint=('see `hg help -v rollback` for information'))
4581 hint=('see `hg help -v rollback` for information'))
4577 return repo.rollback(dryrun=opts.get(r'dry_run'),
4582 return repo.rollback(dryrun=opts.get(r'dry_run'),
4578 force=opts.get(r'force'))
4583 force=opts.get(r'force'))
4579
4584
4580 @command('root', [])
4585 @command('root', [])
4581 def root(ui, repo):
4586 def root(ui, repo):
4582 """print the root (top) of the current working directory
4587 """print the root (top) of the current working directory
4583
4588
4584 Print the root directory of the current repository.
4589 Print the root directory of the current repository.
4585
4590
4586 Returns 0 on success.
4591 Returns 0 on success.
4587 """
4592 """
4588 ui.write(repo.root + "\n")
4593 ui.write(repo.root + "\n")
4589
4594
4590 @command('^serve',
4595 @command('^serve',
4591 [('A', 'accesslog', '', _('name of access log file to write to'),
4596 [('A', 'accesslog', '', _('name of access log file to write to'),
4592 _('FILE')),
4597 _('FILE')),
4593 ('d', 'daemon', None, _('run server in background')),
4598 ('d', 'daemon', None, _('run server in background')),
4594 ('', 'daemon-postexec', [], _('used internally by daemon mode')),
4599 ('', 'daemon-postexec', [], _('used internally by daemon mode')),
4595 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4600 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4596 # use string type, then we can check if something was passed
4601 # use string type, then we can check if something was passed
4597 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4602 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4598 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4603 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4599 _('ADDR')),
4604 _('ADDR')),
4600 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4605 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4601 _('PREFIX')),
4606 _('PREFIX')),
4602 ('n', 'name', '',
4607 ('n', 'name', '',
4603 _('name to show in web pages (default: working directory)'), _('NAME')),
4608 _('name to show in web pages (default: working directory)'), _('NAME')),
4604 ('', 'web-conf', '',
4609 ('', 'web-conf', '',
4605 _("name of the hgweb config file (see 'hg help hgweb')"), _('FILE')),
4610 _("name of the hgweb config file (see 'hg help hgweb')"), _('FILE')),
4606 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4611 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4607 _('FILE')),
4612 _('FILE')),
4608 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4613 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4609 ('', 'stdio', None, _('for remote clients (ADVANCED)')),
4614 ('', 'stdio', None, _('for remote clients (ADVANCED)')),
4610 ('', 'cmdserver', '', _('for remote clients (ADVANCED)'), _('MODE')),
4615 ('', 'cmdserver', '', _('for remote clients (ADVANCED)'), _('MODE')),
4611 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4616 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4612 ('', 'style', '', _('template style to use'), _('STYLE')),
4617 ('', 'style', '', _('template style to use'), _('STYLE')),
4613 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4618 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4614 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))]
4619 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))]
4615 + subrepoopts,
4620 + subrepoopts,
4616 _('[OPTION]...'),
4621 _('[OPTION]...'),
4617 optionalrepo=True)
4622 optionalrepo=True)
4618 def serve(ui, repo, **opts):
4623 def serve(ui, repo, **opts):
4619 """start stand-alone webserver
4624 """start stand-alone webserver
4620
4625
4621 Start a local HTTP repository browser and pull server. You can use
4626 Start a local HTTP repository browser and pull server. You can use
4622 this for ad-hoc sharing and browsing of repositories. It is
4627 this for ad-hoc sharing and browsing of repositories. It is
4623 recommended to use a real web server to serve a repository for
4628 recommended to use a real web server to serve a repository for
4624 longer periods of time.
4629 longer periods of time.
4625
4630
4626 Please note that the server does not implement access control.
4631 Please note that the server does not implement access control.
4627 This means that, by default, anybody can read from the server and
4632 This means that, by default, anybody can read from the server and
4628 nobody can write to it by default. Set the ``web.allow_push``
4633 nobody can write to it by default. Set the ``web.allow_push``
4629 option to ``*`` to allow everybody to push to the server. You
4634 option to ``*`` to allow everybody to push to the server. You
4630 should use a real web server if you need to authenticate users.
4635 should use a real web server if you need to authenticate users.
4631
4636
4632 By default, the server logs accesses to stdout and errors to
4637 By default, the server logs accesses to stdout and errors to
4633 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
4638 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
4634 files.
4639 files.
4635
4640
4636 To have the server choose a free port number to listen on, specify
4641 To have the server choose a free port number to listen on, specify
4637 a port number of 0; in this case, the server will print the port
4642 a port number of 0; in this case, the server will print the port
4638 number it uses.
4643 number it uses.
4639
4644
4640 Returns 0 on success.
4645 Returns 0 on success.
4641 """
4646 """
4642
4647
4643 opts = pycompat.byteskwargs(opts)
4648 opts = pycompat.byteskwargs(opts)
4644 if opts["stdio"] and opts["cmdserver"]:
4649 if opts["stdio"] and opts["cmdserver"]:
4645 raise error.Abort(_("cannot use --stdio with --cmdserver"))
4650 raise error.Abort(_("cannot use --stdio with --cmdserver"))
4646
4651
4647 if opts["stdio"]:
4652 if opts["stdio"]:
4648 if repo is None:
4653 if repo is None:
4649 raise error.RepoError(_("there is no Mercurial repository here"
4654 raise error.RepoError(_("there is no Mercurial repository here"
4650 " (.hg not found)"))
4655 " (.hg not found)"))
4651 s = sshserver.sshserver(ui, repo)
4656 s = sshserver.sshserver(ui, repo)
4652 s.serve_forever()
4657 s.serve_forever()
4653
4658
4654 service = server.createservice(ui, repo, opts)
4659 service = server.createservice(ui, repo, opts)
4655 return server.runservice(opts, initfn=service.init, runfn=service.run)
4660 return server.runservice(opts, initfn=service.init, runfn=service.run)
4656
4661
4657 @command('^status|st',
4662 @command('^status|st',
4658 [('A', 'all', None, _('show status of all files')),
4663 [('A', 'all', None, _('show status of all files')),
4659 ('m', 'modified', None, _('show only modified files')),
4664 ('m', 'modified', None, _('show only modified files')),
4660 ('a', 'added', None, _('show only added files')),
4665 ('a', 'added', None, _('show only added files')),
4661 ('r', 'removed', None, _('show only removed files')),
4666 ('r', 'removed', None, _('show only removed files')),
4662 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4667 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4663 ('c', 'clean', None, _('show only files without changes')),
4668 ('c', 'clean', None, _('show only files without changes')),
4664 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4669 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4665 ('i', 'ignored', None, _('show only ignored files')),
4670 ('i', 'ignored', None, _('show only ignored files')),
4666 ('n', 'no-status', None, _('hide status prefix')),
4671 ('n', 'no-status', None, _('hide status prefix')),
4667 ('C', 'copies', None, _('show source of copied files')),
4672 ('C', 'copies', None, _('show source of copied files')),
4668 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4673 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4669 ('', 'rev', [], _('show difference from revision'), _('REV')),
4674 ('', 'rev', [], _('show difference from revision'), _('REV')),
4670 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
4675 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
4671 ] + walkopts + subrepoopts + formatteropts,
4676 ] + walkopts + subrepoopts + formatteropts,
4672 _('[OPTION]... [FILE]...'),
4677 _('[OPTION]... [FILE]...'),
4673 inferrepo=True)
4678 inferrepo=True)
4674 def status(ui, repo, *pats, **opts):
4679 def status(ui, repo, *pats, **opts):
4675 """show changed files in the working directory
4680 """show changed files in the working directory
4676
4681
4677 Show status of files in the repository. If names are given, only
4682 Show status of files in the repository. If names are given, only
4678 files that match are shown. Files that are clean or ignored or
4683 files that match are shown. Files that are clean or ignored or
4679 the source of a copy/move operation, are not listed unless
4684 the source of a copy/move operation, are not listed unless
4680 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
4685 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
4681 Unless options described with "show only ..." are given, the
4686 Unless options described with "show only ..." are given, the
4682 options -mardu are used.
4687 options -mardu are used.
4683
4688
4684 Option -q/--quiet hides untracked (unknown and ignored) files
4689 Option -q/--quiet hides untracked (unknown and ignored) files
4685 unless explicitly requested with -u/--unknown or -i/--ignored.
4690 unless explicitly requested with -u/--unknown or -i/--ignored.
4686
4691
4687 .. note::
4692 .. note::
4688
4693
4689 :hg:`status` may appear to disagree with diff if permissions have
4694 :hg:`status` may appear to disagree with diff if permissions have
4690 changed or a merge has occurred. The standard diff format does
4695 changed or a merge has occurred. The standard diff format does
4691 not report permission changes and diff only reports changes
4696 not report permission changes and diff only reports changes
4692 relative to one merge parent.
4697 relative to one merge parent.
4693
4698
4694 If one revision is given, it is used as the base revision.
4699 If one revision is given, it is used as the base revision.
4695 If two revisions are given, the differences between them are
4700 If two revisions are given, the differences between them are
4696 shown. The --change option can also be used as a shortcut to list
4701 shown. The --change option can also be used as a shortcut to list
4697 the changed files of a revision from its first parent.
4702 the changed files of a revision from its first parent.
4698
4703
4699 The codes used to show the status of files are::
4704 The codes used to show the status of files are::
4700
4705
4701 M = modified
4706 M = modified
4702 A = added
4707 A = added
4703 R = removed
4708 R = removed
4704 C = clean
4709 C = clean
4705 ! = missing (deleted by non-hg command, but still tracked)
4710 ! = missing (deleted by non-hg command, but still tracked)
4706 ? = not tracked
4711 ? = not tracked
4707 I = ignored
4712 I = ignored
4708 = origin of the previous file (with --copies)
4713 = origin of the previous file (with --copies)
4709
4714
4710 .. container:: verbose
4715 .. container:: verbose
4711
4716
4712 Examples:
4717 Examples:
4713
4718
4714 - show changes in the working directory relative to a
4719 - show changes in the working directory relative to a
4715 changeset::
4720 changeset::
4716
4721
4717 hg status --rev 9353
4722 hg status --rev 9353
4718
4723
4719 - show changes in the working directory relative to the
4724 - show changes in the working directory relative to the
4720 current directory (see :hg:`help patterns` for more information)::
4725 current directory (see :hg:`help patterns` for more information)::
4721
4726
4722 hg status re:
4727 hg status re:
4723
4728
4724 - show all changes including copies in an existing changeset::
4729 - show all changes including copies in an existing changeset::
4725
4730
4726 hg status --copies --change 9353
4731 hg status --copies --change 9353
4727
4732
4728 - get a NUL separated list of added files, suitable for xargs::
4733 - get a NUL separated list of added files, suitable for xargs::
4729
4734
4730 hg status -an0
4735 hg status -an0
4731
4736
4732 Returns 0 on success.
4737 Returns 0 on success.
4733 """
4738 """
4734
4739
4735 opts = pycompat.byteskwargs(opts)
4740 opts = pycompat.byteskwargs(opts)
4736 revs = opts.get('rev')
4741 revs = opts.get('rev')
4737 change = opts.get('change')
4742 change = opts.get('change')
4738
4743
4739 if revs and change:
4744 if revs and change:
4740 msg = _('cannot specify --rev and --change at the same time')
4745 msg = _('cannot specify --rev and --change at the same time')
4741 raise error.Abort(msg)
4746 raise error.Abort(msg)
4742 elif change:
4747 elif change:
4743 node2 = scmutil.revsingle(repo, change, None).node()
4748 node2 = scmutil.revsingle(repo, change, None).node()
4744 node1 = repo[node2].p1().node()
4749 node1 = repo[node2].p1().node()
4745 else:
4750 else:
4746 node1, node2 = scmutil.revpair(repo, revs)
4751 node1, node2 = scmutil.revpair(repo, revs)
4747
4752
4748 if pats or ui.configbool('commands', 'status.relative'):
4753 if pats or ui.configbool('commands', 'status.relative'):
4749 cwd = repo.getcwd()
4754 cwd = repo.getcwd()
4750 else:
4755 else:
4751 cwd = ''
4756 cwd = ''
4752
4757
4753 if opts.get('print0'):
4758 if opts.get('print0'):
4754 end = '\0'
4759 end = '\0'
4755 else:
4760 else:
4756 end = '\n'
4761 end = '\n'
4757 copy = {}
4762 copy = {}
4758 states = 'modified added removed deleted unknown ignored clean'.split()
4763 states = 'modified added removed deleted unknown ignored clean'.split()
4759 show = [k for k in states if opts.get(k)]
4764 show = [k for k in states if opts.get(k)]
4760 if opts.get('all'):
4765 if opts.get('all'):
4761 show += ui.quiet and (states[:4] + ['clean']) or states
4766 show += ui.quiet and (states[:4] + ['clean']) or states
4762 if not show:
4767 if not show:
4763 if ui.quiet:
4768 if ui.quiet:
4764 show = states[:4]
4769 show = states[:4]
4765 else:
4770 else:
4766 show = states[:5]
4771 show = states[:5]
4767
4772
4768 m = scmutil.match(repo[node2], pats, opts)
4773 m = scmutil.match(repo[node2], pats, opts)
4769 stat = repo.status(node1, node2, m,
4774 stat = repo.status(node1, node2, m,
4770 'ignored' in show, 'clean' in show, 'unknown' in show,
4775 'ignored' in show, 'clean' in show, 'unknown' in show,
4771 opts.get('subrepos'))
4776 opts.get('subrepos'))
4772 changestates = zip(states, pycompat.iterbytestr('MAR!?IC'), stat)
4777 changestates = zip(states, pycompat.iterbytestr('MAR!?IC'), stat)
4773
4778
4774 if (opts.get('all') or opts.get('copies')
4779 if (opts.get('all') or opts.get('copies')
4775 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
4780 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
4776 copy = copies.pathcopies(repo[node1], repo[node2], m)
4781 copy = copies.pathcopies(repo[node1], repo[node2], m)
4777
4782
4778 ui.pager('status')
4783 ui.pager('status')
4779 fm = ui.formatter('status', opts)
4784 fm = ui.formatter('status', opts)
4780 fmt = '%s' + end
4785 fmt = '%s' + end
4781 showchar = not opts.get('no_status')
4786 showchar = not opts.get('no_status')
4782
4787
4783 for state, char, files in changestates:
4788 for state, char, files in changestates:
4784 if state in show:
4789 if state in show:
4785 label = 'status.' + state
4790 label = 'status.' + state
4786 for f in files:
4791 for f in files:
4787 fm.startitem()
4792 fm.startitem()
4788 fm.condwrite(showchar, 'status', '%s ', char, label=label)
4793 fm.condwrite(showchar, 'status', '%s ', char, label=label)
4789 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
4794 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
4790 if f in copy:
4795 if f in copy:
4791 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
4796 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
4792 label='status.copied')
4797 label='status.copied')
4793 fm.end()
4798 fm.end()
4794
4799
4795 @command('^summary|sum',
4800 @command('^summary|sum',
4796 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
4801 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
4797 def summary(ui, repo, **opts):
4802 def summary(ui, repo, **opts):
4798 """summarize working directory state
4803 """summarize working directory state
4799
4804
4800 This generates a brief summary of the working directory state,
4805 This generates a brief summary of the working directory state,
4801 including parents, branch, commit status, phase and available updates.
4806 including parents, branch, commit status, phase and available updates.
4802
4807
4803 With the --remote option, this will check the default paths for
4808 With the --remote option, this will check the default paths for
4804 incoming and outgoing changes. This can be time-consuming.
4809 incoming and outgoing changes. This can be time-consuming.
4805
4810
4806 Returns 0 on success.
4811 Returns 0 on success.
4807 """
4812 """
4808
4813
4809 opts = pycompat.byteskwargs(opts)
4814 opts = pycompat.byteskwargs(opts)
4810 ui.pager('summary')
4815 ui.pager('summary')
4811 ctx = repo[None]
4816 ctx = repo[None]
4812 parents = ctx.parents()
4817 parents = ctx.parents()
4813 pnode = parents[0].node()
4818 pnode = parents[0].node()
4814 marks = []
4819 marks = []
4815
4820
4816 ms = None
4821 ms = None
4817 try:
4822 try:
4818 ms = mergemod.mergestate.read(repo)
4823 ms = mergemod.mergestate.read(repo)
4819 except error.UnsupportedMergeRecords as e:
4824 except error.UnsupportedMergeRecords as e:
4820 s = ' '.join(e.recordtypes)
4825 s = ' '.join(e.recordtypes)
4821 ui.warn(
4826 ui.warn(
4822 _('warning: merge state has unsupported record types: %s\n') % s)
4827 _('warning: merge state has unsupported record types: %s\n') % s)
4823 unresolved = 0
4828 unresolved = 0
4824 else:
4829 else:
4825 unresolved = [f for f in ms if ms[f] == 'u']
4830 unresolved = [f for f in ms if ms[f] == 'u']
4826
4831
4827 for p in parents:
4832 for p in parents:
4828 # label with log.changeset (instead of log.parent) since this
4833 # label with log.changeset (instead of log.parent) since this
4829 # shows a working directory parent *changeset*:
4834 # shows a working directory parent *changeset*:
4830 # i18n: column positioning for "hg summary"
4835 # i18n: column positioning for "hg summary"
4831 ui.write(_('parent: %d:%s ') % (p.rev(), p),
4836 ui.write(_('parent: %d:%s ') % (p.rev(), p),
4832 label=cmdutil._changesetlabels(p))
4837 label=cmdutil._changesetlabels(p))
4833 ui.write(' '.join(p.tags()), label='log.tag')
4838 ui.write(' '.join(p.tags()), label='log.tag')
4834 if p.bookmarks():
4839 if p.bookmarks():
4835 marks.extend(p.bookmarks())
4840 marks.extend(p.bookmarks())
4836 if p.rev() == -1:
4841 if p.rev() == -1:
4837 if not len(repo):
4842 if not len(repo):
4838 ui.write(_(' (empty repository)'))
4843 ui.write(_(' (empty repository)'))
4839 else:
4844 else:
4840 ui.write(_(' (no revision checked out)'))
4845 ui.write(_(' (no revision checked out)'))
4841 if p.obsolete():
4846 if p.obsolete():
4842 ui.write(_(' (obsolete)'))
4847 ui.write(_(' (obsolete)'))
4843 if p.troubled():
4848 if p.troubled():
4844 ui.write(' ('
4849 ui.write(' ('
4845 + ', '.join(ui.label(trouble, 'trouble.%s' % trouble)
4850 + ', '.join(ui.label(trouble, 'trouble.%s' % trouble)
4846 for trouble in p.troubles())
4851 for trouble in p.troubles())
4847 + ')')
4852 + ')')
4848 ui.write('\n')
4853 ui.write('\n')
4849 if p.description():
4854 if p.description():
4850 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
4855 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
4851 label='log.summary')
4856 label='log.summary')
4852
4857
4853 branch = ctx.branch()
4858 branch = ctx.branch()
4854 bheads = repo.branchheads(branch)
4859 bheads = repo.branchheads(branch)
4855 # i18n: column positioning for "hg summary"
4860 # i18n: column positioning for "hg summary"
4856 m = _('branch: %s\n') % branch
4861 m = _('branch: %s\n') % branch
4857 if branch != 'default':
4862 if branch != 'default':
4858 ui.write(m, label='log.branch')
4863 ui.write(m, label='log.branch')
4859 else:
4864 else:
4860 ui.status(m, label='log.branch')
4865 ui.status(m, label='log.branch')
4861
4866
4862 if marks:
4867 if marks:
4863 active = repo._activebookmark
4868 active = repo._activebookmark
4864 # i18n: column positioning for "hg summary"
4869 # i18n: column positioning for "hg summary"
4865 ui.write(_('bookmarks:'), label='log.bookmark')
4870 ui.write(_('bookmarks:'), label='log.bookmark')
4866 if active is not None:
4871 if active is not None:
4867 if active in marks:
4872 if active in marks:
4868 ui.write(' *' + active, label=activebookmarklabel)
4873 ui.write(' *' + active, label=activebookmarklabel)
4869 marks.remove(active)
4874 marks.remove(active)
4870 else:
4875 else:
4871 ui.write(' [%s]' % active, label=activebookmarklabel)
4876 ui.write(' [%s]' % active, label=activebookmarklabel)
4872 for m in marks:
4877 for m in marks:
4873 ui.write(' ' + m, label='log.bookmark')
4878 ui.write(' ' + m, label='log.bookmark')
4874 ui.write('\n', label='log.bookmark')
4879 ui.write('\n', label='log.bookmark')
4875
4880
4876 status = repo.status(unknown=True)
4881 status = repo.status(unknown=True)
4877
4882
4878 c = repo.dirstate.copies()
4883 c = repo.dirstate.copies()
4879 copied, renamed = [], []
4884 copied, renamed = [], []
4880 for d, s in c.iteritems():
4885 for d, s in c.iteritems():
4881 if s in status.removed:
4886 if s in status.removed:
4882 status.removed.remove(s)
4887 status.removed.remove(s)
4883 renamed.append(d)
4888 renamed.append(d)
4884 else:
4889 else:
4885 copied.append(d)
4890 copied.append(d)
4886 if d in status.added:
4891 if d in status.added:
4887 status.added.remove(d)
4892 status.added.remove(d)
4888
4893
4889 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
4894 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
4890
4895
4891 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
4896 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
4892 (ui.label(_('%d added'), 'status.added'), status.added),
4897 (ui.label(_('%d added'), 'status.added'), status.added),
4893 (ui.label(_('%d removed'), 'status.removed'), status.removed),
4898 (ui.label(_('%d removed'), 'status.removed'), status.removed),
4894 (ui.label(_('%d renamed'), 'status.copied'), renamed),
4899 (ui.label(_('%d renamed'), 'status.copied'), renamed),
4895 (ui.label(_('%d copied'), 'status.copied'), copied),
4900 (ui.label(_('%d copied'), 'status.copied'), copied),
4896 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
4901 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
4897 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
4902 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
4898 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
4903 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
4899 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
4904 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
4900 t = []
4905 t = []
4901 for l, s in labels:
4906 for l, s in labels:
4902 if s:
4907 if s:
4903 t.append(l % len(s))
4908 t.append(l % len(s))
4904
4909
4905 t = ', '.join(t)
4910 t = ', '.join(t)
4906 cleanworkdir = False
4911 cleanworkdir = False
4907
4912
4908 if repo.vfs.exists('graftstate'):
4913 if repo.vfs.exists('graftstate'):
4909 t += _(' (graft in progress)')
4914 t += _(' (graft in progress)')
4910 if repo.vfs.exists('updatestate'):
4915 if repo.vfs.exists('updatestate'):
4911 t += _(' (interrupted update)')
4916 t += _(' (interrupted update)')
4912 elif len(parents) > 1:
4917 elif len(parents) > 1:
4913 t += _(' (merge)')
4918 t += _(' (merge)')
4914 elif branch != parents[0].branch():
4919 elif branch != parents[0].branch():
4915 t += _(' (new branch)')
4920 t += _(' (new branch)')
4916 elif (parents[0].closesbranch() and
4921 elif (parents[0].closesbranch() and
4917 pnode in repo.branchheads(branch, closed=True)):
4922 pnode in repo.branchheads(branch, closed=True)):
4918 t += _(' (head closed)')
4923 t += _(' (head closed)')
4919 elif not (status.modified or status.added or status.removed or renamed or
4924 elif not (status.modified or status.added or status.removed or renamed or
4920 copied or subs):
4925 copied or subs):
4921 t += _(' (clean)')
4926 t += _(' (clean)')
4922 cleanworkdir = True
4927 cleanworkdir = True
4923 elif pnode not in bheads:
4928 elif pnode not in bheads:
4924 t += _(' (new branch head)')
4929 t += _(' (new branch head)')
4925
4930
4926 if parents:
4931 if parents:
4927 pendingphase = max(p.phase() for p in parents)
4932 pendingphase = max(p.phase() for p in parents)
4928 else:
4933 else:
4929 pendingphase = phases.public
4934 pendingphase = phases.public
4930
4935
4931 if pendingphase > phases.newcommitphase(ui):
4936 if pendingphase > phases.newcommitphase(ui):
4932 t += ' (%s)' % phases.phasenames[pendingphase]
4937 t += ' (%s)' % phases.phasenames[pendingphase]
4933
4938
4934 if cleanworkdir:
4939 if cleanworkdir:
4935 # i18n: column positioning for "hg summary"
4940 # i18n: column positioning for "hg summary"
4936 ui.status(_('commit: %s\n') % t.strip())
4941 ui.status(_('commit: %s\n') % t.strip())
4937 else:
4942 else:
4938 # i18n: column positioning for "hg summary"
4943 # i18n: column positioning for "hg summary"
4939 ui.write(_('commit: %s\n') % t.strip())
4944 ui.write(_('commit: %s\n') % t.strip())
4940
4945
4941 # all ancestors of branch heads - all ancestors of parent = new csets
4946 # all ancestors of branch heads - all ancestors of parent = new csets
4942 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
4947 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
4943 bheads))
4948 bheads))
4944
4949
4945 if new == 0:
4950 if new == 0:
4946 # i18n: column positioning for "hg summary"
4951 # i18n: column positioning for "hg summary"
4947 ui.status(_('update: (current)\n'))
4952 ui.status(_('update: (current)\n'))
4948 elif pnode not in bheads:
4953 elif pnode not in bheads:
4949 # i18n: column positioning for "hg summary"
4954 # i18n: column positioning for "hg summary"
4950 ui.write(_('update: %d new changesets (update)\n') % new)
4955 ui.write(_('update: %d new changesets (update)\n') % new)
4951 else:
4956 else:
4952 # i18n: column positioning for "hg summary"
4957 # i18n: column positioning for "hg summary"
4953 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
4958 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
4954 (new, len(bheads)))
4959 (new, len(bheads)))
4955
4960
4956 t = []
4961 t = []
4957 draft = len(repo.revs('draft()'))
4962 draft = len(repo.revs('draft()'))
4958 if draft:
4963 if draft:
4959 t.append(_('%d draft') % draft)
4964 t.append(_('%d draft') % draft)
4960 secret = len(repo.revs('secret()'))
4965 secret = len(repo.revs('secret()'))
4961 if secret:
4966 if secret:
4962 t.append(_('%d secret') % secret)
4967 t.append(_('%d secret') % secret)
4963
4968
4964 if draft or secret:
4969 if draft or secret:
4965 ui.status(_('phases: %s\n') % ', '.join(t))
4970 ui.status(_('phases: %s\n') % ', '.join(t))
4966
4971
4967 if obsolete.isenabled(repo, obsolete.createmarkersopt):
4972 if obsolete.isenabled(repo, obsolete.createmarkersopt):
4968 for trouble in ("unstable", "divergent", "bumped"):
4973 for trouble in ("unstable", "divergent", "bumped"):
4969 numtrouble = len(repo.revs(trouble + "()"))
4974 numtrouble = len(repo.revs(trouble + "()"))
4970 # We write all the possibilities to ease translation
4975 # We write all the possibilities to ease translation
4971 troublemsg = {
4976 troublemsg = {
4972 "unstable": _("unstable: %d changesets"),
4977 "unstable": _("unstable: %d changesets"),
4973 "divergent": _("divergent: %d changesets"),
4978 "divergent": _("divergent: %d changesets"),
4974 "bumped": _("bumped: %d changesets"),
4979 "bumped": _("bumped: %d changesets"),
4975 }
4980 }
4976 if numtrouble > 0:
4981 if numtrouble > 0:
4977 ui.status(troublemsg[trouble] % numtrouble + "\n")
4982 ui.status(troublemsg[trouble] % numtrouble + "\n")
4978
4983
4979 cmdutil.summaryhooks(ui, repo)
4984 cmdutil.summaryhooks(ui, repo)
4980
4985
4981 if opts.get('remote'):
4986 if opts.get('remote'):
4982 needsincoming, needsoutgoing = True, True
4987 needsincoming, needsoutgoing = True, True
4983 else:
4988 else:
4984 needsincoming, needsoutgoing = False, False
4989 needsincoming, needsoutgoing = False, False
4985 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
4990 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
4986 if i:
4991 if i:
4987 needsincoming = True
4992 needsincoming = True
4988 if o:
4993 if o:
4989 needsoutgoing = True
4994 needsoutgoing = True
4990 if not needsincoming and not needsoutgoing:
4995 if not needsincoming and not needsoutgoing:
4991 return
4996 return
4992
4997
4993 def getincoming():
4998 def getincoming():
4994 source, branches = hg.parseurl(ui.expandpath('default'))
4999 source, branches = hg.parseurl(ui.expandpath('default'))
4995 sbranch = branches[0]
5000 sbranch = branches[0]
4996 try:
5001 try:
4997 other = hg.peer(repo, {}, source)
5002 other = hg.peer(repo, {}, source)
4998 except error.RepoError:
5003 except error.RepoError:
4999 if opts.get('remote'):
5004 if opts.get('remote'):
5000 raise
5005 raise
5001 return source, sbranch, None, None, None
5006 return source, sbranch, None, None, None
5002 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5007 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5003 if revs:
5008 if revs:
5004 revs = [other.lookup(rev) for rev in revs]
5009 revs = [other.lookup(rev) for rev in revs]
5005 ui.debug('comparing with %s\n' % util.hidepassword(source))
5010 ui.debug('comparing with %s\n' % util.hidepassword(source))
5006 repo.ui.pushbuffer()
5011 repo.ui.pushbuffer()
5007 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5012 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5008 repo.ui.popbuffer()
5013 repo.ui.popbuffer()
5009 return source, sbranch, other, commoninc, commoninc[1]
5014 return source, sbranch, other, commoninc, commoninc[1]
5010
5015
5011 if needsincoming:
5016 if needsincoming:
5012 source, sbranch, sother, commoninc, incoming = getincoming()
5017 source, sbranch, sother, commoninc, incoming = getincoming()
5013 else:
5018 else:
5014 source = sbranch = sother = commoninc = incoming = None
5019 source = sbranch = sother = commoninc = incoming = None
5015
5020
5016 def getoutgoing():
5021 def getoutgoing():
5017 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5022 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5018 dbranch = branches[0]
5023 dbranch = branches[0]
5019 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5024 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5020 if source != dest:
5025 if source != dest:
5021 try:
5026 try:
5022 dother = hg.peer(repo, {}, dest)
5027 dother = hg.peer(repo, {}, dest)
5023 except error.RepoError:
5028 except error.RepoError:
5024 if opts.get('remote'):
5029 if opts.get('remote'):
5025 raise
5030 raise
5026 return dest, dbranch, None, None
5031 return dest, dbranch, None, None
5027 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5032 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5028 elif sother is None:
5033 elif sother is None:
5029 # there is no explicit destination peer, but source one is invalid
5034 # there is no explicit destination peer, but source one is invalid
5030 return dest, dbranch, None, None
5035 return dest, dbranch, None, None
5031 else:
5036 else:
5032 dother = sother
5037 dother = sother
5033 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5038 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5034 common = None
5039 common = None
5035 else:
5040 else:
5036 common = commoninc
5041 common = commoninc
5037 if revs:
5042 if revs:
5038 revs = [repo.lookup(rev) for rev in revs]
5043 revs = [repo.lookup(rev) for rev in revs]
5039 repo.ui.pushbuffer()
5044 repo.ui.pushbuffer()
5040 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5045 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5041 commoninc=common)
5046 commoninc=common)
5042 repo.ui.popbuffer()
5047 repo.ui.popbuffer()
5043 return dest, dbranch, dother, outgoing
5048 return dest, dbranch, dother, outgoing
5044
5049
5045 if needsoutgoing:
5050 if needsoutgoing:
5046 dest, dbranch, dother, outgoing = getoutgoing()
5051 dest, dbranch, dother, outgoing = getoutgoing()
5047 else:
5052 else:
5048 dest = dbranch = dother = outgoing = None
5053 dest = dbranch = dother = outgoing = None
5049
5054
5050 if opts.get('remote'):
5055 if opts.get('remote'):
5051 t = []
5056 t = []
5052 if incoming:
5057 if incoming:
5053 t.append(_('1 or more incoming'))
5058 t.append(_('1 or more incoming'))
5054 o = outgoing.missing
5059 o = outgoing.missing
5055 if o:
5060 if o:
5056 t.append(_('%d outgoing') % len(o))
5061 t.append(_('%d outgoing') % len(o))
5057 other = dother or sother
5062 other = dother or sother
5058 if 'bookmarks' in other.listkeys('namespaces'):
5063 if 'bookmarks' in other.listkeys('namespaces'):
5059 counts = bookmarks.summary(repo, other)
5064 counts = bookmarks.summary(repo, other)
5060 if counts[0] > 0:
5065 if counts[0] > 0:
5061 t.append(_('%d incoming bookmarks') % counts[0])
5066 t.append(_('%d incoming bookmarks') % counts[0])
5062 if counts[1] > 0:
5067 if counts[1] > 0:
5063 t.append(_('%d outgoing bookmarks') % counts[1])
5068 t.append(_('%d outgoing bookmarks') % counts[1])
5064
5069
5065 if t:
5070 if t:
5066 # i18n: column positioning for "hg summary"
5071 # i18n: column positioning for "hg summary"
5067 ui.write(_('remote: %s\n') % (', '.join(t)))
5072 ui.write(_('remote: %s\n') % (', '.join(t)))
5068 else:
5073 else:
5069 # i18n: column positioning for "hg summary"
5074 # i18n: column positioning for "hg summary"
5070 ui.status(_('remote: (synced)\n'))
5075 ui.status(_('remote: (synced)\n'))
5071
5076
5072 cmdutil.summaryremotehooks(ui, repo, opts,
5077 cmdutil.summaryremotehooks(ui, repo, opts,
5073 ((source, sbranch, sother, commoninc),
5078 ((source, sbranch, sother, commoninc),
5074 (dest, dbranch, dother, outgoing)))
5079 (dest, dbranch, dother, outgoing)))
5075
5080
5076 @command('tag',
5081 @command('tag',
5077 [('f', 'force', None, _('force tag')),
5082 [('f', 'force', None, _('force tag')),
5078 ('l', 'local', None, _('make the tag local')),
5083 ('l', 'local', None, _('make the tag local')),
5079 ('r', 'rev', '', _('revision to tag'), _('REV')),
5084 ('r', 'rev', '', _('revision to tag'), _('REV')),
5080 ('', 'remove', None, _('remove a tag')),
5085 ('', 'remove', None, _('remove a tag')),
5081 # -l/--local is already there, commitopts cannot be used
5086 # -l/--local is already there, commitopts cannot be used
5082 ('e', 'edit', None, _('invoke editor on commit messages')),
5087 ('e', 'edit', None, _('invoke editor on commit messages')),
5083 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5088 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5084 ] + commitopts2,
5089 ] + commitopts2,
5085 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5090 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5086 def tag(ui, repo, name1, *names, **opts):
5091 def tag(ui, repo, name1, *names, **opts):
5087 """add one or more tags for the current or given revision
5092 """add one or more tags for the current or given revision
5088
5093
5089 Name a particular revision using <name>.
5094 Name a particular revision using <name>.
5090
5095
5091 Tags are used to name particular revisions of the repository and are
5096 Tags are used to name particular revisions of the repository and are
5092 very useful to compare different revisions, to go back to significant
5097 very useful to compare different revisions, to go back to significant
5093 earlier versions or to mark branch points as releases, etc. Changing
5098 earlier versions or to mark branch points as releases, etc. Changing
5094 an existing tag is normally disallowed; use -f/--force to override.
5099 an existing tag is normally disallowed; use -f/--force to override.
5095
5100
5096 If no revision is given, the parent of the working directory is
5101 If no revision is given, the parent of the working directory is
5097 used.
5102 used.
5098
5103
5099 To facilitate version control, distribution, and merging of tags,
5104 To facilitate version control, distribution, and merging of tags,
5100 they are stored as a file named ".hgtags" which is managed similarly
5105 they are stored as a file named ".hgtags" which is managed similarly
5101 to other project files and can be hand-edited if necessary. This
5106 to other project files and can be hand-edited if necessary. This
5102 also means that tagging creates a new commit. The file
5107 also means that tagging creates a new commit. The file
5103 ".hg/localtags" is used for local tags (not shared among
5108 ".hg/localtags" is used for local tags (not shared among
5104 repositories).
5109 repositories).
5105
5110
5106 Tag commits are usually made at the head of a branch. If the parent
5111 Tag commits are usually made at the head of a branch. If the parent
5107 of the working directory is not a branch head, :hg:`tag` aborts; use
5112 of the working directory is not a branch head, :hg:`tag` aborts; use
5108 -f/--force to force the tag commit to be based on a non-head
5113 -f/--force to force the tag commit to be based on a non-head
5109 changeset.
5114 changeset.
5110
5115
5111 See :hg:`help dates` for a list of formats valid for -d/--date.
5116 See :hg:`help dates` for a list of formats valid for -d/--date.
5112
5117
5113 Since tag names have priority over branch names during revision
5118 Since tag names have priority over branch names during revision
5114 lookup, using an existing branch name as a tag name is discouraged.
5119 lookup, using an existing branch name as a tag name is discouraged.
5115
5120
5116 Returns 0 on success.
5121 Returns 0 on success.
5117 """
5122 """
5118 opts = pycompat.byteskwargs(opts)
5123 opts = pycompat.byteskwargs(opts)
5119 wlock = lock = None
5124 wlock = lock = None
5120 try:
5125 try:
5121 wlock = repo.wlock()
5126 wlock = repo.wlock()
5122 lock = repo.lock()
5127 lock = repo.lock()
5123 rev_ = "."
5128 rev_ = "."
5124 names = [t.strip() for t in (name1,) + names]
5129 names = [t.strip() for t in (name1,) + names]
5125 if len(names) != len(set(names)):
5130 if len(names) != len(set(names)):
5126 raise error.Abort(_('tag names must be unique'))
5131 raise error.Abort(_('tag names must be unique'))
5127 for n in names:
5132 for n in names:
5128 scmutil.checknewlabel(repo, n, 'tag')
5133 scmutil.checknewlabel(repo, n, 'tag')
5129 if not n:
5134 if not n:
5130 raise error.Abort(_('tag names cannot consist entirely of '
5135 raise error.Abort(_('tag names cannot consist entirely of '
5131 'whitespace'))
5136 'whitespace'))
5132 if opts.get('rev') and opts.get('remove'):
5137 if opts.get('rev') and opts.get('remove'):
5133 raise error.Abort(_("--rev and --remove are incompatible"))
5138 raise error.Abort(_("--rev and --remove are incompatible"))
5134 if opts.get('rev'):
5139 if opts.get('rev'):
5135 rev_ = opts['rev']
5140 rev_ = opts['rev']
5136 message = opts.get('message')
5141 message = opts.get('message')
5137 if opts.get('remove'):
5142 if opts.get('remove'):
5138 if opts.get('local'):
5143 if opts.get('local'):
5139 expectedtype = 'local'
5144 expectedtype = 'local'
5140 else:
5145 else:
5141 expectedtype = 'global'
5146 expectedtype = 'global'
5142
5147
5143 for n in names:
5148 for n in names:
5144 if not repo.tagtype(n):
5149 if not repo.tagtype(n):
5145 raise error.Abort(_("tag '%s' does not exist") % n)
5150 raise error.Abort(_("tag '%s' does not exist") % n)
5146 if repo.tagtype(n) != expectedtype:
5151 if repo.tagtype(n) != expectedtype:
5147 if expectedtype == 'global':
5152 if expectedtype == 'global':
5148 raise error.Abort(_("tag '%s' is not a global tag") % n)
5153 raise error.Abort(_("tag '%s' is not a global tag") % n)
5149 else:
5154 else:
5150 raise error.Abort(_("tag '%s' is not a local tag") % n)
5155 raise error.Abort(_("tag '%s' is not a local tag") % n)
5151 rev_ = 'null'
5156 rev_ = 'null'
5152 if not message:
5157 if not message:
5153 # we don't translate commit messages
5158 # we don't translate commit messages
5154 message = 'Removed tag %s' % ', '.join(names)
5159 message = 'Removed tag %s' % ', '.join(names)
5155 elif not opts.get('force'):
5160 elif not opts.get('force'):
5156 for n in names:
5161 for n in names:
5157 if n in repo.tags():
5162 if n in repo.tags():
5158 raise error.Abort(_("tag '%s' already exists "
5163 raise error.Abort(_("tag '%s' already exists "
5159 "(use -f to force)") % n)
5164 "(use -f to force)") % n)
5160 if not opts.get('local'):
5165 if not opts.get('local'):
5161 p1, p2 = repo.dirstate.parents()
5166 p1, p2 = repo.dirstate.parents()
5162 if p2 != nullid:
5167 if p2 != nullid:
5163 raise error.Abort(_('uncommitted merge'))
5168 raise error.Abort(_('uncommitted merge'))
5164 bheads = repo.branchheads()
5169 bheads = repo.branchheads()
5165 if not opts.get('force') and bheads and p1 not in bheads:
5170 if not opts.get('force') and bheads and p1 not in bheads:
5166 raise error.Abort(_('working directory is not at a branch head '
5171 raise error.Abort(_('working directory is not at a branch head '
5167 '(use -f to force)'))
5172 '(use -f to force)'))
5168 r = scmutil.revsingle(repo, rev_).node()
5173 r = scmutil.revsingle(repo, rev_).node()
5169
5174
5170 if not message:
5175 if not message:
5171 # we don't translate commit messages
5176 # we don't translate commit messages
5172 message = ('Added tag %s for changeset %s' %
5177 message = ('Added tag %s for changeset %s' %
5173 (', '.join(names), short(r)))
5178 (', '.join(names), short(r)))
5174
5179
5175 date = opts.get('date')
5180 date = opts.get('date')
5176 if date:
5181 if date:
5177 date = util.parsedate(date)
5182 date = util.parsedate(date)
5178
5183
5179 if opts.get('remove'):
5184 if opts.get('remove'):
5180 editform = 'tag.remove'
5185 editform = 'tag.remove'
5181 else:
5186 else:
5182 editform = 'tag.add'
5187 editform = 'tag.add'
5183 editor = cmdutil.getcommiteditor(editform=editform,
5188 editor = cmdutil.getcommiteditor(editform=editform,
5184 **pycompat.strkwargs(opts))
5189 **pycompat.strkwargs(opts))
5185
5190
5186 # don't allow tagging the null rev
5191 # don't allow tagging the null rev
5187 if (not opts.get('remove') and
5192 if (not opts.get('remove') and
5188 scmutil.revsingle(repo, rev_).rev() == nullrev):
5193 scmutil.revsingle(repo, rev_).rev() == nullrev):
5189 raise error.Abort(_("cannot tag null revision"))
5194 raise error.Abort(_("cannot tag null revision"))
5190
5195
5191 tagsmod.tag(repo, names, r, message, opts.get('local'),
5196 tagsmod.tag(repo, names, r, message, opts.get('local'),
5192 opts.get('user'), date, editor=editor)
5197 opts.get('user'), date, editor=editor)
5193 finally:
5198 finally:
5194 release(lock, wlock)
5199 release(lock, wlock)
5195
5200
5196 @command('tags', formatteropts, '')
5201 @command('tags', formatteropts, '')
5197 def tags(ui, repo, **opts):
5202 def tags(ui, repo, **opts):
5198 """list repository tags
5203 """list repository tags
5199
5204
5200 This lists both regular and local tags. When the -v/--verbose
5205 This lists both regular and local tags. When the -v/--verbose
5201 switch is used, a third column "local" is printed for local tags.
5206 switch is used, a third column "local" is printed for local tags.
5202 When the -q/--quiet switch is used, only the tag name is printed.
5207 When the -q/--quiet switch is used, only the tag name is printed.
5203
5208
5204 Returns 0 on success.
5209 Returns 0 on success.
5205 """
5210 """
5206
5211
5207 opts = pycompat.byteskwargs(opts)
5212 opts = pycompat.byteskwargs(opts)
5208 ui.pager('tags')
5213 ui.pager('tags')
5209 fm = ui.formatter('tags', opts)
5214 fm = ui.formatter('tags', opts)
5210 hexfunc = fm.hexfunc
5215 hexfunc = fm.hexfunc
5211 tagtype = ""
5216 tagtype = ""
5212
5217
5213 for t, n in reversed(repo.tagslist()):
5218 for t, n in reversed(repo.tagslist()):
5214 hn = hexfunc(n)
5219 hn = hexfunc(n)
5215 label = 'tags.normal'
5220 label = 'tags.normal'
5216 tagtype = ''
5221 tagtype = ''
5217 if repo.tagtype(t) == 'local':
5222 if repo.tagtype(t) == 'local':
5218 label = 'tags.local'
5223 label = 'tags.local'
5219 tagtype = 'local'
5224 tagtype = 'local'
5220
5225
5221 fm.startitem()
5226 fm.startitem()
5222 fm.write('tag', '%s', t, label=label)
5227 fm.write('tag', '%s', t, label=label)
5223 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5228 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5224 fm.condwrite(not ui.quiet, 'rev node', fmt,
5229 fm.condwrite(not ui.quiet, 'rev node', fmt,
5225 repo.changelog.rev(n), hn, label=label)
5230 repo.changelog.rev(n), hn, label=label)
5226 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5231 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5227 tagtype, label=label)
5232 tagtype, label=label)
5228 fm.plain('\n')
5233 fm.plain('\n')
5229 fm.end()
5234 fm.end()
5230
5235
5231 @command('tip',
5236 @command('tip',
5232 [('p', 'patch', None, _('show patch')),
5237 [('p', 'patch', None, _('show patch')),
5233 ('g', 'git', None, _('use git extended diff format')),
5238 ('g', 'git', None, _('use git extended diff format')),
5234 ] + templateopts,
5239 ] + templateopts,
5235 _('[-p] [-g]'))
5240 _('[-p] [-g]'))
5236 def tip(ui, repo, **opts):
5241 def tip(ui, repo, **opts):
5237 """show the tip revision (DEPRECATED)
5242 """show the tip revision (DEPRECATED)
5238
5243
5239 The tip revision (usually just called the tip) is the changeset
5244 The tip revision (usually just called the tip) is the changeset
5240 most recently added to the repository (and therefore the most
5245 most recently added to the repository (and therefore the most
5241 recently changed head).
5246 recently changed head).
5242
5247
5243 If you have just made a commit, that commit will be the tip. If
5248 If you have just made a commit, that commit will be the tip. If
5244 you have just pulled changes from another repository, the tip of
5249 you have just pulled changes from another repository, the tip of
5245 that repository becomes the current tip. The "tip" tag is special
5250 that repository becomes the current tip. The "tip" tag is special
5246 and cannot be renamed or assigned to a different changeset.
5251 and cannot be renamed or assigned to a different changeset.
5247
5252
5248 This command is deprecated, please use :hg:`heads` instead.
5253 This command is deprecated, please use :hg:`heads` instead.
5249
5254
5250 Returns 0 on success.
5255 Returns 0 on success.
5251 """
5256 """
5252 opts = pycompat.byteskwargs(opts)
5257 opts = pycompat.byteskwargs(opts)
5253 displayer = cmdutil.show_changeset(ui, repo, opts)
5258 displayer = cmdutil.show_changeset(ui, repo, opts)
5254 displayer.show(repo['tip'])
5259 displayer.show(repo['tip'])
5255 displayer.close()
5260 displayer.close()
5256
5261
5257 @command('unbundle',
5262 @command('unbundle',
5258 [('u', 'update', None,
5263 [('u', 'update', None,
5259 _('update to new branch head if changesets were unbundled'))],
5264 _('update to new branch head if changesets were unbundled'))],
5260 _('[-u] FILE...'))
5265 _('[-u] FILE...'))
5261 def unbundle(ui, repo, fname1, *fnames, **opts):
5266 def unbundle(ui, repo, fname1, *fnames, **opts):
5262 """apply one or more bundle files
5267 """apply one or more bundle files
5263
5268
5264 Apply one or more bundle files generated by :hg:`bundle`.
5269 Apply one or more bundle files generated by :hg:`bundle`.
5265
5270
5266 Returns 0 on success, 1 if an update has unresolved files.
5271 Returns 0 on success, 1 if an update has unresolved files.
5267 """
5272 """
5268 fnames = (fname1,) + fnames
5273 fnames = (fname1,) + fnames
5269
5274
5270 with repo.lock():
5275 with repo.lock():
5271 for fname in fnames:
5276 for fname in fnames:
5272 f = hg.openpath(ui, fname)
5277 f = hg.openpath(ui, fname)
5273 gen = exchange.readbundle(ui, f, fname)
5278 gen = exchange.readbundle(ui, f, fname)
5274 if isinstance(gen, bundle2.unbundle20):
5279 if isinstance(gen, bundle2.unbundle20):
5275 tr = repo.transaction('unbundle')
5280 tr = repo.transaction('unbundle')
5276 try:
5281 try:
5277 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
5282 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
5278 url='bundle:' + fname)
5283 url='bundle:' + fname)
5279 tr.close()
5284 tr.close()
5280 except error.BundleUnknownFeatureError as exc:
5285 except error.BundleUnknownFeatureError as exc:
5281 raise error.Abort(_('%s: unknown bundle feature, %s')
5286 raise error.Abort(_('%s: unknown bundle feature, %s')
5282 % (fname, exc),
5287 % (fname, exc),
5283 hint=_("see https://mercurial-scm.org/"
5288 hint=_("see https://mercurial-scm.org/"
5284 "wiki/BundleFeature for more "
5289 "wiki/BundleFeature for more "
5285 "information"))
5290 "information"))
5286 finally:
5291 finally:
5287 if tr:
5292 if tr:
5288 tr.release()
5293 tr.release()
5289 changes = [r.get('return', 0)
5294 changes = [r.get('return', 0)
5290 for r in op.records['changegroup']]
5295 for r in op.records['changegroup']]
5291 modheads = changegroup.combineresults(changes)
5296 modheads = changegroup.combineresults(changes)
5292 elif isinstance(gen, streamclone.streamcloneapplier):
5297 elif isinstance(gen, streamclone.streamcloneapplier):
5293 raise error.Abort(
5298 raise error.Abort(
5294 _('packed bundles cannot be applied with '
5299 _('packed bundles cannot be applied with '
5295 '"hg unbundle"'),
5300 '"hg unbundle"'),
5296 hint=_('use "hg debugapplystreamclonebundle"'))
5301 hint=_('use "hg debugapplystreamclonebundle"'))
5297 else:
5302 else:
5298 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
5303 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
5299
5304
5300 return postincoming(ui, repo, modheads, opts.get(r'update'), None, None)
5305 return postincoming(ui, repo, modheads, opts.get(r'update'), None, None)
5301
5306
5302 @command('^update|up|checkout|co',
5307 @command('^update|up|checkout|co',
5303 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5308 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5304 ('c', 'check', None, _('require clean working directory')),
5309 ('c', 'check', None, _('require clean working directory')),
5305 ('m', 'merge', None, _('merge uncommitted changes')),
5310 ('m', 'merge', None, _('merge uncommitted changes')),
5306 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5311 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5307 ('r', 'rev', '', _('revision'), _('REV'))
5312 ('r', 'rev', '', _('revision'), _('REV'))
5308 ] + mergetoolopts,
5313 ] + mergetoolopts,
5309 _('[-C|-c|-m] [-d DATE] [[-r] REV]'))
5314 _('[-C|-c|-m] [-d DATE] [[-r] REV]'))
5310 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
5315 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
5311 merge=None, tool=None):
5316 merge=None, tool=None):
5312 """update working directory (or switch revisions)
5317 """update working directory (or switch revisions)
5313
5318
5314 Update the repository's working directory to the specified
5319 Update the repository's working directory to the specified
5315 changeset. If no changeset is specified, update to the tip of the
5320 changeset. If no changeset is specified, update to the tip of the
5316 current named branch and move the active bookmark (see :hg:`help
5321 current named branch and move the active bookmark (see :hg:`help
5317 bookmarks`).
5322 bookmarks`).
5318
5323
5319 Update sets the working directory's parent revision to the specified
5324 Update sets the working directory's parent revision to the specified
5320 changeset (see :hg:`help parents`).
5325 changeset (see :hg:`help parents`).
5321
5326
5322 If the changeset is not a descendant or ancestor of the working
5327 If the changeset is not a descendant or ancestor of the working
5323 directory's parent and there are uncommitted changes, the update is
5328 directory's parent and there are uncommitted changes, the update is
5324 aborted. With the -c/--check option, the working directory is checked
5329 aborted. With the -c/--check option, the working directory is checked
5325 for uncommitted changes; if none are found, the working directory is
5330 for uncommitted changes; if none are found, the working directory is
5326 updated to the specified changeset.
5331 updated to the specified changeset.
5327
5332
5328 .. container:: verbose
5333 .. container:: verbose
5329
5334
5330 The -C/--clean, -c/--check, and -m/--merge options control what
5335 The -C/--clean, -c/--check, and -m/--merge options control what
5331 happens if the working directory contains uncommitted changes.
5336 happens if the working directory contains uncommitted changes.
5332 At most of one of them can be specified.
5337 At most of one of them can be specified.
5333
5338
5334 1. If no option is specified, and if
5339 1. If no option is specified, and if
5335 the requested changeset is an ancestor or descendant of
5340 the requested changeset is an ancestor or descendant of
5336 the working directory's parent, the uncommitted changes
5341 the working directory's parent, the uncommitted changes
5337 are merged into the requested changeset and the merged
5342 are merged into the requested changeset and the merged
5338 result is left uncommitted. If the requested changeset is
5343 result is left uncommitted. If the requested changeset is
5339 not an ancestor or descendant (that is, it is on another
5344 not an ancestor or descendant (that is, it is on another
5340 branch), the update is aborted and the uncommitted changes
5345 branch), the update is aborted and the uncommitted changes
5341 are preserved.
5346 are preserved.
5342
5347
5343 2. With the -m/--merge option, the update is allowed even if the
5348 2. With the -m/--merge option, the update is allowed even if the
5344 requested changeset is not an ancestor or descendant of
5349 requested changeset is not an ancestor or descendant of
5345 the working directory's parent.
5350 the working directory's parent.
5346
5351
5347 3. With the -c/--check option, the update is aborted and the
5352 3. With the -c/--check option, the update is aborted and the
5348 uncommitted changes are preserved.
5353 uncommitted changes are preserved.
5349
5354
5350 4. With the -C/--clean option, uncommitted changes are discarded and
5355 4. With the -C/--clean option, uncommitted changes are discarded and
5351 the working directory is updated to the requested changeset.
5356 the working directory is updated to the requested changeset.
5352
5357
5353 To cancel an uncommitted merge (and lose your changes), use
5358 To cancel an uncommitted merge (and lose your changes), use
5354 :hg:`update --clean .`.
5359 :hg:`update --clean .`.
5355
5360
5356 Use null as the changeset to remove the working directory (like
5361 Use null as the changeset to remove the working directory (like
5357 :hg:`clone -U`).
5362 :hg:`clone -U`).
5358
5363
5359 If you want to revert just one file to an older revision, use
5364 If you want to revert just one file to an older revision, use
5360 :hg:`revert [-r REV] NAME`.
5365 :hg:`revert [-r REV] NAME`.
5361
5366
5362 See :hg:`help dates` for a list of formats valid for -d/--date.
5367 See :hg:`help dates` for a list of formats valid for -d/--date.
5363
5368
5364 Returns 0 on success, 1 if there are unresolved files.
5369 Returns 0 on success, 1 if there are unresolved files.
5365 """
5370 """
5366 if rev and node:
5371 if rev and node:
5367 raise error.Abort(_("please specify just one revision"))
5372 raise error.Abort(_("please specify just one revision"))
5368
5373
5369 if ui.configbool('commands', 'update.requiredest'):
5374 if ui.configbool('commands', 'update.requiredest'):
5370 if not node and not rev and not date:
5375 if not node and not rev and not date:
5371 raise error.Abort(_('you must specify a destination'),
5376 raise error.Abort(_('you must specify a destination'),
5372 hint=_('for example: hg update ".::"'))
5377 hint=_('for example: hg update ".::"'))
5373
5378
5374 if rev is None or rev == '':
5379 if rev is None or rev == '':
5375 rev = node
5380 rev = node
5376
5381
5377 if date and rev is not None:
5382 if date and rev is not None:
5378 raise error.Abort(_("you can't specify a revision and a date"))
5383 raise error.Abort(_("you can't specify a revision and a date"))
5379
5384
5380 if len([x for x in (clean, check, merge) if x]) > 1:
5385 if len([x for x in (clean, check, merge) if x]) > 1:
5381 raise error.Abort(_("can only specify one of -C/--clean, -c/--check, "
5386 raise error.Abort(_("can only specify one of -C/--clean, -c/--check, "
5382 "or -m/merge"))
5387 "or -m/merge"))
5383
5388
5384 updatecheck = None
5389 updatecheck = None
5385 if check:
5390 if check:
5386 updatecheck = 'abort'
5391 updatecheck = 'abort'
5387 elif merge:
5392 elif merge:
5388 updatecheck = 'none'
5393 updatecheck = 'none'
5389
5394
5390 with repo.wlock():
5395 with repo.wlock():
5391 cmdutil.clearunfinished(repo)
5396 cmdutil.clearunfinished(repo)
5392
5397
5393 if date:
5398 if date:
5394 rev = cmdutil.finddate(ui, repo, date)
5399 rev = cmdutil.finddate(ui, repo, date)
5395
5400
5396 # if we defined a bookmark, we have to remember the original name
5401 # if we defined a bookmark, we have to remember the original name
5397 brev = rev
5402 brev = rev
5398 rev = scmutil.revsingle(repo, rev, rev).rev()
5403 rev = scmutil.revsingle(repo, rev, rev).rev()
5399
5404
5400 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
5405 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
5401
5406
5402 return hg.updatetotally(ui, repo, rev, brev, clean=clean,
5407 return hg.updatetotally(ui, repo, rev, brev, clean=clean,
5403 updatecheck=updatecheck)
5408 updatecheck=updatecheck)
5404
5409
5405 @command('verify', [])
5410 @command('verify', [])
5406 def verify(ui, repo):
5411 def verify(ui, repo):
5407 """verify the integrity of the repository
5412 """verify the integrity of the repository
5408
5413
5409 Verify the integrity of the current repository.
5414 Verify the integrity of the current repository.
5410
5415
5411 This will perform an extensive check of the repository's
5416 This will perform an extensive check of the repository's
5412 integrity, validating the hashes and checksums of each entry in
5417 integrity, validating the hashes and checksums of each entry in
5413 the changelog, manifest, and tracked files, as well as the
5418 the changelog, manifest, and tracked files, as well as the
5414 integrity of their crosslinks and indices.
5419 integrity of their crosslinks and indices.
5415
5420
5416 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
5421 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
5417 for more information about recovery from corruption of the
5422 for more information about recovery from corruption of the
5418 repository.
5423 repository.
5419
5424
5420 Returns 0 on success, 1 if errors are encountered.
5425 Returns 0 on success, 1 if errors are encountered.
5421 """
5426 """
5422 return hg.verify(repo)
5427 return hg.verify(repo)
5423
5428
5424 @command('version', [] + formatteropts, norepo=True)
5429 @command('version', [] + formatteropts, norepo=True)
5425 def version_(ui, **opts):
5430 def version_(ui, **opts):
5426 """output version and copyright information"""
5431 """output version and copyright information"""
5427 opts = pycompat.byteskwargs(opts)
5432 opts = pycompat.byteskwargs(opts)
5428 if ui.verbose:
5433 if ui.verbose:
5429 ui.pager('version')
5434 ui.pager('version')
5430 fm = ui.formatter("version", opts)
5435 fm = ui.formatter("version", opts)
5431 fm.startitem()
5436 fm.startitem()
5432 fm.write("ver", _("Mercurial Distributed SCM (version %s)\n"),
5437 fm.write("ver", _("Mercurial Distributed SCM (version %s)\n"),
5433 util.version())
5438 util.version())
5434 license = _(
5439 license = _(
5435 "(see https://mercurial-scm.org for more information)\n"
5440 "(see https://mercurial-scm.org for more information)\n"
5436 "\nCopyright (C) 2005-2017 Matt Mackall and others\n"
5441 "\nCopyright (C) 2005-2017 Matt Mackall and others\n"
5437 "This is free software; see the source for copying conditions. "
5442 "This is free software; see the source for copying conditions. "
5438 "There is NO\nwarranty; "
5443 "There is NO\nwarranty; "
5439 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5444 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5440 )
5445 )
5441 if not ui.quiet:
5446 if not ui.quiet:
5442 fm.plain(license)
5447 fm.plain(license)
5443
5448
5444 if ui.verbose:
5449 if ui.verbose:
5445 fm.plain(_("\nEnabled extensions:\n\n"))
5450 fm.plain(_("\nEnabled extensions:\n\n"))
5446 # format names and versions into columns
5451 # format names and versions into columns
5447 names = []
5452 names = []
5448 vers = []
5453 vers = []
5449 isinternals = []
5454 isinternals = []
5450 for name, module in extensions.extensions():
5455 for name, module in extensions.extensions():
5451 names.append(name)
5456 names.append(name)
5452 vers.append(extensions.moduleversion(module) or None)
5457 vers.append(extensions.moduleversion(module) or None)
5453 isinternals.append(extensions.ismoduleinternal(module))
5458 isinternals.append(extensions.ismoduleinternal(module))
5454 fn = fm.nested("extensions")
5459 fn = fm.nested("extensions")
5455 if names:
5460 if names:
5456 namefmt = " %%-%ds " % max(len(n) for n in names)
5461 namefmt = " %%-%ds " % max(len(n) for n in names)
5457 places = [_("external"), _("internal")]
5462 places = [_("external"), _("internal")]
5458 for n, v, p in zip(names, vers, isinternals):
5463 for n, v, p in zip(names, vers, isinternals):
5459 fn.startitem()
5464 fn.startitem()
5460 fn.condwrite(ui.verbose, "name", namefmt, n)
5465 fn.condwrite(ui.verbose, "name", namefmt, n)
5461 if ui.verbose:
5466 if ui.verbose:
5462 fn.plain("%s " % places[p])
5467 fn.plain("%s " % places[p])
5463 fn.data(bundled=p)
5468 fn.data(bundled=p)
5464 fn.condwrite(ui.verbose and v, "ver", "%s", v)
5469 fn.condwrite(ui.verbose and v, "ver", "%s", v)
5465 if ui.verbose:
5470 if ui.verbose:
5466 fn.plain("\n")
5471 fn.plain("\n")
5467 fn.end()
5472 fn.end()
5468 fm.end()
5473 fm.end()
5469
5474
5470 def loadcmdtable(ui, name, cmdtable):
5475 def loadcmdtable(ui, name, cmdtable):
5471 """Load command functions from specified cmdtable
5476 """Load command functions from specified cmdtable
5472 """
5477 """
5473 overrides = [cmd for cmd in cmdtable if cmd in table]
5478 overrides = [cmd for cmd in cmdtable if cmd in table]
5474 if overrides:
5479 if overrides:
5475 ui.warn(_("extension '%s' overrides commands: %s\n")
5480 ui.warn(_("extension '%s' overrides commands: %s\n")
5476 % (name, " ".join(overrides)))
5481 % (name, " ".join(overrides)))
5477 table.update(cmdtable)
5482 table.update(cmdtable)
@@ -1,962 +1,990
1 $ hg init repo
1 $ hg init repo
2 $ cd repo
2 $ cd repo
3
3
4 no bookmarks
4 no bookmarks
5
5
6 $ hg bookmarks
6 $ hg bookmarks
7 no bookmarks set
7 no bookmarks set
8
8
9 $ hg bookmarks -Tjson
9 $ hg bookmarks -Tjson
10 [
10 [
11 ]
11 ]
12
12
13 bookmark rev -1
13 bookmark rev -1
14
14
15 $ hg bookmark X
15 $ hg bookmark X
16
16
17 list bookmarks
17 list bookmarks
18
18
19 $ hg bookmarks
19 $ hg bookmarks
20 * X -1:000000000000
20 * X -1:000000000000
21
21
22 list bookmarks with color
22 list bookmarks with color
23
23
24 $ hg --config extensions.color= --config color.mode=ansi \
24 $ hg --config extensions.color= --config color.mode=ansi \
25 > bookmarks --color=always
25 > bookmarks --color=always
26 \x1b[0;32m * \x1b[0m\x1b[0;32mX\x1b[0m\x1b[0;32m -1:000000000000\x1b[0m (esc)
26 \x1b[0;32m * \x1b[0m\x1b[0;32mX\x1b[0m\x1b[0;32m -1:000000000000\x1b[0m (esc)
27
27
28 $ echo a > a
28 $ echo a > a
29 $ hg add a
29 $ hg add a
30 $ hg commit -m 0
30 $ hg commit -m 0
31
31
32 bookmark X moved to rev 0
32 bookmark X moved to rev 0
33
33
34 $ hg bookmarks
34 $ hg bookmarks
35 * X 0:f7b1eb17ad24
35 * X 0:f7b1eb17ad24
36
36
37 look up bookmark
37 look up bookmark
38
38
39 $ hg log -r X
39 $ hg log -r X
40 changeset: 0:f7b1eb17ad24
40 changeset: 0:f7b1eb17ad24
41 bookmark: X
41 bookmark: X
42 tag: tip
42 tag: tip
43 user: test
43 user: test
44 date: Thu Jan 01 00:00:00 1970 +0000
44 date: Thu Jan 01 00:00:00 1970 +0000
45 summary: 0
45 summary: 0
46
46
47
47
48 second bookmark for rev 0, command should work even with ui.strict on
48 second bookmark for rev 0, command should work even with ui.strict on
49
49
50 $ hg --config ui.strict=1 bookmark X2
50 $ hg --config ui.strict=1 bookmark X2
51
51
52 bookmark rev -1 again
52 bookmark rev -1 again
53
53
54 $ hg bookmark -r null Y
54 $ hg bookmark -r null Y
55
55
56 list bookmarks
56 list bookmarks
57
57
58 $ hg bookmarks
58 $ hg bookmarks
59 X 0:f7b1eb17ad24
59 X 0:f7b1eb17ad24
60 * X2 0:f7b1eb17ad24
60 * X2 0:f7b1eb17ad24
61 Y -1:000000000000
61 Y -1:000000000000
62
62
63 $ echo b > b
63 $ echo b > b
64 $ hg add b
64 $ hg add b
65 $ hg commit -m 1
65 $ hg commit -m 1
66
66
67 $ hg bookmarks -Tjson
67 $ hg bookmarks -Tjson
68 [
68 [
69 {
69 {
70 "active": false,
70 "active": false,
71 "bookmark": "X",
71 "bookmark": "X",
72 "node": "f7b1eb17ad24730a1651fccd46c43826d1bbc2ac",
72 "node": "f7b1eb17ad24730a1651fccd46c43826d1bbc2ac",
73 "rev": 0
73 "rev": 0
74 },
74 },
75 {
75 {
76 "active": true,
76 "active": true,
77 "bookmark": "X2",
77 "bookmark": "X2",
78 "node": "925d80f479bb026b0fb3deb27503780b13f74123",
78 "node": "925d80f479bb026b0fb3deb27503780b13f74123",
79 "rev": 1
79 "rev": 1
80 },
80 },
81 {
81 {
82 "active": false,
82 "active": false,
83 "bookmark": "Y",
83 "bookmark": "Y",
84 "node": "0000000000000000000000000000000000000000",
84 "node": "0000000000000000000000000000000000000000",
85 "rev": -1
85 "rev": -1
86 }
86 }
87 ]
87 ]
88
88
89 bookmarks revset
89 bookmarks revset
90
90
91 $ hg log -r 'bookmark()'
91 $ hg log -r 'bookmark()'
92 changeset: 0:f7b1eb17ad24
92 changeset: 0:f7b1eb17ad24
93 bookmark: X
93 bookmark: X
94 user: test
94 user: test
95 date: Thu Jan 01 00:00:00 1970 +0000
95 date: Thu Jan 01 00:00:00 1970 +0000
96 summary: 0
96 summary: 0
97
97
98 changeset: 1:925d80f479bb
98 changeset: 1:925d80f479bb
99 bookmark: X2
99 bookmark: X2
100 tag: tip
100 tag: tip
101 user: test
101 user: test
102 date: Thu Jan 01 00:00:00 1970 +0000
102 date: Thu Jan 01 00:00:00 1970 +0000
103 summary: 1
103 summary: 1
104
104
105 $ hg log -r 'bookmark(Y)'
105 $ hg log -r 'bookmark(Y)'
106 $ hg log -r 'bookmark(X2)'
106 $ hg log -r 'bookmark(X2)'
107 changeset: 1:925d80f479bb
107 changeset: 1:925d80f479bb
108 bookmark: X2
108 bookmark: X2
109 tag: tip
109 tag: tip
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 summary: 1
112 summary: 1
113
113
114 $ hg log -r 'bookmark("re:X")'
114 $ hg log -r 'bookmark("re:X")'
115 changeset: 0:f7b1eb17ad24
115 changeset: 0:f7b1eb17ad24
116 bookmark: X
116 bookmark: X
117 user: test
117 user: test
118 date: Thu Jan 01 00:00:00 1970 +0000
118 date: Thu Jan 01 00:00:00 1970 +0000
119 summary: 0
119 summary: 0
120
120
121 changeset: 1:925d80f479bb
121 changeset: 1:925d80f479bb
122 bookmark: X2
122 bookmark: X2
123 tag: tip
123 tag: tip
124 user: test
124 user: test
125 date: Thu Jan 01 00:00:00 1970 +0000
125 date: Thu Jan 01 00:00:00 1970 +0000
126 summary: 1
126 summary: 1
127
127
128 $ hg log -r 'bookmark("literal:X")'
128 $ hg log -r 'bookmark("literal:X")'
129 changeset: 0:f7b1eb17ad24
129 changeset: 0:f7b1eb17ad24
130 bookmark: X
130 bookmark: X
131 user: test
131 user: test
132 date: Thu Jan 01 00:00:00 1970 +0000
132 date: Thu Jan 01 00:00:00 1970 +0000
133 summary: 0
133 summary: 0
134
134
135
135
136 $ hg log -r 'bookmark(unknown)'
136 $ hg log -r 'bookmark(unknown)'
137 abort: bookmark 'unknown' does not exist!
137 abort: bookmark 'unknown' does not exist!
138 [255]
138 [255]
139 $ hg log -r 'bookmark("literal:unknown")'
139 $ hg log -r 'bookmark("literal:unknown")'
140 abort: bookmark 'unknown' does not exist!
140 abort: bookmark 'unknown' does not exist!
141 [255]
141 [255]
142 $ hg log -r 'bookmark("re:unknown")'
142 $ hg log -r 'bookmark("re:unknown")'
143 abort: no bookmarks exist that match 'unknown'!
143 abort: no bookmarks exist that match 'unknown'!
144 [255]
144 [255]
145 $ hg log -r 'present(bookmark("literal:unknown"))'
145 $ hg log -r 'present(bookmark("literal:unknown"))'
146 $ hg log -r 'present(bookmark("re:unknown"))'
146 $ hg log -r 'present(bookmark("re:unknown"))'
147
147
148 $ hg help revsets | grep 'bookmark('
148 $ hg help revsets | grep 'bookmark('
149 "bookmark([name])"
149 "bookmark([name])"
150
150
151 bookmarks X and X2 moved to rev 1, Y at rev -1
151 bookmarks X and X2 moved to rev 1, Y at rev -1
152
152
153 $ hg bookmarks
153 $ hg bookmarks
154 X 0:f7b1eb17ad24
154 X 0:f7b1eb17ad24
155 * X2 1:925d80f479bb
155 * X2 1:925d80f479bb
156 Y -1:000000000000
156 Y -1:000000000000
157
157
158 bookmark rev 0 again
158 bookmark rev 0 again
159
159
160 $ hg bookmark -r 0 Z
160 $ hg bookmark -r 0 Z
161
161
162 $ hg update X
162 $ hg update X
163 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
163 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
164 (activating bookmark X)
164 (activating bookmark X)
165 $ echo c > c
165 $ echo c > c
166 $ hg add c
166 $ hg add c
167 $ hg commit -m 2
167 $ hg commit -m 2
168 created new head
168 created new head
169
169
170 bookmarks X moved to rev 2, Y at rev -1, Z at rev 0
170 bookmarks X moved to rev 2, Y at rev -1, Z at rev 0
171
171
172 $ hg bookmarks
172 $ hg bookmarks
173 * X 2:db815d6d32e6
173 * X 2:db815d6d32e6
174 X2 1:925d80f479bb
174 X2 1:925d80f479bb
175 Y -1:000000000000
175 Y -1:000000000000
176 Z 0:f7b1eb17ad24
176 Z 0:f7b1eb17ad24
177
177
178 rename nonexistent bookmark
178 rename nonexistent bookmark
179
179
180 $ hg bookmark -m A B
180 $ hg bookmark -m A B
181 abort: bookmark 'A' does not exist
181 abort: bookmark 'A' does not exist
182 [255]
182 [255]
183
183
184 rename to existent bookmark
184 rename to existent bookmark
185
185
186 $ hg bookmark -m X Y
186 $ hg bookmark -m X Y
187 abort: bookmark 'Y' already exists (use -f to force)
187 abort: bookmark 'Y' already exists (use -f to force)
188 [255]
188 [255]
189
189
190 force rename to existent bookmark
190 force rename to existent bookmark
191
191
192 $ hg bookmark -f -m X Y
192 $ hg bookmark -f -m X Y
193
193
194 list bookmarks
194 list bookmarks
195
195
196 $ hg bookmark
196 $ hg bookmark
197 X2 1:925d80f479bb
197 X2 1:925d80f479bb
198 * Y 2:db815d6d32e6
198 * Y 2:db815d6d32e6
199 Z 0:f7b1eb17ad24
199 Z 0:f7b1eb17ad24
200
200
201 bookmarks from a revset
201 bookmarks from a revset
202 $ hg bookmark -r '.^1' REVSET
202 $ hg bookmark -r '.^1' REVSET
203 $ hg bookmark -r ':tip' TIP
203 $ hg bookmark -r ':tip' TIP
204 $ hg up -q TIP
204 $ hg up -q TIP
205 $ hg bookmarks
205 $ hg bookmarks
206 REVSET 0:f7b1eb17ad24
206 REVSET 0:f7b1eb17ad24
207 * TIP 2:db815d6d32e6
207 * TIP 2:db815d6d32e6
208 X2 1:925d80f479bb
208 X2 1:925d80f479bb
209 Y 2:db815d6d32e6
209 Y 2:db815d6d32e6
210 Z 0:f7b1eb17ad24
210 Z 0:f7b1eb17ad24
211
211
212 $ hg bookmark -d REVSET
212 $ hg bookmark -d REVSET
213 $ hg bookmark -d TIP
213 $ hg bookmark -d TIP
214
214
215 rename without new name or multiple names
215 rename without new name or multiple names
216
216
217 $ hg bookmark -m Y
217 $ hg bookmark -m Y
218 abort: new bookmark name required
218 abort: new bookmark name required
219 [255]
219 [255]
220 $ hg bookmark -m Y Y2 Y3
220 $ hg bookmark -m Y Y2 Y3
221 abort: only one new bookmark name allowed
221 abort: only one new bookmark name allowed
222 [255]
222 [255]
223
223
224 delete without name
224 delete without name
225
225
226 $ hg bookmark -d
226 $ hg bookmark -d
227 abort: bookmark name required
227 abort: bookmark name required
228 [255]
228 [255]
229
229
230 delete nonexistent bookmark
230 delete nonexistent bookmark
231
231
232 $ hg bookmark -d A
232 $ hg bookmark -d A
233 abort: bookmark 'A' does not exist
233 abort: bookmark 'A' does not exist
234 [255]
234 [255]
235
235
236 bookmark name with spaces should be stripped
236 bookmark name with spaces should be stripped
237
237
238 $ hg bookmark ' x y '
238 $ hg bookmark ' x y '
239
239
240 list bookmarks
240 list bookmarks
241
241
242 $ hg bookmarks
242 $ hg bookmarks
243 X2 1:925d80f479bb
243 X2 1:925d80f479bb
244 Y 2:db815d6d32e6
244 Y 2:db815d6d32e6
245 Z 0:f7b1eb17ad24
245 Z 0:f7b1eb17ad24
246 * x y 2:db815d6d32e6
246 * x y 2:db815d6d32e6
247
247
248 look up stripped bookmark name
248 look up stripped bookmark name
249
249
250 $ hg log -r '"x y"'
250 $ hg log -r '"x y"'
251 changeset: 2:db815d6d32e6
251 changeset: 2:db815d6d32e6
252 bookmark: Y
252 bookmark: Y
253 bookmark: x y
253 bookmark: x y
254 tag: tip
254 tag: tip
255 parent: 0:f7b1eb17ad24
255 parent: 0:f7b1eb17ad24
256 user: test
256 user: test
257 date: Thu Jan 01 00:00:00 1970 +0000
257 date: Thu Jan 01 00:00:00 1970 +0000
258 summary: 2
258 summary: 2
259
259
260
260
261 reject bookmark name with newline
261 reject bookmark name with newline
262
262
263 $ hg bookmark '
263 $ hg bookmark '
264 > '
264 > '
265 abort: bookmark names cannot consist entirely of whitespace
265 abort: bookmark names cannot consist entirely of whitespace
266 [255]
266 [255]
267
267
268 $ hg bookmark -m Z '
268 $ hg bookmark -m Z '
269 > '
269 > '
270 abort: bookmark names cannot consist entirely of whitespace
270 abort: bookmark names cannot consist entirely of whitespace
271 [255]
271 [255]
272
272
273 bookmark with reserved name
273 bookmark with reserved name
274
274
275 $ hg bookmark tip
275 $ hg bookmark tip
276 abort: the name 'tip' is reserved
276 abort: the name 'tip' is reserved
277 [255]
277 [255]
278
278
279 $ hg bookmark .
279 $ hg bookmark .
280 abort: the name '.' is reserved
280 abort: the name '.' is reserved
281 [255]
281 [255]
282
282
283 $ hg bookmark null
283 $ hg bookmark null
284 abort: the name 'null' is reserved
284 abort: the name 'null' is reserved
285 [255]
285 [255]
286
286
287
287
288 bookmark with existing name
288 bookmark with existing name
289
289
290 $ hg bookmark X2
290 $ hg bookmark X2
291 abort: bookmark 'X2' already exists (use -f to force)
291 abort: bookmark 'X2' already exists (use -f to force)
292 [255]
292 [255]
293
293
294 $ hg bookmark -m Y Z
294 $ hg bookmark -m Y Z
295 abort: bookmark 'Z' already exists (use -f to force)
295 abort: bookmark 'Z' already exists (use -f to force)
296 [255]
296 [255]
297
297
298 bookmark with name of branch
298 bookmark with name of branch
299
299
300 $ hg bookmark default
300 $ hg bookmark default
301 abort: a bookmark cannot have the name of an existing branch
301 abort: a bookmark cannot have the name of an existing branch
302 [255]
302 [255]
303
303
304 $ hg bookmark -m Y default
304 $ hg bookmark -m Y default
305 abort: a bookmark cannot have the name of an existing branch
305 abort: a bookmark cannot have the name of an existing branch
306 [255]
306 [255]
307
307
308 bookmark with integer name
308 bookmark with integer name
309
309
310 $ hg bookmark 10
310 $ hg bookmark 10
311 abort: cannot use an integer as a name
311 abort: cannot use an integer as a name
312 [255]
312 [255]
313
313
314 bookmark with a name that matches a node id
314 bookmark with a name that matches a node id
315 $ hg bookmark 925d80f479bb db815d6d32e6
315 $ hg bookmark 925d80f479bb db815d6d32e6
316 bookmark 925d80f479bb matches a changeset hash
316 bookmark 925d80f479bb matches a changeset hash
317 (did you leave a -r out of an 'hg bookmark' command?)
317 (did you leave a -r out of an 'hg bookmark' command?)
318 bookmark db815d6d32e6 matches a changeset hash
318 bookmark db815d6d32e6 matches a changeset hash
319 (did you leave a -r out of an 'hg bookmark' command?)
319 (did you leave a -r out of an 'hg bookmark' command?)
320 $ hg bookmark -d 925d80f479bb
320 $ hg bookmark -d 925d80f479bb
321 $ hg bookmark -d db815d6d32e6
321 $ hg bookmark -d db815d6d32e6
322
322
323 $ cd ..
324
325 bookmark with a name that matches an ambiguous node id
326
327 $ hg init ambiguous
328 $ cd ambiguous
329 $ echo 0 > a
330 $ hg ci -qAm 0
331 $ for i in 1057 2857 4025; do
332 > hg up -q 0
333 > echo $i > a
334 > hg ci -qm $i
335 > done
336 $ hg up -q null
337 $ hg log -r0: -T '{rev}:{node}\n'
338 0:b4e73ffab476aa0ee32ed81ca51e07169844bc6a
339 1:c56256a09cd28e5764f32e8e2810d0f01e2e357a
340 2:c5623987d205cd6d9d8389bfc40fff9dbb670b48
341 3:c562ddd9c94164376c20b86b0b4991636a3bf84f
342
343 $ hg bookmark -r0 c562
344 $ hg bookmarks
345 c562 0:b4e73ffab476
346
347 $ cd ..
348
323 incompatible options
349 incompatible options
324
350
351 $ cd repo
352
325 $ hg bookmark -m Y -d Z
353 $ hg bookmark -m Y -d Z
326 abort: --delete and --rename are incompatible
354 abort: --delete and --rename are incompatible
327 [255]
355 [255]
328
356
329 $ hg bookmark -r 1 -d Z
357 $ hg bookmark -r 1 -d Z
330 abort: --rev is incompatible with --delete
358 abort: --rev is incompatible with --delete
331 [255]
359 [255]
332
360
333 $ hg bookmark -r 1 -m Z Y
361 $ hg bookmark -r 1 -m Z Y
334 abort: --rev is incompatible with --rename
362 abort: --rev is incompatible with --rename
335 [255]
363 [255]
336
364
337 force bookmark with existing name
365 force bookmark with existing name
338
366
339 $ hg bookmark -f X2
367 $ hg bookmark -f X2
340
368
341 force bookmark back to where it was, should deactivate it
369 force bookmark back to where it was, should deactivate it
342
370
343 $ hg bookmark -fr1 X2
371 $ hg bookmark -fr1 X2
344 $ hg bookmarks
372 $ hg bookmarks
345 X2 1:925d80f479bb
373 X2 1:925d80f479bb
346 Y 2:db815d6d32e6
374 Y 2:db815d6d32e6
347 Z 0:f7b1eb17ad24
375 Z 0:f7b1eb17ad24
348 x y 2:db815d6d32e6
376 x y 2:db815d6d32e6
349
377
350 forward bookmark to descendant without --force
378 forward bookmark to descendant without --force
351
379
352 $ hg bookmark Z
380 $ hg bookmark Z
353 moving bookmark 'Z' forward from f7b1eb17ad24
381 moving bookmark 'Z' forward from f7b1eb17ad24
354
382
355 list bookmarks
383 list bookmarks
356
384
357 $ hg bookmark
385 $ hg bookmark
358 X2 1:925d80f479bb
386 X2 1:925d80f479bb
359 Y 2:db815d6d32e6
387 Y 2:db815d6d32e6
360 * Z 2:db815d6d32e6
388 * Z 2:db815d6d32e6
361 x y 2:db815d6d32e6
389 x y 2:db815d6d32e6
362
390
363 revision but no bookmark name
391 revision but no bookmark name
364
392
365 $ hg bookmark -r .
393 $ hg bookmark -r .
366 abort: bookmark name required
394 abort: bookmark name required
367 [255]
395 [255]
368
396
369 bookmark name with whitespace only
397 bookmark name with whitespace only
370
398
371 $ hg bookmark ' '
399 $ hg bookmark ' '
372 abort: bookmark names cannot consist entirely of whitespace
400 abort: bookmark names cannot consist entirely of whitespace
373 [255]
401 [255]
374
402
375 $ hg bookmark -m Y ' '
403 $ hg bookmark -m Y ' '
376 abort: bookmark names cannot consist entirely of whitespace
404 abort: bookmark names cannot consist entirely of whitespace
377 [255]
405 [255]
378
406
379 invalid bookmark
407 invalid bookmark
380
408
381 $ hg bookmark 'foo:bar'
409 $ hg bookmark 'foo:bar'
382 abort: ':' cannot be used in a name
410 abort: ':' cannot be used in a name
383 [255]
411 [255]
384
412
385 $ hg bookmark 'foo
413 $ hg bookmark 'foo
386 > bar'
414 > bar'
387 abort: '\n' cannot be used in a name
415 abort: '\n' cannot be used in a name
388 [255]
416 [255]
389
417
390 the bookmark extension should be ignored now that it is part of core
418 the bookmark extension should be ignored now that it is part of core
391
419
392 $ echo "[extensions]" >> $HGRCPATH
420 $ echo "[extensions]" >> $HGRCPATH
393 $ echo "bookmarks=" >> $HGRCPATH
421 $ echo "bookmarks=" >> $HGRCPATH
394 $ hg bookmarks
422 $ hg bookmarks
395 X2 1:925d80f479bb
423 X2 1:925d80f479bb
396 Y 2:db815d6d32e6
424 Y 2:db815d6d32e6
397 * Z 2:db815d6d32e6
425 * Z 2:db815d6d32e6
398 x y 2:db815d6d32e6
426 x y 2:db815d6d32e6
399
427
400 test summary
428 test summary
401
429
402 $ hg summary
430 $ hg summary
403 parent: 2:db815d6d32e6 tip
431 parent: 2:db815d6d32e6 tip
404 2
432 2
405 branch: default
433 branch: default
406 bookmarks: *Z Y x y
434 bookmarks: *Z Y x y
407 commit: (clean)
435 commit: (clean)
408 update: 1 new changesets, 2 branch heads (merge)
436 update: 1 new changesets, 2 branch heads (merge)
409 phases: 3 draft
437 phases: 3 draft
410
438
411 test id
439 test id
412
440
413 $ hg id
441 $ hg id
414 db815d6d32e6 tip Y/Z/x y
442 db815d6d32e6 tip Y/Z/x y
415
443
416 test rollback
444 test rollback
417
445
418 $ echo foo > f1
446 $ echo foo > f1
419 $ hg bookmark tmp-rollback
447 $ hg bookmark tmp-rollback
420 $ hg ci -Amr
448 $ hg ci -Amr
421 adding f1
449 adding f1
422 $ hg bookmarks
450 $ hg bookmarks
423 X2 1:925d80f479bb
451 X2 1:925d80f479bb
424 Y 2:db815d6d32e6
452 Y 2:db815d6d32e6
425 Z 2:db815d6d32e6
453 Z 2:db815d6d32e6
426 * tmp-rollback 3:2bf5cfec5864
454 * tmp-rollback 3:2bf5cfec5864
427 x y 2:db815d6d32e6
455 x y 2:db815d6d32e6
428 $ hg rollback
456 $ hg rollback
429 repository tip rolled back to revision 2 (undo commit)
457 repository tip rolled back to revision 2 (undo commit)
430 working directory now based on revision 2
458 working directory now based on revision 2
431 $ hg bookmarks
459 $ hg bookmarks
432 X2 1:925d80f479bb
460 X2 1:925d80f479bb
433 Y 2:db815d6d32e6
461 Y 2:db815d6d32e6
434 Z 2:db815d6d32e6
462 Z 2:db815d6d32e6
435 * tmp-rollback 2:db815d6d32e6
463 * tmp-rollback 2:db815d6d32e6
436 x y 2:db815d6d32e6
464 x y 2:db815d6d32e6
437 $ hg bookmark -f Z -r 1
465 $ hg bookmark -f Z -r 1
438 $ hg rollback
466 $ hg rollback
439 repository tip rolled back to revision 2 (undo bookmark)
467 repository tip rolled back to revision 2 (undo bookmark)
440 $ hg bookmarks
468 $ hg bookmarks
441 X2 1:925d80f479bb
469 X2 1:925d80f479bb
442 Y 2:db815d6d32e6
470 Y 2:db815d6d32e6
443 Z 2:db815d6d32e6
471 Z 2:db815d6d32e6
444 * tmp-rollback 2:db815d6d32e6
472 * tmp-rollback 2:db815d6d32e6
445 x y 2:db815d6d32e6
473 x y 2:db815d6d32e6
446 $ hg bookmark -d tmp-rollback
474 $ hg bookmark -d tmp-rollback
447
475
448 activate bookmark on working dir parent without --force
476 activate bookmark on working dir parent without --force
449
477
450 $ hg bookmark --inactive Z
478 $ hg bookmark --inactive Z
451 $ hg bookmark Z
479 $ hg bookmark Z
452
480
453 test clone
481 test clone
454
482
455 $ hg bookmark -r 2 -i @
483 $ hg bookmark -r 2 -i @
456 $ hg bookmark -r 2 -i a@
484 $ hg bookmark -r 2 -i a@
457 $ hg bookmarks
485 $ hg bookmarks
458 @ 2:db815d6d32e6
486 @ 2:db815d6d32e6
459 X2 1:925d80f479bb
487 X2 1:925d80f479bb
460 Y 2:db815d6d32e6
488 Y 2:db815d6d32e6
461 * Z 2:db815d6d32e6
489 * Z 2:db815d6d32e6
462 a@ 2:db815d6d32e6
490 a@ 2:db815d6d32e6
463 x y 2:db815d6d32e6
491 x y 2:db815d6d32e6
464 $ hg clone . cloned-bookmarks
492 $ hg clone . cloned-bookmarks
465 updating to bookmark @
493 updating to bookmark @
466 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
494 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
467 $ hg -R cloned-bookmarks bookmarks
495 $ hg -R cloned-bookmarks bookmarks
468 * @ 2:db815d6d32e6
496 * @ 2:db815d6d32e6
469 X2 1:925d80f479bb
497 X2 1:925d80f479bb
470 Y 2:db815d6d32e6
498 Y 2:db815d6d32e6
471 Z 2:db815d6d32e6
499 Z 2:db815d6d32e6
472 a@ 2:db815d6d32e6
500 a@ 2:db815d6d32e6
473 x y 2:db815d6d32e6
501 x y 2:db815d6d32e6
474
502
475 test clone with pull protocol
503 test clone with pull protocol
476
504
477 $ hg clone --pull . cloned-bookmarks-pull
505 $ hg clone --pull . cloned-bookmarks-pull
478 requesting all changes
506 requesting all changes
479 adding changesets
507 adding changesets
480 adding manifests
508 adding manifests
481 adding file changes
509 adding file changes
482 added 3 changesets with 3 changes to 3 files (+1 heads)
510 added 3 changesets with 3 changes to 3 files (+1 heads)
483 updating to bookmark @
511 updating to bookmark @
484 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
512 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
485 $ hg -R cloned-bookmarks-pull bookmarks
513 $ hg -R cloned-bookmarks-pull bookmarks
486 * @ 2:db815d6d32e6
514 * @ 2:db815d6d32e6
487 X2 1:925d80f479bb
515 X2 1:925d80f479bb
488 Y 2:db815d6d32e6
516 Y 2:db815d6d32e6
489 Z 2:db815d6d32e6
517 Z 2:db815d6d32e6
490 a@ 2:db815d6d32e6
518 a@ 2:db815d6d32e6
491 x y 2:db815d6d32e6
519 x y 2:db815d6d32e6
492
520
493 delete multiple bookmarks at once
521 delete multiple bookmarks at once
494
522
495 $ hg bookmark -d @ a@
523 $ hg bookmark -d @ a@
496
524
497 test clone with a bookmark named "default" (issue3677)
525 test clone with a bookmark named "default" (issue3677)
498
526
499 $ hg bookmark -r 1 -f -i default
527 $ hg bookmark -r 1 -f -i default
500 $ hg clone . cloned-bookmark-default
528 $ hg clone . cloned-bookmark-default
501 updating to branch default
529 updating to branch default
502 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
530 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
503 $ hg -R cloned-bookmark-default bookmarks
531 $ hg -R cloned-bookmark-default bookmarks
504 X2 1:925d80f479bb
532 X2 1:925d80f479bb
505 Y 2:db815d6d32e6
533 Y 2:db815d6d32e6
506 Z 2:db815d6d32e6
534 Z 2:db815d6d32e6
507 default 1:925d80f479bb
535 default 1:925d80f479bb
508 x y 2:db815d6d32e6
536 x y 2:db815d6d32e6
509 $ hg -R cloned-bookmark-default parents -q
537 $ hg -R cloned-bookmark-default parents -q
510 2:db815d6d32e6
538 2:db815d6d32e6
511 $ hg bookmark -d default
539 $ hg bookmark -d default
512
540
513 test clone with a specific revision
541 test clone with a specific revision
514
542
515 $ hg clone -r 925d80 . cloned-bookmarks-rev
543 $ hg clone -r 925d80 . cloned-bookmarks-rev
516 adding changesets
544 adding changesets
517 adding manifests
545 adding manifests
518 adding file changes
546 adding file changes
519 added 2 changesets with 2 changes to 2 files
547 added 2 changesets with 2 changes to 2 files
520 updating to branch default
548 updating to branch default
521 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
549 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
522 $ hg -R cloned-bookmarks-rev bookmarks
550 $ hg -R cloned-bookmarks-rev bookmarks
523 X2 1:925d80f479bb
551 X2 1:925d80f479bb
524
552
525 test clone with update to a bookmark
553 test clone with update to a bookmark
526
554
527 $ hg clone -u Z . ../cloned-bookmarks-update
555 $ hg clone -u Z . ../cloned-bookmarks-update
528 updating to branch default
556 updating to branch default
529 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
557 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
530 $ hg -R ../cloned-bookmarks-update bookmarks
558 $ hg -R ../cloned-bookmarks-update bookmarks
531 X2 1:925d80f479bb
559 X2 1:925d80f479bb
532 Y 2:db815d6d32e6
560 Y 2:db815d6d32e6
533 * Z 2:db815d6d32e6
561 * Z 2:db815d6d32e6
534 x y 2:db815d6d32e6
562 x y 2:db815d6d32e6
535
563
536 create bundle with two heads
564 create bundle with two heads
537
565
538 $ hg clone . tobundle
566 $ hg clone . tobundle
539 updating to branch default
567 updating to branch default
540 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
568 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
541 $ echo x > tobundle/x
569 $ echo x > tobundle/x
542 $ hg -R tobundle add tobundle/x
570 $ hg -R tobundle add tobundle/x
543 $ hg -R tobundle commit -m'x'
571 $ hg -R tobundle commit -m'x'
544 $ hg -R tobundle update -r -2
572 $ hg -R tobundle update -r -2
545 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
573 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
546 $ echo y > tobundle/y
574 $ echo y > tobundle/y
547 $ hg -R tobundle branch test
575 $ hg -R tobundle branch test
548 marked working directory as branch test
576 marked working directory as branch test
549 (branches are permanent and global, did you want a bookmark?)
577 (branches are permanent and global, did you want a bookmark?)
550 $ hg -R tobundle add tobundle/y
578 $ hg -R tobundle add tobundle/y
551 $ hg -R tobundle commit -m'y'
579 $ hg -R tobundle commit -m'y'
552 $ hg -R tobundle bundle tobundle.hg
580 $ hg -R tobundle bundle tobundle.hg
553 searching for changes
581 searching for changes
554 2 changesets found
582 2 changesets found
555 $ hg unbundle tobundle.hg
583 $ hg unbundle tobundle.hg
556 adding changesets
584 adding changesets
557 adding manifests
585 adding manifests
558 adding file changes
586 adding file changes
559 added 2 changesets with 2 changes to 2 files (+1 heads)
587 added 2 changesets with 2 changes to 2 files (+1 heads)
560 (run 'hg heads' to see heads, 'hg merge' to merge)
588 (run 'hg heads' to see heads, 'hg merge' to merge)
561
589
562 update to active bookmark if it's not the parent
590 update to active bookmark if it's not the parent
563
591
564 $ hg summary
592 $ hg summary
565 parent: 2:db815d6d32e6
593 parent: 2:db815d6d32e6
566 2
594 2
567 branch: default
595 branch: default
568 bookmarks: *Z Y x y
596 bookmarks: *Z Y x y
569 commit: 1 added, 1 unknown (new branch head)
597 commit: 1 added, 1 unknown (new branch head)
570 update: 2 new changesets (update)
598 update: 2 new changesets (update)
571 phases: 5 draft
599 phases: 5 draft
572 $ hg update
600 $ hg update
573 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
601 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
574 updating bookmark Z
602 updating bookmark Z
575 $ hg bookmarks
603 $ hg bookmarks
576 X2 1:925d80f479bb
604 X2 1:925d80f479bb
577 Y 2:db815d6d32e6
605 Y 2:db815d6d32e6
578 * Z 3:125c9a1d6df6
606 * Z 3:125c9a1d6df6
579 x y 2:db815d6d32e6
607 x y 2:db815d6d32e6
580
608
581 pull --update works the same as pull && update
609 pull --update works the same as pull && update
582
610
583 $ hg bookmark -r3 Y
611 $ hg bookmark -r3 Y
584 moving bookmark 'Y' forward from db815d6d32e6
612 moving bookmark 'Y' forward from db815d6d32e6
585 $ cp -R ../cloned-bookmarks-update ../cloned-bookmarks-manual-update
613 $ cp -R ../cloned-bookmarks-update ../cloned-bookmarks-manual-update
586 $ cp -R ../cloned-bookmarks-update ../cloned-bookmarks-manual-update-with-divergence
614 $ cp -R ../cloned-bookmarks-update ../cloned-bookmarks-manual-update-with-divergence
587
615
588 (manual version)
616 (manual version)
589
617
590 $ hg -R ../cloned-bookmarks-manual-update update Y
618 $ hg -R ../cloned-bookmarks-manual-update update Y
591 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
619 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
592 (activating bookmark Y)
620 (activating bookmark Y)
593 $ hg -R ../cloned-bookmarks-manual-update pull .
621 $ hg -R ../cloned-bookmarks-manual-update pull .
594 pulling from .
622 pulling from .
595 searching for changes
623 searching for changes
596 adding changesets
624 adding changesets
597 adding manifests
625 adding manifests
598 adding file changes
626 adding file changes
599 added 2 changesets with 2 changes to 2 files (+1 heads)
627 added 2 changesets with 2 changes to 2 files (+1 heads)
600 updating bookmark Y
628 updating bookmark Y
601 updating bookmark Z
629 updating bookmark Z
602 (run 'hg heads' to see heads, 'hg merge' to merge)
630 (run 'hg heads' to see heads, 'hg merge' to merge)
603
631
604 (# tests strange but with --date crashing when bookmark have to move)
632 (# tests strange but with --date crashing when bookmark have to move)
605
633
606 $ hg -R ../cloned-bookmarks-manual-update update -d 1986
634 $ hg -R ../cloned-bookmarks-manual-update update -d 1986
607 abort: revision matching date not found
635 abort: revision matching date not found
608 [255]
636 [255]
609 $ hg -R ../cloned-bookmarks-manual-update update
637 $ hg -R ../cloned-bookmarks-manual-update update
610 updating to active bookmark Y
638 updating to active bookmark Y
611 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
639 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
612
640
613 (all in one version)
641 (all in one version)
614
642
615 $ hg -R ../cloned-bookmarks-update update Y
643 $ hg -R ../cloned-bookmarks-update update Y
616 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
644 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
617 (activating bookmark Y)
645 (activating bookmark Y)
618 $ hg -R ../cloned-bookmarks-update pull --update .
646 $ hg -R ../cloned-bookmarks-update pull --update .
619 pulling from .
647 pulling from .
620 searching for changes
648 searching for changes
621 adding changesets
649 adding changesets
622 adding manifests
650 adding manifests
623 adding file changes
651 adding file changes
624 added 2 changesets with 2 changes to 2 files (+1 heads)
652 added 2 changesets with 2 changes to 2 files (+1 heads)
625 updating bookmark Y
653 updating bookmark Y
626 updating bookmark Z
654 updating bookmark Z
627 updating to active bookmark Y
655 updating to active bookmark Y
628 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
656 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
629
657
630 We warn about divergent during bare update to the active bookmark
658 We warn about divergent during bare update to the active bookmark
631
659
632 $ hg -R ../cloned-bookmarks-manual-update-with-divergence update Y
660 $ hg -R ../cloned-bookmarks-manual-update-with-divergence update Y
633 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
661 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
634 (activating bookmark Y)
662 (activating bookmark Y)
635 $ hg -R ../cloned-bookmarks-manual-update-with-divergence bookmarks -r X2 Y@1
663 $ hg -R ../cloned-bookmarks-manual-update-with-divergence bookmarks -r X2 Y@1
636 $ hg -R ../cloned-bookmarks-manual-update-with-divergence bookmarks
664 $ hg -R ../cloned-bookmarks-manual-update-with-divergence bookmarks
637 X2 1:925d80f479bb
665 X2 1:925d80f479bb
638 * Y 2:db815d6d32e6
666 * Y 2:db815d6d32e6
639 Y@1 1:925d80f479bb
667 Y@1 1:925d80f479bb
640 Z 2:db815d6d32e6
668 Z 2:db815d6d32e6
641 x y 2:db815d6d32e6
669 x y 2:db815d6d32e6
642 $ hg -R ../cloned-bookmarks-manual-update-with-divergence pull
670 $ hg -R ../cloned-bookmarks-manual-update-with-divergence pull
643 pulling from $TESTTMP/repo (glob)
671 pulling from $TESTTMP/repo (glob)
644 searching for changes
672 searching for changes
645 adding changesets
673 adding changesets
646 adding manifests
674 adding manifests
647 adding file changes
675 adding file changes
648 added 2 changesets with 2 changes to 2 files (+1 heads)
676 added 2 changesets with 2 changes to 2 files (+1 heads)
649 updating bookmark Y
677 updating bookmark Y
650 updating bookmark Z
678 updating bookmark Z
651 (run 'hg heads' to see heads, 'hg merge' to merge)
679 (run 'hg heads' to see heads, 'hg merge' to merge)
652 $ hg -R ../cloned-bookmarks-manual-update-with-divergence update
680 $ hg -R ../cloned-bookmarks-manual-update-with-divergence update
653 updating to active bookmark Y
681 updating to active bookmark Y
654 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
682 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
655 1 other divergent bookmarks for "Y"
683 1 other divergent bookmarks for "Y"
656
684
657 test wrongly formated bookmark
685 test wrongly formated bookmark
658
686
659 $ echo '' >> .hg/bookmarks
687 $ echo '' >> .hg/bookmarks
660 $ hg bookmarks
688 $ hg bookmarks
661 X2 1:925d80f479bb
689 X2 1:925d80f479bb
662 Y 3:125c9a1d6df6
690 Y 3:125c9a1d6df6
663 * Z 3:125c9a1d6df6
691 * Z 3:125c9a1d6df6
664 x y 2:db815d6d32e6
692 x y 2:db815d6d32e6
665 $ echo "Ican'thasformatedlines" >> .hg/bookmarks
693 $ echo "Ican'thasformatedlines" >> .hg/bookmarks
666 $ hg bookmarks
694 $ hg bookmarks
667 malformed line in .hg/bookmarks: "Ican'thasformatedlines"
695 malformed line in .hg/bookmarks: "Ican'thasformatedlines"
668 X2 1:925d80f479bb
696 X2 1:925d80f479bb
669 Y 3:125c9a1d6df6
697 Y 3:125c9a1d6df6
670 * Z 3:125c9a1d6df6
698 * Z 3:125c9a1d6df6
671 x y 2:db815d6d32e6
699 x y 2:db815d6d32e6
672
700
673 test missing revisions
701 test missing revisions
674
702
675 $ echo "925d80f479bc z" > .hg/bookmarks
703 $ echo "925d80f479bc z" > .hg/bookmarks
676 $ hg book
704 $ hg book
677 no bookmarks set
705 no bookmarks set
678
706
679 test stripping a non-checked-out but bookmarked revision
707 test stripping a non-checked-out but bookmarked revision
680
708
681 $ hg log --graph
709 $ hg log --graph
682 o changeset: 4:9ba5f110a0b3
710 o changeset: 4:9ba5f110a0b3
683 | branch: test
711 | branch: test
684 | tag: tip
712 | tag: tip
685 | parent: 2:db815d6d32e6
713 | parent: 2:db815d6d32e6
686 | user: test
714 | user: test
687 | date: Thu Jan 01 00:00:00 1970 +0000
715 | date: Thu Jan 01 00:00:00 1970 +0000
688 | summary: y
716 | summary: y
689 |
717 |
690 | @ changeset: 3:125c9a1d6df6
718 | @ changeset: 3:125c9a1d6df6
691 |/ user: test
719 |/ user: test
692 | date: Thu Jan 01 00:00:00 1970 +0000
720 | date: Thu Jan 01 00:00:00 1970 +0000
693 | summary: x
721 | summary: x
694 |
722 |
695 o changeset: 2:db815d6d32e6
723 o changeset: 2:db815d6d32e6
696 | parent: 0:f7b1eb17ad24
724 | parent: 0:f7b1eb17ad24
697 | user: test
725 | user: test
698 | date: Thu Jan 01 00:00:00 1970 +0000
726 | date: Thu Jan 01 00:00:00 1970 +0000
699 | summary: 2
727 | summary: 2
700 |
728 |
701 | o changeset: 1:925d80f479bb
729 | o changeset: 1:925d80f479bb
702 |/ user: test
730 |/ user: test
703 | date: Thu Jan 01 00:00:00 1970 +0000
731 | date: Thu Jan 01 00:00:00 1970 +0000
704 | summary: 1
732 | summary: 1
705 |
733 |
706 o changeset: 0:f7b1eb17ad24
734 o changeset: 0:f7b1eb17ad24
707 user: test
735 user: test
708 date: Thu Jan 01 00:00:00 1970 +0000
736 date: Thu Jan 01 00:00:00 1970 +0000
709 summary: 0
737 summary: 0
710
738
711 $ hg book should-end-on-two
739 $ hg book should-end-on-two
712 $ hg co --clean 4
740 $ hg co --clean 4
713 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
741 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
714 (leaving bookmark should-end-on-two)
742 (leaving bookmark should-end-on-two)
715 $ hg book four
743 $ hg book four
716 $ hg --config extensions.mq= strip 3
744 $ hg --config extensions.mq= strip 3
717 saved backup bundle to * (glob)
745 saved backup bundle to * (glob)
718 should-end-on-two should end up pointing to revision 2, as that's the
746 should-end-on-two should end up pointing to revision 2, as that's the
719 tipmost surviving ancestor of the stripped revision.
747 tipmost surviving ancestor of the stripped revision.
720 $ hg log --graph
748 $ hg log --graph
721 @ changeset: 3:9ba5f110a0b3
749 @ changeset: 3:9ba5f110a0b3
722 | branch: test
750 | branch: test
723 | bookmark: four
751 | bookmark: four
724 | tag: tip
752 | tag: tip
725 | user: test
753 | user: test
726 | date: Thu Jan 01 00:00:00 1970 +0000
754 | date: Thu Jan 01 00:00:00 1970 +0000
727 | summary: y
755 | summary: y
728 |
756 |
729 o changeset: 2:db815d6d32e6
757 o changeset: 2:db815d6d32e6
730 | bookmark: should-end-on-two
758 | bookmark: should-end-on-two
731 | parent: 0:f7b1eb17ad24
759 | parent: 0:f7b1eb17ad24
732 | user: test
760 | user: test
733 | date: Thu Jan 01 00:00:00 1970 +0000
761 | date: Thu Jan 01 00:00:00 1970 +0000
734 | summary: 2
762 | summary: 2
735 |
763 |
736 | o changeset: 1:925d80f479bb
764 | o changeset: 1:925d80f479bb
737 |/ user: test
765 |/ user: test
738 | date: Thu Jan 01 00:00:00 1970 +0000
766 | date: Thu Jan 01 00:00:00 1970 +0000
739 | summary: 1
767 | summary: 1
740 |
768 |
741 o changeset: 0:f7b1eb17ad24
769 o changeset: 0:f7b1eb17ad24
742 user: test
770 user: test
743 date: Thu Jan 01 00:00:00 1970 +0000
771 date: Thu Jan 01 00:00:00 1970 +0000
744 summary: 0
772 summary: 0
745
773
746
774
747 no-op update doesn't deactivate bookmarks
775 no-op update doesn't deactivate bookmarks
748
776
749 $ hg bookmarks
777 $ hg bookmarks
750 * four 3:9ba5f110a0b3
778 * four 3:9ba5f110a0b3
751 should-end-on-two 2:db815d6d32e6
779 should-end-on-two 2:db815d6d32e6
752 $ hg up four
780 $ hg up four
753 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
781 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
754 $ hg up
782 $ hg up
755 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
783 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
756 $ hg sum
784 $ hg sum
757 parent: 3:9ba5f110a0b3 tip
785 parent: 3:9ba5f110a0b3 tip
758 y
786 y
759 branch: test
787 branch: test
760 bookmarks: *four
788 bookmarks: *four
761 commit: 2 unknown (clean)
789 commit: 2 unknown (clean)
762 update: (current)
790 update: (current)
763 phases: 4 draft
791 phases: 4 draft
764
792
765 test clearing divergent bookmarks of linear ancestors
793 test clearing divergent bookmarks of linear ancestors
766
794
767 $ hg bookmark Z -r 0
795 $ hg bookmark Z -r 0
768 $ hg bookmark Z@1 -r 1
796 $ hg bookmark Z@1 -r 1
769 $ hg bookmark Z@2 -r 2
797 $ hg bookmark Z@2 -r 2
770 $ hg bookmark Z@3 -r 3
798 $ hg bookmark Z@3 -r 3
771 $ hg book
799 $ hg book
772 Z 0:f7b1eb17ad24
800 Z 0:f7b1eb17ad24
773 Z@1 1:925d80f479bb
801 Z@1 1:925d80f479bb
774 Z@2 2:db815d6d32e6
802 Z@2 2:db815d6d32e6
775 Z@3 3:9ba5f110a0b3
803 Z@3 3:9ba5f110a0b3
776 * four 3:9ba5f110a0b3
804 * four 3:9ba5f110a0b3
777 should-end-on-two 2:db815d6d32e6
805 should-end-on-two 2:db815d6d32e6
778 $ hg bookmark Z
806 $ hg bookmark Z
779 moving bookmark 'Z' forward from f7b1eb17ad24
807 moving bookmark 'Z' forward from f7b1eb17ad24
780 $ hg book
808 $ hg book
781 * Z 3:9ba5f110a0b3
809 * Z 3:9ba5f110a0b3
782 Z@1 1:925d80f479bb
810 Z@1 1:925d80f479bb
783 four 3:9ba5f110a0b3
811 four 3:9ba5f110a0b3
784 should-end-on-two 2:db815d6d32e6
812 should-end-on-two 2:db815d6d32e6
785
813
786 test clearing only a single divergent bookmark across branches
814 test clearing only a single divergent bookmark across branches
787
815
788 $ hg book foo -r 1
816 $ hg book foo -r 1
789 $ hg book foo@1 -r 0
817 $ hg book foo@1 -r 0
790 $ hg book foo@2 -r 2
818 $ hg book foo@2 -r 2
791 $ hg book foo@3 -r 3
819 $ hg book foo@3 -r 3
792 $ hg book foo -r foo@3
820 $ hg book foo -r foo@3
793 $ hg book
821 $ hg book
794 * Z 3:9ba5f110a0b3
822 * Z 3:9ba5f110a0b3
795 Z@1 1:925d80f479bb
823 Z@1 1:925d80f479bb
796 foo 3:9ba5f110a0b3
824 foo 3:9ba5f110a0b3
797 foo@1 0:f7b1eb17ad24
825 foo@1 0:f7b1eb17ad24
798 foo@2 2:db815d6d32e6
826 foo@2 2:db815d6d32e6
799 four 3:9ba5f110a0b3
827 four 3:9ba5f110a0b3
800 should-end-on-two 2:db815d6d32e6
828 should-end-on-two 2:db815d6d32e6
801
829
802 pull --update works the same as pull && update (case #2)
830 pull --update works the same as pull && update (case #2)
803
831
804 It is assumed that "hg pull" itself doesn't update current active
832 It is assumed that "hg pull" itself doesn't update current active
805 bookmark ('Y' in tests below).
833 bookmark ('Y' in tests below).
806
834
807 $ hg pull -q ../cloned-bookmarks-update
835 $ hg pull -q ../cloned-bookmarks-update
808 divergent bookmark Z stored as Z@2
836 divergent bookmark Z stored as Z@2
809
837
810 (pulling revision on another named branch with --update updates
838 (pulling revision on another named branch with --update updates
811 neither the working directory nor current active bookmark: "no-op"
839 neither the working directory nor current active bookmark: "no-op"
812 case)
840 case)
813
841
814 $ echo yy >> y
842 $ echo yy >> y
815 $ hg commit -m yy
843 $ hg commit -m yy
816
844
817 $ hg -R ../cloned-bookmarks-update bookmarks | grep ' Y '
845 $ hg -R ../cloned-bookmarks-update bookmarks | grep ' Y '
818 * Y 3:125c9a1d6df6
846 * Y 3:125c9a1d6df6
819 $ hg -R ../cloned-bookmarks-update pull . --update
847 $ hg -R ../cloned-bookmarks-update pull . --update
820 pulling from .
848 pulling from .
821 searching for changes
849 searching for changes
822 adding changesets
850 adding changesets
823 adding manifests
851 adding manifests
824 adding file changes
852 adding file changes
825 added 1 changesets with 1 changes to 1 files
853 added 1 changesets with 1 changes to 1 files
826 divergent bookmark Z stored as Z@default
854 divergent bookmark Z stored as Z@default
827 adding remote bookmark foo
855 adding remote bookmark foo
828 adding remote bookmark four
856 adding remote bookmark four
829 adding remote bookmark should-end-on-two
857 adding remote bookmark should-end-on-two
830 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
858 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
831 $ hg -R ../cloned-bookmarks-update parents -T "{rev}:{node|short}\n"
859 $ hg -R ../cloned-bookmarks-update parents -T "{rev}:{node|short}\n"
832 3:125c9a1d6df6
860 3:125c9a1d6df6
833 $ hg -R ../cloned-bookmarks-update bookmarks | grep ' Y '
861 $ hg -R ../cloned-bookmarks-update bookmarks | grep ' Y '
834 * Y 3:125c9a1d6df6
862 * Y 3:125c9a1d6df6
835
863
836 (pulling revision on current named/topological branch with --update
864 (pulling revision on current named/topological branch with --update
837 updates the working directory and current active bookmark)
865 updates the working directory and current active bookmark)
838
866
839 $ hg update -C -q 125c9a1d6df6
867 $ hg update -C -q 125c9a1d6df6
840 $ echo xx >> x
868 $ echo xx >> x
841 $ hg commit -m xx
869 $ hg commit -m xx
842
870
843 $ hg -R ../cloned-bookmarks-update bookmarks | grep ' Y '
871 $ hg -R ../cloned-bookmarks-update bookmarks | grep ' Y '
844 * Y 3:125c9a1d6df6
872 * Y 3:125c9a1d6df6
845 $ hg -R ../cloned-bookmarks-update pull . --update
873 $ hg -R ../cloned-bookmarks-update pull . --update
846 pulling from .
874 pulling from .
847 searching for changes
875 searching for changes
848 adding changesets
876 adding changesets
849 adding manifests
877 adding manifests
850 adding file changes
878 adding file changes
851 added 1 changesets with 1 changes to 1 files
879 added 1 changesets with 1 changes to 1 files
852 divergent bookmark Z stored as Z@default
880 divergent bookmark Z stored as Z@default
853 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
881 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
854 updating bookmark Y
882 updating bookmark Y
855 $ hg -R ../cloned-bookmarks-update parents -T "{rev}:{node|short}\n"
883 $ hg -R ../cloned-bookmarks-update parents -T "{rev}:{node|short}\n"
856 6:81dcce76aa0b
884 6:81dcce76aa0b
857 $ hg -R ../cloned-bookmarks-update bookmarks | grep ' Y '
885 $ hg -R ../cloned-bookmarks-update bookmarks | grep ' Y '
858 * Y 6:81dcce76aa0b
886 * Y 6:81dcce76aa0b
859
887
860 $ cd ..
888 $ cd ..
861
889
862 ensure changelog is written before bookmarks
890 ensure changelog is written before bookmarks
863 $ hg init orderrepo
891 $ hg init orderrepo
864 $ cd orderrepo
892 $ cd orderrepo
865 $ touch a
893 $ touch a
866 $ hg commit -Aqm one
894 $ hg commit -Aqm one
867 $ hg book mybook
895 $ hg book mybook
868 $ echo a > a
896 $ echo a > a
869
897
870 $ cat > $TESTTMP/pausefinalize.py <<EOF
898 $ cat > $TESTTMP/pausefinalize.py <<EOF
871 > from mercurial import extensions, localrepo
899 > from mercurial import extensions, localrepo
872 > import os, time
900 > import os, time
873 > def transaction(orig, self, desc, report=None):
901 > def transaction(orig, self, desc, report=None):
874 > tr = orig(self, desc, report)
902 > tr = orig(self, desc, report)
875 > def sleep(*args, **kwargs):
903 > def sleep(*args, **kwargs):
876 > retry = 20
904 > retry = 20
877 > while retry > 0 and not os.path.exists("$TESTTMP/unpause"):
905 > while retry > 0 and not os.path.exists("$TESTTMP/unpause"):
878 > retry -= 1
906 > retry -= 1
879 > time.sleep(0.5)
907 > time.sleep(0.5)
880 > if os.path.exists("$TESTTMP/unpause"):
908 > if os.path.exists("$TESTTMP/unpause"):
881 > os.remove("$TESTTMP/unpause")
909 > os.remove("$TESTTMP/unpause")
882 > # It is important that this finalizer start with 'a', so it runs before
910 > # It is important that this finalizer start with 'a', so it runs before
883 > # the changelog finalizer appends to the changelog.
911 > # the changelog finalizer appends to the changelog.
884 > tr.addfinalize('a-sleep', sleep)
912 > tr.addfinalize('a-sleep', sleep)
885 > return tr
913 > return tr
886 >
914 >
887 > def extsetup(ui):
915 > def extsetup(ui):
888 > # This extension inserts an artifical pause during the transaction
916 > # This extension inserts an artifical pause during the transaction
889 > # finalizer, so we can run commands mid-transaction-close.
917 > # finalizer, so we can run commands mid-transaction-close.
890 > extensions.wrapfunction(localrepo.localrepository, 'transaction',
918 > extensions.wrapfunction(localrepo.localrepository, 'transaction',
891 > transaction)
919 > transaction)
892 > EOF
920 > EOF
893 $ hg commit -qm two --config extensions.pausefinalize=$TESTTMP/pausefinalize.py &
921 $ hg commit -qm two --config extensions.pausefinalize=$TESTTMP/pausefinalize.py &
894 $ sleep 2
922 $ sleep 2
895 $ hg log -r .
923 $ hg log -r .
896 changeset: 0:867bc5792c8c
924 changeset: 0:867bc5792c8c
897 bookmark: mybook
925 bookmark: mybook
898 tag: tip
926 tag: tip
899 user: test
927 user: test
900 date: Thu Jan 01 00:00:00 1970 +0000
928 date: Thu Jan 01 00:00:00 1970 +0000
901 summary: one
929 summary: one
902
930
903 $ hg bookmarks
931 $ hg bookmarks
904 * mybook 0:867bc5792c8c
932 * mybook 0:867bc5792c8c
905 $ touch $TESTTMP/unpause
933 $ touch $TESTTMP/unpause
906
934
907 $ cd ..
935 $ cd ..
908
936
909 check whether HG_PENDING makes pending changes only in related
937 check whether HG_PENDING makes pending changes only in related
910 repositories visible to an external hook.
938 repositories visible to an external hook.
911
939
912 (emulate a transaction running concurrently by copied
940 (emulate a transaction running concurrently by copied
913 .hg/bookmarks.pending in subsequent test)
941 .hg/bookmarks.pending in subsequent test)
914
942
915 $ cat > $TESTTMP/savepending.sh <<EOF
943 $ cat > $TESTTMP/savepending.sh <<EOF
916 > cp .hg/bookmarks.pending .hg/bookmarks.pending.saved
944 > cp .hg/bookmarks.pending .hg/bookmarks.pending.saved
917 > exit 1 # to avoid adding new bookmark for subsequent tests
945 > exit 1 # to avoid adding new bookmark for subsequent tests
918 > EOF
946 > EOF
919
947
920 $ hg init unrelated
948 $ hg init unrelated
921 $ cd unrelated
949 $ cd unrelated
922 $ echo a > a
950 $ echo a > a
923 $ hg add a
951 $ hg add a
924 $ hg commit -m '#0'
952 $ hg commit -m '#0'
925 $ hg --config hooks.pretxnclose="sh $TESTTMP/savepending.sh" bookmarks INVISIBLE
953 $ hg --config hooks.pretxnclose="sh $TESTTMP/savepending.sh" bookmarks INVISIBLE
926 transaction abort!
954 transaction abort!
927 rollback completed
955 rollback completed
928 abort: pretxnclose hook exited with status 1
956 abort: pretxnclose hook exited with status 1
929 [255]
957 [255]
930 $ cp .hg/bookmarks.pending.saved .hg/bookmarks.pending
958 $ cp .hg/bookmarks.pending.saved .hg/bookmarks.pending
931
959
932 (check visible bookmarks while transaction running in repo)
960 (check visible bookmarks while transaction running in repo)
933
961
934 $ cat > $TESTTMP/checkpending.sh <<EOF
962 $ cat > $TESTTMP/checkpending.sh <<EOF
935 > echo "@repo"
963 > echo "@repo"
936 > hg -R "$TESTTMP/repo" bookmarks
964 > hg -R "$TESTTMP/repo" bookmarks
937 > echo "@unrelated"
965 > echo "@unrelated"
938 > hg -R "$TESTTMP/unrelated" bookmarks
966 > hg -R "$TESTTMP/unrelated" bookmarks
939 > exit 1 # to avoid adding new bookmark for subsequent tests
967 > exit 1 # to avoid adding new bookmark for subsequent tests
940 > EOF
968 > EOF
941
969
942 $ cd ../repo
970 $ cd ../repo
943 $ hg --config hooks.pretxnclose="sh $TESTTMP/checkpending.sh" bookmarks NEW
971 $ hg --config hooks.pretxnclose="sh $TESTTMP/checkpending.sh" bookmarks NEW
944 @repo
972 @repo
945 * NEW 6:81dcce76aa0b
973 * NEW 6:81dcce76aa0b
946 X2 1:925d80f479bb
974 X2 1:925d80f479bb
947 Y 4:125c9a1d6df6
975 Y 4:125c9a1d6df6
948 Z 5:5fb12f0f2d51
976 Z 5:5fb12f0f2d51
949 Z@1 1:925d80f479bb
977 Z@1 1:925d80f479bb
950 Z@2 4:125c9a1d6df6
978 Z@2 4:125c9a1d6df6
951 foo 3:9ba5f110a0b3
979 foo 3:9ba5f110a0b3
952 foo@1 0:f7b1eb17ad24
980 foo@1 0:f7b1eb17ad24
953 foo@2 2:db815d6d32e6
981 foo@2 2:db815d6d32e6
954 four 3:9ba5f110a0b3
982 four 3:9ba5f110a0b3
955 should-end-on-two 2:db815d6d32e6
983 should-end-on-two 2:db815d6d32e6
956 x y 2:db815d6d32e6
984 x y 2:db815d6d32e6
957 @unrelated
985 @unrelated
958 no bookmarks set
986 no bookmarks set
959 transaction abort!
987 transaction abort!
960 rollback completed
988 rollback completed
961 abort: pretxnclose hook exited with status 1
989 abort: pretxnclose hook exited with status 1
962 [255]
990 [255]
General Comments 0
You need to be logged in to leave comments. Login now