##// END OF EJS Templates
py3: handle keyword arguments correctly in commands.py...
Pulkit Goyal -
r35353:920cca6c default
parent child Browse files
Show More
@@ -1,5587 +1,5589 b''
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import difflib
10 import difflib
11 import errno
11 import errno
12 import os
12 import os
13 import re
13 import re
14 import sys
14 import sys
15
15
16 from .i18n import _
16 from .i18n import _
17 from .node import (
17 from .node import (
18 hex,
18 hex,
19 nullid,
19 nullid,
20 nullrev,
20 nullrev,
21 short,
21 short,
22 )
22 )
23 from . import (
23 from . import (
24 archival,
24 archival,
25 bookmarks,
25 bookmarks,
26 bundle2,
26 bundle2,
27 changegroup,
27 changegroup,
28 cmdutil,
28 cmdutil,
29 copies,
29 copies,
30 debugcommands as debugcommandsmod,
30 debugcommands as debugcommandsmod,
31 destutil,
31 destutil,
32 dirstateguard,
32 dirstateguard,
33 discovery,
33 discovery,
34 encoding,
34 encoding,
35 error,
35 error,
36 exchange,
36 exchange,
37 extensions,
37 extensions,
38 formatter,
38 formatter,
39 graphmod,
39 graphmod,
40 hbisect,
40 hbisect,
41 help,
41 help,
42 hg,
42 hg,
43 lock as lockmod,
43 lock as lockmod,
44 merge as mergemod,
44 merge as mergemod,
45 obsolete,
45 obsolete,
46 patch,
46 patch,
47 phases,
47 phases,
48 pycompat,
48 pycompat,
49 rcutil,
49 rcutil,
50 registrar,
50 registrar,
51 revsetlang,
51 revsetlang,
52 rewriteutil,
52 rewriteutil,
53 scmutil,
53 scmutil,
54 server,
54 server,
55 sshserver,
55 sshserver,
56 streamclone,
56 streamclone,
57 tags as tagsmod,
57 tags as tagsmod,
58 templatekw,
58 templatekw,
59 ui as uimod,
59 ui as uimod,
60 util,
60 util,
61 )
61 )
62
62
63 release = lockmod.release
63 release = lockmod.release
64
64
65 table = {}
65 table = {}
66 table.update(debugcommandsmod.command._table)
66 table.update(debugcommandsmod.command._table)
67
67
68 command = registrar.command(table)
68 command = registrar.command(table)
69 readonly = registrar.command.readonly
69 readonly = registrar.command.readonly
70
70
71 # common command options
71 # common command options
72
72
73 globalopts = [
73 globalopts = [
74 ('R', 'repository', '',
74 ('R', 'repository', '',
75 _('repository root directory or name of overlay bundle file'),
75 _('repository root directory or name of overlay bundle file'),
76 _('REPO')),
76 _('REPO')),
77 ('', 'cwd', '',
77 ('', 'cwd', '',
78 _('change working directory'), _('DIR')),
78 _('change working directory'), _('DIR')),
79 ('y', 'noninteractive', None,
79 ('y', 'noninteractive', None,
80 _('do not prompt, automatically pick the first choice for all prompts')),
80 _('do not prompt, automatically pick the first choice for all prompts')),
81 ('q', 'quiet', None, _('suppress output')),
81 ('q', 'quiet', None, _('suppress output')),
82 ('v', 'verbose', None, _('enable additional output')),
82 ('v', 'verbose', None, _('enable additional output')),
83 ('', 'color', '',
83 ('', 'color', '',
84 # i18n: 'always', 'auto', 'never', and 'debug' are keywords
84 # i18n: 'always', 'auto', 'never', and 'debug' are keywords
85 # and should not be translated
85 # and should not be translated
86 _("when to colorize (boolean, always, auto, never, or debug)"),
86 _("when to colorize (boolean, always, auto, never, or debug)"),
87 _('TYPE')),
87 _('TYPE')),
88 ('', 'config', [],
88 ('', 'config', [],
89 _('set/override config option (use \'section.name=value\')'),
89 _('set/override config option (use \'section.name=value\')'),
90 _('CONFIG')),
90 _('CONFIG')),
91 ('', 'debug', None, _('enable debugging output')),
91 ('', 'debug', None, _('enable debugging output')),
92 ('', 'debugger', None, _('start debugger')),
92 ('', 'debugger', None, _('start debugger')),
93 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
93 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
94 _('ENCODE')),
94 _('ENCODE')),
95 ('', 'encodingmode', encoding.encodingmode,
95 ('', 'encodingmode', encoding.encodingmode,
96 _('set the charset encoding mode'), _('MODE')),
96 _('set the charset encoding mode'), _('MODE')),
97 ('', 'traceback', None, _('always print a traceback on exception')),
97 ('', 'traceback', None, _('always print a traceback on exception')),
98 ('', 'time', None, _('time how long the command takes')),
98 ('', 'time', None, _('time how long the command takes')),
99 ('', 'profile', None, _('print command execution profile')),
99 ('', 'profile', None, _('print command execution profile')),
100 ('', 'version', None, _('output version information and exit')),
100 ('', 'version', None, _('output version information and exit')),
101 ('h', 'help', None, _('display help and exit')),
101 ('h', 'help', None, _('display help and exit')),
102 ('', 'hidden', False, _('consider hidden changesets')),
102 ('', 'hidden', False, _('consider hidden changesets')),
103 ('', 'pager', 'auto',
103 ('', 'pager', 'auto',
104 _("when to paginate (boolean, always, auto, or never)"), _('TYPE')),
104 _("when to paginate (boolean, always, auto, or never)"), _('TYPE')),
105 ]
105 ]
106
106
107 dryrunopts = cmdutil.dryrunopts
107 dryrunopts = cmdutil.dryrunopts
108 remoteopts = cmdutil.remoteopts
108 remoteopts = cmdutil.remoteopts
109 walkopts = cmdutil.walkopts
109 walkopts = cmdutil.walkopts
110 commitopts = cmdutil.commitopts
110 commitopts = cmdutil.commitopts
111 commitopts2 = cmdutil.commitopts2
111 commitopts2 = cmdutil.commitopts2
112 formatteropts = cmdutil.formatteropts
112 formatteropts = cmdutil.formatteropts
113 templateopts = cmdutil.templateopts
113 templateopts = cmdutil.templateopts
114 logopts = cmdutil.logopts
114 logopts = cmdutil.logopts
115 diffopts = cmdutil.diffopts
115 diffopts = cmdutil.diffopts
116 diffwsopts = cmdutil.diffwsopts
116 diffwsopts = cmdutil.diffwsopts
117 diffopts2 = cmdutil.diffopts2
117 diffopts2 = cmdutil.diffopts2
118 mergetoolopts = cmdutil.mergetoolopts
118 mergetoolopts = cmdutil.mergetoolopts
119 similarityopts = cmdutil.similarityopts
119 similarityopts = cmdutil.similarityopts
120 subrepoopts = cmdutil.subrepoopts
120 subrepoopts = cmdutil.subrepoopts
121 debugrevlogopts = cmdutil.debugrevlogopts
121 debugrevlogopts = cmdutil.debugrevlogopts
122
122
123 # Commands start here, listed alphabetically
123 # Commands start here, listed alphabetically
124
124
125 @command('^add',
125 @command('^add',
126 walkopts + subrepoopts + dryrunopts,
126 walkopts + subrepoopts + dryrunopts,
127 _('[OPTION]... [FILE]...'),
127 _('[OPTION]... [FILE]...'),
128 inferrepo=True)
128 inferrepo=True)
129 def add(ui, repo, *pats, **opts):
129 def add(ui, repo, *pats, **opts):
130 """add the specified files on the next commit
130 """add the specified files on the next commit
131
131
132 Schedule files to be version controlled and added to the
132 Schedule files to be version controlled and added to the
133 repository.
133 repository.
134
134
135 The files will be added to the repository at the next commit. To
135 The files will be added to the repository at the next commit. To
136 undo an add before that, see :hg:`forget`.
136 undo an add before that, see :hg:`forget`.
137
137
138 If no names are given, add all files to the repository (except
138 If no names are given, add all files to the repository (except
139 files matching ``.hgignore``).
139 files matching ``.hgignore``).
140
140
141 .. container:: verbose
141 .. container:: verbose
142
142
143 Examples:
143 Examples:
144
144
145 - New (unknown) files are added
145 - New (unknown) files are added
146 automatically by :hg:`add`::
146 automatically by :hg:`add`::
147
147
148 $ ls
148 $ ls
149 foo.c
149 foo.c
150 $ hg status
150 $ hg status
151 ? foo.c
151 ? foo.c
152 $ hg add
152 $ hg add
153 adding foo.c
153 adding foo.c
154 $ hg status
154 $ hg status
155 A foo.c
155 A foo.c
156
156
157 - Specific files to be added can be specified::
157 - Specific files to be added can be specified::
158
158
159 $ ls
159 $ ls
160 bar.c foo.c
160 bar.c foo.c
161 $ hg status
161 $ hg status
162 ? bar.c
162 ? bar.c
163 ? foo.c
163 ? foo.c
164 $ hg add bar.c
164 $ hg add bar.c
165 $ hg status
165 $ hg status
166 A bar.c
166 A bar.c
167 ? foo.c
167 ? foo.c
168
168
169 Returns 0 if all files are successfully added.
169 Returns 0 if all files are successfully added.
170 """
170 """
171
171
172 m = scmutil.match(repo[None], pats, pycompat.byteskwargs(opts))
172 m = scmutil.match(repo[None], pats, pycompat.byteskwargs(opts))
173 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
173 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
174 return rejected and 1 or 0
174 return rejected and 1 or 0
175
175
176 @command('addremove',
176 @command('addremove',
177 similarityopts + subrepoopts + walkopts + dryrunopts,
177 similarityopts + subrepoopts + walkopts + dryrunopts,
178 _('[OPTION]... [FILE]...'),
178 _('[OPTION]... [FILE]...'),
179 inferrepo=True)
179 inferrepo=True)
180 def addremove(ui, repo, *pats, **opts):
180 def addremove(ui, repo, *pats, **opts):
181 """add all new files, delete all missing files
181 """add all new files, delete all missing files
182
182
183 Add all new files and remove all missing files from the
183 Add all new files and remove all missing files from the
184 repository.
184 repository.
185
185
186 Unless names are given, new files are ignored if they match any of
186 Unless names are given, new files are ignored if they match any of
187 the patterns in ``.hgignore``. As with add, these changes take
187 the patterns in ``.hgignore``. As with add, these changes take
188 effect at the next commit.
188 effect at the next commit.
189
189
190 Use the -s/--similarity option to detect renamed files. This
190 Use the -s/--similarity option to detect renamed files. This
191 option takes a percentage between 0 (disabled) and 100 (files must
191 option takes a percentage between 0 (disabled) and 100 (files must
192 be identical) as its parameter. With a parameter greater than 0,
192 be identical) as its parameter. With a parameter greater than 0,
193 this compares every removed file with every added file and records
193 this compares every removed file with every added file and records
194 those similar enough as renames. Detecting renamed files this way
194 those similar enough as renames. Detecting renamed files this way
195 can be expensive. After using this option, :hg:`status -C` can be
195 can be expensive. After using this option, :hg:`status -C` can be
196 used to check which files were identified as moved or renamed. If
196 used to check which files were identified as moved or renamed. If
197 not specified, -s/--similarity defaults to 100 and only renames of
197 not specified, -s/--similarity defaults to 100 and only renames of
198 identical files are detected.
198 identical files are detected.
199
199
200 .. container:: verbose
200 .. container:: verbose
201
201
202 Examples:
202 Examples:
203
203
204 - A number of files (bar.c and foo.c) are new,
204 - A number of files (bar.c and foo.c) are new,
205 while foobar.c has been removed (without using :hg:`remove`)
205 while foobar.c has been removed (without using :hg:`remove`)
206 from the repository::
206 from the repository::
207
207
208 $ ls
208 $ ls
209 bar.c foo.c
209 bar.c foo.c
210 $ hg status
210 $ hg status
211 ! foobar.c
211 ! foobar.c
212 ? bar.c
212 ? bar.c
213 ? foo.c
213 ? foo.c
214 $ hg addremove
214 $ hg addremove
215 adding bar.c
215 adding bar.c
216 adding foo.c
216 adding foo.c
217 removing foobar.c
217 removing foobar.c
218 $ hg status
218 $ hg status
219 A bar.c
219 A bar.c
220 A foo.c
220 A foo.c
221 R foobar.c
221 R foobar.c
222
222
223 - A file foobar.c was moved to foo.c without using :hg:`rename`.
223 - A file foobar.c was moved to foo.c without using :hg:`rename`.
224 Afterwards, it was edited slightly::
224 Afterwards, it was edited slightly::
225
225
226 $ ls
226 $ ls
227 foo.c
227 foo.c
228 $ hg status
228 $ hg status
229 ! foobar.c
229 ! foobar.c
230 ? foo.c
230 ? foo.c
231 $ hg addremove --similarity 90
231 $ hg addremove --similarity 90
232 removing foobar.c
232 removing foobar.c
233 adding foo.c
233 adding foo.c
234 recording removal of foobar.c as rename to foo.c (94% similar)
234 recording removal of foobar.c as rename to foo.c (94% similar)
235 $ hg status -C
235 $ hg status -C
236 A foo.c
236 A foo.c
237 foobar.c
237 foobar.c
238 R foobar.c
238 R foobar.c
239
239
240 Returns 0 if all files are successfully added.
240 Returns 0 if all files are successfully added.
241 """
241 """
242 opts = pycompat.byteskwargs(opts)
242 opts = pycompat.byteskwargs(opts)
243 try:
243 try:
244 sim = float(opts.get('similarity') or 100)
244 sim = float(opts.get('similarity') or 100)
245 except ValueError:
245 except ValueError:
246 raise error.Abort(_('similarity must be a number'))
246 raise error.Abort(_('similarity must be a number'))
247 if sim < 0 or sim > 100:
247 if sim < 0 or sim > 100:
248 raise error.Abort(_('similarity must be between 0 and 100'))
248 raise error.Abort(_('similarity must be between 0 and 100'))
249 matcher = scmutil.match(repo[None], pats, opts)
249 matcher = scmutil.match(repo[None], pats, opts)
250 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
250 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
251
251
252 @command('^annotate|blame',
252 @command('^annotate|blame',
253 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
253 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
254 ('', 'follow', None,
254 ('', 'follow', None,
255 _('follow copies/renames and list the filename (DEPRECATED)')),
255 _('follow copies/renames and list the filename (DEPRECATED)')),
256 ('', 'no-follow', None, _("don't follow copies and renames")),
256 ('', 'no-follow', None, _("don't follow copies and renames")),
257 ('a', 'text', None, _('treat all files as text')),
257 ('a', 'text', None, _('treat all files as text')),
258 ('u', 'user', None, _('list the author (long with -v)')),
258 ('u', 'user', None, _('list the author (long with -v)')),
259 ('f', 'file', None, _('list the filename')),
259 ('f', 'file', None, _('list the filename')),
260 ('d', 'date', None, _('list the date (short with -q)')),
260 ('d', 'date', None, _('list the date (short with -q)')),
261 ('n', 'number', None, _('list the revision number (default)')),
261 ('n', 'number', None, _('list the revision number (default)')),
262 ('c', 'changeset', None, _('list the changeset')),
262 ('c', 'changeset', None, _('list the changeset')),
263 ('l', 'line-number', None, _('show line number at the first appearance')),
263 ('l', 'line-number', None, _('show line number at the first appearance')),
264 ('', 'skip', [], _('revision to not display (EXPERIMENTAL)'), _('REV')),
264 ('', 'skip', [], _('revision to not display (EXPERIMENTAL)'), _('REV')),
265 ] + diffwsopts + walkopts + formatteropts,
265 ] + diffwsopts + walkopts + formatteropts,
266 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
266 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
267 inferrepo=True)
267 inferrepo=True)
268 def annotate(ui, repo, *pats, **opts):
268 def annotate(ui, repo, *pats, **opts):
269 """show changeset information by line for each file
269 """show changeset information by line for each file
270
270
271 List changes in files, showing the revision id responsible for
271 List changes in files, showing the revision id responsible for
272 each line.
272 each line.
273
273
274 This command is useful for discovering when a change was made and
274 This command is useful for discovering when a change was made and
275 by whom.
275 by whom.
276
276
277 If you include --file, --user, or --date, the revision number is
277 If you include --file, --user, or --date, the revision number is
278 suppressed unless you also include --number.
278 suppressed unless you also include --number.
279
279
280 Without the -a/--text option, annotate will avoid processing files
280 Without the -a/--text option, annotate will avoid processing files
281 it detects as binary. With -a, annotate will annotate the file
281 it detects as binary. With -a, annotate will annotate the file
282 anyway, although the results will probably be neither useful
282 anyway, although the results will probably be neither useful
283 nor desirable.
283 nor desirable.
284
284
285 Returns 0 on success.
285 Returns 0 on success.
286 """
286 """
287 opts = pycompat.byteskwargs(opts)
287 opts = pycompat.byteskwargs(opts)
288 if not pats:
288 if not pats:
289 raise error.Abort(_('at least one filename or pattern is required'))
289 raise error.Abort(_('at least one filename or pattern is required'))
290
290
291 if opts.get('follow'):
291 if opts.get('follow'):
292 # --follow is deprecated and now just an alias for -f/--file
292 # --follow is deprecated and now just an alias for -f/--file
293 # to mimic the behavior of Mercurial before version 1.5
293 # to mimic the behavior of Mercurial before version 1.5
294 opts['file'] = True
294 opts['file'] = True
295
295
296 ctx = scmutil.revsingle(repo, opts.get('rev'))
296 ctx = scmutil.revsingle(repo, opts.get('rev'))
297
297
298 rootfm = ui.formatter('annotate', opts)
298 rootfm = ui.formatter('annotate', opts)
299 if ui.quiet:
299 if ui.quiet:
300 datefunc = util.shortdate
300 datefunc = util.shortdate
301 else:
301 else:
302 datefunc = util.datestr
302 datefunc = util.datestr
303 if ctx.rev() is None:
303 if ctx.rev() is None:
304 def hexfn(node):
304 def hexfn(node):
305 if node is None:
305 if node is None:
306 return None
306 return None
307 else:
307 else:
308 return rootfm.hexfunc(node)
308 return rootfm.hexfunc(node)
309 if opts.get('changeset'):
309 if opts.get('changeset'):
310 # omit "+" suffix which is appended to node hex
310 # omit "+" suffix which is appended to node hex
311 def formatrev(rev):
311 def formatrev(rev):
312 if rev is None:
312 if rev is None:
313 return '%d' % ctx.p1().rev()
313 return '%d' % ctx.p1().rev()
314 else:
314 else:
315 return '%d' % rev
315 return '%d' % rev
316 else:
316 else:
317 def formatrev(rev):
317 def formatrev(rev):
318 if rev is None:
318 if rev is None:
319 return '%d+' % ctx.p1().rev()
319 return '%d+' % ctx.p1().rev()
320 else:
320 else:
321 return '%d ' % rev
321 return '%d ' % rev
322 def formathex(hex):
322 def formathex(hex):
323 if hex is None:
323 if hex is None:
324 return '%s+' % rootfm.hexfunc(ctx.p1().node())
324 return '%s+' % rootfm.hexfunc(ctx.p1().node())
325 else:
325 else:
326 return '%s ' % hex
326 return '%s ' % hex
327 else:
327 else:
328 hexfn = rootfm.hexfunc
328 hexfn = rootfm.hexfunc
329 formatrev = formathex = pycompat.bytestr
329 formatrev = formathex = pycompat.bytestr
330
330
331 opmap = [('user', ' ', lambda x: x.fctx.user(), ui.shortuser),
331 opmap = [('user', ' ', lambda x: x.fctx.user(), ui.shortuser),
332 ('number', ' ', lambda x: x.fctx.rev(), formatrev),
332 ('number', ' ', lambda x: x.fctx.rev(), formatrev),
333 ('changeset', ' ', lambda x: hexfn(x.fctx.node()), formathex),
333 ('changeset', ' ', lambda x: hexfn(x.fctx.node()), formathex),
334 ('date', ' ', lambda x: x.fctx.date(), util.cachefunc(datefunc)),
334 ('date', ' ', lambda x: x.fctx.date(), util.cachefunc(datefunc)),
335 ('file', ' ', lambda x: x.fctx.path(), str),
335 ('file', ' ', lambda x: x.fctx.path(), str),
336 ('line_number', ':', lambda x: x.lineno, str),
336 ('line_number', ':', lambda x: x.lineno, str),
337 ]
337 ]
338 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
338 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
339
339
340 if (not opts.get('user') and not opts.get('changeset')
340 if (not opts.get('user') and not opts.get('changeset')
341 and not opts.get('date') and not opts.get('file')):
341 and not opts.get('date') and not opts.get('file')):
342 opts['number'] = True
342 opts['number'] = True
343
343
344 linenumber = opts.get('line_number') is not None
344 linenumber = opts.get('line_number') is not None
345 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
345 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
346 raise error.Abort(_('at least one of -n/-c is required for -l'))
346 raise error.Abort(_('at least one of -n/-c is required for -l'))
347
347
348 ui.pager('annotate')
348 ui.pager('annotate')
349
349
350 if rootfm.isplain():
350 if rootfm.isplain():
351 def makefunc(get, fmt):
351 def makefunc(get, fmt):
352 return lambda x: fmt(get(x))
352 return lambda x: fmt(get(x))
353 else:
353 else:
354 def makefunc(get, fmt):
354 def makefunc(get, fmt):
355 return get
355 return get
356 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
356 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
357 if opts.get(op)]
357 if opts.get(op)]
358 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
358 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
359 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
359 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
360 if opts.get(op))
360 if opts.get(op))
361
361
362 def bad(x, y):
362 def bad(x, y):
363 raise error.Abort("%s: %s" % (x, y))
363 raise error.Abort("%s: %s" % (x, y))
364
364
365 m = scmutil.match(ctx, pats, opts, badfn=bad)
365 m = scmutil.match(ctx, pats, opts, badfn=bad)
366
366
367 follow = not opts.get('no_follow')
367 follow = not opts.get('no_follow')
368 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
368 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
369 whitespace=True)
369 whitespace=True)
370 skiprevs = opts.get('skip')
370 skiprevs = opts.get('skip')
371 if skiprevs:
371 if skiprevs:
372 skiprevs = scmutil.revrange(repo, skiprevs)
372 skiprevs = scmutil.revrange(repo, skiprevs)
373
373
374 for abs in ctx.walk(m):
374 for abs in ctx.walk(m):
375 fctx = ctx[abs]
375 fctx = ctx[abs]
376 rootfm.startitem()
376 rootfm.startitem()
377 rootfm.data(abspath=abs, path=m.rel(abs))
377 rootfm.data(abspath=abs, path=m.rel(abs))
378 if not opts.get('text') and fctx.isbinary():
378 if not opts.get('text') and fctx.isbinary():
379 rootfm.plain(_("%s: binary file\n")
379 rootfm.plain(_("%s: binary file\n")
380 % ((pats and m.rel(abs)) or abs))
380 % ((pats and m.rel(abs)) or abs))
381 continue
381 continue
382
382
383 fm = rootfm.nested('lines')
383 fm = rootfm.nested('lines')
384 lines = fctx.annotate(follow=follow, linenumber=linenumber,
384 lines = fctx.annotate(follow=follow, linenumber=linenumber,
385 skiprevs=skiprevs, diffopts=diffopts)
385 skiprevs=skiprevs, diffopts=diffopts)
386 if not lines:
386 if not lines:
387 fm.end()
387 fm.end()
388 continue
388 continue
389 formats = []
389 formats = []
390 pieces = []
390 pieces = []
391
391
392 for f, sep in funcmap:
392 for f, sep in funcmap:
393 l = [f(n) for n, dummy in lines]
393 l = [f(n) for n, dummy in lines]
394 if fm.isplain():
394 if fm.isplain():
395 sizes = [encoding.colwidth(x) for x in l]
395 sizes = [encoding.colwidth(x) for x in l]
396 ml = max(sizes)
396 ml = max(sizes)
397 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
397 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
398 else:
398 else:
399 formats.append(['%s' for x in l])
399 formats.append(['%s' for x in l])
400 pieces.append(l)
400 pieces.append(l)
401
401
402 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
402 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
403 fm.startitem()
403 fm.startitem()
404 fm.write(fields, "".join(f), *p)
404 fm.write(fields, "".join(f), *p)
405 if l[0].skip:
405 if l[0].skip:
406 fmt = "* %s"
406 fmt = "* %s"
407 else:
407 else:
408 fmt = ": %s"
408 fmt = ": %s"
409 fm.write('line', fmt, l[1])
409 fm.write('line', fmt, l[1])
410
410
411 if not lines[-1][1].endswith('\n'):
411 if not lines[-1][1].endswith('\n'):
412 fm.plain('\n')
412 fm.plain('\n')
413 fm.end()
413 fm.end()
414
414
415 rootfm.end()
415 rootfm.end()
416
416
417 @command('archive',
417 @command('archive',
418 [('', 'no-decode', None, _('do not pass files through decoders')),
418 [('', 'no-decode', None, _('do not pass files through decoders')),
419 ('p', 'prefix', '', _('directory prefix for files in archive'),
419 ('p', 'prefix', '', _('directory prefix for files in archive'),
420 _('PREFIX')),
420 _('PREFIX')),
421 ('r', 'rev', '', _('revision to distribute'), _('REV')),
421 ('r', 'rev', '', _('revision to distribute'), _('REV')),
422 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
422 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
423 ] + subrepoopts + walkopts,
423 ] + subrepoopts + walkopts,
424 _('[OPTION]... DEST'))
424 _('[OPTION]... DEST'))
425 def archive(ui, repo, dest, **opts):
425 def archive(ui, repo, dest, **opts):
426 '''create an unversioned archive of a repository revision
426 '''create an unversioned archive of a repository revision
427
427
428 By default, the revision used is the parent of the working
428 By default, the revision used is the parent of the working
429 directory; use -r/--rev to specify a different revision.
429 directory; use -r/--rev to specify a different revision.
430
430
431 The archive type is automatically detected based on file
431 The archive type is automatically detected based on file
432 extension (to override, use -t/--type).
432 extension (to override, use -t/--type).
433
433
434 .. container:: verbose
434 .. container:: verbose
435
435
436 Examples:
436 Examples:
437
437
438 - create a zip file containing the 1.0 release::
438 - create a zip file containing the 1.0 release::
439
439
440 hg archive -r 1.0 project-1.0.zip
440 hg archive -r 1.0 project-1.0.zip
441
441
442 - create a tarball excluding .hg files::
442 - create a tarball excluding .hg files::
443
443
444 hg archive project.tar.gz -X ".hg*"
444 hg archive project.tar.gz -X ".hg*"
445
445
446 Valid types are:
446 Valid types are:
447
447
448 :``files``: a directory full of files (default)
448 :``files``: a directory full of files (default)
449 :``tar``: tar archive, uncompressed
449 :``tar``: tar archive, uncompressed
450 :``tbz2``: tar archive, compressed using bzip2
450 :``tbz2``: tar archive, compressed using bzip2
451 :``tgz``: tar archive, compressed using gzip
451 :``tgz``: tar archive, compressed using gzip
452 :``uzip``: zip archive, uncompressed
452 :``uzip``: zip archive, uncompressed
453 :``zip``: zip archive, compressed using deflate
453 :``zip``: zip archive, compressed using deflate
454
454
455 The exact name of the destination archive or directory is given
455 The exact name of the destination archive or directory is given
456 using a format string; see :hg:`help export` for details.
456 using a format string; see :hg:`help export` for details.
457
457
458 Each member added to an archive file has a directory prefix
458 Each member added to an archive file has a directory prefix
459 prepended. Use -p/--prefix to specify a format string for the
459 prepended. Use -p/--prefix to specify a format string for the
460 prefix. The default is the basename of the archive, with suffixes
460 prefix. The default is the basename of the archive, with suffixes
461 removed.
461 removed.
462
462
463 Returns 0 on success.
463 Returns 0 on success.
464 '''
464 '''
465
465
466 opts = pycompat.byteskwargs(opts)
466 opts = pycompat.byteskwargs(opts)
467 ctx = scmutil.revsingle(repo, opts.get('rev'))
467 ctx = scmutil.revsingle(repo, opts.get('rev'))
468 if not ctx:
468 if not ctx:
469 raise error.Abort(_('no working directory: please specify a revision'))
469 raise error.Abort(_('no working directory: please specify a revision'))
470 node = ctx.node()
470 node = ctx.node()
471 dest = cmdutil.makefilename(repo, dest, node)
471 dest = cmdutil.makefilename(repo, dest, node)
472 if os.path.realpath(dest) == repo.root:
472 if os.path.realpath(dest) == repo.root:
473 raise error.Abort(_('repository root cannot be destination'))
473 raise error.Abort(_('repository root cannot be destination'))
474
474
475 kind = opts.get('type') or archival.guesskind(dest) or 'files'
475 kind = opts.get('type') or archival.guesskind(dest) or 'files'
476 prefix = opts.get('prefix')
476 prefix = opts.get('prefix')
477
477
478 if dest == '-':
478 if dest == '-':
479 if kind == 'files':
479 if kind == 'files':
480 raise error.Abort(_('cannot archive plain files to stdout'))
480 raise error.Abort(_('cannot archive plain files to stdout'))
481 dest = cmdutil.makefileobj(repo, dest)
481 dest = cmdutil.makefileobj(repo, dest)
482 if not prefix:
482 if not prefix:
483 prefix = os.path.basename(repo.root) + '-%h'
483 prefix = os.path.basename(repo.root) + '-%h'
484
484
485 prefix = cmdutil.makefilename(repo, prefix, node)
485 prefix = cmdutil.makefilename(repo, prefix, node)
486 match = scmutil.match(ctx, [], opts)
486 match = scmutil.match(ctx, [], opts)
487 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
487 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
488 match, prefix, subrepos=opts.get('subrepos'))
488 match, prefix, subrepos=opts.get('subrepos'))
489
489
490 @command('backout',
490 @command('backout',
491 [('', 'merge', None, _('merge with old dirstate parent after backout')),
491 [('', 'merge', None, _('merge with old dirstate parent after backout')),
492 ('', 'commit', None,
492 ('', 'commit', None,
493 _('commit if no conflicts were encountered (DEPRECATED)')),
493 _('commit if no conflicts were encountered (DEPRECATED)')),
494 ('', 'no-commit', None, _('do not commit')),
494 ('', 'no-commit', None, _('do not commit')),
495 ('', 'parent', '',
495 ('', 'parent', '',
496 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
496 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
497 ('r', 'rev', '', _('revision to backout'), _('REV')),
497 ('r', 'rev', '', _('revision to backout'), _('REV')),
498 ('e', 'edit', False, _('invoke editor on commit messages')),
498 ('e', 'edit', False, _('invoke editor on commit messages')),
499 ] + mergetoolopts + walkopts + commitopts + commitopts2,
499 ] + mergetoolopts + walkopts + commitopts + commitopts2,
500 _('[OPTION]... [-r] REV'))
500 _('[OPTION]... [-r] REV'))
501 def backout(ui, repo, node=None, rev=None, **opts):
501 def backout(ui, repo, node=None, rev=None, **opts):
502 '''reverse effect of earlier changeset
502 '''reverse effect of earlier changeset
503
503
504 Prepare a new changeset with the effect of REV undone in the
504 Prepare a new changeset with the effect of REV undone in the
505 current working directory. If no conflicts were encountered,
505 current working directory. If no conflicts were encountered,
506 it will be committed immediately.
506 it will be committed immediately.
507
507
508 If REV is the parent of the working directory, then this new changeset
508 If REV is the parent of the working directory, then this new changeset
509 is committed automatically (unless --no-commit is specified).
509 is committed automatically (unless --no-commit is specified).
510
510
511 .. note::
511 .. note::
512
512
513 :hg:`backout` cannot be used to fix either an unwanted or
513 :hg:`backout` cannot be used to fix either an unwanted or
514 incorrect merge.
514 incorrect merge.
515
515
516 .. container:: verbose
516 .. container:: verbose
517
517
518 Examples:
518 Examples:
519
519
520 - Reverse the effect of the parent of the working directory.
520 - Reverse the effect of the parent of the working directory.
521 This backout will be committed immediately::
521 This backout will be committed immediately::
522
522
523 hg backout -r .
523 hg backout -r .
524
524
525 - Reverse the effect of previous bad revision 23::
525 - Reverse the effect of previous bad revision 23::
526
526
527 hg backout -r 23
527 hg backout -r 23
528
528
529 - Reverse the effect of previous bad revision 23 and
529 - Reverse the effect of previous bad revision 23 and
530 leave changes uncommitted::
530 leave changes uncommitted::
531
531
532 hg backout -r 23 --no-commit
532 hg backout -r 23 --no-commit
533 hg commit -m "Backout revision 23"
533 hg commit -m "Backout revision 23"
534
534
535 By default, the pending changeset will have one parent,
535 By default, the pending changeset will have one parent,
536 maintaining a linear history. With --merge, the pending
536 maintaining a linear history. With --merge, the pending
537 changeset will instead have two parents: the old parent of the
537 changeset will instead have two parents: the old parent of the
538 working directory and a new child of REV that simply undoes REV.
538 working directory and a new child of REV that simply undoes REV.
539
539
540 Before version 1.7, the behavior without --merge was equivalent
540 Before version 1.7, the behavior without --merge was equivalent
541 to specifying --merge followed by :hg:`update --clean .` to
541 to specifying --merge followed by :hg:`update --clean .` to
542 cancel the merge and leave the child of REV as a head to be
542 cancel the merge and leave the child of REV as a head to be
543 merged separately.
543 merged separately.
544
544
545 See :hg:`help dates` for a list of formats valid for -d/--date.
545 See :hg:`help dates` for a list of formats valid for -d/--date.
546
546
547 See :hg:`help revert` for a way to restore files to the state
547 See :hg:`help revert` for a way to restore files to the state
548 of another revision.
548 of another revision.
549
549
550 Returns 0 on success, 1 if nothing to backout or there are unresolved
550 Returns 0 on success, 1 if nothing to backout or there are unresolved
551 files.
551 files.
552 '''
552 '''
553 wlock = lock = None
553 wlock = lock = None
554 try:
554 try:
555 wlock = repo.wlock()
555 wlock = repo.wlock()
556 lock = repo.lock()
556 lock = repo.lock()
557 return _dobackout(ui, repo, node, rev, **opts)
557 return _dobackout(ui, repo, node, rev, **opts)
558 finally:
558 finally:
559 release(lock, wlock)
559 release(lock, wlock)
560
560
561 def _dobackout(ui, repo, node=None, rev=None, **opts):
561 def _dobackout(ui, repo, node=None, rev=None, **opts):
562 opts = pycompat.byteskwargs(opts)
562 opts = pycompat.byteskwargs(opts)
563 if opts.get('commit') and opts.get('no_commit'):
563 if opts.get('commit') and opts.get('no_commit'):
564 raise error.Abort(_("cannot use --commit with --no-commit"))
564 raise error.Abort(_("cannot use --commit with --no-commit"))
565 if opts.get('merge') and opts.get('no_commit'):
565 if opts.get('merge') and opts.get('no_commit'):
566 raise error.Abort(_("cannot use --merge with --no-commit"))
566 raise error.Abort(_("cannot use --merge with --no-commit"))
567
567
568 if rev and node:
568 if rev and node:
569 raise error.Abort(_("please specify just one revision"))
569 raise error.Abort(_("please specify just one revision"))
570
570
571 if not rev:
571 if not rev:
572 rev = node
572 rev = node
573
573
574 if not rev:
574 if not rev:
575 raise error.Abort(_("please specify a revision to backout"))
575 raise error.Abort(_("please specify a revision to backout"))
576
576
577 date = opts.get('date')
577 date = opts.get('date')
578 if date:
578 if date:
579 opts['date'] = util.parsedate(date)
579 opts['date'] = util.parsedate(date)
580
580
581 cmdutil.checkunfinished(repo)
581 cmdutil.checkunfinished(repo)
582 cmdutil.bailifchanged(repo)
582 cmdutil.bailifchanged(repo)
583 node = scmutil.revsingle(repo, rev).node()
583 node = scmutil.revsingle(repo, rev).node()
584
584
585 op1, op2 = repo.dirstate.parents()
585 op1, op2 = repo.dirstate.parents()
586 if not repo.changelog.isancestor(node, op1):
586 if not repo.changelog.isancestor(node, op1):
587 raise error.Abort(_('cannot backout change that is not an ancestor'))
587 raise error.Abort(_('cannot backout change that is not an ancestor'))
588
588
589 p1, p2 = repo.changelog.parents(node)
589 p1, p2 = repo.changelog.parents(node)
590 if p1 == nullid:
590 if p1 == nullid:
591 raise error.Abort(_('cannot backout a change with no parents'))
591 raise error.Abort(_('cannot backout a change with no parents'))
592 if p2 != nullid:
592 if p2 != nullid:
593 if not opts.get('parent'):
593 if not opts.get('parent'):
594 raise error.Abort(_('cannot backout a merge changeset'))
594 raise error.Abort(_('cannot backout a merge changeset'))
595 p = repo.lookup(opts['parent'])
595 p = repo.lookup(opts['parent'])
596 if p not in (p1, p2):
596 if p not in (p1, p2):
597 raise error.Abort(_('%s is not a parent of %s') %
597 raise error.Abort(_('%s is not a parent of %s') %
598 (short(p), short(node)))
598 (short(p), short(node)))
599 parent = p
599 parent = p
600 else:
600 else:
601 if opts.get('parent'):
601 if opts.get('parent'):
602 raise error.Abort(_('cannot use --parent on non-merge changeset'))
602 raise error.Abort(_('cannot use --parent on non-merge changeset'))
603 parent = p1
603 parent = p1
604
604
605 # the backout should appear on the same branch
605 # the backout should appear on the same branch
606 branch = repo.dirstate.branch()
606 branch = repo.dirstate.branch()
607 bheads = repo.branchheads(branch)
607 bheads = repo.branchheads(branch)
608 rctx = scmutil.revsingle(repo, hex(parent))
608 rctx = scmutil.revsingle(repo, hex(parent))
609 if not opts.get('merge') and op1 != node:
609 if not opts.get('merge') and op1 != node:
610 dsguard = dirstateguard.dirstateguard(repo, 'backout')
610 dsguard = dirstateguard.dirstateguard(repo, 'backout')
611 try:
611 try:
612 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
612 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
613 'backout')
613 'backout')
614 stats = mergemod.update(repo, parent, True, True, node, False)
614 stats = mergemod.update(repo, parent, True, True, node, False)
615 repo.setparents(op1, op2)
615 repo.setparents(op1, op2)
616 dsguard.close()
616 dsguard.close()
617 hg._showstats(repo, stats)
617 hg._showstats(repo, stats)
618 if stats[3]:
618 if stats[3]:
619 repo.ui.status(_("use 'hg resolve' to retry unresolved "
619 repo.ui.status(_("use 'hg resolve' to retry unresolved "
620 "file merges\n"))
620 "file merges\n"))
621 return 1
621 return 1
622 finally:
622 finally:
623 ui.setconfig('ui', 'forcemerge', '', '')
623 ui.setconfig('ui', 'forcemerge', '', '')
624 lockmod.release(dsguard)
624 lockmod.release(dsguard)
625 else:
625 else:
626 hg.clean(repo, node, show_stats=False)
626 hg.clean(repo, node, show_stats=False)
627 repo.dirstate.setbranch(branch)
627 repo.dirstate.setbranch(branch)
628 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
628 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
629
629
630 if opts.get('no_commit'):
630 if opts.get('no_commit'):
631 msg = _("changeset %s backed out, "
631 msg = _("changeset %s backed out, "
632 "don't forget to commit.\n")
632 "don't forget to commit.\n")
633 ui.status(msg % short(node))
633 ui.status(msg % short(node))
634 return 0
634 return 0
635
635
636 def commitfunc(ui, repo, message, match, opts):
636 def commitfunc(ui, repo, message, match, opts):
637 editform = 'backout'
637 editform = 'backout'
638 e = cmdutil.getcommiteditor(editform=editform,
638 e = cmdutil.getcommiteditor(editform=editform,
639 **pycompat.strkwargs(opts))
639 **pycompat.strkwargs(opts))
640 if not message:
640 if not message:
641 # we don't translate commit messages
641 # we don't translate commit messages
642 message = "Backed out changeset %s" % short(node)
642 message = "Backed out changeset %s" % short(node)
643 e = cmdutil.getcommiteditor(edit=True, editform=editform)
643 e = cmdutil.getcommiteditor(edit=True, editform=editform)
644 return repo.commit(message, opts.get('user'), opts.get('date'),
644 return repo.commit(message, opts.get('user'), opts.get('date'),
645 match, editor=e)
645 match, editor=e)
646 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
646 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
647 if not newnode:
647 if not newnode:
648 ui.status(_("nothing changed\n"))
648 ui.status(_("nothing changed\n"))
649 return 1
649 return 1
650 cmdutil.commitstatus(repo, newnode, branch, bheads)
650 cmdutil.commitstatus(repo, newnode, branch, bheads)
651
651
652 def nice(node):
652 def nice(node):
653 return '%d:%s' % (repo.changelog.rev(node), short(node))
653 return '%d:%s' % (repo.changelog.rev(node), short(node))
654 ui.status(_('changeset %s backs out changeset %s\n') %
654 ui.status(_('changeset %s backs out changeset %s\n') %
655 (nice(repo.changelog.tip()), nice(node)))
655 (nice(repo.changelog.tip()), nice(node)))
656 if opts.get('merge') and op1 != node:
656 if opts.get('merge') and op1 != node:
657 hg.clean(repo, op1, show_stats=False)
657 hg.clean(repo, op1, show_stats=False)
658 ui.status(_('merging with changeset %s\n')
658 ui.status(_('merging with changeset %s\n')
659 % nice(repo.changelog.tip()))
659 % nice(repo.changelog.tip()))
660 try:
660 try:
661 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
661 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
662 'backout')
662 'backout')
663 return hg.merge(repo, hex(repo.changelog.tip()))
663 return hg.merge(repo, hex(repo.changelog.tip()))
664 finally:
664 finally:
665 ui.setconfig('ui', 'forcemerge', '', '')
665 ui.setconfig('ui', 'forcemerge', '', '')
666 return 0
666 return 0
667
667
668 @command('bisect',
668 @command('bisect',
669 [('r', 'reset', False, _('reset bisect state')),
669 [('r', 'reset', False, _('reset bisect state')),
670 ('g', 'good', False, _('mark changeset good')),
670 ('g', 'good', False, _('mark changeset good')),
671 ('b', 'bad', False, _('mark changeset bad')),
671 ('b', 'bad', False, _('mark changeset bad')),
672 ('s', 'skip', False, _('skip testing changeset')),
672 ('s', 'skip', False, _('skip testing changeset')),
673 ('e', 'extend', False, _('extend the bisect range')),
673 ('e', 'extend', False, _('extend the bisect range')),
674 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
674 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
675 ('U', 'noupdate', False, _('do not update to target'))],
675 ('U', 'noupdate', False, _('do not update to target'))],
676 _("[-gbsr] [-U] [-c CMD] [REV]"))
676 _("[-gbsr] [-U] [-c CMD] [REV]"))
677 def bisect(ui, repo, rev=None, extra=None, command=None,
677 def bisect(ui, repo, rev=None, extra=None, command=None,
678 reset=None, good=None, bad=None, skip=None, extend=None,
678 reset=None, good=None, bad=None, skip=None, extend=None,
679 noupdate=None):
679 noupdate=None):
680 """subdivision search of changesets
680 """subdivision search of changesets
681
681
682 This command helps to find changesets which introduce problems. To
682 This command helps to find changesets which introduce problems. To
683 use, mark the earliest changeset you know exhibits the problem as
683 use, mark the earliest changeset you know exhibits the problem as
684 bad, then mark the latest changeset which is free from the problem
684 bad, then mark the latest changeset which is free from the problem
685 as good. Bisect will update your working directory to a revision
685 as good. Bisect will update your working directory to a revision
686 for testing (unless the -U/--noupdate option is specified). Once
686 for testing (unless the -U/--noupdate option is specified). Once
687 you have performed tests, mark the working directory as good or
687 you have performed tests, mark the working directory as good or
688 bad, and bisect will either update to another candidate changeset
688 bad, and bisect will either update to another candidate changeset
689 or announce that it has found the bad revision.
689 or announce that it has found the bad revision.
690
690
691 As a shortcut, you can also use the revision argument to mark a
691 As a shortcut, you can also use the revision argument to mark a
692 revision as good or bad without checking it out first.
692 revision as good or bad without checking it out first.
693
693
694 If you supply a command, it will be used for automatic bisection.
694 If you supply a command, it will be used for automatic bisection.
695 The environment variable HG_NODE will contain the ID of the
695 The environment variable HG_NODE will contain the ID of the
696 changeset being tested. The exit status of the command will be
696 changeset being tested. The exit status of the command will be
697 used to mark revisions as good or bad: status 0 means good, 125
697 used to mark revisions as good or bad: status 0 means good, 125
698 means to skip the revision, 127 (command not found) will abort the
698 means to skip the revision, 127 (command not found) will abort the
699 bisection, and any other non-zero exit status means the revision
699 bisection, and any other non-zero exit status means the revision
700 is bad.
700 is bad.
701
701
702 .. container:: verbose
702 .. container:: verbose
703
703
704 Some examples:
704 Some examples:
705
705
706 - start a bisection with known bad revision 34, and good revision 12::
706 - start a bisection with known bad revision 34, and good revision 12::
707
707
708 hg bisect --bad 34
708 hg bisect --bad 34
709 hg bisect --good 12
709 hg bisect --good 12
710
710
711 - advance the current bisection by marking current revision as good or
711 - advance the current bisection by marking current revision as good or
712 bad::
712 bad::
713
713
714 hg bisect --good
714 hg bisect --good
715 hg bisect --bad
715 hg bisect --bad
716
716
717 - mark the current revision, or a known revision, to be skipped (e.g. if
717 - mark the current revision, or a known revision, to be skipped (e.g. if
718 that revision is not usable because of another issue)::
718 that revision is not usable because of another issue)::
719
719
720 hg bisect --skip
720 hg bisect --skip
721 hg bisect --skip 23
721 hg bisect --skip 23
722
722
723 - skip all revisions that do not touch directories ``foo`` or ``bar``::
723 - skip all revisions that do not touch directories ``foo`` or ``bar``::
724
724
725 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
725 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
726
726
727 - forget the current bisection::
727 - forget the current bisection::
728
728
729 hg bisect --reset
729 hg bisect --reset
730
730
731 - use 'make && make tests' to automatically find the first broken
731 - use 'make && make tests' to automatically find the first broken
732 revision::
732 revision::
733
733
734 hg bisect --reset
734 hg bisect --reset
735 hg bisect --bad 34
735 hg bisect --bad 34
736 hg bisect --good 12
736 hg bisect --good 12
737 hg bisect --command "make && make tests"
737 hg bisect --command "make && make tests"
738
738
739 - see all changesets whose states are already known in the current
739 - see all changesets whose states are already known in the current
740 bisection::
740 bisection::
741
741
742 hg log -r "bisect(pruned)"
742 hg log -r "bisect(pruned)"
743
743
744 - see the changeset currently being bisected (especially useful
744 - see the changeset currently being bisected (especially useful
745 if running with -U/--noupdate)::
745 if running with -U/--noupdate)::
746
746
747 hg log -r "bisect(current)"
747 hg log -r "bisect(current)"
748
748
749 - see all changesets that took part in the current bisection::
749 - see all changesets that took part in the current bisection::
750
750
751 hg log -r "bisect(range)"
751 hg log -r "bisect(range)"
752
752
753 - you can even get a nice graph::
753 - you can even get a nice graph::
754
754
755 hg log --graph -r "bisect(range)"
755 hg log --graph -r "bisect(range)"
756
756
757 See :hg:`help revisions.bisect` for more about the `bisect()` predicate.
757 See :hg:`help revisions.bisect` for more about the `bisect()` predicate.
758
758
759 Returns 0 on success.
759 Returns 0 on success.
760 """
760 """
761 # backward compatibility
761 # backward compatibility
762 if rev in "good bad reset init".split():
762 if rev in "good bad reset init".split():
763 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
763 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
764 cmd, rev, extra = rev, extra, None
764 cmd, rev, extra = rev, extra, None
765 if cmd == "good":
765 if cmd == "good":
766 good = True
766 good = True
767 elif cmd == "bad":
767 elif cmd == "bad":
768 bad = True
768 bad = True
769 else:
769 else:
770 reset = True
770 reset = True
771 elif extra:
771 elif extra:
772 raise error.Abort(_('incompatible arguments'))
772 raise error.Abort(_('incompatible arguments'))
773
773
774 incompatibles = {
774 incompatibles = {
775 '--bad': bad,
775 '--bad': bad,
776 '--command': bool(command),
776 '--command': bool(command),
777 '--extend': extend,
777 '--extend': extend,
778 '--good': good,
778 '--good': good,
779 '--reset': reset,
779 '--reset': reset,
780 '--skip': skip,
780 '--skip': skip,
781 }
781 }
782
782
783 enabled = [x for x in incompatibles if incompatibles[x]]
783 enabled = [x for x in incompatibles if incompatibles[x]]
784
784
785 if len(enabled) > 1:
785 if len(enabled) > 1:
786 raise error.Abort(_('%s and %s are incompatible') %
786 raise error.Abort(_('%s and %s are incompatible') %
787 tuple(sorted(enabled)[0:2]))
787 tuple(sorted(enabled)[0:2]))
788
788
789 if reset:
789 if reset:
790 hbisect.resetstate(repo)
790 hbisect.resetstate(repo)
791 return
791 return
792
792
793 state = hbisect.load_state(repo)
793 state = hbisect.load_state(repo)
794
794
795 # update state
795 # update state
796 if good or bad or skip:
796 if good or bad or skip:
797 if rev:
797 if rev:
798 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
798 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
799 else:
799 else:
800 nodes = [repo.lookup('.')]
800 nodes = [repo.lookup('.')]
801 if good:
801 if good:
802 state['good'] += nodes
802 state['good'] += nodes
803 elif bad:
803 elif bad:
804 state['bad'] += nodes
804 state['bad'] += nodes
805 elif skip:
805 elif skip:
806 state['skip'] += nodes
806 state['skip'] += nodes
807 hbisect.save_state(repo, state)
807 hbisect.save_state(repo, state)
808 if not (state['good'] and state['bad']):
808 if not (state['good'] and state['bad']):
809 return
809 return
810
810
811 def mayupdate(repo, node, show_stats=True):
811 def mayupdate(repo, node, show_stats=True):
812 """common used update sequence"""
812 """common used update sequence"""
813 if noupdate:
813 if noupdate:
814 return
814 return
815 cmdutil.checkunfinished(repo)
815 cmdutil.checkunfinished(repo)
816 cmdutil.bailifchanged(repo)
816 cmdutil.bailifchanged(repo)
817 return hg.clean(repo, node, show_stats=show_stats)
817 return hg.clean(repo, node, show_stats=show_stats)
818
818
819 displayer = cmdutil.show_changeset(ui, repo, {})
819 displayer = cmdutil.show_changeset(ui, repo, {})
820
820
821 if command:
821 if command:
822 changesets = 1
822 changesets = 1
823 if noupdate:
823 if noupdate:
824 try:
824 try:
825 node = state['current'][0]
825 node = state['current'][0]
826 except LookupError:
826 except LookupError:
827 raise error.Abort(_('current bisect revision is unknown - '
827 raise error.Abort(_('current bisect revision is unknown - '
828 'start a new bisect to fix'))
828 'start a new bisect to fix'))
829 else:
829 else:
830 node, p2 = repo.dirstate.parents()
830 node, p2 = repo.dirstate.parents()
831 if p2 != nullid:
831 if p2 != nullid:
832 raise error.Abort(_('current bisect revision is a merge'))
832 raise error.Abort(_('current bisect revision is a merge'))
833 if rev:
833 if rev:
834 node = repo[scmutil.revsingle(repo, rev, node)].node()
834 node = repo[scmutil.revsingle(repo, rev, node)].node()
835 try:
835 try:
836 while changesets:
836 while changesets:
837 # update state
837 # update state
838 state['current'] = [node]
838 state['current'] = [node]
839 hbisect.save_state(repo, state)
839 hbisect.save_state(repo, state)
840 status = ui.system(command, environ={'HG_NODE': hex(node)},
840 status = ui.system(command, environ={'HG_NODE': hex(node)},
841 blockedtag='bisect_check')
841 blockedtag='bisect_check')
842 if status == 125:
842 if status == 125:
843 transition = "skip"
843 transition = "skip"
844 elif status == 0:
844 elif status == 0:
845 transition = "good"
845 transition = "good"
846 # status < 0 means process was killed
846 # status < 0 means process was killed
847 elif status == 127:
847 elif status == 127:
848 raise error.Abort(_("failed to execute %s") % command)
848 raise error.Abort(_("failed to execute %s") % command)
849 elif status < 0:
849 elif status < 0:
850 raise error.Abort(_("%s killed") % command)
850 raise error.Abort(_("%s killed") % command)
851 else:
851 else:
852 transition = "bad"
852 transition = "bad"
853 state[transition].append(node)
853 state[transition].append(node)
854 ctx = repo[node]
854 ctx = repo[node]
855 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
855 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
856 hbisect.checkstate(state)
856 hbisect.checkstate(state)
857 # bisect
857 # bisect
858 nodes, changesets, bgood = hbisect.bisect(repo, state)
858 nodes, changesets, bgood = hbisect.bisect(repo, state)
859 # update to next check
859 # update to next check
860 node = nodes[0]
860 node = nodes[0]
861 mayupdate(repo, node, show_stats=False)
861 mayupdate(repo, node, show_stats=False)
862 finally:
862 finally:
863 state['current'] = [node]
863 state['current'] = [node]
864 hbisect.save_state(repo, state)
864 hbisect.save_state(repo, state)
865 hbisect.printresult(ui, repo, state, displayer, nodes, bgood)
865 hbisect.printresult(ui, repo, state, displayer, nodes, bgood)
866 return
866 return
867
867
868 hbisect.checkstate(state)
868 hbisect.checkstate(state)
869
869
870 # actually bisect
870 # actually bisect
871 nodes, changesets, good = hbisect.bisect(repo, state)
871 nodes, changesets, good = hbisect.bisect(repo, state)
872 if extend:
872 if extend:
873 if not changesets:
873 if not changesets:
874 extendnode = hbisect.extendrange(repo, state, nodes, good)
874 extendnode = hbisect.extendrange(repo, state, nodes, good)
875 if extendnode is not None:
875 if extendnode is not None:
876 ui.write(_("Extending search to changeset %d:%s\n")
876 ui.write(_("Extending search to changeset %d:%s\n")
877 % (extendnode.rev(), extendnode))
877 % (extendnode.rev(), extendnode))
878 state['current'] = [extendnode.node()]
878 state['current'] = [extendnode.node()]
879 hbisect.save_state(repo, state)
879 hbisect.save_state(repo, state)
880 return mayupdate(repo, extendnode.node())
880 return mayupdate(repo, extendnode.node())
881 raise error.Abort(_("nothing to extend"))
881 raise error.Abort(_("nothing to extend"))
882
882
883 if changesets == 0:
883 if changesets == 0:
884 hbisect.printresult(ui, repo, state, displayer, nodes, good)
884 hbisect.printresult(ui, repo, state, displayer, nodes, good)
885 else:
885 else:
886 assert len(nodes) == 1 # only a single node can be tested next
886 assert len(nodes) == 1 # only a single node can be tested next
887 node = nodes[0]
887 node = nodes[0]
888 # compute the approximate number of remaining tests
888 # compute the approximate number of remaining tests
889 tests, size = 0, 2
889 tests, size = 0, 2
890 while size <= changesets:
890 while size <= changesets:
891 tests, size = tests + 1, size * 2
891 tests, size = tests + 1, size * 2
892 rev = repo.changelog.rev(node)
892 rev = repo.changelog.rev(node)
893 ui.write(_("Testing changeset %d:%s "
893 ui.write(_("Testing changeset %d:%s "
894 "(%d changesets remaining, ~%d tests)\n")
894 "(%d changesets remaining, ~%d tests)\n")
895 % (rev, short(node), changesets, tests))
895 % (rev, short(node), changesets, tests))
896 state['current'] = [node]
896 state['current'] = [node]
897 hbisect.save_state(repo, state)
897 hbisect.save_state(repo, state)
898 return mayupdate(repo, node)
898 return mayupdate(repo, node)
899
899
900 @command('bookmarks|bookmark',
900 @command('bookmarks|bookmark',
901 [('f', 'force', False, _('force')),
901 [('f', 'force', False, _('force')),
902 ('r', 'rev', '', _('revision for bookmark action'), _('REV')),
902 ('r', 'rev', '', _('revision for bookmark action'), _('REV')),
903 ('d', 'delete', False, _('delete a given bookmark')),
903 ('d', 'delete', False, _('delete a given bookmark')),
904 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
904 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
905 ('i', 'inactive', False, _('mark a bookmark inactive')),
905 ('i', 'inactive', False, _('mark a bookmark inactive')),
906 ] + formatteropts,
906 ] + formatteropts,
907 _('hg bookmarks [OPTIONS]... [NAME]...'))
907 _('hg bookmarks [OPTIONS]... [NAME]...'))
908 def bookmark(ui, repo, *names, **opts):
908 def bookmark(ui, repo, *names, **opts):
909 '''create a new bookmark or list existing bookmarks
909 '''create a new bookmark or list existing bookmarks
910
910
911 Bookmarks are labels on changesets to help track lines of development.
911 Bookmarks are labels on changesets to help track lines of development.
912 Bookmarks are unversioned and can be moved, renamed and deleted.
912 Bookmarks are unversioned and can be moved, renamed and deleted.
913 Deleting or moving a bookmark has no effect on the associated changesets.
913 Deleting or moving a bookmark has no effect on the associated changesets.
914
914
915 Creating or updating to a bookmark causes it to be marked as 'active'.
915 Creating or updating to a bookmark causes it to be marked as 'active'.
916 The active bookmark is indicated with a '*'.
916 The active bookmark is indicated with a '*'.
917 When a commit is made, the active bookmark will advance to the new commit.
917 When a commit is made, the active bookmark will advance to the new commit.
918 A plain :hg:`update` will also advance an active bookmark, if possible.
918 A plain :hg:`update` will also advance an active bookmark, if possible.
919 Updating away from a bookmark will cause it to be deactivated.
919 Updating away from a bookmark will cause it to be deactivated.
920
920
921 Bookmarks can be pushed and pulled between repositories (see
921 Bookmarks can be pushed and pulled between repositories (see
922 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
922 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
923 diverged, a new 'divergent bookmark' of the form 'name@path' will
923 diverged, a new 'divergent bookmark' of the form 'name@path' will
924 be created. Using :hg:`merge` will resolve the divergence.
924 be created. Using :hg:`merge` will resolve the divergence.
925
925
926 Specifying bookmark as '.' to -m or -d options is equivalent to specifying
926 Specifying bookmark as '.' to -m or -d options is equivalent to specifying
927 the active bookmark's name.
927 the active bookmark's name.
928
928
929 A bookmark named '@' has the special property that :hg:`clone` will
929 A bookmark named '@' has the special property that :hg:`clone` will
930 check it out by default if it exists.
930 check it out by default if it exists.
931
931
932 .. container:: verbose
932 .. container:: verbose
933
933
934 Examples:
934 Examples:
935
935
936 - create an active bookmark for a new line of development::
936 - create an active bookmark for a new line of development::
937
937
938 hg book new-feature
938 hg book new-feature
939
939
940 - create an inactive bookmark as a place marker::
940 - create an inactive bookmark as a place marker::
941
941
942 hg book -i reviewed
942 hg book -i reviewed
943
943
944 - create an inactive bookmark on another changeset::
944 - create an inactive bookmark on another changeset::
945
945
946 hg book -r .^ tested
946 hg book -r .^ tested
947
947
948 - rename bookmark turkey to dinner::
948 - rename bookmark turkey to dinner::
949
949
950 hg book -m turkey dinner
950 hg book -m turkey dinner
951
951
952 - move the '@' bookmark from another branch::
952 - move the '@' bookmark from another branch::
953
953
954 hg book -f @
954 hg book -f @
955 '''
955 '''
956 force = opts.get(r'force')
956 force = opts.get(r'force')
957 rev = opts.get(r'rev')
957 rev = opts.get(r'rev')
958 delete = opts.get(r'delete')
958 delete = opts.get(r'delete')
959 rename = opts.get(r'rename')
959 rename = opts.get(r'rename')
960 inactive = opts.get(r'inactive')
960 inactive = opts.get(r'inactive')
961
961
962 if delete and rename:
962 if delete and rename:
963 raise error.Abort(_("--delete and --rename are incompatible"))
963 raise error.Abort(_("--delete and --rename are incompatible"))
964 if delete and rev:
964 if delete and rev:
965 raise error.Abort(_("--rev is incompatible with --delete"))
965 raise error.Abort(_("--rev is incompatible with --delete"))
966 if rename and rev:
966 if rename and rev:
967 raise error.Abort(_("--rev is incompatible with --rename"))
967 raise error.Abort(_("--rev is incompatible with --rename"))
968 if not names and (delete or rev):
968 if not names and (delete or rev):
969 raise error.Abort(_("bookmark name required"))
969 raise error.Abort(_("bookmark name required"))
970
970
971 if delete or rename or names or inactive:
971 if delete or rename or names or inactive:
972 with repo.wlock(), repo.lock(), repo.transaction('bookmark') as tr:
972 with repo.wlock(), repo.lock(), repo.transaction('bookmark') as tr:
973 if delete:
973 if delete:
974 names = pycompat.maplist(repo._bookmarks.expandname, names)
974 names = pycompat.maplist(repo._bookmarks.expandname, names)
975 bookmarks.delete(repo, tr, names)
975 bookmarks.delete(repo, tr, names)
976 elif rename:
976 elif rename:
977 if not names:
977 if not names:
978 raise error.Abort(_("new bookmark name required"))
978 raise error.Abort(_("new bookmark name required"))
979 elif len(names) > 1:
979 elif len(names) > 1:
980 raise error.Abort(_("only one new bookmark name allowed"))
980 raise error.Abort(_("only one new bookmark name allowed"))
981 rename = repo._bookmarks.expandname(rename)
981 rename = repo._bookmarks.expandname(rename)
982 bookmarks.rename(repo, tr, rename, names[0], force, inactive)
982 bookmarks.rename(repo, tr, rename, names[0], force, inactive)
983 elif names:
983 elif names:
984 bookmarks.addbookmarks(repo, tr, names, rev, force, inactive)
984 bookmarks.addbookmarks(repo, tr, names, rev, force, inactive)
985 elif inactive:
985 elif inactive:
986 if len(repo._bookmarks) == 0:
986 if len(repo._bookmarks) == 0:
987 ui.status(_("no bookmarks set\n"))
987 ui.status(_("no bookmarks set\n"))
988 elif not repo._activebookmark:
988 elif not repo._activebookmark:
989 ui.status(_("no active bookmark\n"))
989 ui.status(_("no active bookmark\n"))
990 else:
990 else:
991 bookmarks.deactivate(repo)
991 bookmarks.deactivate(repo)
992 else: # show bookmarks
992 else: # show bookmarks
993 bookmarks.printbookmarks(ui, repo, **opts)
993 bookmarks.printbookmarks(ui, repo, **opts)
994
994
995 @command('branch',
995 @command('branch',
996 [('f', 'force', None,
996 [('f', 'force', None,
997 _('set branch name even if it shadows an existing branch')),
997 _('set branch name even if it shadows an existing branch')),
998 ('C', 'clean', None, _('reset branch name to parent branch name'))],
998 ('C', 'clean', None, _('reset branch name to parent branch name'))],
999 _('[-fC] [NAME]'))
999 _('[-fC] [NAME]'))
1000 def branch(ui, repo, label=None, **opts):
1000 def branch(ui, repo, label=None, **opts):
1001 """set or show the current branch name
1001 """set or show the current branch name
1002
1002
1003 .. note::
1003 .. note::
1004
1004
1005 Branch names are permanent and global. Use :hg:`bookmark` to create a
1005 Branch names are permanent and global. Use :hg:`bookmark` to create a
1006 light-weight bookmark instead. See :hg:`help glossary` for more
1006 light-weight bookmark instead. See :hg:`help glossary` for more
1007 information about named branches and bookmarks.
1007 information about named branches and bookmarks.
1008
1008
1009 With no argument, show the current branch name. With one argument,
1009 With no argument, show the current branch name. With one argument,
1010 set the working directory branch name (the branch will not exist
1010 set the working directory branch name (the branch will not exist
1011 in the repository until the next commit). Standard practice
1011 in the repository until the next commit). Standard practice
1012 recommends that primary development take place on the 'default'
1012 recommends that primary development take place on the 'default'
1013 branch.
1013 branch.
1014
1014
1015 Unless -f/--force is specified, branch will not let you set a
1015 Unless -f/--force is specified, branch will not let you set a
1016 branch name that already exists.
1016 branch name that already exists.
1017
1017
1018 Use -C/--clean to reset the working directory branch to that of
1018 Use -C/--clean to reset the working directory branch to that of
1019 the parent of the working directory, negating a previous branch
1019 the parent of the working directory, negating a previous branch
1020 change.
1020 change.
1021
1021
1022 Use the command :hg:`update` to switch to an existing branch. Use
1022 Use the command :hg:`update` to switch to an existing branch. Use
1023 :hg:`commit --close-branch` to mark this branch head as closed.
1023 :hg:`commit --close-branch` to mark this branch head as closed.
1024 When all heads of a branch are closed, the branch will be
1024 When all heads of a branch are closed, the branch will be
1025 considered closed.
1025 considered closed.
1026
1026
1027 Returns 0 on success.
1027 Returns 0 on success.
1028 """
1028 """
1029 opts = pycompat.byteskwargs(opts)
1029 opts = pycompat.byteskwargs(opts)
1030 if label:
1030 if label:
1031 label = label.strip()
1031 label = label.strip()
1032
1032
1033 if not opts.get('clean') and not label:
1033 if not opts.get('clean') and not label:
1034 ui.write("%s\n" % repo.dirstate.branch())
1034 ui.write("%s\n" % repo.dirstate.branch())
1035 return
1035 return
1036
1036
1037 with repo.wlock():
1037 with repo.wlock():
1038 if opts.get('clean'):
1038 if opts.get('clean'):
1039 label = repo[None].p1().branch()
1039 label = repo[None].p1().branch()
1040 repo.dirstate.setbranch(label)
1040 repo.dirstate.setbranch(label)
1041 ui.status(_('reset working directory to branch %s\n') % label)
1041 ui.status(_('reset working directory to branch %s\n') % label)
1042 elif label:
1042 elif label:
1043 if not opts.get('force') and label in repo.branchmap():
1043 if not opts.get('force') and label in repo.branchmap():
1044 if label not in [p.branch() for p in repo[None].parents()]:
1044 if label not in [p.branch() for p in repo[None].parents()]:
1045 raise error.Abort(_('a branch of the same name already'
1045 raise error.Abort(_('a branch of the same name already'
1046 ' exists'),
1046 ' exists'),
1047 # i18n: "it" refers to an existing branch
1047 # i18n: "it" refers to an existing branch
1048 hint=_("use 'hg update' to switch to it"))
1048 hint=_("use 'hg update' to switch to it"))
1049 scmutil.checknewlabel(repo, label, 'branch')
1049 scmutil.checknewlabel(repo, label, 'branch')
1050 repo.dirstate.setbranch(label)
1050 repo.dirstate.setbranch(label)
1051 ui.status(_('marked working directory as branch %s\n') % label)
1051 ui.status(_('marked working directory as branch %s\n') % label)
1052
1052
1053 # find any open named branches aside from default
1053 # find any open named branches aside from default
1054 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1054 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1055 if n != "default" and not c]
1055 if n != "default" and not c]
1056 if not others:
1056 if not others:
1057 ui.status(_('(branches are permanent and global, '
1057 ui.status(_('(branches are permanent and global, '
1058 'did you want a bookmark?)\n'))
1058 'did you want a bookmark?)\n'))
1059
1059
1060 @command('branches',
1060 @command('branches',
1061 [('a', 'active', False,
1061 [('a', 'active', False,
1062 _('show only branches that have unmerged heads (DEPRECATED)')),
1062 _('show only branches that have unmerged heads (DEPRECATED)')),
1063 ('c', 'closed', False, _('show normal and closed branches')),
1063 ('c', 'closed', False, _('show normal and closed branches')),
1064 ] + formatteropts,
1064 ] + formatteropts,
1065 _('[-c]'), cmdtype=readonly)
1065 _('[-c]'), cmdtype=readonly)
1066 def branches(ui, repo, active=False, closed=False, **opts):
1066 def branches(ui, repo, active=False, closed=False, **opts):
1067 """list repository named branches
1067 """list repository named branches
1068
1068
1069 List the repository's named branches, indicating which ones are
1069 List the repository's named branches, indicating which ones are
1070 inactive. If -c/--closed is specified, also list branches which have
1070 inactive. If -c/--closed is specified, also list branches which have
1071 been marked closed (see :hg:`commit --close-branch`).
1071 been marked closed (see :hg:`commit --close-branch`).
1072
1072
1073 Use the command :hg:`update` to switch to an existing branch.
1073 Use the command :hg:`update` to switch to an existing branch.
1074
1074
1075 Returns 0.
1075 Returns 0.
1076 """
1076 """
1077
1077
1078 opts = pycompat.byteskwargs(opts)
1078 opts = pycompat.byteskwargs(opts)
1079 ui.pager('branches')
1079 ui.pager('branches')
1080 fm = ui.formatter('branches', opts)
1080 fm = ui.formatter('branches', opts)
1081 hexfunc = fm.hexfunc
1081 hexfunc = fm.hexfunc
1082
1082
1083 allheads = set(repo.heads())
1083 allheads = set(repo.heads())
1084 branches = []
1084 branches = []
1085 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1085 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1086 isactive = False
1086 isactive = False
1087 if not isclosed:
1087 if not isclosed:
1088 openheads = set(repo.branchmap().iteropen(heads))
1088 openheads = set(repo.branchmap().iteropen(heads))
1089 isactive = bool(openheads & allheads)
1089 isactive = bool(openheads & allheads)
1090 branches.append((tag, repo[tip], isactive, not isclosed))
1090 branches.append((tag, repo[tip], isactive, not isclosed))
1091 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1091 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1092 reverse=True)
1092 reverse=True)
1093
1093
1094 for tag, ctx, isactive, isopen in branches:
1094 for tag, ctx, isactive, isopen in branches:
1095 if active and not isactive:
1095 if active and not isactive:
1096 continue
1096 continue
1097 if isactive:
1097 if isactive:
1098 label = 'branches.active'
1098 label = 'branches.active'
1099 notice = ''
1099 notice = ''
1100 elif not isopen:
1100 elif not isopen:
1101 if not closed:
1101 if not closed:
1102 continue
1102 continue
1103 label = 'branches.closed'
1103 label = 'branches.closed'
1104 notice = _(' (closed)')
1104 notice = _(' (closed)')
1105 else:
1105 else:
1106 label = 'branches.inactive'
1106 label = 'branches.inactive'
1107 notice = _(' (inactive)')
1107 notice = _(' (inactive)')
1108 current = (tag == repo.dirstate.branch())
1108 current = (tag == repo.dirstate.branch())
1109 if current:
1109 if current:
1110 label = 'branches.current'
1110 label = 'branches.current'
1111
1111
1112 fm.startitem()
1112 fm.startitem()
1113 fm.write('branch', '%s', tag, label=label)
1113 fm.write('branch', '%s', tag, label=label)
1114 rev = ctx.rev()
1114 rev = ctx.rev()
1115 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1115 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1116 fmt = ' ' * padsize + ' %d:%s'
1116 fmt = ' ' * padsize + ' %d:%s'
1117 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1117 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1118 label='log.changeset changeset.%s' % ctx.phasestr())
1118 label='log.changeset changeset.%s' % ctx.phasestr())
1119 fm.context(ctx=ctx)
1119 fm.context(ctx=ctx)
1120 fm.data(active=isactive, closed=not isopen, current=current)
1120 fm.data(active=isactive, closed=not isopen, current=current)
1121 if not ui.quiet:
1121 if not ui.quiet:
1122 fm.plain(notice)
1122 fm.plain(notice)
1123 fm.plain('\n')
1123 fm.plain('\n')
1124 fm.end()
1124 fm.end()
1125
1125
1126 @command('bundle',
1126 @command('bundle',
1127 [('f', 'force', None, _('run even when the destination is unrelated')),
1127 [('f', 'force', None, _('run even when the destination is unrelated')),
1128 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1128 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1129 _('REV')),
1129 _('REV')),
1130 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1130 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1131 _('BRANCH')),
1131 _('BRANCH')),
1132 ('', 'base', [],
1132 ('', 'base', [],
1133 _('a base changeset assumed to be available at the destination'),
1133 _('a base changeset assumed to be available at the destination'),
1134 _('REV')),
1134 _('REV')),
1135 ('a', 'all', None, _('bundle all changesets in the repository')),
1135 ('a', 'all', None, _('bundle all changesets in the repository')),
1136 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1136 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1137 ] + remoteopts,
1137 ] + remoteopts,
1138 _('[-f] [-t BUNDLESPEC] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1138 _('[-f] [-t BUNDLESPEC] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1139 def bundle(ui, repo, fname, dest=None, **opts):
1139 def bundle(ui, repo, fname, dest=None, **opts):
1140 """create a bundle file
1140 """create a bundle file
1141
1141
1142 Generate a bundle file containing data to be added to a repository.
1142 Generate a bundle file containing data to be added to a repository.
1143
1143
1144 To create a bundle containing all changesets, use -a/--all
1144 To create a bundle containing all changesets, use -a/--all
1145 (or --base null). Otherwise, hg assumes the destination will have
1145 (or --base null). Otherwise, hg assumes the destination will have
1146 all the nodes you specify with --base parameters. Otherwise, hg
1146 all the nodes you specify with --base parameters. Otherwise, hg
1147 will assume the repository has all the nodes in destination, or
1147 will assume the repository has all the nodes in destination, or
1148 default-push/default if no destination is specified.
1148 default-push/default if no destination is specified.
1149
1149
1150 You can change bundle format with the -t/--type option. See
1150 You can change bundle format with the -t/--type option. See
1151 :hg:`help bundlespec` for documentation on this format. By default,
1151 :hg:`help bundlespec` for documentation on this format. By default,
1152 the most appropriate format is used and compression defaults to
1152 the most appropriate format is used and compression defaults to
1153 bzip2.
1153 bzip2.
1154
1154
1155 The bundle file can then be transferred using conventional means
1155 The bundle file can then be transferred using conventional means
1156 and applied to another repository with the unbundle or pull
1156 and applied to another repository with the unbundle or pull
1157 command. This is useful when direct push and pull are not
1157 command. This is useful when direct push and pull are not
1158 available or when exporting an entire repository is undesirable.
1158 available or when exporting an entire repository is undesirable.
1159
1159
1160 Applying bundles preserves all changeset contents including
1160 Applying bundles preserves all changeset contents including
1161 permissions, copy/rename information, and revision history.
1161 permissions, copy/rename information, and revision history.
1162
1162
1163 Returns 0 on success, 1 if no changes found.
1163 Returns 0 on success, 1 if no changes found.
1164 """
1164 """
1165 opts = pycompat.byteskwargs(opts)
1165 opts = pycompat.byteskwargs(opts)
1166 revs = None
1166 revs = None
1167 if 'rev' in opts:
1167 if 'rev' in opts:
1168 revstrings = opts['rev']
1168 revstrings = opts['rev']
1169 revs = scmutil.revrange(repo, revstrings)
1169 revs = scmutil.revrange(repo, revstrings)
1170 if revstrings and not revs:
1170 if revstrings and not revs:
1171 raise error.Abort(_('no commits to bundle'))
1171 raise error.Abort(_('no commits to bundle'))
1172
1172
1173 bundletype = opts.get('type', 'bzip2').lower()
1173 bundletype = opts.get('type', 'bzip2').lower()
1174 try:
1174 try:
1175 bcompression, cgversion, params = exchange.parsebundlespec(
1175 bcompression, cgversion, params = exchange.parsebundlespec(
1176 repo, bundletype, strict=False)
1176 repo, bundletype, strict=False)
1177 except error.UnsupportedBundleSpecification as e:
1177 except error.UnsupportedBundleSpecification as e:
1178 raise error.Abort(str(e),
1178 raise error.Abort(str(e),
1179 hint=_("see 'hg help bundlespec' for supported "
1179 hint=_("see 'hg help bundlespec' for supported "
1180 "values for --type"))
1180 "values for --type"))
1181
1181
1182 # Packed bundles are a pseudo bundle format for now.
1182 # Packed bundles are a pseudo bundle format for now.
1183 if cgversion == 's1':
1183 if cgversion == 's1':
1184 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1184 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1185 hint=_("use 'hg debugcreatestreamclonebundle'"))
1185 hint=_("use 'hg debugcreatestreamclonebundle'"))
1186
1186
1187 if opts.get('all'):
1187 if opts.get('all'):
1188 if dest:
1188 if dest:
1189 raise error.Abort(_("--all is incompatible with specifying "
1189 raise error.Abort(_("--all is incompatible with specifying "
1190 "a destination"))
1190 "a destination"))
1191 if opts.get('base'):
1191 if opts.get('base'):
1192 ui.warn(_("ignoring --base because --all was specified\n"))
1192 ui.warn(_("ignoring --base because --all was specified\n"))
1193 base = ['null']
1193 base = ['null']
1194 else:
1194 else:
1195 base = scmutil.revrange(repo, opts.get('base'))
1195 base = scmutil.revrange(repo, opts.get('base'))
1196 if cgversion not in changegroup.supportedoutgoingversions(repo):
1196 if cgversion not in changegroup.supportedoutgoingversions(repo):
1197 raise error.Abort(_("repository does not support bundle version %s") %
1197 raise error.Abort(_("repository does not support bundle version %s") %
1198 cgversion)
1198 cgversion)
1199
1199
1200 if base:
1200 if base:
1201 if dest:
1201 if dest:
1202 raise error.Abort(_("--base is incompatible with specifying "
1202 raise error.Abort(_("--base is incompatible with specifying "
1203 "a destination"))
1203 "a destination"))
1204 common = [repo.lookup(rev) for rev in base]
1204 common = [repo.lookup(rev) for rev in base]
1205 heads = revs and map(repo.lookup, revs) or None
1205 heads = revs and map(repo.lookup, revs) or None
1206 outgoing = discovery.outgoing(repo, common, heads)
1206 outgoing = discovery.outgoing(repo, common, heads)
1207 else:
1207 else:
1208 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1208 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1209 dest, branches = hg.parseurl(dest, opts.get('branch'))
1209 dest, branches = hg.parseurl(dest, opts.get('branch'))
1210 other = hg.peer(repo, opts, dest)
1210 other = hg.peer(repo, opts, dest)
1211 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1211 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1212 heads = revs and map(repo.lookup, revs) or revs
1212 heads = revs and map(repo.lookup, revs) or revs
1213 outgoing = discovery.findcommonoutgoing(repo, other,
1213 outgoing = discovery.findcommonoutgoing(repo, other,
1214 onlyheads=heads,
1214 onlyheads=heads,
1215 force=opts.get('force'),
1215 force=opts.get('force'),
1216 portable=True)
1216 portable=True)
1217
1217
1218 if not outgoing.missing:
1218 if not outgoing.missing:
1219 scmutil.nochangesfound(ui, repo, not base and outgoing.excluded)
1219 scmutil.nochangesfound(ui, repo, not base and outgoing.excluded)
1220 return 1
1220 return 1
1221
1221
1222 if cgversion == '01': #bundle1
1222 if cgversion == '01': #bundle1
1223 if bcompression is None:
1223 if bcompression is None:
1224 bcompression = 'UN'
1224 bcompression = 'UN'
1225 bversion = 'HG10' + bcompression
1225 bversion = 'HG10' + bcompression
1226 bcompression = None
1226 bcompression = None
1227 elif cgversion in ('02', '03'):
1227 elif cgversion in ('02', '03'):
1228 bversion = 'HG20'
1228 bversion = 'HG20'
1229 else:
1229 else:
1230 raise error.ProgrammingError(
1230 raise error.ProgrammingError(
1231 'bundle: unexpected changegroup version %s' % cgversion)
1231 'bundle: unexpected changegroup version %s' % cgversion)
1232
1232
1233 # TODO compression options should be derived from bundlespec parsing.
1233 # TODO compression options should be derived from bundlespec parsing.
1234 # This is a temporary hack to allow adjusting bundle compression
1234 # This is a temporary hack to allow adjusting bundle compression
1235 # level without a) formalizing the bundlespec changes to declare it
1235 # level without a) formalizing the bundlespec changes to declare it
1236 # b) introducing a command flag.
1236 # b) introducing a command flag.
1237 compopts = {}
1237 compopts = {}
1238 complevel = ui.configint('experimental', 'bundlecomplevel')
1238 complevel = ui.configint('experimental', 'bundlecomplevel')
1239 if complevel is not None:
1239 if complevel is not None:
1240 compopts['level'] = complevel
1240 compopts['level'] = complevel
1241
1241
1242
1242
1243 contentopts = {'cg.version': cgversion}
1243 contentopts = {'cg.version': cgversion}
1244 if repo.ui.configbool('experimental', 'evolution.bundle-obsmarker'):
1244 if repo.ui.configbool('experimental', 'evolution.bundle-obsmarker'):
1245 contentopts['obsolescence'] = True
1245 contentopts['obsolescence'] = True
1246 if repo.ui.configbool('experimental', 'bundle-phases'):
1246 if repo.ui.configbool('experimental', 'bundle-phases'):
1247 contentopts['phases'] = True
1247 contentopts['phases'] = True
1248 bundle2.writenewbundle(ui, repo, 'bundle', fname, bversion, outgoing,
1248 bundle2.writenewbundle(ui, repo, 'bundle', fname, bversion, outgoing,
1249 contentopts, compression=bcompression,
1249 contentopts, compression=bcompression,
1250 compopts=compopts)
1250 compopts=compopts)
1251
1251
1252 @command('cat',
1252 @command('cat',
1253 [('o', 'output', '',
1253 [('o', 'output', '',
1254 _('print output to file with formatted name'), _('FORMAT')),
1254 _('print output to file with formatted name'), _('FORMAT')),
1255 ('r', 'rev', '', _('print the given revision'), _('REV')),
1255 ('r', 'rev', '', _('print the given revision'), _('REV')),
1256 ('', 'decode', None, _('apply any matching decode filter')),
1256 ('', 'decode', None, _('apply any matching decode filter')),
1257 ] + walkopts + formatteropts,
1257 ] + walkopts + formatteropts,
1258 _('[OPTION]... FILE...'),
1258 _('[OPTION]... FILE...'),
1259 inferrepo=True, cmdtype=readonly)
1259 inferrepo=True, cmdtype=readonly)
1260 def cat(ui, repo, file1, *pats, **opts):
1260 def cat(ui, repo, file1, *pats, **opts):
1261 """output the current or given revision of files
1261 """output the current or given revision of files
1262
1262
1263 Print the specified files as they were at the given revision. If
1263 Print the specified files as they were at the given revision. If
1264 no revision is given, the parent of the working directory is used.
1264 no revision is given, the parent of the working directory is used.
1265
1265
1266 Output may be to a file, in which case the name of the file is
1266 Output may be to a file, in which case the name of the file is
1267 given using a format string. The formatting rules as follows:
1267 given using a format string. The formatting rules as follows:
1268
1268
1269 :``%%``: literal "%" character
1269 :``%%``: literal "%" character
1270 :``%s``: basename of file being printed
1270 :``%s``: basename of file being printed
1271 :``%d``: dirname of file being printed, or '.' if in repository root
1271 :``%d``: dirname of file being printed, or '.' if in repository root
1272 :``%p``: root-relative path name of file being printed
1272 :``%p``: root-relative path name of file being printed
1273 :``%H``: changeset hash (40 hexadecimal digits)
1273 :``%H``: changeset hash (40 hexadecimal digits)
1274 :``%R``: changeset revision number
1274 :``%R``: changeset revision number
1275 :``%h``: short-form changeset hash (12 hexadecimal digits)
1275 :``%h``: short-form changeset hash (12 hexadecimal digits)
1276 :``%r``: zero-padded changeset revision number
1276 :``%r``: zero-padded changeset revision number
1277 :``%b``: basename of the exporting repository
1277 :``%b``: basename of the exporting repository
1278
1278
1279 Returns 0 on success.
1279 Returns 0 on success.
1280 """
1280 """
1281 opts = pycompat.byteskwargs(opts)
1281 ctx = scmutil.revsingle(repo, opts.get('rev'))
1282 ctx = scmutil.revsingle(repo, opts.get('rev'))
1282 m = scmutil.match(ctx, (file1,) + pats, opts)
1283 m = scmutil.match(ctx, (file1,) + pats, opts)
1283 fntemplate = opts.pop('output', '')
1284 fntemplate = opts.pop('output', '')
1284 if cmdutil.isstdiofilename(fntemplate):
1285 if cmdutil.isstdiofilename(fntemplate):
1285 fntemplate = ''
1286 fntemplate = ''
1286
1287
1287 if fntemplate:
1288 if fntemplate:
1288 fm = formatter.nullformatter(ui, 'cat')
1289 fm = formatter.nullformatter(ui, 'cat')
1289 else:
1290 else:
1290 ui.pager('cat')
1291 ui.pager('cat')
1291 fm = ui.formatter('cat', opts)
1292 fm = ui.formatter('cat', opts)
1292 with fm:
1293 with fm:
1293 return cmdutil.cat(ui, repo, ctx, m, fm, fntemplate, '', **opts)
1294 return cmdutil.cat(ui, repo, ctx, m, fm, fntemplate, '',
1295 **pycompat.strkwargs(opts))
1294
1296
1295 @command('^clone',
1297 @command('^clone',
1296 [('U', 'noupdate', None, _('the clone will include an empty working '
1298 [('U', 'noupdate', None, _('the clone will include an empty working '
1297 'directory (only a repository)')),
1299 'directory (only a repository)')),
1298 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1300 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1299 _('REV')),
1301 _('REV')),
1300 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1302 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1301 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1303 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1302 ('', 'pull', None, _('use pull protocol to copy metadata')),
1304 ('', 'pull', None, _('use pull protocol to copy metadata')),
1303 ('', 'uncompressed', None,
1305 ('', 'uncompressed', None,
1304 _('an alias to --stream (DEPRECATED)')),
1306 _('an alias to --stream (DEPRECATED)')),
1305 ('', 'stream', None,
1307 ('', 'stream', None,
1306 _('clone with minimal data processing')),
1308 _('clone with minimal data processing')),
1307 ] + remoteopts,
1309 ] + remoteopts,
1308 _('[OPTION]... SOURCE [DEST]'),
1310 _('[OPTION]... SOURCE [DEST]'),
1309 norepo=True)
1311 norepo=True)
1310 def clone(ui, source, dest=None, **opts):
1312 def clone(ui, source, dest=None, **opts):
1311 """make a copy of an existing repository
1313 """make a copy of an existing repository
1312
1314
1313 Create a copy of an existing repository in a new directory.
1315 Create a copy of an existing repository in a new directory.
1314
1316
1315 If no destination directory name is specified, it defaults to the
1317 If no destination directory name is specified, it defaults to the
1316 basename of the source.
1318 basename of the source.
1317
1319
1318 The location of the source is added to the new repository's
1320 The location of the source is added to the new repository's
1319 ``.hg/hgrc`` file, as the default to be used for future pulls.
1321 ``.hg/hgrc`` file, as the default to be used for future pulls.
1320
1322
1321 Only local paths and ``ssh://`` URLs are supported as
1323 Only local paths and ``ssh://`` URLs are supported as
1322 destinations. For ``ssh://`` destinations, no working directory or
1324 destinations. For ``ssh://`` destinations, no working directory or
1323 ``.hg/hgrc`` will be created on the remote side.
1325 ``.hg/hgrc`` will be created on the remote side.
1324
1326
1325 If the source repository has a bookmark called '@' set, that
1327 If the source repository has a bookmark called '@' set, that
1326 revision will be checked out in the new repository by default.
1328 revision will be checked out in the new repository by default.
1327
1329
1328 To check out a particular version, use -u/--update, or
1330 To check out a particular version, use -u/--update, or
1329 -U/--noupdate to create a clone with no working directory.
1331 -U/--noupdate to create a clone with no working directory.
1330
1332
1331 To pull only a subset of changesets, specify one or more revisions
1333 To pull only a subset of changesets, specify one or more revisions
1332 identifiers with -r/--rev or branches with -b/--branch. The
1334 identifiers with -r/--rev or branches with -b/--branch. The
1333 resulting clone will contain only the specified changesets and
1335 resulting clone will contain only the specified changesets and
1334 their ancestors. These options (or 'clone src#rev dest') imply
1336 their ancestors. These options (or 'clone src#rev dest') imply
1335 --pull, even for local source repositories.
1337 --pull, even for local source repositories.
1336
1338
1337 In normal clone mode, the remote normalizes repository data into a common
1339 In normal clone mode, the remote normalizes repository data into a common
1338 exchange format and the receiving end translates this data into its local
1340 exchange format and the receiving end translates this data into its local
1339 storage format. --stream activates a different clone mode that essentially
1341 storage format. --stream activates a different clone mode that essentially
1340 copies repository files from the remote with minimal data processing. This
1342 copies repository files from the remote with minimal data processing. This
1341 significantly reduces the CPU cost of a clone both remotely and locally.
1343 significantly reduces the CPU cost of a clone both remotely and locally.
1342 However, it often increases the transferred data size by 30-40%. This can
1344 However, it often increases the transferred data size by 30-40%. This can
1343 result in substantially faster clones where I/O throughput is plentiful,
1345 result in substantially faster clones where I/O throughput is plentiful,
1344 especially for larger repositories. A side-effect of --stream clones is
1346 especially for larger repositories. A side-effect of --stream clones is
1345 that storage settings and requirements on the remote are applied locally:
1347 that storage settings and requirements on the remote are applied locally:
1346 a modern client may inherit legacy or inefficient storage used by the
1348 a modern client may inherit legacy or inefficient storage used by the
1347 remote or a legacy Mercurial client may not be able to clone from a
1349 remote or a legacy Mercurial client may not be able to clone from a
1348 modern Mercurial remote.
1350 modern Mercurial remote.
1349
1351
1350 .. note::
1352 .. note::
1351
1353
1352 Specifying a tag will include the tagged changeset but not the
1354 Specifying a tag will include the tagged changeset but not the
1353 changeset containing the tag.
1355 changeset containing the tag.
1354
1356
1355 .. container:: verbose
1357 .. container:: verbose
1356
1358
1357 For efficiency, hardlinks are used for cloning whenever the
1359 For efficiency, hardlinks are used for cloning whenever the
1358 source and destination are on the same filesystem (note this
1360 source and destination are on the same filesystem (note this
1359 applies only to the repository data, not to the working
1361 applies only to the repository data, not to the working
1360 directory). Some filesystems, such as AFS, implement hardlinking
1362 directory). Some filesystems, such as AFS, implement hardlinking
1361 incorrectly, but do not report errors. In these cases, use the
1363 incorrectly, but do not report errors. In these cases, use the
1362 --pull option to avoid hardlinking.
1364 --pull option to avoid hardlinking.
1363
1365
1364 Mercurial will update the working directory to the first applicable
1366 Mercurial will update the working directory to the first applicable
1365 revision from this list:
1367 revision from this list:
1366
1368
1367 a) null if -U or the source repository has no changesets
1369 a) null if -U or the source repository has no changesets
1368 b) if -u . and the source repository is local, the first parent of
1370 b) if -u . and the source repository is local, the first parent of
1369 the source repository's working directory
1371 the source repository's working directory
1370 c) the changeset specified with -u (if a branch name, this means the
1372 c) the changeset specified with -u (if a branch name, this means the
1371 latest head of that branch)
1373 latest head of that branch)
1372 d) the changeset specified with -r
1374 d) the changeset specified with -r
1373 e) the tipmost head specified with -b
1375 e) the tipmost head specified with -b
1374 f) the tipmost head specified with the url#branch source syntax
1376 f) the tipmost head specified with the url#branch source syntax
1375 g) the revision marked with the '@' bookmark, if present
1377 g) the revision marked with the '@' bookmark, if present
1376 h) the tipmost head of the default branch
1378 h) the tipmost head of the default branch
1377 i) tip
1379 i) tip
1378
1380
1379 When cloning from servers that support it, Mercurial may fetch
1381 When cloning from servers that support it, Mercurial may fetch
1380 pre-generated data from a server-advertised URL. When this is done,
1382 pre-generated data from a server-advertised URL. When this is done,
1381 hooks operating on incoming changesets and changegroups may fire twice,
1383 hooks operating on incoming changesets and changegroups may fire twice,
1382 once for the bundle fetched from the URL and another for any additional
1384 once for the bundle fetched from the URL and another for any additional
1383 data not fetched from this URL. In addition, if an error occurs, the
1385 data not fetched from this URL. In addition, if an error occurs, the
1384 repository may be rolled back to a partial clone. This behavior may
1386 repository may be rolled back to a partial clone. This behavior may
1385 change in future releases. See :hg:`help -e clonebundles` for more.
1387 change in future releases. See :hg:`help -e clonebundles` for more.
1386
1388
1387 Examples:
1389 Examples:
1388
1390
1389 - clone a remote repository to a new directory named hg/::
1391 - clone a remote repository to a new directory named hg/::
1390
1392
1391 hg clone https://www.mercurial-scm.org/repo/hg/
1393 hg clone https://www.mercurial-scm.org/repo/hg/
1392
1394
1393 - create a lightweight local clone::
1395 - create a lightweight local clone::
1394
1396
1395 hg clone project/ project-feature/
1397 hg clone project/ project-feature/
1396
1398
1397 - clone from an absolute path on an ssh server (note double-slash)::
1399 - clone from an absolute path on an ssh server (note double-slash)::
1398
1400
1399 hg clone ssh://user@server//home/projects/alpha/
1401 hg clone ssh://user@server//home/projects/alpha/
1400
1402
1401 - do a streaming clone while checking out a specified version::
1403 - do a streaming clone while checking out a specified version::
1402
1404
1403 hg clone --stream http://server/repo -u 1.5
1405 hg clone --stream http://server/repo -u 1.5
1404
1406
1405 - create a repository without changesets after a particular revision::
1407 - create a repository without changesets after a particular revision::
1406
1408
1407 hg clone -r 04e544 experimental/ good/
1409 hg clone -r 04e544 experimental/ good/
1408
1410
1409 - clone (and track) a particular named branch::
1411 - clone (and track) a particular named branch::
1410
1412
1411 hg clone https://www.mercurial-scm.org/repo/hg/#stable
1413 hg clone https://www.mercurial-scm.org/repo/hg/#stable
1412
1414
1413 See :hg:`help urls` for details on specifying URLs.
1415 See :hg:`help urls` for details on specifying URLs.
1414
1416
1415 Returns 0 on success.
1417 Returns 0 on success.
1416 """
1418 """
1417 opts = pycompat.byteskwargs(opts)
1419 opts = pycompat.byteskwargs(opts)
1418 if opts.get('noupdate') and opts.get('updaterev'):
1420 if opts.get('noupdate') and opts.get('updaterev'):
1419 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1421 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1420
1422
1421 r = hg.clone(ui, opts, source, dest,
1423 r = hg.clone(ui, opts, source, dest,
1422 pull=opts.get('pull'),
1424 pull=opts.get('pull'),
1423 stream=opts.get('stream') or opts.get('uncompressed'),
1425 stream=opts.get('stream') or opts.get('uncompressed'),
1424 rev=opts.get('rev'),
1426 rev=opts.get('rev'),
1425 update=opts.get('updaterev') or not opts.get('noupdate'),
1427 update=opts.get('updaterev') or not opts.get('noupdate'),
1426 branch=opts.get('branch'),
1428 branch=opts.get('branch'),
1427 shareopts=opts.get('shareopts'))
1429 shareopts=opts.get('shareopts'))
1428
1430
1429 return r is None
1431 return r is None
1430
1432
1431 @command('^commit|ci',
1433 @command('^commit|ci',
1432 [('A', 'addremove', None,
1434 [('A', 'addremove', None,
1433 _('mark new/missing files as added/removed before committing')),
1435 _('mark new/missing files as added/removed before committing')),
1434 ('', 'close-branch', None,
1436 ('', 'close-branch', None,
1435 _('mark a branch head as closed')),
1437 _('mark a branch head as closed')),
1436 ('', 'amend', None, _('amend the parent of the working directory')),
1438 ('', 'amend', None, _('amend the parent of the working directory')),
1437 ('s', 'secret', None, _('use the secret phase for committing')),
1439 ('s', 'secret', None, _('use the secret phase for committing')),
1438 ('e', 'edit', None, _('invoke editor on commit messages')),
1440 ('e', 'edit', None, _('invoke editor on commit messages')),
1439 ('i', 'interactive', None, _('use interactive mode')),
1441 ('i', 'interactive', None, _('use interactive mode')),
1440 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1442 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1441 _('[OPTION]... [FILE]...'),
1443 _('[OPTION]... [FILE]...'),
1442 inferrepo=True)
1444 inferrepo=True)
1443 def commit(ui, repo, *pats, **opts):
1445 def commit(ui, repo, *pats, **opts):
1444 """commit the specified files or all outstanding changes
1446 """commit the specified files or all outstanding changes
1445
1447
1446 Commit changes to the given files into the repository. Unlike a
1448 Commit changes to the given files into the repository. Unlike a
1447 centralized SCM, this operation is a local operation. See
1449 centralized SCM, this operation is a local operation. See
1448 :hg:`push` for a way to actively distribute your changes.
1450 :hg:`push` for a way to actively distribute your changes.
1449
1451
1450 If a list of files is omitted, all changes reported by :hg:`status`
1452 If a list of files is omitted, all changes reported by :hg:`status`
1451 will be committed.
1453 will be committed.
1452
1454
1453 If you are committing the result of a merge, do not provide any
1455 If you are committing the result of a merge, do not provide any
1454 filenames or -I/-X filters.
1456 filenames or -I/-X filters.
1455
1457
1456 If no commit message is specified, Mercurial starts your
1458 If no commit message is specified, Mercurial starts your
1457 configured editor where you can enter a message. In case your
1459 configured editor where you can enter a message. In case your
1458 commit fails, you will find a backup of your message in
1460 commit fails, you will find a backup of your message in
1459 ``.hg/last-message.txt``.
1461 ``.hg/last-message.txt``.
1460
1462
1461 The --close-branch flag can be used to mark the current branch
1463 The --close-branch flag can be used to mark the current branch
1462 head closed. When all heads of a branch are closed, the branch
1464 head closed. When all heads of a branch are closed, the branch
1463 will be considered closed and no longer listed.
1465 will be considered closed and no longer listed.
1464
1466
1465 The --amend flag can be used to amend the parent of the
1467 The --amend flag can be used to amend the parent of the
1466 working directory with a new commit that contains the changes
1468 working directory with a new commit that contains the changes
1467 in the parent in addition to those currently reported by :hg:`status`,
1469 in the parent in addition to those currently reported by :hg:`status`,
1468 if there are any. The old commit is stored in a backup bundle in
1470 if there are any. The old commit is stored in a backup bundle in
1469 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1471 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1470 on how to restore it).
1472 on how to restore it).
1471
1473
1472 Message, user and date are taken from the amended commit unless
1474 Message, user and date are taken from the amended commit unless
1473 specified. When a message isn't specified on the command line,
1475 specified. When a message isn't specified on the command line,
1474 the editor will open with the message of the amended commit.
1476 the editor will open with the message of the amended commit.
1475
1477
1476 It is not possible to amend public changesets (see :hg:`help phases`)
1478 It is not possible to amend public changesets (see :hg:`help phases`)
1477 or changesets that have children.
1479 or changesets that have children.
1478
1480
1479 See :hg:`help dates` for a list of formats valid for -d/--date.
1481 See :hg:`help dates` for a list of formats valid for -d/--date.
1480
1482
1481 Returns 0 on success, 1 if nothing changed.
1483 Returns 0 on success, 1 if nothing changed.
1482
1484
1483 .. container:: verbose
1485 .. container:: verbose
1484
1486
1485 Examples:
1487 Examples:
1486
1488
1487 - commit all files ending in .py::
1489 - commit all files ending in .py::
1488
1490
1489 hg commit --include "set:**.py"
1491 hg commit --include "set:**.py"
1490
1492
1491 - commit all non-binary files::
1493 - commit all non-binary files::
1492
1494
1493 hg commit --exclude "set:binary()"
1495 hg commit --exclude "set:binary()"
1494
1496
1495 - amend the current commit and set the date to now::
1497 - amend the current commit and set the date to now::
1496
1498
1497 hg commit --amend --date now
1499 hg commit --amend --date now
1498 """
1500 """
1499 wlock = lock = None
1501 wlock = lock = None
1500 try:
1502 try:
1501 wlock = repo.wlock()
1503 wlock = repo.wlock()
1502 lock = repo.lock()
1504 lock = repo.lock()
1503 return _docommit(ui, repo, *pats, **opts)
1505 return _docommit(ui, repo, *pats, **opts)
1504 finally:
1506 finally:
1505 release(lock, wlock)
1507 release(lock, wlock)
1506
1508
1507 def _docommit(ui, repo, *pats, **opts):
1509 def _docommit(ui, repo, *pats, **opts):
1508 if opts.get(r'interactive'):
1510 if opts.get(r'interactive'):
1509 opts.pop(r'interactive')
1511 opts.pop(r'interactive')
1510 ret = cmdutil.dorecord(ui, repo, commit, None, False,
1512 ret = cmdutil.dorecord(ui, repo, commit, None, False,
1511 cmdutil.recordfilter, *pats,
1513 cmdutil.recordfilter, *pats,
1512 **opts)
1514 **opts)
1513 # ret can be 0 (no changes to record) or the value returned by
1515 # ret can be 0 (no changes to record) or the value returned by
1514 # commit(), 1 if nothing changed or None on success.
1516 # commit(), 1 if nothing changed or None on success.
1515 return 1 if ret == 0 else ret
1517 return 1 if ret == 0 else ret
1516
1518
1517 opts = pycompat.byteskwargs(opts)
1519 opts = pycompat.byteskwargs(opts)
1518 if opts.get('subrepos'):
1520 if opts.get('subrepos'):
1519 if opts.get('amend'):
1521 if opts.get('amend'):
1520 raise error.Abort(_('cannot amend with --subrepos'))
1522 raise error.Abort(_('cannot amend with --subrepos'))
1521 # Let --subrepos on the command line override config setting.
1523 # Let --subrepos on the command line override config setting.
1522 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1524 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1523
1525
1524 cmdutil.checkunfinished(repo, commit=True)
1526 cmdutil.checkunfinished(repo, commit=True)
1525
1527
1526 branch = repo[None].branch()
1528 branch = repo[None].branch()
1527 bheads = repo.branchheads(branch)
1529 bheads = repo.branchheads(branch)
1528
1530
1529 extra = {}
1531 extra = {}
1530 if opts.get('close_branch'):
1532 if opts.get('close_branch'):
1531 extra['close'] = 1
1533 extra['close'] = 1
1532
1534
1533 if not bheads:
1535 if not bheads:
1534 raise error.Abort(_('can only close branch heads'))
1536 raise error.Abort(_('can only close branch heads'))
1535 elif opts.get('amend'):
1537 elif opts.get('amend'):
1536 if repo[None].parents()[0].p1().branch() != branch and \
1538 if repo[None].parents()[0].p1().branch() != branch and \
1537 repo[None].parents()[0].p2().branch() != branch:
1539 repo[None].parents()[0].p2().branch() != branch:
1538 raise error.Abort(_('can only close branch heads'))
1540 raise error.Abort(_('can only close branch heads'))
1539
1541
1540 if opts.get('amend'):
1542 if opts.get('amend'):
1541 if ui.configbool('ui', 'commitsubrepos'):
1543 if ui.configbool('ui', 'commitsubrepos'):
1542 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1544 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1543
1545
1544 old = repo['.']
1546 old = repo['.']
1545 rewriteutil.precheck(repo, [old.rev()], 'amend')
1547 rewriteutil.precheck(repo, [old.rev()], 'amend')
1546
1548
1547 # Currently histedit gets confused if an amend happens while histedit
1549 # Currently histedit gets confused if an amend happens while histedit
1548 # is in progress. Since we have a checkunfinished command, we are
1550 # is in progress. Since we have a checkunfinished command, we are
1549 # temporarily honoring it.
1551 # temporarily honoring it.
1550 #
1552 #
1551 # Note: eventually this guard will be removed. Please do not expect
1553 # Note: eventually this guard will be removed. Please do not expect
1552 # this behavior to remain.
1554 # this behavior to remain.
1553 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
1555 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
1554 cmdutil.checkunfinished(repo)
1556 cmdutil.checkunfinished(repo)
1555
1557
1556 node = cmdutil.amend(ui, repo, old, extra, pats, opts)
1558 node = cmdutil.amend(ui, repo, old, extra, pats, opts)
1557 if node == old.node():
1559 if node == old.node():
1558 ui.status(_("nothing changed\n"))
1560 ui.status(_("nothing changed\n"))
1559 return 1
1561 return 1
1560 else:
1562 else:
1561 def commitfunc(ui, repo, message, match, opts):
1563 def commitfunc(ui, repo, message, match, opts):
1562 overrides = {}
1564 overrides = {}
1563 if opts.get('secret'):
1565 if opts.get('secret'):
1564 overrides[('phases', 'new-commit')] = 'secret'
1566 overrides[('phases', 'new-commit')] = 'secret'
1565
1567
1566 baseui = repo.baseui
1568 baseui = repo.baseui
1567 with baseui.configoverride(overrides, 'commit'):
1569 with baseui.configoverride(overrides, 'commit'):
1568 with ui.configoverride(overrides, 'commit'):
1570 with ui.configoverride(overrides, 'commit'):
1569 editform = cmdutil.mergeeditform(repo[None],
1571 editform = cmdutil.mergeeditform(repo[None],
1570 'commit.normal')
1572 'commit.normal')
1571 editor = cmdutil.getcommiteditor(
1573 editor = cmdutil.getcommiteditor(
1572 editform=editform, **pycompat.strkwargs(opts))
1574 editform=editform, **pycompat.strkwargs(opts))
1573 return repo.commit(message,
1575 return repo.commit(message,
1574 opts.get('user'),
1576 opts.get('user'),
1575 opts.get('date'),
1577 opts.get('date'),
1576 match,
1578 match,
1577 editor=editor,
1579 editor=editor,
1578 extra=extra)
1580 extra=extra)
1579
1581
1580 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1582 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1581
1583
1582 if not node:
1584 if not node:
1583 stat = cmdutil.postcommitstatus(repo, pats, opts)
1585 stat = cmdutil.postcommitstatus(repo, pats, opts)
1584 if stat[3]:
1586 if stat[3]:
1585 ui.status(_("nothing changed (%d missing files, see "
1587 ui.status(_("nothing changed (%d missing files, see "
1586 "'hg status')\n") % len(stat[3]))
1588 "'hg status')\n") % len(stat[3]))
1587 else:
1589 else:
1588 ui.status(_("nothing changed\n"))
1590 ui.status(_("nothing changed\n"))
1589 return 1
1591 return 1
1590
1592
1591 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1593 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1592
1594
1593 @command('config|showconfig|debugconfig',
1595 @command('config|showconfig|debugconfig',
1594 [('u', 'untrusted', None, _('show untrusted configuration options')),
1596 [('u', 'untrusted', None, _('show untrusted configuration options')),
1595 ('e', 'edit', None, _('edit user config')),
1597 ('e', 'edit', None, _('edit user config')),
1596 ('l', 'local', None, _('edit repository config')),
1598 ('l', 'local', None, _('edit repository config')),
1597 ('g', 'global', None, _('edit global config'))] + formatteropts,
1599 ('g', 'global', None, _('edit global config'))] + formatteropts,
1598 _('[-u] [NAME]...'),
1600 _('[-u] [NAME]...'),
1599 optionalrepo=True, cmdtype=readonly)
1601 optionalrepo=True, cmdtype=readonly)
1600 def config(ui, repo, *values, **opts):
1602 def config(ui, repo, *values, **opts):
1601 """show combined config settings from all hgrc files
1603 """show combined config settings from all hgrc files
1602
1604
1603 With no arguments, print names and values of all config items.
1605 With no arguments, print names and values of all config items.
1604
1606
1605 With one argument of the form section.name, print just the value
1607 With one argument of the form section.name, print just the value
1606 of that config item.
1608 of that config item.
1607
1609
1608 With multiple arguments, print names and values of all config
1610 With multiple arguments, print names and values of all config
1609 items with matching section names.
1611 items with matching section names.
1610
1612
1611 With --edit, start an editor on the user-level config file. With
1613 With --edit, start an editor on the user-level config file. With
1612 --global, edit the system-wide config file. With --local, edit the
1614 --global, edit the system-wide config file. With --local, edit the
1613 repository-level config file.
1615 repository-level config file.
1614
1616
1615 With --debug, the source (filename and line number) is printed
1617 With --debug, the source (filename and line number) is printed
1616 for each config item.
1618 for each config item.
1617
1619
1618 See :hg:`help config` for more information about config files.
1620 See :hg:`help config` for more information about config files.
1619
1621
1620 Returns 0 on success, 1 if NAME does not exist.
1622 Returns 0 on success, 1 if NAME does not exist.
1621
1623
1622 """
1624 """
1623
1625
1624 opts = pycompat.byteskwargs(opts)
1626 opts = pycompat.byteskwargs(opts)
1625 if opts.get('edit') or opts.get('local') or opts.get('global'):
1627 if opts.get('edit') or opts.get('local') or opts.get('global'):
1626 if opts.get('local') and opts.get('global'):
1628 if opts.get('local') and opts.get('global'):
1627 raise error.Abort(_("can't use --local and --global together"))
1629 raise error.Abort(_("can't use --local and --global together"))
1628
1630
1629 if opts.get('local'):
1631 if opts.get('local'):
1630 if not repo:
1632 if not repo:
1631 raise error.Abort(_("can't use --local outside a repository"))
1633 raise error.Abort(_("can't use --local outside a repository"))
1632 paths = [repo.vfs.join('hgrc')]
1634 paths = [repo.vfs.join('hgrc')]
1633 elif opts.get('global'):
1635 elif opts.get('global'):
1634 paths = rcutil.systemrcpath()
1636 paths = rcutil.systemrcpath()
1635 else:
1637 else:
1636 paths = rcutil.userrcpath()
1638 paths = rcutil.userrcpath()
1637
1639
1638 for f in paths:
1640 for f in paths:
1639 if os.path.exists(f):
1641 if os.path.exists(f):
1640 break
1642 break
1641 else:
1643 else:
1642 if opts.get('global'):
1644 if opts.get('global'):
1643 samplehgrc = uimod.samplehgrcs['global']
1645 samplehgrc = uimod.samplehgrcs['global']
1644 elif opts.get('local'):
1646 elif opts.get('local'):
1645 samplehgrc = uimod.samplehgrcs['local']
1647 samplehgrc = uimod.samplehgrcs['local']
1646 else:
1648 else:
1647 samplehgrc = uimod.samplehgrcs['user']
1649 samplehgrc = uimod.samplehgrcs['user']
1648
1650
1649 f = paths[0]
1651 f = paths[0]
1650 fp = open(f, "wb")
1652 fp = open(f, "wb")
1651 fp.write(util.tonativeeol(samplehgrc))
1653 fp.write(util.tonativeeol(samplehgrc))
1652 fp.close()
1654 fp.close()
1653
1655
1654 editor = ui.geteditor()
1656 editor = ui.geteditor()
1655 ui.system("%s \"%s\"" % (editor, f),
1657 ui.system("%s \"%s\"" % (editor, f),
1656 onerr=error.Abort, errprefix=_("edit failed"),
1658 onerr=error.Abort, errprefix=_("edit failed"),
1657 blockedtag='config_edit')
1659 blockedtag='config_edit')
1658 return
1660 return
1659 ui.pager('config')
1661 ui.pager('config')
1660 fm = ui.formatter('config', opts)
1662 fm = ui.formatter('config', opts)
1661 for t, f in rcutil.rccomponents():
1663 for t, f in rcutil.rccomponents():
1662 if t == 'path':
1664 if t == 'path':
1663 ui.debug('read config from: %s\n' % f)
1665 ui.debug('read config from: %s\n' % f)
1664 elif t == 'items':
1666 elif t == 'items':
1665 for section, name, value, source in f:
1667 for section, name, value, source in f:
1666 ui.debug('set config by: %s\n' % source)
1668 ui.debug('set config by: %s\n' % source)
1667 else:
1669 else:
1668 raise error.ProgrammingError('unknown rctype: %s' % t)
1670 raise error.ProgrammingError('unknown rctype: %s' % t)
1669 untrusted = bool(opts.get('untrusted'))
1671 untrusted = bool(opts.get('untrusted'))
1670 if values:
1672 if values:
1671 sections = [v for v in values if '.' not in v]
1673 sections = [v for v in values if '.' not in v]
1672 items = [v for v in values if '.' in v]
1674 items = [v for v in values if '.' in v]
1673 if len(items) > 1 or items and sections:
1675 if len(items) > 1 or items and sections:
1674 raise error.Abort(_('only one config item permitted'))
1676 raise error.Abort(_('only one config item permitted'))
1675 matched = False
1677 matched = False
1676 for section, name, value in ui.walkconfig(untrusted=untrusted):
1678 for section, name, value in ui.walkconfig(untrusted=untrusted):
1677 source = ui.configsource(section, name, untrusted)
1679 source = ui.configsource(section, name, untrusted)
1678 value = pycompat.bytestr(value)
1680 value = pycompat.bytestr(value)
1679 if fm.isplain():
1681 if fm.isplain():
1680 source = source or 'none'
1682 source = source or 'none'
1681 value = value.replace('\n', '\\n')
1683 value = value.replace('\n', '\\n')
1682 entryname = section + '.' + name
1684 entryname = section + '.' + name
1683 if values:
1685 if values:
1684 for v in values:
1686 for v in values:
1685 if v == section:
1687 if v == section:
1686 fm.startitem()
1688 fm.startitem()
1687 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1689 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1688 fm.write('name value', '%s=%s\n', entryname, value)
1690 fm.write('name value', '%s=%s\n', entryname, value)
1689 matched = True
1691 matched = True
1690 elif v == entryname:
1692 elif v == entryname:
1691 fm.startitem()
1693 fm.startitem()
1692 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1694 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1693 fm.write('value', '%s\n', value)
1695 fm.write('value', '%s\n', value)
1694 fm.data(name=entryname)
1696 fm.data(name=entryname)
1695 matched = True
1697 matched = True
1696 else:
1698 else:
1697 fm.startitem()
1699 fm.startitem()
1698 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1700 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1699 fm.write('name value', '%s=%s\n', entryname, value)
1701 fm.write('name value', '%s=%s\n', entryname, value)
1700 matched = True
1702 matched = True
1701 fm.end()
1703 fm.end()
1702 if matched:
1704 if matched:
1703 return 0
1705 return 0
1704 return 1
1706 return 1
1705
1707
1706 @command('copy|cp',
1708 @command('copy|cp',
1707 [('A', 'after', None, _('record a copy that has already occurred')),
1709 [('A', 'after', None, _('record a copy that has already occurred')),
1708 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1710 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1709 ] + walkopts + dryrunopts,
1711 ] + walkopts + dryrunopts,
1710 _('[OPTION]... [SOURCE]... DEST'))
1712 _('[OPTION]... [SOURCE]... DEST'))
1711 def copy(ui, repo, *pats, **opts):
1713 def copy(ui, repo, *pats, **opts):
1712 """mark files as copied for the next commit
1714 """mark files as copied for the next commit
1713
1715
1714 Mark dest as having copies of source files. If dest is a
1716 Mark dest as having copies of source files. If dest is a
1715 directory, copies are put in that directory. If dest is a file,
1717 directory, copies are put in that directory. If dest is a file,
1716 the source must be a single file.
1718 the source must be a single file.
1717
1719
1718 By default, this command copies the contents of files as they
1720 By default, this command copies the contents of files as they
1719 exist in the working directory. If invoked with -A/--after, the
1721 exist in the working directory. If invoked with -A/--after, the
1720 operation is recorded, but no copying is performed.
1722 operation is recorded, but no copying is performed.
1721
1723
1722 This command takes effect with the next commit. To undo a copy
1724 This command takes effect with the next commit. To undo a copy
1723 before that, see :hg:`revert`.
1725 before that, see :hg:`revert`.
1724
1726
1725 Returns 0 on success, 1 if errors are encountered.
1727 Returns 0 on success, 1 if errors are encountered.
1726 """
1728 """
1727 opts = pycompat.byteskwargs(opts)
1729 opts = pycompat.byteskwargs(opts)
1728 with repo.wlock(False):
1730 with repo.wlock(False):
1729 return cmdutil.copy(ui, repo, pats, opts)
1731 return cmdutil.copy(ui, repo, pats, opts)
1730
1732
1731 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1733 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1732 def debugcommands(ui, cmd='', *args):
1734 def debugcommands(ui, cmd='', *args):
1733 """list all available commands and options"""
1735 """list all available commands and options"""
1734 for cmd, vals in sorted(table.iteritems()):
1736 for cmd, vals in sorted(table.iteritems()):
1735 cmd = cmd.split('|')[0].strip('^')
1737 cmd = cmd.split('|')[0].strip('^')
1736 opts = ', '.join([i[1] for i in vals[1]])
1738 opts = ', '.join([i[1] for i in vals[1]])
1737 ui.write('%s: %s\n' % (cmd, opts))
1739 ui.write('%s: %s\n' % (cmd, opts))
1738
1740
1739 @command('debugcomplete',
1741 @command('debugcomplete',
1740 [('o', 'options', None, _('show the command options'))],
1742 [('o', 'options', None, _('show the command options'))],
1741 _('[-o] CMD'),
1743 _('[-o] CMD'),
1742 norepo=True)
1744 norepo=True)
1743 def debugcomplete(ui, cmd='', **opts):
1745 def debugcomplete(ui, cmd='', **opts):
1744 """returns the completion list associated with the given command"""
1746 """returns the completion list associated with the given command"""
1745
1747
1746 if opts.get('options'):
1748 if opts.get(r'options'):
1747 options = []
1749 options = []
1748 otables = [globalopts]
1750 otables = [globalopts]
1749 if cmd:
1751 if cmd:
1750 aliases, entry = cmdutil.findcmd(cmd, table, False)
1752 aliases, entry = cmdutil.findcmd(cmd, table, False)
1751 otables.append(entry[1])
1753 otables.append(entry[1])
1752 for t in otables:
1754 for t in otables:
1753 for o in t:
1755 for o in t:
1754 if "(DEPRECATED)" in o[3]:
1756 if "(DEPRECATED)" in o[3]:
1755 continue
1757 continue
1756 if o[0]:
1758 if o[0]:
1757 options.append('-%s' % o[0])
1759 options.append('-%s' % o[0])
1758 options.append('--%s' % o[1])
1760 options.append('--%s' % o[1])
1759 ui.write("%s\n" % "\n".join(options))
1761 ui.write("%s\n" % "\n".join(options))
1760 return
1762 return
1761
1763
1762 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
1764 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
1763 if ui.verbose:
1765 if ui.verbose:
1764 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1766 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1765 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1767 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1766
1768
1767 @command('^diff',
1769 @command('^diff',
1768 [('r', 'rev', [], _('revision'), _('REV')),
1770 [('r', 'rev', [], _('revision'), _('REV')),
1769 ('c', 'change', '', _('change made by revision'), _('REV'))
1771 ('c', 'change', '', _('change made by revision'), _('REV'))
1770 ] + diffopts + diffopts2 + walkopts + subrepoopts,
1772 ] + diffopts + diffopts2 + walkopts + subrepoopts,
1771 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
1773 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
1772 inferrepo=True, cmdtype=readonly)
1774 inferrepo=True, cmdtype=readonly)
1773 def diff(ui, repo, *pats, **opts):
1775 def diff(ui, repo, *pats, **opts):
1774 """diff repository (or selected files)
1776 """diff repository (or selected files)
1775
1777
1776 Show differences between revisions for the specified files.
1778 Show differences between revisions for the specified files.
1777
1779
1778 Differences between files are shown using the unified diff format.
1780 Differences between files are shown using the unified diff format.
1779
1781
1780 .. note::
1782 .. note::
1781
1783
1782 :hg:`diff` may generate unexpected results for merges, as it will
1784 :hg:`diff` may generate unexpected results for merges, as it will
1783 default to comparing against the working directory's first
1785 default to comparing against the working directory's first
1784 parent changeset if no revisions are specified.
1786 parent changeset if no revisions are specified.
1785
1787
1786 When two revision arguments are given, then changes are shown
1788 When two revision arguments are given, then changes are shown
1787 between those revisions. If only one revision is specified then
1789 between those revisions. If only one revision is specified then
1788 that revision is compared to the working directory, and, when no
1790 that revision is compared to the working directory, and, when no
1789 revisions are specified, the working directory files are compared
1791 revisions are specified, the working directory files are compared
1790 to its first parent.
1792 to its first parent.
1791
1793
1792 Alternatively you can specify -c/--change with a revision to see
1794 Alternatively you can specify -c/--change with a revision to see
1793 the changes in that changeset relative to its first parent.
1795 the changes in that changeset relative to its first parent.
1794
1796
1795 Without the -a/--text option, diff will avoid generating diffs of
1797 Without the -a/--text option, diff will avoid generating diffs of
1796 files it detects as binary. With -a, diff will generate a diff
1798 files it detects as binary. With -a, diff will generate a diff
1797 anyway, probably with undesirable results.
1799 anyway, probably with undesirable results.
1798
1800
1799 Use the -g/--git option to generate diffs in the git extended diff
1801 Use the -g/--git option to generate diffs in the git extended diff
1800 format. For more information, read :hg:`help diffs`.
1802 format. For more information, read :hg:`help diffs`.
1801
1803
1802 .. container:: verbose
1804 .. container:: verbose
1803
1805
1804 Examples:
1806 Examples:
1805
1807
1806 - compare a file in the current working directory to its parent::
1808 - compare a file in the current working directory to its parent::
1807
1809
1808 hg diff foo.c
1810 hg diff foo.c
1809
1811
1810 - compare two historical versions of a directory, with rename info::
1812 - compare two historical versions of a directory, with rename info::
1811
1813
1812 hg diff --git -r 1.0:1.2 lib/
1814 hg diff --git -r 1.0:1.2 lib/
1813
1815
1814 - get change stats relative to the last change on some date::
1816 - get change stats relative to the last change on some date::
1815
1817
1816 hg diff --stat -r "date('may 2')"
1818 hg diff --stat -r "date('may 2')"
1817
1819
1818 - diff all newly-added files that contain a keyword::
1820 - diff all newly-added files that contain a keyword::
1819
1821
1820 hg diff "set:added() and grep(GNU)"
1822 hg diff "set:added() and grep(GNU)"
1821
1823
1822 - compare a revision and its parents::
1824 - compare a revision and its parents::
1823
1825
1824 hg diff -c 9353 # compare against first parent
1826 hg diff -c 9353 # compare against first parent
1825 hg diff -r 9353^:9353 # same using revset syntax
1827 hg diff -r 9353^:9353 # same using revset syntax
1826 hg diff -r 9353^2:9353 # compare against the second parent
1828 hg diff -r 9353^2:9353 # compare against the second parent
1827
1829
1828 Returns 0 on success.
1830 Returns 0 on success.
1829 """
1831 """
1830
1832
1831 opts = pycompat.byteskwargs(opts)
1833 opts = pycompat.byteskwargs(opts)
1832 revs = opts.get('rev')
1834 revs = opts.get('rev')
1833 change = opts.get('change')
1835 change = opts.get('change')
1834 stat = opts.get('stat')
1836 stat = opts.get('stat')
1835 reverse = opts.get('reverse')
1837 reverse = opts.get('reverse')
1836
1838
1837 if revs and change:
1839 if revs and change:
1838 msg = _('cannot specify --rev and --change at the same time')
1840 msg = _('cannot specify --rev and --change at the same time')
1839 raise error.Abort(msg)
1841 raise error.Abort(msg)
1840 elif change:
1842 elif change:
1841 node2 = scmutil.revsingle(repo, change, None).node()
1843 node2 = scmutil.revsingle(repo, change, None).node()
1842 node1 = repo[node2].p1().node()
1844 node1 = repo[node2].p1().node()
1843 else:
1845 else:
1844 node1, node2 = scmutil.revpair(repo, revs)
1846 node1, node2 = scmutil.revpair(repo, revs)
1845
1847
1846 if reverse:
1848 if reverse:
1847 node1, node2 = node2, node1
1849 node1, node2 = node2, node1
1848
1850
1849 diffopts = patch.diffallopts(ui, opts)
1851 diffopts = patch.diffallopts(ui, opts)
1850 m = scmutil.match(repo[node2], pats, opts)
1852 m = scmutil.match(repo[node2], pats, opts)
1851 ui.pager('diff')
1853 ui.pager('diff')
1852 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
1854 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
1853 listsubrepos=opts.get('subrepos'),
1855 listsubrepos=opts.get('subrepos'),
1854 root=opts.get('root'))
1856 root=opts.get('root'))
1855
1857
1856 @command('^export',
1858 @command('^export',
1857 [('o', 'output', '',
1859 [('o', 'output', '',
1858 _('print output to file with formatted name'), _('FORMAT')),
1860 _('print output to file with formatted name'), _('FORMAT')),
1859 ('', 'switch-parent', None, _('diff against the second parent')),
1861 ('', 'switch-parent', None, _('diff against the second parent')),
1860 ('r', 'rev', [], _('revisions to export'), _('REV')),
1862 ('r', 'rev', [], _('revisions to export'), _('REV')),
1861 ] + diffopts,
1863 ] + diffopts,
1862 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'), cmdtype=readonly)
1864 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'), cmdtype=readonly)
1863 def export(ui, repo, *changesets, **opts):
1865 def export(ui, repo, *changesets, **opts):
1864 """dump the header and diffs for one or more changesets
1866 """dump the header and diffs for one or more changesets
1865
1867
1866 Print the changeset header and diffs for one or more revisions.
1868 Print the changeset header and diffs for one or more revisions.
1867 If no revision is given, the parent of the working directory is used.
1869 If no revision is given, the parent of the working directory is used.
1868
1870
1869 The information shown in the changeset header is: author, date,
1871 The information shown in the changeset header is: author, date,
1870 branch name (if non-default), changeset hash, parent(s) and commit
1872 branch name (if non-default), changeset hash, parent(s) and commit
1871 comment.
1873 comment.
1872
1874
1873 .. note::
1875 .. note::
1874
1876
1875 :hg:`export` may generate unexpected diff output for merge
1877 :hg:`export` may generate unexpected diff output for merge
1876 changesets, as it will compare the merge changeset against its
1878 changesets, as it will compare the merge changeset against its
1877 first parent only.
1879 first parent only.
1878
1880
1879 Output may be to a file, in which case the name of the file is
1881 Output may be to a file, in which case the name of the file is
1880 given using a format string. The formatting rules are as follows:
1882 given using a format string. The formatting rules are as follows:
1881
1883
1882 :``%%``: literal "%" character
1884 :``%%``: literal "%" character
1883 :``%H``: changeset hash (40 hexadecimal digits)
1885 :``%H``: changeset hash (40 hexadecimal digits)
1884 :``%N``: number of patches being generated
1886 :``%N``: number of patches being generated
1885 :``%R``: changeset revision number
1887 :``%R``: changeset revision number
1886 :``%b``: basename of the exporting repository
1888 :``%b``: basename of the exporting repository
1887 :``%h``: short-form changeset hash (12 hexadecimal digits)
1889 :``%h``: short-form changeset hash (12 hexadecimal digits)
1888 :``%m``: first line of the commit message (only alphanumeric characters)
1890 :``%m``: first line of the commit message (only alphanumeric characters)
1889 :``%n``: zero-padded sequence number, starting at 1
1891 :``%n``: zero-padded sequence number, starting at 1
1890 :``%r``: zero-padded changeset revision number
1892 :``%r``: zero-padded changeset revision number
1891
1893
1892 Without the -a/--text option, export will avoid generating diffs
1894 Without the -a/--text option, export will avoid generating diffs
1893 of files it detects as binary. With -a, export will generate a
1895 of files it detects as binary. With -a, export will generate a
1894 diff anyway, probably with undesirable results.
1896 diff anyway, probably with undesirable results.
1895
1897
1896 Use the -g/--git option to generate diffs in the git extended diff
1898 Use the -g/--git option to generate diffs in the git extended diff
1897 format. See :hg:`help diffs` for more information.
1899 format. See :hg:`help diffs` for more information.
1898
1900
1899 With the --switch-parent option, the diff will be against the
1901 With the --switch-parent option, the diff will be against the
1900 second parent. It can be useful to review a merge.
1902 second parent. It can be useful to review a merge.
1901
1903
1902 .. container:: verbose
1904 .. container:: verbose
1903
1905
1904 Examples:
1906 Examples:
1905
1907
1906 - use export and import to transplant a bugfix to the current
1908 - use export and import to transplant a bugfix to the current
1907 branch::
1909 branch::
1908
1910
1909 hg export -r 9353 | hg import -
1911 hg export -r 9353 | hg import -
1910
1912
1911 - export all the changesets between two revisions to a file with
1913 - export all the changesets between two revisions to a file with
1912 rename information::
1914 rename information::
1913
1915
1914 hg export --git -r 123:150 > changes.txt
1916 hg export --git -r 123:150 > changes.txt
1915
1917
1916 - split outgoing changes into a series of patches with
1918 - split outgoing changes into a series of patches with
1917 descriptive names::
1919 descriptive names::
1918
1920
1919 hg export -r "outgoing()" -o "%n-%m.patch"
1921 hg export -r "outgoing()" -o "%n-%m.patch"
1920
1922
1921 Returns 0 on success.
1923 Returns 0 on success.
1922 """
1924 """
1923 opts = pycompat.byteskwargs(opts)
1925 opts = pycompat.byteskwargs(opts)
1924 changesets += tuple(opts.get('rev', []))
1926 changesets += tuple(opts.get('rev', []))
1925 if not changesets:
1927 if not changesets:
1926 changesets = ['.']
1928 changesets = ['.']
1927 revs = scmutil.revrange(repo, changesets)
1929 revs = scmutil.revrange(repo, changesets)
1928 if not revs:
1930 if not revs:
1929 raise error.Abort(_("export requires at least one changeset"))
1931 raise error.Abort(_("export requires at least one changeset"))
1930 if len(revs) > 1:
1932 if len(revs) > 1:
1931 ui.note(_('exporting patches:\n'))
1933 ui.note(_('exporting patches:\n'))
1932 else:
1934 else:
1933 ui.note(_('exporting patch:\n'))
1935 ui.note(_('exporting patch:\n'))
1934 ui.pager('export')
1936 ui.pager('export')
1935 cmdutil.export(repo, revs, fntemplate=opts.get('output'),
1937 cmdutil.export(repo, revs, fntemplate=opts.get('output'),
1936 switch_parent=opts.get('switch_parent'),
1938 switch_parent=opts.get('switch_parent'),
1937 opts=patch.diffallopts(ui, opts))
1939 opts=patch.diffallopts(ui, opts))
1938
1940
1939 @command('files',
1941 @command('files',
1940 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
1942 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
1941 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
1943 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
1942 ] + walkopts + formatteropts + subrepoopts,
1944 ] + walkopts + formatteropts + subrepoopts,
1943 _('[OPTION]... [FILE]...'), cmdtype=readonly)
1945 _('[OPTION]... [FILE]...'), cmdtype=readonly)
1944 def files(ui, repo, *pats, **opts):
1946 def files(ui, repo, *pats, **opts):
1945 """list tracked files
1947 """list tracked files
1946
1948
1947 Print files under Mercurial control in the working directory or
1949 Print files under Mercurial control in the working directory or
1948 specified revision for given files (excluding removed files).
1950 specified revision for given files (excluding removed files).
1949 Files can be specified as filenames or filesets.
1951 Files can be specified as filenames or filesets.
1950
1952
1951 If no files are given to match, this command prints the names
1953 If no files are given to match, this command prints the names
1952 of all files under Mercurial control.
1954 of all files under Mercurial control.
1953
1955
1954 .. container:: verbose
1956 .. container:: verbose
1955
1957
1956 Examples:
1958 Examples:
1957
1959
1958 - list all files under the current directory::
1960 - list all files under the current directory::
1959
1961
1960 hg files .
1962 hg files .
1961
1963
1962 - shows sizes and flags for current revision::
1964 - shows sizes and flags for current revision::
1963
1965
1964 hg files -vr .
1966 hg files -vr .
1965
1967
1966 - list all files named README::
1968 - list all files named README::
1967
1969
1968 hg files -I "**/README"
1970 hg files -I "**/README"
1969
1971
1970 - list all binary files::
1972 - list all binary files::
1971
1973
1972 hg files "set:binary()"
1974 hg files "set:binary()"
1973
1975
1974 - find files containing a regular expression::
1976 - find files containing a regular expression::
1975
1977
1976 hg files "set:grep('bob')"
1978 hg files "set:grep('bob')"
1977
1979
1978 - search tracked file contents with xargs and grep::
1980 - search tracked file contents with xargs and grep::
1979
1981
1980 hg files -0 | xargs -0 grep foo
1982 hg files -0 | xargs -0 grep foo
1981
1983
1982 See :hg:`help patterns` and :hg:`help filesets` for more information
1984 See :hg:`help patterns` and :hg:`help filesets` for more information
1983 on specifying file patterns.
1985 on specifying file patterns.
1984
1986
1985 Returns 0 if a match is found, 1 otherwise.
1987 Returns 0 if a match is found, 1 otherwise.
1986
1988
1987 """
1989 """
1988
1990
1989 opts = pycompat.byteskwargs(opts)
1991 opts = pycompat.byteskwargs(opts)
1990 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1992 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1991
1993
1992 end = '\n'
1994 end = '\n'
1993 if opts.get('print0'):
1995 if opts.get('print0'):
1994 end = '\0'
1996 end = '\0'
1995 fmt = '%s' + end
1997 fmt = '%s' + end
1996
1998
1997 m = scmutil.match(ctx, pats, opts)
1999 m = scmutil.match(ctx, pats, opts)
1998 ui.pager('files')
2000 ui.pager('files')
1999 with ui.formatter('files', opts) as fm:
2001 with ui.formatter('files', opts) as fm:
2000 return cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
2002 return cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
2001
2003
2002 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
2004 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
2003 def forget(ui, repo, *pats, **opts):
2005 def forget(ui, repo, *pats, **opts):
2004 """forget the specified files on the next commit
2006 """forget the specified files on the next commit
2005
2007
2006 Mark the specified files so they will no longer be tracked
2008 Mark the specified files so they will no longer be tracked
2007 after the next commit.
2009 after the next commit.
2008
2010
2009 This only removes files from the current branch, not from the
2011 This only removes files from the current branch, not from the
2010 entire project history, and it does not delete them from the
2012 entire project history, and it does not delete them from the
2011 working directory.
2013 working directory.
2012
2014
2013 To delete the file from the working directory, see :hg:`remove`.
2015 To delete the file from the working directory, see :hg:`remove`.
2014
2016
2015 To undo a forget before the next commit, see :hg:`add`.
2017 To undo a forget before the next commit, see :hg:`add`.
2016
2018
2017 .. container:: verbose
2019 .. container:: verbose
2018
2020
2019 Examples:
2021 Examples:
2020
2022
2021 - forget newly-added binary files::
2023 - forget newly-added binary files::
2022
2024
2023 hg forget "set:added() and binary()"
2025 hg forget "set:added() and binary()"
2024
2026
2025 - forget files that would be excluded by .hgignore::
2027 - forget files that would be excluded by .hgignore::
2026
2028
2027 hg forget "set:hgignore()"
2029 hg forget "set:hgignore()"
2028
2030
2029 Returns 0 on success.
2031 Returns 0 on success.
2030 """
2032 """
2031
2033
2032 opts = pycompat.byteskwargs(opts)
2034 opts = pycompat.byteskwargs(opts)
2033 if not pats:
2035 if not pats:
2034 raise error.Abort(_('no files specified'))
2036 raise error.Abort(_('no files specified'))
2035
2037
2036 m = scmutil.match(repo[None], pats, opts)
2038 m = scmutil.match(repo[None], pats, opts)
2037 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2039 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2038 return rejected and 1 or 0
2040 return rejected and 1 or 0
2039
2041
2040 @command(
2042 @command(
2041 'graft',
2043 'graft',
2042 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2044 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2043 ('c', 'continue', False, _('resume interrupted graft')),
2045 ('c', 'continue', False, _('resume interrupted graft')),
2044 ('e', 'edit', False, _('invoke editor on commit messages')),
2046 ('e', 'edit', False, _('invoke editor on commit messages')),
2045 ('', 'log', None, _('append graft info to log message')),
2047 ('', 'log', None, _('append graft info to log message')),
2046 ('f', 'force', False, _('force graft')),
2048 ('f', 'force', False, _('force graft')),
2047 ('D', 'currentdate', False,
2049 ('D', 'currentdate', False,
2048 _('record the current date as commit date')),
2050 _('record the current date as commit date')),
2049 ('U', 'currentuser', False,
2051 ('U', 'currentuser', False,
2050 _('record the current user as committer'), _('DATE'))]
2052 _('record the current user as committer'), _('DATE'))]
2051 + commitopts2 + mergetoolopts + dryrunopts,
2053 + commitopts2 + mergetoolopts + dryrunopts,
2052 _('[OPTION]... [-r REV]... REV...'))
2054 _('[OPTION]... [-r REV]... REV...'))
2053 def graft(ui, repo, *revs, **opts):
2055 def graft(ui, repo, *revs, **opts):
2054 '''copy changes from other branches onto the current branch
2056 '''copy changes from other branches onto the current branch
2055
2057
2056 This command uses Mercurial's merge logic to copy individual
2058 This command uses Mercurial's merge logic to copy individual
2057 changes from other branches without merging branches in the
2059 changes from other branches without merging branches in the
2058 history graph. This is sometimes known as 'backporting' or
2060 history graph. This is sometimes known as 'backporting' or
2059 'cherry-picking'. By default, graft will copy user, date, and
2061 'cherry-picking'. By default, graft will copy user, date, and
2060 description from the source changesets.
2062 description from the source changesets.
2061
2063
2062 Changesets that are ancestors of the current revision, that have
2064 Changesets that are ancestors of the current revision, that have
2063 already been grafted, or that are merges will be skipped.
2065 already been grafted, or that are merges will be skipped.
2064
2066
2065 If --log is specified, log messages will have a comment appended
2067 If --log is specified, log messages will have a comment appended
2066 of the form::
2068 of the form::
2067
2069
2068 (grafted from CHANGESETHASH)
2070 (grafted from CHANGESETHASH)
2069
2071
2070 If --force is specified, revisions will be grafted even if they
2072 If --force is specified, revisions will be grafted even if they
2071 are already ancestors of, or have been grafted to, the destination.
2073 are already ancestors of, or have been grafted to, the destination.
2072 This is useful when the revisions have since been backed out.
2074 This is useful when the revisions have since been backed out.
2073
2075
2074 If a graft merge results in conflicts, the graft process is
2076 If a graft merge results in conflicts, the graft process is
2075 interrupted so that the current merge can be manually resolved.
2077 interrupted so that the current merge can be manually resolved.
2076 Once all conflicts are addressed, the graft process can be
2078 Once all conflicts are addressed, the graft process can be
2077 continued with the -c/--continue option.
2079 continued with the -c/--continue option.
2078
2080
2079 .. note::
2081 .. note::
2080
2082
2081 The -c/--continue option does not reapply earlier options, except
2083 The -c/--continue option does not reapply earlier options, except
2082 for --force.
2084 for --force.
2083
2085
2084 .. container:: verbose
2086 .. container:: verbose
2085
2087
2086 Examples:
2088 Examples:
2087
2089
2088 - copy a single change to the stable branch and edit its description::
2090 - copy a single change to the stable branch and edit its description::
2089
2091
2090 hg update stable
2092 hg update stable
2091 hg graft --edit 9393
2093 hg graft --edit 9393
2092
2094
2093 - graft a range of changesets with one exception, updating dates::
2095 - graft a range of changesets with one exception, updating dates::
2094
2096
2095 hg graft -D "2085::2093 and not 2091"
2097 hg graft -D "2085::2093 and not 2091"
2096
2098
2097 - continue a graft after resolving conflicts::
2099 - continue a graft after resolving conflicts::
2098
2100
2099 hg graft -c
2101 hg graft -c
2100
2102
2101 - show the source of a grafted changeset::
2103 - show the source of a grafted changeset::
2102
2104
2103 hg log --debug -r .
2105 hg log --debug -r .
2104
2106
2105 - show revisions sorted by date::
2107 - show revisions sorted by date::
2106
2108
2107 hg log -r "sort(all(), date)"
2109 hg log -r "sort(all(), date)"
2108
2110
2109 See :hg:`help revisions` for more about specifying revisions.
2111 See :hg:`help revisions` for more about specifying revisions.
2110
2112
2111 Returns 0 on successful completion.
2113 Returns 0 on successful completion.
2112 '''
2114 '''
2113 with repo.wlock():
2115 with repo.wlock():
2114 return _dograft(ui, repo, *revs, **opts)
2116 return _dograft(ui, repo, *revs, **opts)
2115
2117
2116 def _dograft(ui, repo, *revs, **opts):
2118 def _dograft(ui, repo, *revs, **opts):
2117 opts = pycompat.byteskwargs(opts)
2119 opts = pycompat.byteskwargs(opts)
2118 if revs and opts.get('rev'):
2120 if revs and opts.get('rev'):
2119 ui.warn(_('warning: inconsistent use of --rev might give unexpected '
2121 ui.warn(_('warning: inconsistent use of --rev might give unexpected '
2120 'revision ordering!\n'))
2122 'revision ordering!\n'))
2121
2123
2122 revs = list(revs)
2124 revs = list(revs)
2123 revs.extend(opts.get('rev'))
2125 revs.extend(opts.get('rev'))
2124
2126
2125 if not opts.get('user') and opts.get('currentuser'):
2127 if not opts.get('user') and opts.get('currentuser'):
2126 opts['user'] = ui.username()
2128 opts['user'] = ui.username()
2127 if not opts.get('date') and opts.get('currentdate'):
2129 if not opts.get('date') and opts.get('currentdate'):
2128 opts['date'] = "%d %d" % util.makedate()
2130 opts['date'] = "%d %d" % util.makedate()
2129
2131
2130 editor = cmdutil.getcommiteditor(editform='graft',
2132 editor = cmdutil.getcommiteditor(editform='graft',
2131 **pycompat.strkwargs(opts))
2133 **pycompat.strkwargs(opts))
2132
2134
2133 cont = False
2135 cont = False
2134 if opts.get('continue'):
2136 if opts.get('continue'):
2135 cont = True
2137 cont = True
2136 if revs:
2138 if revs:
2137 raise error.Abort(_("can't specify --continue and revisions"))
2139 raise error.Abort(_("can't specify --continue and revisions"))
2138 # read in unfinished revisions
2140 # read in unfinished revisions
2139 try:
2141 try:
2140 nodes = repo.vfs.read('graftstate').splitlines()
2142 nodes = repo.vfs.read('graftstate').splitlines()
2141 revs = [repo[node].rev() for node in nodes]
2143 revs = [repo[node].rev() for node in nodes]
2142 except IOError as inst:
2144 except IOError as inst:
2143 if inst.errno != errno.ENOENT:
2145 if inst.errno != errno.ENOENT:
2144 raise
2146 raise
2145 cmdutil.wrongtooltocontinue(repo, _('graft'))
2147 cmdutil.wrongtooltocontinue(repo, _('graft'))
2146 else:
2148 else:
2147 cmdutil.checkunfinished(repo)
2149 cmdutil.checkunfinished(repo)
2148 cmdutil.bailifchanged(repo)
2150 cmdutil.bailifchanged(repo)
2149 if not revs:
2151 if not revs:
2150 raise error.Abort(_('no revisions specified'))
2152 raise error.Abort(_('no revisions specified'))
2151 revs = scmutil.revrange(repo, revs)
2153 revs = scmutil.revrange(repo, revs)
2152
2154
2153 skipped = set()
2155 skipped = set()
2154 # check for merges
2156 # check for merges
2155 for rev in repo.revs('%ld and merge()', revs):
2157 for rev in repo.revs('%ld and merge()', revs):
2156 ui.warn(_('skipping ungraftable merge revision %d\n') % rev)
2158 ui.warn(_('skipping ungraftable merge revision %d\n') % rev)
2157 skipped.add(rev)
2159 skipped.add(rev)
2158 revs = [r for r in revs if r not in skipped]
2160 revs = [r for r in revs if r not in skipped]
2159 if not revs:
2161 if not revs:
2160 return -1
2162 return -1
2161
2163
2162 # Don't check in the --continue case, in effect retaining --force across
2164 # Don't check in the --continue case, in effect retaining --force across
2163 # --continues. That's because without --force, any revisions we decided to
2165 # --continues. That's because without --force, any revisions we decided to
2164 # skip would have been filtered out here, so they wouldn't have made their
2166 # skip would have been filtered out here, so they wouldn't have made their
2165 # way to the graftstate. With --force, any revisions we would have otherwise
2167 # way to the graftstate. With --force, any revisions we would have otherwise
2166 # skipped would not have been filtered out, and if they hadn't been applied
2168 # skipped would not have been filtered out, and if they hadn't been applied
2167 # already, they'd have been in the graftstate.
2169 # already, they'd have been in the graftstate.
2168 if not (cont or opts.get('force')):
2170 if not (cont or opts.get('force')):
2169 # check for ancestors of dest branch
2171 # check for ancestors of dest branch
2170 crev = repo['.'].rev()
2172 crev = repo['.'].rev()
2171 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2173 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2172 # XXX make this lazy in the future
2174 # XXX make this lazy in the future
2173 # don't mutate while iterating, create a copy
2175 # don't mutate while iterating, create a copy
2174 for rev in list(revs):
2176 for rev in list(revs):
2175 if rev in ancestors:
2177 if rev in ancestors:
2176 ui.warn(_('skipping ancestor revision %d:%s\n') %
2178 ui.warn(_('skipping ancestor revision %d:%s\n') %
2177 (rev, repo[rev]))
2179 (rev, repo[rev]))
2178 # XXX remove on list is slow
2180 # XXX remove on list is slow
2179 revs.remove(rev)
2181 revs.remove(rev)
2180 if not revs:
2182 if not revs:
2181 return -1
2183 return -1
2182
2184
2183 # analyze revs for earlier grafts
2185 # analyze revs for earlier grafts
2184 ids = {}
2186 ids = {}
2185 for ctx in repo.set("%ld", revs):
2187 for ctx in repo.set("%ld", revs):
2186 ids[ctx.hex()] = ctx.rev()
2188 ids[ctx.hex()] = ctx.rev()
2187 n = ctx.extra().get('source')
2189 n = ctx.extra().get('source')
2188 if n:
2190 if n:
2189 ids[n] = ctx.rev()
2191 ids[n] = ctx.rev()
2190
2192
2191 # check ancestors for earlier grafts
2193 # check ancestors for earlier grafts
2192 ui.debug('scanning for duplicate grafts\n')
2194 ui.debug('scanning for duplicate grafts\n')
2193
2195
2194 # The only changesets we can be sure doesn't contain grafts of any
2196 # The only changesets we can be sure doesn't contain grafts of any
2195 # revs, are the ones that are common ancestors of *all* revs:
2197 # revs, are the ones that are common ancestors of *all* revs:
2196 for rev in repo.revs('only(%d,ancestor(%ld))', crev, revs):
2198 for rev in repo.revs('only(%d,ancestor(%ld))', crev, revs):
2197 ctx = repo[rev]
2199 ctx = repo[rev]
2198 n = ctx.extra().get('source')
2200 n = ctx.extra().get('source')
2199 if n in ids:
2201 if n in ids:
2200 try:
2202 try:
2201 r = repo[n].rev()
2203 r = repo[n].rev()
2202 except error.RepoLookupError:
2204 except error.RepoLookupError:
2203 r = None
2205 r = None
2204 if r in revs:
2206 if r in revs:
2205 ui.warn(_('skipping revision %d:%s '
2207 ui.warn(_('skipping revision %d:%s '
2206 '(already grafted to %d:%s)\n')
2208 '(already grafted to %d:%s)\n')
2207 % (r, repo[r], rev, ctx))
2209 % (r, repo[r], rev, ctx))
2208 revs.remove(r)
2210 revs.remove(r)
2209 elif ids[n] in revs:
2211 elif ids[n] in revs:
2210 if r is None:
2212 if r is None:
2211 ui.warn(_('skipping already grafted revision %d:%s '
2213 ui.warn(_('skipping already grafted revision %d:%s '
2212 '(%d:%s also has unknown origin %s)\n')
2214 '(%d:%s also has unknown origin %s)\n')
2213 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
2215 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
2214 else:
2216 else:
2215 ui.warn(_('skipping already grafted revision %d:%s '
2217 ui.warn(_('skipping already grafted revision %d:%s '
2216 '(%d:%s also has origin %d:%s)\n')
2218 '(%d:%s also has origin %d:%s)\n')
2217 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
2219 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
2218 revs.remove(ids[n])
2220 revs.remove(ids[n])
2219 elif ctx.hex() in ids:
2221 elif ctx.hex() in ids:
2220 r = ids[ctx.hex()]
2222 r = ids[ctx.hex()]
2221 ui.warn(_('skipping already grafted revision %d:%s '
2223 ui.warn(_('skipping already grafted revision %d:%s '
2222 '(was grafted from %d:%s)\n') %
2224 '(was grafted from %d:%s)\n') %
2223 (r, repo[r], rev, ctx))
2225 (r, repo[r], rev, ctx))
2224 revs.remove(r)
2226 revs.remove(r)
2225 if not revs:
2227 if not revs:
2226 return -1
2228 return -1
2227
2229
2228 for pos, ctx in enumerate(repo.set("%ld", revs)):
2230 for pos, ctx in enumerate(repo.set("%ld", revs)):
2229 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
2231 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
2230 ctx.description().split('\n', 1)[0])
2232 ctx.description().split('\n', 1)[0])
2231 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
2233 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
2232 if names:
2234 if names:
2233 desc += ' (%s)' % ' '.join(names)
2235 desc += ' (%s)' % ' '.join(names)
2234 ui.status(_('grafting %s\n') % desc)
2236 ui.status(_('grafting %s\n') % desc)
2235 if opts.get('dry_run'):
2237 if opts.get('dry_run'):
2236 continue
2238 continue
2237
2239
2238 source = ctx.extra().get('source')
2240 source = ctx.extra().get('source')
2239 extra = {}
2241 extra = {}
2240 if source:
2242 if source:
2241 extra['source'] = source
2243 extra['source'] = source
2242 extra['intermediate-source'] = ctx.hex()
2244 extra['intermediate-source'] = ctx.hex()
2243 else:
2245 else:
2244 extra['source'] = ctx.hex()
2246 extra['source'] = ctx.hex()
2245 user = ctx.user()
2247 user = ctx.user()
2246 if opts.get('user'):
2248 if opts.get('user'):
2247 user = opts['user']
2249 user = opts['user']
2248 date = ctx.date()
2250 date = ctx.date()
2249 if opts.get('date'):
2251 if opts.get('date'):
2250 date = opts['date']
2252 date = opts['date']
2251 message = ctx.description()
2253 message = ctx.description()
2252 if opts.get('log'):
2254 if opts.get('log'):
2253 message += '\n(grafted from %s)' % ctx.hex()
2255 message += '\n(grafted from %s)' % ctx.hex()
2254
2256
2255 # we don't merge the first commit when continuing
2257 # we don't merge the first commit when continuing
2256 if not cont:
2258 if not cont:
2257 # perform the graft merge with p1(rev) as 'ancestor'
2259 # perform the graft merge with p1(rev) as 'ancestor'
2258 try:
2260 try:
2259 # ui.forcemerge is an internal variable, do not document
2261 # ui.forcemerge is an internal variable, do not document
2260 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
2262 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
2261 'graft')
2263 'graft')
2262 stats = mergemod.graft(repo, ctx, ctx.p1(),
2264 stats = mergemod.graft(repo, ctx, ctx.p1(),
2263 ['local', 'graft'])
2265 ['local', 'graft'])
2264 finally:
2266 finally:
2265 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
2267 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
2266 # report any conflicts
2268 # report any conflicts
2267 if stats and stats[3] > 0:
2269 if stats and stats[3] > 0:
2268 # write out state for --continue
2270 # write out state for --continue
2269 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2271 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2270 repo.vfs.write('graftstate', ''.join(nodelines))
2272 repo.vfs.write('graftstate', ''.join(nodelines))
2271 extra = ''
2273 extra = ''
2272 if opts.get('user'):
2274 if opts.get('user'):
2273 extra += ' --user %s' % util.shellquote(opts['user'])
2275 extra += ' --user %s' % util.shellquote(opts['user'])
2274 if opts.get('date'):
2276 if opts.get('date'):
2275 extra += ' --date %s' % util.shellquote(opts['date'])
2277 extra += ' --date %s' % util.shellquote(opts['date'])
2276 if opts.get('log'):
2278 if opts.get('log'):
2277 extra += ' --log'
2279 extra += ' --log'
2278 hint=_("use 'hg resolve' and 'hg graft --continue%s'") % extra
2280 hint=_("use 'hg resolve' and 'hg graft --continue%s'") % extra
2279 raise error.Abort(
2281 raise error.Abort(
2280 _("unresolved conflicts, can't continue"),
2282 _("unresolved conflicts, can't continue"),
2281 hint=hint)
2283 hint=hint)
2282 else:
2284 else:
2283 cont = False
2285 cont = False
2284
2286
2285 # commit
2287 # commit
2286 node = repo.commit(text=message, user=user,
2288 node = repo.commit(text=message, user=user,
2287 date=date, extra=extra, editor=editor)
2289 date=date, extra=extra, editor=editor)
2288 if node is None:
2290 if node is None:
2289 ui.warn(
2291 ui.warn(
2290 _('note: graft of %d:%s created no changes to commit\n') %
2292 _('note: graft of %d:%s created no changes to commit\n') %
2291 (ctx.rev(), ctx))
2293 (ctx.rev(), ctx))
2292
2294
2293 # remove state when we complete successfully
2295 # remove state when we complete successfully
2294 if not opts.get('dry_run'):
2296 if not opts.get('dry_run'):
2295 repo.vfs.unlinkpath('graftstate', ignoremissing=True)
2297 repo.vfs.unlinkpath('graftstate', ignoremissing=True)
2296
2298
2297 return 0
2299 return 0
2298
2300
2299 @command('grep',
2301 @command('grep',
2300 [('0', 'print0', None, _('end fields with NUL')),
2302 [('0', 'print0', None, _('end fields with NUL')),
2301 ('', 'all', None, _('print all revisions that match')),
2303 ('', 'all', None, _('print all revisions that match')),
2302 ('a', 'text', None, _('treat all files as text')),
2304 ('a', 'text', None, _('treat all files as text')),
2303 ('f', 'follow', None,
2305 ('f', 'follow', None,
2304 _('follow changeset history,'
2306 _('follow changeset history,'
2305 ' or file history across copies and renames')),
2307 ' or file history across copies and renames')),
2306 ('i', 'ignore-case', None, _('ignore case when matching')),
2308 ('i', 'ignore-case', None, _('ignore case when matching')),
2307 ('l', 'files-with-matches', None,
2309 ('l', 'files-with-matches', None,
2308 _('print only filenames and revisions that match')),
2310 _('print only filenames and revisions that match')),
2309 ('n', 'line-number', None, _('print matching line numbers')),
2311 ('n', 'line-number', None, _('print matching line numbers')),
2310 ('r', 'rev', [],
2312 ('r', 'rev', [],
2311 _('only search files changed within revision range'), _('REV')),
2313 _('only search files changed within revision range'), _('REV')),
2312 ('u', 'user', None, _('list the author (long with -v)')),
2314 ('u', 'user', None, _('list the author (long with -v)')),
2313 ('d', 'date', None, _('list the date (short with -q)')),
2315 ('d', 'date', None, _('list the date (short with -q)')),
2314 ] + formatteropts + walkopts,
2316 ] + formatteropts + walkopts,
2315 _('[OPTION]... PATTERN [FILE]...'),
2317 _('[OPTION]... PATTERN [FILE]...'),
2316 inferrepo=True, cmdtype=readonly)
2318 inferrepo=True, cmdtype=readonly)
2317 def grep(ui, repo, pattern, *pats, **opts):
2319 def grep(ui, repo, pattern, *pats, **opts):
2318 """search revision history for a pattern in specified files
2320 """search revision history for a pattern in specified files
2319
2321
2320 Search revision history for a regular expression in the specified
2322 Search revision history for a regular expression in the specified
2321 files or the entire project.
2323 files or the entire project.
2322
2324
2323 By default, grep prints the most recent revision number for each
2325 By default, grep prints the most recent revision number for each
2324 file in which it finds a match. To get it to print every revision
2326 file in which it finds a match. To get it to print every revision
2325 that contains a change in match status ("-" for a match that becomes
2327 that contains a change in match status ("-" for a match that becomes
2326 a non-match, or "+" for a non-match that becomes a match), use the
2328 a non-match, or "+" for a non-match that becomes a match), use the
2327 --all flag.
2329 --all flag.
2328
2330
2329 PATTERN can be any Python (roughly Perl-compatible) regular
2331 PATTERN can be any Python (roughly Perl-compatible) regular
2330 expression.
2332 expression.
2331
2333
2332 If no FILEs are specified (and -f/--follow isn't set), all files in
2334 If no FILEs are specified (and -f/--follow isn't set), all files in
2333 the repository are searched, including those that don't exist in the
2335 the repository are searched, including those that don't exist in the
2334 current branch or have been deleted in a prior changeset.
2336 current branch or have been deleted in a prior changeset.
2335
2337
2336 Returns 0 if a match is found, 1 otherwise.
2338 Returns 0 if a match is found, 1 otherwise.
2337 """
2339 """
2338 opts = pycompat.byteskwargs(opts)
2340 opts = pycompat.byteskwargs(opts)
2339 reflags = re.M
2341 reflags = re.M
2340 if opts.get('ignore_case'):
2342 if opts.get('ignore_case'):
2341 reflags |= re.I
2343 reflags |= re.I
2342 try:
2344 try:
2343 regexp = util.re.compile(pattern, reflags)
2345 regexp = util.re.compile(pattern, reflags)
2344 except re.error as inst:
2346 except re.error as inst:
2345 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2347 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2346 return 1
2348 return 1
2347 sep, eol = ':', '\n'
2349 sep, eol = ':', '\n'
2348 if opts.get('print0'):
2350 if opts.get('print0'):
2349 sep = eol = '\0'
2351 sep = eol = '\0'
2350
2352
2351 getfile = util.lrucachefunc(repo.file)
2353 getfile = util.lrucachefunc(repo.file)
2352
2354
2353 def matchlines(body):
2355 def matchlines(body):
2354 begin = 0
2356 begin = 0
2355 linenum = 0
2357 linenum = 0
2356 while begin < len(body):
2358 while begin < len(body):
2357 match = regexp.search(body, begin)
2359 match = regexp.search(body, begin)
2358 if not match:
2360 if not match:
2359 break
2361 break
2360 mstart, mend = match.span()
2362 mstart, mend = match.span()
2361 linenum += body.count('\n', begin, mstart) + 1
2363 linenum += body.count('\n', begin, mstart) + 1
2362 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2364 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2363 begin = body.find('\n', mend) + 1 or len(body) + 1
2365 begin = body.find('\n', mend) + 1 or len(body) + 1
2364 lend = begin - 1
2366 lend = begin - 1
2365 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2367 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2366
2368
2367 class linestate(object):
2369 class linestate(object):
2368 def __init__(self, line, linenum, colstart, colend):
2370 def __init__(self, line, linenum, colstart, colend):
2369 self.line = line
2371 self.line = line
2370 self.linenum = linenum
2372 self.linenum = linenum
2371 self.colstart = colstart
2373 self.colstart = colstart
2372 self.colend = colend
2374 self.colend = colend
2373
2375
2374 def __hash__(self):
2376 def __hash__(self):
2375 return hash((self.linenum, self.line))
2377 return hash((self.linenum, self.line))
2376
2378
2377 def __eq__(self, other):
2379 def __eq__(self, other):
2378 return self.line == other.line
2380 return self.line == other.line
2379
2381
2380 def findpos(self):
2382 def findpos(self):
2381 """Iterate all (start, end) indices of matches"""
2383 """Iterate all (start, end) indices of matches"""
2382 yield self.colstart, self.colend
2384 yield self.colstart, self.colend
2383 p = self.colend
2385 p = self.colend
2384 while p < len(self.line):
2386 while p < len(self.line):
2385 m = regexp.search(self.line, p)
2387 m = regexp.search(self.line, p)
2386 if not m:
2388 if not m:
2387 break
2389 break
2388 yield m.span()
2390 yield m.span()
2389 p = m.end()
2391 p = m.end()
2390
2392
2391 matches = {}
2393 matches = {}
2392 copies = {}
2394 copies = {}
2393 def grepbody(fn, rev, body):
2395 def grepbody(fn, rev, body):
2394 matches[rev].setdefault(fn, [])
2396 matches[rev].setdefault(fn, [])
2395 m = matches[rev][fn]
2397 m = matches[rev][fn]
2396 for lnum, cstart, cend, line in matchlines(body):
2398 for lnum, cstart, cend, line in matchlines(body):
2397 s = linestate(line, lnum, cstart, cend)
2399 s = linestate(line, lnum, cstart, cend)
2398 m.append(s)
2400 m.append(s)
2399
2401
2400 def difflinestates(a, b):
2402 def difflinestates(a, b):
2401 sm = difflib.SequenceMatcher(None, a, b)
2403 sm = difflib.SequenceMatcher(None, a, b)
2402 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2404 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2403 if tag == 'insert':
2405 if tag == 'insert':
2404 for i in xrange(blo, bhi):
2406 for i in xrange(blo, bhi):
2405 yield ('+', b[i])
2407 yield ('+', b[i])
2406 elif tag == 'delete':
2408 elif tag == 'delete':
2407 for i in xrange(alo, ahi):
2409 for i in xrange(alo, ahi):
2408 yield ('-', a[i])
2410 yield ('-', a[i])
2409 elif tag == 'replace':
2411 elif tag == 'replace':
2410 for i in xrange(alo, ahi):
2412 for i in xrange(alo, ahi):
2411 yield ('-', a[i])
2413 yield ('-', a[i])
2412 for i in xrange(blo, bhi):
2414 for i in xrange(blo, bhi):
2413 yield ('+', b[i])
2415 yield ('+', b[i])
2414
2416
2415 def display(fm, fn, ctx, pstates, states):
2417 def display(fm, fn, ctx, pstates, states):
2416 rev = ctx.rev()
2418 rev = ctx.rev()
2417 if fm.isplain():
2419 if fm.isplain():
2418 formatuser = ui.shortuser
2420 formatuser = ui.shortuser
2419 else:
2421 else:
2420 formatuser = str
2422 formatuser = str
2421 if ui.quiet:
2423 if ui.quiet:
2422 datefmt = '%Y-%m-%d'
2424 datefmt = '%Y-%m-%d'
2423 else:
2425 else:
2424 datefmt = '%a %b %d %H:%M:%S %Y %1%2'
2426 datefmt = '%a %b %d %H:%M:%S %Y %1%2'
2425 found = False
2427 found = False
2426 @util.cachefunc
2428 @util.cachefunc
2427 def binary():
2429 def binary():
2428 flog = getfile(fn)
2430 flog = getfile(fn)
2429 return util.binary(flog.read(ctx.filenode(fn)))
2431 return util.binary(flog.read(ctx.filenode(fn)))
2430
2432
2431 fieldnamemap = {'filename': 'file', 'linenumber': 'line_number'}
2433 fieldnamemap = {'filename': 'file', 'linenumber': 'line_number'}
2432 if opts.get('all'):
2434 if opts.get('all'):
2433 iter = difflinestates(pstates, states)
2435 iter = difflinestates(pstates, states)
2434 else:
2436 else:
2435 iter = [('', l) for l in states]
2437 iter = [('', l) for l in states]
2436 for change, l in iter:
2438 for change, l in iter:
2437 fm.startitem()
2439 fm.startitem()
2438 fm.data(node=fm.hexfunc(ctx.node()))
2440 fm.data(node=fm.hexfunc(ctx.node()))
2439 cols = [
2441 cols = [
2440 ('filename', fn, True),
2442 ('filename', fn, True),
2441 ('rev', rev, True),
2443 ('rev', rev, True),
2442 ('linenumber', l.linenum, opts.get('line_number')),
2444 ('linenumber', l.linenum, opts.get('line_number')),
2443 ]
2445 ]
2444 if opts.get('all'):
2446 if opts.get('all'):
2445 cols.append(('change', change, True))
2447 cols.append(('change', change, True))
2446 cols.extend([
2448 cols.extend([
2447 ('user', formatuser(ctx.user()), opts.get('user')),
2449 ('user', formatuser(ctx.user()), opts.get('user')),
2448 ('date', fm.formatdate(ctx.date(), datefmt), opts.get('date')),
2450 ('date', fm.formatdate(ctx.date(), datefmt), opts.get('date')),
2449 ])
2451 ])
2450 lastcol = next(name for name, data, cond in reversed(cols) if cond)
2452 lastcol = next(name for name, data, cond in reversed(cols) if cond)
2451 for name, data, cond in cols:
2453 for name, data, cond in cols:
2452 field = fieldnamemap.get(name, name)
2454 field = fieldnamemap.get(name, name)
2453 fm.condwrite(cond, field, '%s', data, label='grep.%s' % name)
2455 fm.condwrite(cond, field, '%s', data, label='grep.%s' % name)
2454 if cond and name != lastcol:
2456 if cond and name != lastcol:
2455 fm.plain(sep, label='grep.sep')
2457 fm.plain(sep, label='grep.sep')
2456 if not opts.get('files_with_matches'):
2458 if not opts.get('files_with_matches'):
2457 fm.plain(sep, label='grep.sep')
2459 fm.plain(sep, label='grep.sep')
2458 if not opts.get('text') and binary():
2460 if not opts.get('text') and binary():
2459 fm.plain(_(" Binary file matches"))
2461 fm.plain(_(" Binary file matches"))
2460 else:
2462 else:
2461 displaymatches(fm.nested('texts'), l)
2463 displaymatches(fm.nested('texts'), l)
2462 fm.plain(eol)
2464 fm.plain(eol)
2463 found = True
2465 found = True
2464 if opts.get('files_with_matches'):
2466 if opts.get('files_with_matches'):
2465 break
2467 break
2466 return found
2468 return found
2467
2469
2468 def displaymatches(fm, l):
2470 def displaymatches(fm, l):
2469 p = 0
2471 p = 0
2470 for s, e in l.findpos():
2472 for s, e in l.findpos():
2471 if p < s:
2473 if p < s:
2472 fm.startitem()
2474 fm.startitem()
2473 fm.write('text', '%s', l.line[p:s])
2475 fm.write('text', '%s', l.line[p:s])
2474 fm.data(matched=False)
2476 fm.data(matched=False)
2475 fm.startitem()
2477 fm.startitem()
2476 fm.write('text', '%s', l.line[s:e], label='grep.match')
2478 fm.write('text', '%s', l.line[s:e], label='grep.match')
2477 fm.data(matched=True)
2479 fm.data(matched=True)
2478 p = e
2480 p = e
2479 if p < len(l.line):
2481 if p < len(l.line):
2480 fm.startitem()
2482 fm.startitem()
2481 fm.write('text', '%s', l.line[p:])
2483 fm.write('text', '%s', l.line[p:])
2482 fm.data(matched=False)
2484 fm.data(matched=False)
2483 fm.end()
2485 fm.end()
2484
2486
2485 skip = {}
2487 skip = {}
2486 revfiles = {}
2488 revfiles = {}
2487 match = scmutil.match(repo[None], pats, opts)
2489 match = scmutil.match(repo[None], pats, opts)
2488 found = False
2490 found = False
2489 follow = opts.get('follow')
2491 follow = opts.get('follow')
2490
2492
2491 def prep(ctx, fns):
2493 def prep(ctx, fns):
2492 rev = ctx.rev()
2494 rev = ctx.rev()
2493 pctx = ctx.p1()
2495 pctx = ctx.p1()
2494 parent = pctx.rev()
2496 parent = pctx.rev()
2495 matches.setdefault(rev, {})
2497 matches.setdefault(rev, {})
2496 matches.setdefault(parent, {})
2498 matches.setdefault(parent, {})
2497 files = revfiles.setdefault(rev, [])
2499 files = revfiles.setdefault(rev, [])
2498 for fn in fns:
2500 for fn in fns:
2499 flog = getfile(fn)
2501 flog = getfile(fn)
2500 try:
2502 try:
2501 fnode = ctx.filenode(fn)
2503 fnode = ctx.filenode(fn)
2502 except error.LookupError:
2504 except error.LookupError:
2503 continue
2505 continue
2504
2506
2505 copied = flog.renamed(fnode)
2507 copied = flog.renamed(fnode)
2506 copy = follow and copied and copied[0]
2508 copy = follow and copied and copied[0]
2507 if copy:
2509 if copy:
2508 copies.setdefault(rev, {})[fn] = copy
2510 copies.setdefault(rev, {})[fn] = copy
2509 if fn in skip:
2511 if fn in skip:
2510 if copy:
2512 if copy:
2511 skip[copy] = True
2513 skip[copy] = True
2512 continue
2514 continue
2513 files.append(fn)
2515 files.append(fn)
2514
2516
2515 if fn not in matches[rev]:
2517 if fn not in matches[rev]:
2516 grepbody(fn, rev, flog.read(fnode))
2518 grepbody(fn, rev, flog.read(fnode))
2517
2519
2518 pfn = copy or fn
2520 pfn = copy or fn
2519 if pfn not in matches[parent]:
2521 if pfn not in matches[parent]:
2520 try:
2522 try:
2521 fnode = pctx.filenode(pfn)
2523 fnode = pctx.filenode(pfn)
2522 grepbody(pfn, parent, flog.read(fnode))
2524 grepbody(pfn, parent, flog.read(fnode))
2523 except error.LookupError:
2525 except error.LookupError:
2524 pass
2526 pass
2525
2527
2526 ui.pager('grep')
2528 ui.pager('grep')
2527 fm = ui.formatter('grep', opts)
2529 fm = ui.formatter('grep', opts)
2528 for ctx in cmdutil.walkchangerevs(repo, match, opts, prep):
2530 for ctx in cmdutil.walkchangerevs(repo, match, opts, prep):
2529 rev = ctx.rev()
2531 rev = ctx.rev()
2530 parent = ctx.p1().rev()
2532 parent = ctx.p1().rev()
2531 for fn in sorted(revfiles.get(rev, [])):
2533 for fn in sorted(revfiles.get(rev, [])):
2532 states = matches[rev][fn]
2534 states = matches[rev][fn]
2533 copy = copies.get(rev, {}).get(fn)
2535 copy = copies.get(rev, {}).get(fn)
2534 if fn in skip:
2536 if fn in skip:
2535 if copy:
2537 if copy:
2536 skip[copy] = True
2538 skip[copy] = True
2537 continue
2539 continue
2538 pstates = matches.get(parent, {}).get(copy or fn, [])
2540 pstates = matches.get(parent, {}).get(copy or fn, [])
2539 if pstates or states:
2541 if pstates or states:
2540 r = display(fm, fn, ctx, pstates, states)
2542 r = display(fm, fn, ctx, pstates, states)
2541 found = found or r
2543 found = found or r
2542 if r and not opts.get('all'):
2544 if r and not opts.get('all'):
2543 skip[fn] = True
2545 skip[fn] = True
2544 if copy:
2546 if copy:
2545 skip[copy] = True
2547 skip[copy] = True
2546 del matches[rev]
2548 del matches[rev]
2547 del revfiles[rev]
2549 del revfiles[rev]
2548 fm.end()
2550 fm.end()
2549
2551
2550 return not found
2552 return not found
2551
2553
2552 @command('heads',
2554 @command('heads',
2553 [('r', 'rev', '',
2555 [('r', 'rev', '',
2554 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2556 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2555 ('t', 'topo', False, _('show topological heads only')),
2557 ('t', 'topo', False, _('show topological heads only')),
2556 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2558 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2557 ('c', 'closed', False, _('show normal and closed branch heads')),
2559 ('c', 'closed', False, _('show normal and closed branch heads')),
2558 ] + templateopts,
2560 ] + templateopts,
2559 _('[-ct] [-r STARTREV] [REV]...'), cmdtype=readonly)
2561 _('[-ct] [-r STARTREV] [REV]...'), cmdtype=readonly)
2560 def heads(ui, repo, *branchrevs, **opts):
2562 def heads(ui, repo, *branchrevs, **opts):
2561 """show branch heads
2563 """show branch heads
2562
2564
2563 With no arguments, show all open branch heads in the repository.
2565 With no arguments, show all open branch heads in the repository.
2564 Branch heads are changesets that have no descendants on the
2566 Branch heads are changesets that have no descendants on the
2565 same branch. They are where development generally takes place and
2567 same branch. They are where development generally takes place and
2566 are the usual targets for update and merge operations.
2568 are the usual targets for update and merge operations.
2567
2569
2568 If one or more REVs are given, only open branch heads on the
2570 If one or more REVs are given, only open branch heads on the
2569 branches associated with the specified changesets are shown. This
2571 branches associated with the specified changesets are shown. This
2570 means that you can use :hg:`heads .` to see the heads on the
2572 means that you can use :hg:`heads .` to see the heads on the
2571 currently checked-out branch.
2573 currently checked-out branch.
2572
2574
2573 If -c/--closed is specified, also show branch heads marked closed
2575 If -c/--closed is specified, also show branch heads marked closed
2574 (see :hg:`commit --close-branch`).
2576 (see :hg:`commit --close-branch`).
2575
2577
2576 If STARTREV is specified, only those heads that are descendants of
2578 If STARTREV is specified, only those heads that are descendants of
2577 STARTREV will be displayed.
2579 STARTREV will be displayed.
2578
2580
2579 If -t/--topo is specified, named branch mechanics will be ignored and only
2581 If -t/--topo is specified, named branch mechanics will be ignored and only
2580 topological heads (changesets with no children) will be shown.
2582 topological heads (changesets with no children) will be shown.
2581
2583
2582 Returns 0 if matching heads are found, 1 if not.
2584 Returns 0 if matching heads are found, 1 if not.
2583 """
2585 """
2584
2586
2585 opts = pycompat.byteskwargs(opts)
2587 opts = pycompat.byteskwargs(opts)
2586 start = None
2588 start = None
2587 if 'rev' in opts:
2589 if 'rev' in opts:
2588 start = scmutil.revsingle(repo, opts['rev'], None).node()
2590 start = scmutil.revsingle(repo, opts['rev'], None).node()
2589
2591
2590 if opts.get('topo'):
2592 if opts.get('topo'):
2591 heads = [repo[h] for h in repo.heads(start)]
2593 heads = [repo[h] for h in repo.heads(start)]
2592 else:
2594 else:
2593 heads = []
2595 heads = []
2594 for branch in repo.branchmap():
2596 for branch in repo.branchmap():
2595 heads += repo.branchheads(branch, start, opts.get('closed'))
2597 heads += repo.branchheads(branch, start, opts.get('closed'))
2596 heads = [repo[h] for h in heads]
2598 heads = [repo[h] for h in heads]
2597
2599
2598 if branchrevs:
2600 if branchrevs:
2599 branches = set(repo[br].branch() for br in branchrevs)
2601 branches = set(repo[br].branch() for br in branchrevs)
2600 heads = [h for h in heads if h.branch() in branches]
2602 heads = [h for h in heads if h.branch() in branches]
2601
2603
2602 if opts.get('active') and branchrevs:
2604 if opts.get('active') and branchrevs:
2603 dagheads = repo.heads(start)
2605 dagheads = repo.heads(start)
2604 heads = [h for h in heads if h.node() in dagheads]
2606 heads = [h for h in heads if h.node() in dagheads]
2605
2607
2606 if branchrevs:
2608 if branchrevs:
2607 haveheads = set(h.branch() for h in heads)
2609 haveheads = set(h.branch() for h in heads)
2608 if branches - haveheads:
2610 if branches - haveheads:
2609 headless = ', '.join(b for b in branches - haveheads)
2611 headless = ', '.join(b for b in branches - haveheads)
2610 msg = _('no open branch heads found on branches %s')
2612 msg = _('no open branch heads found on branches %s')
2611 if opts.get('rev'):
2613 if opts.get('rev'):
2612 msg += _(' (started at %s)') % opts['rev']
2614 msg += _(' (started at %s)') % opts['rev']
2613 ui.warn((msg + '\n') % headless)
2615 ui.warn((msg + '\n') % headless)
2614
2616
2615 if not heads:
2617 if not heads:
2616 return 1
2618 return 1
2617
2619
2618 ui.pager('heads')
2620 ui.pager('heads')
2619 heads = sorted(heads, key=lambda x: -x.rev())
2621 heads = sorted(heads, key=lambda x: -x.rev())
2620 displayer = cmdutil.show_changeset(ui, repo, opts)
2622 displayer = cmdutil.show_changeset(ui, repo, opts)
2621 for ctx in heads:
2623 for ctx in heads:
2622 displayer.show(ctx)
2624 displayer.show(ctx)
2623 displayer.close()
2625 displayer.close()
2624
2626
2625 @command('help',
2627 @command('help',
2626 [('e', 'extension', None, _('show only help for extensions')),
2628 [('e', 'extension', None, _('show only help for extensions')),
2627 ('c', 'command', None, _('show only help for commands')),
2629 ('c', 'command', None, _('show only help for commands')),
2628 ('k', 'keyword', None, _('show topics matching keyword')),
2630 ('k', 'keyword', None, _('show topics matching keyword')),
2629 ('s', 'system', [], _('show help for specific platform(s)')),
2631 ('s', 'system', [], _('show help for specific platform(s)')),
2630 ],
2632 ],
2631 _('[-ecks] [TOPIC]'),
2633 _('[-ecks] [TOPIC]'),
2632 norepo=True, cmdtype=readonly)
2634 norepo=True, cmdtype=readonly)
2633 def help_(ui, name=None, **opts):
2635 def help_(ui, name=None, **opts):
2634 """show help for a given topic or a help overview
2636 """show help for a given topic or a help overview
2635
2637
2636 With no arguments, print a list of commands with short help messages.
2638 With no arguments, print a list of commands with short help messages.
2637
2639
2638 Given a topic, extension, or command name, print help for that
2640 Given a topic, extension, or command name, print help for that
2639 topic.
2641 topic.
2640
2642
2641 Returns 0 if successful.
2643 Returns 0 if successful.
2642 """
2644 """
2643
2645
2644 keep = opts.get(r'system') or []
2646 keep = opts.get(r'system') or []
2645 if len(keep) == 0:
2647 if len(keep) == 0:
2646 if pycompat.sysplatform.startswith('win'):
2648 if pycompat.sysplatform.startswith('win'):
2647 keep.append('windows')
2649 keep.append('windows')
2648 elif pycompat.sysplatform == 'OpenVMS':
2650 elif pycompat.sysplatform == 'OpenVMS':
2649 keep.append('vms')
2651 keep.append('vms')
2650 elif pycompat.sysplatform == 'plan9':
2652 elif pycompat.sysplatform == 'plan9':
2651 keep.append('plan9')
2653 keep.append('plan9')
2652 else:
2654 else:
2653 keep.append('unix')
2655 keep.append('unix')
2654 keep.append(pycompat.sysplatform.lower())
2656 keep.append(pycompat.sysplatform.lower())
2655 if ui.verbose:
2657 if ui.verbose:
2656 keep.append('verbose')
2658 keep.append('verbose')
2657
2659
2658 commands = sys.modules[__name__]
2660 commands = sys.modules[__name__]
2659 formatted = help.formattedhelp(ui, commands, name, keep=keep, **opts)
2661 formatted = help.formattedhelp(ui, commands, name, keep=keep, **opts)
2660 ui.pager('help')
2662 ui.pager('help')
2661 ui.write(formatted)
2663 ui.write(formatted)
2662
2664
2663
2665
2664 @command('identify|id',
2666 @command('identify|id',
2665 [('r', 'rev', '',
2667 [('r', 'rev', '',
2666 _('identify the specified revision'), _('REV')),
2668 _('identify the specified revision'), _('REV')),
2667 ('n', 'num', None, _('show local revision number')),
2669 ('n', 'num', None, _('show local revision number')),
2668 ('i', 'id', None, _('show global revision id')),
2670 ('i', 'id', None, _('show global revision id')),
2669 ('b', 'branch', None, _('show branch')),
2671 ('b', 'branch', None, _('show branch')),
2670 ('t', 'tags', None, _('show tags')),
2672 ('t', 'tags', None, _('show tags')),
2671 ('B', 'bookmarks', None, _('show bookmarks')),
2673 ('B', 'bookmarks', None, _('show bookmarks')),
2672 ] + remoteopts + formatteropts,
2674 ] + remoteopts + formatteropts,
2673 _('[-nibtB] [-r REV] [SOURCE]'),
2675 _('[-nibtB] [-r REV] [SOURCE]'),
2674 optionalrepo=True, cmdtype=readonly)
2676 optionalrepo=True, cmdtype=readonly)
2675 def identify(ui, repo, source=None, rev=None,
2677 def identify(ui, repo, source=None, rev=None,
2676 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
2678 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
2677 """identify the working directory or specified revision
2679 """identify the working directory or specified revision
2678
2680
2679 Print a summary identifying the repository state at REV using one or
2681 Print a summary identifying the repository state at REV using one or
2680 two parent hash identifiers, followed by a "+" if the working
2682 two parent hash identifiers, followed by a "+" if the working
2681 directory has uncommitted changes, the branch name (if not default),
2683 directory has uncommitted changes, the branch name (if not default),
2682 a list of tags, and a list of bookmarks.
2684 a list of tags, and a list of bookmarks.
2683
2685
2684 When REV is not given, print a summary of the current state of the
2686 When REV is not given, print a summary of the current state of the
2685 repository.
2687 repository.
2686
2688
2687 Specifying a path to a repository root or Mercurial bundle will
2689 Specifying a path to a repository root or Mercurial bundle will
2688 cause lookup to operate on that repository/bundle.
2690 cause lookup to operate on that repository/bundle.
2689
2691
2690 .. container:: verbose
2692 .. container:: verbose
2691
2693
2692 Examples:
2694 Examples:
2693
2695
2694 - generate a build identifier for the working directory::
2696 - generate a build identifier for the working directory::
2695
2697
2696 hg id --id > build-id.dat
2698 hg id --id > build-id.dat
2697
2699
2698 - find the revision corresponding to a tag::
2700 - find the revision corresponding to a tag::
2699
2701
2700 hg id -n -r 1.3
2702 hg id -n -r 1.3
2701
2703
2702 - check the most recent revision of a remote repository::
2704 - check the most recent revision of a remote repository::
2703
2705
2704 hg id -r tip https://www.mercurial-scm.org/repo/hg/
2706 hg id -r tip https://www.mercurial-scm.org/repo/hg/
2705
2707
2706 See :hg:`log` for generating more information about specific revisions,
2708 See :hg:`log` for generating more information about specific revisions,
2707 including full hash identifiers.
2709 including full hash identifiers.
2708
2710
2709 Returns 0 if successful.
2711 Returns 0 if successful.
2710 """
2712 """
2711
2713
2712 opts = pycompat.byteskwargs(opts)
2714 opts = pycompat.byteskwargs(opts)
2713 if not repo and not source:
2715 if not repo and not source:
2714 raise error.Abort(_("there is no Mercurial repository here "
2716 raise error.Abort(_("there is no Mercurial repository here "
2715 "(.hg not found)"))
2717 "(.hg not found)"))
2716
2718
2717 if ui.debugflag:
2719 if ui.debugflag:
2718 hexfunc = hex
2720 hexfunc = hex
2719 else:
2721 else:
2720 hexfunc = short
2722 hexfunc = short
2721 default = not (num or id or branch or tags or bookmarks)
2723 default = not (num or id or branch or tags or bookmarks)
2722 output = []
2724 output = []
2723 revs = []
2725 revs = []
2724
2726
2725 if source:
2727 if source:
2726 source, branches = hg.parseurl(ui.expandpath(source))
2728 source, branches = hg.parseurl(ui.expandpath(source))
2727 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
2729 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
2728 repo = peer.local()
2730 repo = peer.local()
2729 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
2731 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
2730
2732
2731 fm = ui.formatter('identify', opts)
2733 fm = ui.formatter('identify', opts)
2732 fm.startitem()
2734 fm.startitem()
2733
2735
2734 if not repo:
2736 if not repo:
2735 if num or branch or tags:
2737 if num or branch or tags:
2736 raise error.Abort(
2738 raise error.Abort(
2737 _("can't query remote revision number, branch, or tags"))
2739 _("can't query remote revision number, branch, or tags"))
2738 if not rev and revs:
2740 if not rev and revs:
2739 rev = revs[0]
2741 rev = revs[0]
2740 if not rev:
2742 if not rev:
2741 rev = "tip"
2743 rev = "tip"
2742
2744
2743 remoterev = peer.lookup(rev)
2745 remoterev = peer.lookup(rev)
2744 hexrev = hexfunc(remoterev)
2746 hexrev = hexfunc(remoterev)
2745 if default or id:
2747 if default or id:
2746 output = [hexrev]
2748 output = [hexrev]
2747 fm.data(id=hexrev)
2749 fm.data(id=hexrev)
2748
2750
2749 def getbms():
2751 def getbms():
2750 bms = []
2752 bms = []
2751
2753
2752 if 'bookmarks' in peer.listkeys('namespaces'):
2754 if 'bookmarks' in peer.listkeys('namespaces'):
2753 hexremoterev = hex(remoterev)
2755 hexremoterev = hex(remoterev)
2754 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
2756 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
2755 if bmr == hexremoterev]
2757 if bmr == hexremoterev]
2756
2758
2757 return sorted(bms)
2759 return sorted(bms)
2758
2760
2759 bms = getbms()
2761 bms = getbms()
2760 if bookmarks:
2762 if bookmarks:
2761 output.extend(bms)
2763 output.extend(bms)
2762 elif default and not ui.quiet:
2764 elif default and not ui.quiet:
2763 # multiple bookmarks for a single parent separated by '/'
2765 # multiple bookmarks for a single parent separated by '/'
2764 bm = '/'.join(bms)
2766 bm = '/'.join(bms)
2765 if bm:
2767 if bm:
2766 output.append(bm)
2768 output.append(bm)
2767
2769
2768 fm.data(node=hex(remoterev))
2770 fm.data(node=hex(remoterev))
2769 fm.data(bookmarks=fm.formatlist(bms, name='bookmark'))
2771 fm.data(bookmarks=fm.formatlist(bms, name='bookmark'))
2770 else:
2772 else:
2771 ctx = scmutil.revsingle(repo, rev, None)
2773 ctx = scmutil.revsingle(repo, rev, None)
2772
2774
2773 if ctx.rev() is None:
2775 if ctx.rev() is None:
2774 ctx = repo[None]
2776 ctx = repo[None]
2775 parents = ctx.parents()
2777 parents = ctx.parents()
2776 taglist = []
2778 taglist = []
2777 for p in parents:
2779 for p in parents:
2778 taglist.extend(p.tags())
2780 taglist.extend(p.tags())
2779
2781
2780 dirty = ""
2782 dirty = ""
2781 if ctx.dirty(missing=True, merge=False, branch=False):
2783 if ctx.dirty(missing=True, merge=False, branch=False):
2782 dirty = '+'
2784 dirty = '+'
2783 fm.data(dirty=dirty)
2785 fm.data(dirty=dirty)
2784
2786
2785 hexoutput = [hexfunc(p.node()) for p in parents]
2787 hexoutput = [hexfunc(p.node()) for p in parents]
2786 if default or id:
2788 if default or id:
2787 output = ["%s%s" % ('+'.join(hexoutput), dirty)]
2789 output = ["%s%s" % ('+'.join(hexoutput), dirty)]
2788 fm.data(id="%s%s" % ('+'.join(hexoutput), dirty))
2790 fm.data(id="%s%s" % ('+'.join(hexoutput), dirty))
2789
2791
2790 if num:
2792 if num:
2791 numoutput = ["%d" % p.rev() for p in parents]
2793 numoutput = ["%d" % p.rev() for p in parents]
2792 output.append("%s%s" % ('+'.join(numoutput), dirty))
2794 output.append("%s%s" % ('+'.join(numoutput), dirty))
2793
2795
2794 fn = fm.nested('parents')
2796 fn = fm.nested('parents')
2795 for p in parents:
2797 for p in parents:
2796 fn.startitem()
2798 fn.startitem()
2797 fn.data(rev=p.rev())
2799 fn.data(rev=p.rev())
2798 fn.data(node=p.hex())
2800 fn.data(node=p.hex())
2799 fn.context(ctx=p)
2801 fn.context(ctx=p)
2800 fn.end()
2802 fn.end()
2801 else:
2803 else:
2802 hexoutput = hexfunc(ctx.node())
2804 hexoutput = hexfunc(ctx.node())
2803 if default or id:
2805 if default or id:
2804 output = [hexoutput]
2806 output = [hexoutput]
2805 fm.data(id=hexoutput)
2807 fm.data(id=hexoutput)
2806
2808
2807 if num:
2809 if num:
2808 output.append(pycompat.bytestr(ctx.rev()))
2810 output.append(pycompat.bytestr(ctx.rev()))
2809 taglist = ctx.tags()
2811 taglist = ctx.tags()
2810
2812
2811 if default and not ui.quiet:
2813 if default and not ui.quiet:
2812 b = ctx.branch()
2814 b = ctx.branch()
2813 if b != 'default':
2815 if b != 'default':
2814 output.append("(%s)" % b)
2816 output.append("(%s)" % b)
2815
2817
2816 # multiple tags for a single parent separated by '/'
2818 # multiple tags for a single parent separated by '/'
2817 t = '/'.join(taglist)
2819 t = '/'.join(taglist)
2818 if t:
2820 if t:
2819 output.append(t)
2821 output.append(t)
2820
2822
2821 # multiple bookmarks for a single parent separated by '/'
2823 # multiple bookmarks for a single parent separated by '/'
2822 bm = '/'.join(ctx.bookmarks())
2824 bm = '/'.join(ctx.bookmarks())
2823 if bm:
2825 if bm:
2824 output.append(bm)
2826 output.append(bm)
2825 else:
2827 else:
2826 if branch:
2828 if branch:
2827 output.append(ctx.branch())
2829 output.append(ctx.branch())
2828
2830
2829 if tags:
2831 if tags:
2830 output.extend(taglist)
2832 output.extend(taglist)
2831
2833
2832 if bookmarks:
2834 if bookmarks:
2833 output.extend(ctx.bookmarks())
2835 output.extend(ctx.bookmarks())
2834
2836
2835 fm.data(node=ctx.hex())
2837 fm.data(node=ctx.hex())
2836 fm.data(branch=ctx.branch())
2838 fm.data(branch=ctx.branch())
2837 fm.data(tags=fm.formatlist(taglist, name='tag', sep=':'))
2839 fm.data(tags=fm.formatlist(taglist, name='tag', sep=':'))
2838 fm.data(bookmarks=fm.formatlist(ctx.bookmarks(), name='bookmark'))
2840 fm.data(bookmarks=fm.formatlist(ctx.bookmarks(), name='bookmark'))
2839 fm.context(ctx=ctx)
2841 fm.context(ctx=ctx)
2840
2842
2841 fm.plain("%s\n" % ' '.join(output))
2843 fm.plain("%s\n" % ' '.join(output))
2842 fm.end()
2844 fm.end()
2843
2845
2844 @command('import|patch',
2846 @command('import|patch',
2845 [('p', 'strip', 1,
2847 [('p', 'strip', 1,
2846 _('directory strip option for patch. This has the same '
2848 _('directory strip option for patch. This has the same '
2847 'meaning as the corresponding patch option'), _('NUM')),
2849 'meaning as the corresponding patch option'), _('NUM')),
2848 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
2850 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
2849 ('e', 'edit', False, _('invoke editor on commit messages')),
2851 ('e', 'edit', False, _('invoke editor on commit messages')),
2850 ('f', 'force', None,
2852 ('f', 'force', None,
2851 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
2853 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
2852 ('', 'no-commit', None,
2854 ('', 'no-commit', None,
2853 _("don't commit, just update the working directory")),
2855 _("don't commit, just update the working directory")),
2854 ('', 'bypass', None,
2856 ('', 'bypass', None,
2855 _("apply patch without touching the working directory")),
2857 _("apply patch without touching the working directory")),
2856 ('', 'partial', None,
2858 ('', 'partial', None,
2857 _('commit even if some hunks fail')),
2859 _('commit even if some hunks fail')),
2858 ('', 'exact', None,
2860 ('', 'exact', None,
2859 _('abort if patch would apply lossily')),
2861 _('abort if patch would apply lossily')),
2860 ('', 'prefix', '',
2862 ('', 'prefix', '',
2861 _('apply patch to subdirectory'), _('DIR')),
2863 _('apply patch to subdirectory'), _('DIR')),
2862 ('', 'import-branch', None,
2864 ('', 'import-branch', None,
2863 _('use any branch information in patch (implied by --exact)'))] +
2865 _('use any branch information in patch (implied by --exact)'))] +
2864 commitopts + commitopts2 + similarityopts,
2866 commitopts + commitopts2 + similarityopts,
2865 _('[OPTION]... PATCH...'))
2867 _('[OPTION]... PATCH...'))
2866 def import_(ui, repo, patch1=None, *patches, **opts):
2868 def import_(ui, repo, patch1=None, *patches, **opts):
2867 """import an ordered set of patches
2869 """import an ordered set of patches
2868
2870
2869 Import a list of patches and commit them individually (unless
2871 Import a list of patches and commit them individually (unless
2870 --no-commit is specified).
2872 --no-commit is specified).
2871
2873
2872 To read a patch from standard input (stdin), use "-" as the patch
2874 To read a patch from standard input (stdin), use "-" as the patch
2873 name. If a URL is specified, the patch will be downloaded from
2875 name. If a URL is specified, the patch will be downloaded from
2874 there.
2876 there.
2875
2877
2876 Import first applies changes to the working directory (unless
2878 Import first applies changes to the working directory (unless
2877 --bypass is specified), import will abort if there are outstanding
2879 --bypass is specified), import will abort if there are outstanding
2878 changes.
2880 changes.
2879
2881
2880 Use --bypass to apply and commit patches directly to the
2882 Use --bypass to apply and commit patches directly to the
2881 repository, without affecting the working directory. Without
2883 repository, without affecting the working directory. Without
2882 --exact, patches will be applied on top of the working directory
2884 --exact, patches will be applied on top of the working directory
2883 parent revision.
2885 parent revision.
2884
2886
2885 You can import a patch straight from a mail message. Even patches
2887 You can import a patch straight from a mail message. Even patches
2886 as attachments work (to use the body part, it must have type
2888 as attachments work (to use the body part, it must have type
2887 text/plain or text/x-patch). From and Subject headers of email
2889 text/plain or text/x-patch). From and Subject headers of email
2888 message are used as default committer and commit message. All
2890 message are used as default committer and commit message. All
2889 text/plain body parts before first diff are added to the commit
2891 text/plain body parts before first diff are added to the commit
2890 message.
2892 message.
2891
2893
2892 If the imported patch was generated by :hg:`export`, user and
2894 If the imported patch was generated by :hg:`export`, user and
2893 description from patch override values from message headers and
2895 description from patch override values from message headers and
2894 body. Values given on command line with -m/--message and -u/--user
2896 body. Values given on command line with -m/--message and -u/--user
2895 override these.
2897 override these.
2896
2898
2897 If --exact is specified, import will set the working directory to
2899 If --exact is specified, import will set the working directory to
2898 the parent of each patch before applying it, and will abort if the
2900 the parent of each patch before applying it, and will abort if the
2899 resulting changeset has a different ID than the one recorded in
2901 resulting changeset has a different ID than the one recorded in
2900 the patch. This will guard against various ways that portable
2902 the patch. This will guard against various ways that portable
2901 patch formats and mail systems might fail to transfer Mercurial
2903 patch formats and mail systems might fail to transfer Mercurial
2902 data or metadata. See :hg:`bundle` for lossless transmission.
2904 data or metadata. See :hg:`bundle` for lossless transmission.
2903
2905
2904 Use --partial to ensure a changeset will be created from the patch
2906 Use --partial to ensure a changeset will be created from the patch
2905 even if some hunks fail to apply. Hunks that fail to apply will be
2907 even if some hunks fail to apply. Hunks that fail to apply will be
2906 written to a <target-file>.rej file. Conflicts can then be resolved
2908 written to a <target-file>.rej file. Conflicts can then be resolved
2907 by hand before :hg:`commit --amend` is run to update the created
2909 by hand before :hg:`commit --amend` is run to update the created
2908 changeset. This flag exists to let people import patches that
2910 changeset. This flag exists to let people import patches that
2909 partially apply without losing the associated metadata (author,
2911 partially apply without losing the associated metadata (author,
2910 date, description, ...).
2912 date, description, ...).
2911
2913
2912 .. note::
2914 .. note::
2913
2915
2914 When no hunks apply cleanly, :hg:`import --partial` will create
2916 When no hunks apply cleanly, :hg:`import --partial` will create
2915 an empty changeset, importing only the patch metadata.
2917 an empty changeset, importing only the patch metadata.
2916
2918
2917 With -s/--similarity, hg will attempt to discover renames and
2919 With -s/--similarity, hg will attempt to discover renames and
2918 copies in the patch in the same way as :hg:`addremove`.
2920 copies in the patch in the same way as :hg:`addremove`.
2919
2921
2920 It is possible to use external patch programs to perform the patch
2922 It is possible to use external patch programs to perform the patch
2921 by setting the ``ui.patch`` configuration option. For the default
2923 by setting the ``ui.patch`` configuration option. For the default
2922 internal tool, the fuzz can also be configured via ``patch.fuzz``.
2924 internal tool, the fuzz can also be configured via ``patch.fuzz``.
2923 See :hg:`help config` for more information about configuration
2925 See :hg:`help config` for more information about configuration
2924 files and how to use these options.
2926 files and how to use these options.
2925
2927
2926 See :hg:`help dates` for a list of formats valid for -d/--date.
2928 See :hg:`help dates` for a list of formats valid for -d/--date.
2927
2929
2928 .. container:: verbose
2930 .. container:: verbose
2929
2931
2930 Examples:
2932 Examples:
2931
2933
2932 - import a traditional patch from a website and detect renames::
2934 - import a traditional patch from a website and detect renames::
2933
2935
2934 hg import -s 80 http://example.com/bugfix.patch
2936 hg import -s 80 http://example.com/bugfix.patch
2935
2937
2936 - import a changeset from an hgweb server::
2938 - import a changeset from an hgweb server::
2937
2939
2938 hg import https://www.mercurial-scm.org/repo/hg/rev/5ca8c111e9aa
2940 hg import https://www.mercurial-scm.org/repo/hg/rev/5ca8c111e9aa
2939
2941
2940 - import all the patches in an Unix-style mbox::
2942 - import all the patches in an Unix-style mbox::
2941
2943
2942 hg import incoming-patches.mbox
2944 hg import incoming-patches.mbox
2943
2945
2944 - import patches from stdin::
2946 - import patches from stdin::
2945
2947
2946 hg import -
2948 hg import -
2947
2949
2948 - attempt to exactly restore an exported changeset (not always
2950 - attempt to exactly restore an exported changeset (not always
2949 possible)::
2951 possible)::
2950
2952
2951 hg import --exact proposed-fix.patch
2953 hg import --exact proposed-fix.patch
2952
2954
2953 - use an external tool to apply a patch which is too fuzzy for
2955 - use an external tool to apply a patch which is too fuzzy for
2954 the default internal tool.
2956 the default internal tool.
2955
2957
2956 hg import --config ui.patch="patch --merge" fuzzy.patch
2958 hg import --config ui.patch="patch --merge" fuzzy.patch
2957
2959
2958 - change the default fuzzing from 2 to a less strict 7
2960 - change the default fuzzing from 2 to a less strict 7
2959
2961
2960 hg import --config ui.fuzz=7 fuzz.patch
2962 hg import --config ui.fuzz=7 fuzz.patch
2961
2963
2962 Returns 0 on success, 1 on partial success (see --partial).
2964 Returns 0 on success, 1 on partial success (see --partial).
2963 """
2965 """
2964
2966
2965 opts = pycompat.byteskwargs(opts)
2967 opts = pycompat.byteskwargs(opts)
2966 if not patch1:
2968 if not patch1:
2967 raise error.Abort(_('need at least one patch to import'))
2969 raise error.Abort(_('need at least one patch to import'))
2968
2970
2969 patches = (patch1,) + patches
2971 patches = (patch1,) + patches
2970
2972
2971 date = opts.get('date')
2973 date = opts.get('date')
2972 if date:
2974 if date:
2973 opts['date'] = util.parsedate(date)
2975 opts['date'] = util.parsedate(date)
2974
2976
2975 exact = opts.get('exact')
2977 exact = opts.get('exact')
2976 update = not opts.get('bypass')
2978 update = not opts.get('bypass')
2977 if not update and opts.get('no_commit'):
2979 if not update and opts.get('no_commit'):
2978 raise error.Abort(_('cannot use --no-commit with --bypass'))
2980 raise error.Abort(_('cannot use --no-commit with --bypass'))
2979 try:
2981 try:
2980 sim = float(opts.get('similarity') or 0)
2982 sim = float(opts.get('similarity') or 0)
2981 except ValueError:
2983 except ValueError:
2982 raise error.Abort(_('similarity must be a number'))
2984 raise error.Abort(_('similarity must be a number'))
2983 if sim < 0 or sim > 100:
2985 if sim < 0 or sim > 100:
2984 raise error.Abort(_('similarity must be between 0 and 100'))
2986 raise error.Abort(_('similarity must be between 0 and 100'))
2985 if sim and not update:
2987 if sim and not update:
2986 raise error.Abort(_('cannot use --similarity with --bypass'))
2988 raise error.Abort(_('cannot use --similarity with --bypass'))
2987 if exact:
2989 if exact:
2988 if opts.get('edit'):
2990 if opts.get('edit'):
2989 raise error.Abort(_('cannot use --exact with --edit'))
2991 raise error.Abort(_('cannot use --exact with --edit'))
2990 if opts.get('prefix'):
2992 if opts.get('prefix'):
2991 raise error.Abort(_('cannot use --exact with --prefix'))
2993 raise error.Abort(_('cannot use --exact with --prefix'))
2992
2994
2993 base = opts["base"]
2995 base = opts["base"]
2994 wlock = dsguard = lock = tr = None
2996 wlock = dsguard = lock = tr = None
2995 msgs = []
2997 msgs = []
2996 ret = 0
2998 ret = 0
2997
2999
2998
3000
2999 try:
3001 try:
3000 wlock = repo.wlock()
3002 wlock = repo.wlock()
3001
3003
3002 if update:
3004 if update:
3003 cmdutil.checkunfinished(repo)
3005 cmdutil.checkunfinished(repo)
3004 if (exact or not opts.get('force')):
3006 if (exact or not opts.get('force')):
3005 cmdutil.bailifchanged(repo)
3007 cmdutil.bailifchanged(repo)
3006
3008
3007 if not opts.get('no_commit'):
3009 if not opts.get('no_commit'):
3008 lock = repo.lock()
3010 lock = repo.lock()
3009 tr = repo.transaction('import')
3011 tr = repo.transaction('import')
3010 else:
3012 else:
3011 dsguard = dirstateguard.dirstateguard(repo, 'import')
3013 dsguard = dirstateguard.dirstateguard(repo, 'import')
3012 parents = repo[None].parents()
3014 parents = repo[None].parents()
3013 for patchurl in patches:
3015 for patchurl in patches:
3014 if patchurl == '-':
3016 if patchurl == '-':
3015 ui.status(_('applying patch from stdin\n'))
3017 ui.status(_('applying patch from stdin\n'))
3016 patchfile = ui.fin
3018 patchfile = ui.fin
3017 patchurl = 'stdin' # for error message
3019 patchurl = 'stdin' # for error message
3018 else:
3020 else:
3019 patchurl = os.path.join(base, patchurl)
3021 patchurl = os.path.join(base, patchurl)
3020 ui.status(_('applying %s\n') % patchurl)
3022 ui.status(_('applying %s\n') % patchurl)
3021 patchfile = hg.openpath(ui, patchurl)
3023 patchfile = hg.openpath(ui, patchurl)
3022
3024
3023 haspatch = False
3025 haspatch = False
3024 for hunk in patch.split(patchfile):
3026 for hunk in patch.split(patchfile):
3025 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
3027 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
3026 parents, opts,
3028 parents, opts,
3027 msgs, hg.clean)
3029 msgs, hg.clean)
3028 if msg:
3030 if msg:
3029 haspatch = True
3031 haspatch = True
3030 ui.note(msg + '\n')
3032 ui.note(msg + '\n')
3031 if update or exact:
3033 if update or exact:
3032 parents = repo[None].parents()
3034 parents = repo[None].parents()
3033 else:
3035 else:
3034 parents = [repo[node]]
3036 parents = [repo[node]]
3035 if rej:
3037 if rej:
3036 ui.write_err(_("patch applied partially\n"))
3038 ui.write_err(_("patch applied partially\n"))
3037 ui.write_err(_("(fix the .rej files and run "
3039 ui.write_err(_("(fix the .rej files and run "
3038 "`hg commit --amend`)\n"))
3040 "`hg commit --amend`)\n"))
3039 ret = 1
3041 ret = 1
3040 break
3042 break
3041
3043
3042 if not haspatch:
3044 if not haspatch:
3043 raise error.Abort(_('%s: no diffs found') % patchurl)
3045 raise error.Abort(_('%s: no diffs found') % patchurl)
3044
3046
3045 if tr:
3047 if tr:
3046 tr.close()
3048 tr.close()
3047 if msgs:
3049 if msgs:
3048 repo.savecommitmessage('\n* * *\n'.join(msgs))
3050 repo.savecommitmessage('\n* * *\n'.join(msgs))
3049 if dsguard:
3051 if dsguard:
3050 dsguard.close()
3052 dsguard.close()
3051 return ret
3053 return ret
3052 finally:
3054 finally:
3053 if tr:
3055 if tr:
3054 tr.release()
3056 tr.release()
3055 release(lock, dsguard, wlock)
3057 release(lock, dsguard, wlock)
3056
3058
3057 @command('incoming|in',
3059 @command('incoming|in',
3058 [('f', 'force', None,
3060 [('f', 'force', None,
3059 _('run even if remote repository is unrelated')),
3061 _('run even if remote repository is unrelated')),
3060 ('n', 'newest-first', None, _('show newest record first')),
3062 ('n', 'newest-first', None, _('show newest record first')),
3061 ('', 'bundle', '',
3063 ('', 'bundle', '',
3062 _('file to store the bundles into'), _('FILE')),
3064 _('file to store the bundles into'), _('FILE')),
3063 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3065 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3064 ('B', 'bookmarks', False, _("compare bookmarks")),
3066 ('B', 'bookmarks', False, _("compare bookmarks")),
3065 ('b', 'branch', [],
3067 ('b', 'branch', [],
3066 _('a specific branch you would like to pull'), _('BRANCH')),
3068 _('a specific branch you would like to pull'), _('BRANCH')),
3067 ] + logopts + remoteopts + subrepoopts,
3069 ] + logopts + remoteopts + subrepoopts,
3068 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3070 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3069 def incoming(ui, repo, source="default", **opts):
3071 def incoming(ui, repo, source="default", **opts):
3070 """show new changesets found in source
3072 """show new changesets found in source
3071
3073
3072 Show new changesets found in the specified path/URL or the default
3074 Show new changesets found in the specified path/URL or the default
3073 pull location. These are the changesets that would have been pulled
3075 pull location. These are the changesets that would have been pulled
3074 by :hg:`pull` at the time you issued this command.
3076 by :hg:`pull` at the time you issued this command.
3075
3077
3076 See pull for valid source format details.
3078 See pull for valid source format details.
3077
3079
3078 .. container:: verbose
3080 .. container:: verbose
3079
3081
3080 With -B/--bookmarks, the result of bookmark comparison between
3082 With -B/--bookmarks, the result of bookmark comparison between
3081 local and remote repositories is displayed. With -v/--verbose,
3083 local and remote repositories is displayed. With -v/--verbose,
3082 status is also displayed for each bookmark like below::
3084 status is also displayed for each bookmark like below::
3083
3085
3084 BM1 01234567890a added
3086 BM1 01234567890a added
3085 BM2 1234567890ab advanced
3087 BM2 1234567890ab advanced
3086 BM3 234567890abc diverged
3088 BM3 234567890abc diverged
3087 BM4 34567890abcd changed
3089 BM4 34567890abcd changed
3088
3090
3089 The action taken locally when pulling depends on the
3091 The action taken locally when pulling depends on the
3090 status of each bookmark:
3092 status of each bookmark:
3091
3093
3092 :``added``: pull will create it
3094 :``added``: pull will create it
3093 :``advanced``: pull will update it
3095 :``advanced``: pull will update it
3094 :``diverged``: pull will create a divergent bookmark
3096 :``diverged``: pull will create a divergent bookmark
3095 :``changed``: result depends on remote changesets
3097 :``changed``: result depends on remote changesets
3096
3098
3097 From the point of view of pulling behavior, bookmark
3099 From the point of view of pulling behavior, bookmark
3098 existing only in the remote repository are treated as ``added``,
3100 existing only in the remote repository are treated as ``added``,
3099 even if it is in fact locally deleted.
3101 even if it is in fact locally deleted.
3100
3102
3101 .. container:: verbose
3103 .. container:: verbose
3102
3104
3103 For remote repository, using --bundle avoids downloading the
3105 For remote repository, using --bundle avoids downloading the
3104 changesets twice if the incoming is followed by a pull.
3106 changesets twice if the incoming is followed by a pull.
3105
3107
3106 Examples:
3108 Examples:
3107
3109
3108 - show incoming changes with patches and full description::
3110 - show incoming changes with patches and full description::
3109
3111
3110 hg incoming -vp
3112 hg incoming -vp
3111
3113
3112 - show incoming changes excluding merges, store a bundle::
3114 - show incoming changes excluding merges, store a bundle::
3113
3115
3114 hg in -vpM --bundle incoming.hg
3116 hg in -vpM --bundle incoming.hg
3115 hg pull incoming.hg
3117 hg pull incoming.hg
3116
3118
3117 - briefly list changes inside a bundle::
3119 - briefly list changes inside a bundle::
3118
3120
3119 hg in changes.hg -T "{desc|firstline}\\n"
3121 hg in changes.hg -T "{desc|firstline}\\n"
3120
3122
3121 Returns 0 if there are incoming changes, 1 otherwise.
3123 Returns 0 if there are incoming changes, 1 otherwise.
3122 """
3124 """
3123 opts = pycompat.byteskwargs(opts)
3125 opts = pycompat.byteskwargs(opts)
3124 if opts.get('graph'):
3126 if opts.get('graph'):
3125 cmdutil.checkunsupportedgraphflags([], opts)
3127 cmdutil.checkunsupportedgraphflags([], opts)
3126 def display(other, chlist, displayer):
3128 def display(other, chlist, displayer):
3127 revdag = cmdutil.graphrevs(other, chlist, opts)
3129 revdag = cmdutil.graphrevs(other, chlist, opts)
3128 cmdutil.displaygraph(ui, repo, revdag, displayer,
3130 cmdutil.displaygraph(ui, repo, revdag, displayer,
3129 graphmod.asciiedges)
3131 graphmod.asciiedges)
3130
3132
3131 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3133 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3132 return 0
3134 return 0
3133
3135
3134 if opts.get('bundle') and opts.get('subrepos'):
3136 if opts.get('bundle') and opts.get('subrepos'):
3135 raise error.Abort(_('cannot combine --bundle and --subrepos'))
3137 raise error.Abort(_('cannot combine --bundle and --subrepos'))
3136
3138
3137 if opts.get('bookmarks'):
3139 if opts.get('bookmarks'):
3138 source, branches = hg.parseurl(ui.expandpath(source),
3140 source, branches = hg.parseurl(ui.expandpath(source),
3139 opts.get('branch'))
3141 opts.get('branch'))
3140 other = hg.peer(repo, opts, source)
3142 other = hg.peer(repo, opts, source)
3141 if 'bookmarks' not in other.listkeys('namespaces'):
3143 if 'bookmarks' not in other.listkeys('namespaces'):
3142 ui.warn(_("remote doesn't support bookmarks\n"))
3144 ui.warn(_("remote doesn't support bookmarks\n"))
3143 return 0
3145 return 0
3144 ui.pager('incoming')
3146 ui.pager('incoming')
3145 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3147 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3146 return bookmarks.incoming(ui, repo, other)
3148 return bookmarks.incoming(ui, repo, other)
3147
3149
3148 repo._subtoppath = ui.expandpath(source)
3150 repo._subtoppath = ui.expandpath(source)
3149 try:
3151 try:
3150 return hg.incoming(ui, repo, source, opts)
3152 return hg.incoming(ui, repo, source, opts)
3151 finally:
3153 finally:
3152 del repo._subtoppath
3154 del repo._subtoppath
3153
3155
3154
3156
3155 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
3157 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
3156 norepo=True)
3158 norepo=True)
3157 def init(ui, dest=".", **opts):
3159 def init(ui, dest=".", **opts):
3158 """create a new repository in the given directory
3160 """create a new repository in the given directory
3159
3161
3160 Initialize a new repository in the given directory. If the given
3162 Initialize a new repository in the given directory. If the given
3161 directory does not exist, it will be created.
3163 directory does not exist, it will be created.
3162
3164
3163 If no directory is given, the current directory is used.
3165 If no directory is given, the current directory is used.
3164
3166
3165 It is possible to specify an ``ssh://`` URL as the destination.
3167 It is possible to specify an ``ssh://`` URL as the destination.
3166 See :hg:`help urls` for more information.
3168 See :hg:`help urls` for more information.
3167
3169
3168 Returns 0 on success.
3170 Returns 0 on success.
3169 """
3171 """
3170 opts = pycompat.byteskwargs(opts)
3172 opts = pycompat.byteskwargs(opts)
3171 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3173 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3172
3174
3173 @command('locate',
3175 @command('locate',
3174 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3176 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3175 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3177 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3176 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3178 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3177 ] + walkopts,
3179 ] + walkopts,
3178 _('[OPTION]... [PATTERN]...'))
3180 _('[OPTION]... [PATTERN]...'))
3179 def locate(ui, repo, *pats, **opts):
3181 def locate(ui, repo, *pats, **opts):
3180 """locate files matching specific patterns (DEPRECATED)
3182 """locate files matching specific patterns (DEPRECATED)
3181
3183
3182 Print files under Mercurial control in the working directory whose
3184 Print files under Mercurial control in the working directory whose
3183 names match the given patterns.
3185 names match the given patterns.
3184
3186
3185 By default, this command searches all directories in the working
3187 By default, this command searches all directories in the working
3186 directory. To search just the current directory and its
3188 directory. To search just the current directory and its
3187 subdirectories, use "--include .".
3189 subdirectories, use "--include .".
3188
3190
3189 If no patterns are given to match, this command prints the names
3191 If no patterns are given to match, this command prints the names
3190 of all files under Mercurial control in the working directory.
3192 of all files under Mercurial control in the working directory.
3191
3193
3192 If you want to feed the output of this command into the "xargs"
3194 If you want to feed the output of this command into the "xargs"
3193 command, use the -0 option to both this command and "xargs". This
3195 command, use the -0 option to both this command and "xargs". This
3194 will avoid the problem of "xargs" treating single filenames that
3196 will avoid the problem of "xargs" treating single filenames that
3195 contain whitespace as multiple filenames.
3197 contain whitespace as multiple filenames.
3196
3198
3197 See :hg:`help files` for a more versatile command.
3199 See :hg:`help files` for a more versatile command.
3198
3200
3199 Returns 0 if a match is found, 1 otherwise.
3201 Returns 0 if a match is found, 1 otherwise.
3200 """
3202 """
3201 opts = pycompat.byteskwargs(opts)
3203 opts = pycompat.byteskwargs(opts)
3202 if opts.get('print0'):
3204 if opts.get('print0'):
3203 end = '\0'
3205 end = '\0'
3204 else:
3206 else:
3205 end = '\n'
3207 end = '\n'
3206 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3208 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3207
3209
3208 ret = 1
3210 ret = 1
3209 ctx = repo[rev]
3211 ctx = repo[rev]
3210 m = scmutil.match(ctx, pats, opts, default='relglob',
3212 m = scmutil.match(ctx, pats, opts, default='relglob',
3211 badfn=lambda x, y: False)
3213 badfn=lambda x, y: False)
3212
3214
3213 ui.pager('locate')
3215 ui.pager('locate')
3214 for abs in ctx.matches(m):
3216 for abs in ctx.matches(m):
3215 if opts.get('fullpath'):
3217 if opts.get('fullpath'):
3216 ui.write(repo.wjoin(abs), end)
3218 ui.write(repo.wjoin(abs), end)
3217 else:
3219 else:
3218 ui.write(((pats and m.rel(abs)) or abs), end)
3220 ui.write(((pats and m.rel(abs)) or abs), end)
3219 ret = 0
3221 ret = 0
3220
3222
3221 return ret
3223 return ret
3222
3224
3223 @command('^log|history',
3225 @command('^log|history',
3224 [('f', 'follow', None,
3226 [('f', 'follow', None,
3225 _('follow changeset history, or file history across copies and renames')),
3227 _('follow changeset history, or file history across copies and renames')),
3226 ('', 'follow-first', None,
3228 ('', 'follow-first', None,
3227 _('only follow the first parent of merge changesets (DEPRECATED)')),
3229 _('only follow the first parent of merge changesets (DEPRECATED)')),
3228 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3230 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3229 ('C', 'copies', None, _('show copied files')),
3231 ('C', 'copies', None, _('show copied files')),
3230 ('k', 'keyword', [],
3232 ('k', 'keyword', [],
3231 _('do case-insensitive search for a given text'), _('TEXT')),
3233 _('do case-insensitive search for a given text'), _('TEXT')),
3232 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
3234 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
3233 ('L', 'line-range', [],
3235 ('L', 'line-range', [],
3234 _('follow line range of specified file (EXPERIMENTAL)'),
3236 _('follow line range of specified file (EXPERIMENTAL)'),
3235 _('FILE,RANGE')),
3237 _('FILE,RANGE')),
3236 ('', 'removed', None, _('include revisions where files were removed')),
3238 ('', 'removed', None, _('include revisions where files were removed')),
3237 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3239 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3238 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3240 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3239 ('', 'only-branch', [],
3241 ('', 'only-branch', [],
3240 _('show only changesets within the given named branch (DEPRECATED)'),
3242 _('show only changesets within the given named branch (DEPRECATED)'),
3241 _('BRANCH')),
3243 _('BRANCH')),
3242 ('b', 'branch', [],
3244 ('b', 'branch', [],
3243 _('show changesets within the given named branch'), _('BRANCH')),
3245 _('show changesets within the given named branch'), _('BRANCH')),
3244 ('P', 'prune', [],
3246 ('P', 'prune', [],
3245 _('do not display revision or any of its ancestors'), _('REV')),
3247 _('do not display revision or any of its ancestors'), _('REV')),
3246 ] + logopts + walkopts,
3248 ] + logopts + walkopts,
3247 _('[OPTION]... [FILE]'),
3249 _('[OPTION]... [FILE]'),
3248 inferrepo=True, cmdtype=readonly)
3250 inferrepo=True, cmdtype=readonly)
3249 def log(ui, repo, *pats, **opts):
3251 def log(ui, repo, *pats, **opts):
3250 """show revision history of entire repository or files
3252 """show revision history of entire repository or files
3251
3253
3252 Print the revision history of the specified files or the entire
3254 Print the revision history of the specified files or the entire
3253 project.
3255 project.
3254
3256
3255 If no revision range is specified, the default is ``tip:0`` unless
3257 If no revision range is specified, the default is ``tip:0`` unless
3256 --follow is set, in which case the working directory parent is
3258 --follow is set, in which case the working directory parent is
3257 used as the starting revision.
3259 used as the starting revision.
3258
3260
3259 File history is shown without following rename or copy history of
3261 File history is shown without following rename or copy history of
3260 files. Use -f/--follow with a filename to follow history across
3262 files. Use -f/--follow with a filename to follow history across
3261 renames and copies. --follow without a filename will only show
3263 renames and copies. --follow without a filename will only show
3262 ancestors or descendants of the starting revision.
3264 ancestors or descendants of the starting revision.
3263
3265
3264 By default this command prints revision number and changeset id,
3266 By default this command prints revision number and changeset id,
3265 tags, non-trivial parents, user, date and time, and a summary for
3267 tags, non-trivial parents, user, date and time, and a summary for
3266 each commit. When the -v/--verbose switch is used, the list of
3268 each commit. When the -v/--verbose switch is used, the list of
3267 changed files and full commit message are shown.
3269 changed files and full commit message are shown.
3268
3270
3269 With --graph the revisions are shown as an ASCII art DAG with the most
3271 With --graph the revisions are shown as an ASCII art DAG with the most
3270 recent changeset at the top.
3272 recent changeset at the top.
3271 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
3273 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
3272 and '+' represents a fork where the changeset from the lines below is a
3274 and '+' represents a fork where the changeset from the lines below is a
3273 parent of the 'o' merge on the same line.
3275 parent of the 'o' merge on the same line.
3274 Paths in the DAG are represented with '|', '/' and so forth. ':' in place
3276 Paths in the DAG are represented with '|', '/' and so forth. ':' in place
3275 of a '|' indicates one or more revisions in a path are omitted.
3277 of a '|' indicates one or more revisions in a path are omitted.
3276
3278
3277 .. container:: verbose
3279 .. container:: verbose
3278
3280
3279 Use -L/--line-range FILE,M:N options to follow the history of lines
3281 Use -L/--line-range FILE,M:N options to follow the history of lines
3280 from M to N in FILE. With -p/--patch only diff hunks affecting
3282 from M to N in FILE. With -p/--patch only diff hunks affecting
3281 specified line range will be shown. This option requires --follow;
3283 specified line range will be shown. This option requires --follow;
3282 it can be specified multiple times. Currently, this option is not
3284 it can be specified multiple times. Currently, this option is not
3283 compatible with --graph. This option is experimental.
3285 compatible with --graph. This option is experimental.
3284
3286
3285 .. note::
3287 .. note::
3286
3288
3287 :hg:`log --patch` may generate unexpected diff output for merge
3289 :hg:`log --patch` may generate unexpected diff output for merge
3288 changesets, as it will only compare the merge changeset against
3290 changesets, as it will only compare the merge changeset against
3289 its first parent. Also, only files different from BOTH parents
3291 its first parent. Also, only files different from BOTH parents
3290 will appear in files:.
3292 will appear in files:.
3291
3293
3292 .. note::
3294 .. note::
3293
3295
3294 For performance reasons, :hg:`log FILE` may omit duplicate changes
3296 For performance reasons, :hg:`log FILE` may omit duplicate changes
3295 made on branches and will not show removals or mode changes. To
3297 made on branches and will not show removals or mode changes. To
3296 see all such changes, use the --removed switch.
3298 see all such changes, use the --removed switch.
3297
3299
3298 .. container:: verbose
3300 .. container:: verbose
3299
3301
3300 .. note::
3302 .. note::
3301
3303
3302 The history resulting from -L/--line-range options depends on diff
3304 The history resulting from -L/--line-range options depends on diff
3303 options; for instance if white-spaces are ignored, respective changes
3305 options; for instance if white-spaces are ignored, respective changes
3304 with only white-spaces in specified line range will not be listed.
3306 with only white-spaces in specified line range will not be listed.
3305
3307
3306 .. container:: verbose
3308 .. container:: verbose
3307
3309
3308 Some examples:
3310 Some examples:
3309
3311
3310 - changesets with full descriptions and file lists::
3312 - changesets with full descriptions and file lists::
3311
3313
3312 hg log -v
3314 hg log -v
3313
3315
3314 - changesets ancestral to the working directory::
3316 - changesets ancestral to the working directory::
3315
3317
3316 hg log -f
3318 hg log -f
3317
3319
3318 - last 10 commits on the current branch::
3320 - last 10 commits on the current branch::
3319
3321
3320 hg log -l 10 -b .
3322 hg log -l 10 -b .
3321
3323
3322 - changesets showing all modifications of a file, including removals::
3324 - changesets showing all modifications of a file, including removals::
3323
3325
3324 hg log --removed file.c
3326 hg log --removed file.c
3325
3327
3326 - all changesets that touch a directory, with diffs, excluding merges::
3328 - all changesets that touch a directory, with diffs, excluding merges::
3327
3329
3328 hg log -Mp lib/
3330 hg log -Mp lib/
3329
3331
3330 - all revision numbers that match a keyword::
3332 - all revision numbers that match a keyword::
3331
3333
3332 hg log -k bug --template "{rev}\\n"
3334 hg log -k bug --template "{rev}\\n"
3333
3335
3334 - the full hash identifier of the working directory parent::
3336 - the full hash identifier of the working directory parent::
3335
3337
3336 hg log -r . --template "{node}\\n"
3338 hg log -r . --template "{node}\\n"
3337
3339
3338 - list available log templates::
3340 - list available log templates::
3339
3341
3340 hg log -T list
3342 hg log -T list
3341
3343
3342 - check if a given changeset is included in a tagged release::
3344 - check if a given changeset is included in a tagged release::
3343
3345
3344 hg log -r "a21ccf and ancestor(1.9)"
3346 hg log -r "a21ccf and ancestor(1.9)"
3345
3347
3346 - find all changesets by some user in a date range::
3348 - find all changesets by some user in a date range::
3347
3349
3348 hg log -k alice -d "may 2008 to jul 2008"
3350 hg log -k alice -d "may 2008 to jul 2008"
3349
3351
3350 - summary of all changesets after the last tag::
3352 - summary of all changesets after the last tag::
3351
3353
3352 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3354 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3353
3355
3354 - changesets touching lines 13 to 23 for file.c::
3356 - changesets touching lines 13 to 23 for file.c::
3355
3357
3356 hg log -L file.c,13:23
3358 hg log -L file.c,13:23
3357
3359
3358 - changesets touching lines 13 to 23 for file.c and lines 2 to 6 of
3360 - changesets touching lines 13 to 23 for file.c and lines 2 to 6 of
3359 main.c with patch::
3361 main.c with patch::
3360
3362
3361 hg log -L file.c,13:23 -L main.c,2:6 -p
3363 hg log -L file.c,13:23 -L main.c,2:6 -p
3362
3364
3363 See :hg:`help dates` for a list of formats valid for -d/--date.
3365 See :hg:`help dates` for a list of formats valid for -d/--date.
3364
3366
3365 See :hg:`help revisions` for more about specifying and ordering
3367 See :hg:`help revisions` for more about specifying and ordering
3366 revisions.
3368 revisions.
3367
3369
3368 See :hg:`help templates` for more about pre-packaged styles and
3370 See :hg:`help templates` for more about pre-packaged styles and
3369 specifying custom templates. The default template used by the log
3371 specifying custom templates. The default template used by the log
3370 command can be customized via the ``ui.logtemplate`` configuration
3372 command can be customized via the ``ui.logtemplate`` configuration
3371 setting.
3373 setting.
3372
3374
3373 Returns 0 on success.
3375 Returns 0 on success.
3374
3376
3375 """
3377 """
3376 opts = pycompat.byteskwargs(opts)
3378 opts = pycompat.byteskwargs(opts)
3377 linerange = opts.get('line_range')
3379 linerange = opts.get('line_range')
3378
3380
3379 if linerange and not opts.get('follow'):
3381 if linerange and not opts.get('follow'):
3380 raise error.Abort(_('--line-range requires --follow'))
3382 raise error.Abort(_('--line-range requires --follow'))
3381
3383
3382 if linerange and pats:
3384 if linerange and pats:
3383 raise error.Abort(
3385 raise error.Abort(
3384 _('FILE arguments are not compatible with --line-range option')
3386 _('FILE arguments are not compatible with --line-range option')
3385 )
3387 )
3386
3388
3387 if opts.get('follow') and opts.get('rev'):
3389 if opts.get('follow') and opts.get('rev'):
3388 opts['rev'] = [revsetlang.formatspec('reverse(::%lr)', opts.get('rev'))]
3390 opts['rev'] = [revsetlang.formatspec('reverse(::%lr)', opts.get('rev'))]
3389 del opts['follow']
3391 del opts['follow']
3390
3392
3391 if opts.get('graph'):
3393 if opts.get('graph'):
3392 if linerange:
3394 if linerange:
3393 raise error.Abort(_('graph not supported with line range patterns'))
3395 raise error.Abort(_('graph not supported with line range patterns'))
3394 return cmdutil.graphlog(ui, repo, pats, opts)
3396 return cmdutil.graphlog(ui, repo, pats, opts)
3395
3397
3396 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
3398 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
3397 hunksfilter = None
3399 hunksfilter = None
3398
3400
3399 if linerange:
3401 if linerange:
3400 revs, lrfilematcher, hunksfilter = cmdutil.getloglinerangerevs(
3402 revs, lrfilematcher, hunksfilter = cmdutil.getloglinerangerevs(
3401 repo, revs, opts)
3403 repo, revs, opts)
3402
3404
3403 if filematcher is not None and lrfilematcher is not None:
3405 if filematcher is not None and lrfilematcher is not None:
3404 basefilematcher = filematcher
3406 basefilematcher = filematcher
3405
3407
3406 def filematcher(rev):
3408 def filematcher(rev):
3407 files = (basefilematcher(rev).files()
3409 files = (basefilematcher(rev).files()
3408 + lrfilematcher(rev).files())
3410 + lrfilematcher(rev).files())
3409 return scmutil.matchfiles(repo, files)
3411 return scmutil.matchfiles(repo, files)
3410
3412
3411 elif filematcher is None:
3413 elif filematcher is None:
3412 filematcher = lrfilematcher
3414 filematcher = lrfilematcher
3413
3415
3414 limit = cmdutil.loglimit(opts)
3416 limit = cmdutil.loglimit(opts)
3415 count = 0
3417 count = 0
3416
3418
3417 getrenamed = None
3419 getrenamed = None
3418 if opts.get('copies'):
3420 if opts.get('copies'):
3419 endrev = None
3421 endrev = None
3420 if opts.get('rev'):
3422 if opts.get('rev'):
3421 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
3423 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
3422 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3424 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3423
3425
3424 ui.pager('log')
3426 ui.pager('log')
3425 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
3427 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
3426 for rev in revs:
3428 for rev in revs:
3427 if count == limit:
3429 if count == limit:
3428 break
3430 break
3429 ctx = repo[rev]
3431 ctx = repo[rev]
3430 copies = None
3432 copies = None
3431 if getrenamed is not None and rev:
3433 if getrenamed is not None and rev:
3432 copies = []
3434 copies = []
3433 for fn in ctx.files():
3435 for fn in ctx.files():
3434 rename = getrenamed(fn, rev)
3436 rename = getrenamed(fn, rev)
3435 if rename:
3437 if rename:
3436 copies.append((fn, rename[0]))
3438 copies.append((fn, rename[0]))
3437 if filematcher:
3439 if filematcher:
3438 revmatchfn = filematcher(ctx.rev())
3440 revmatchfn = filematcher(ctx.rev())
3439 else:
3441 else:
3440 revmatchfn = None
3442 revmatchfn = None
3441 if hunksfilter:
3443 if hunksfilter:
3442 revhunksfilter = hunksfilter(rev)
3444 revhunksfilter = hunksfilter(rev)
3443 else:
3445 else:
3444 revhunksfilter = None
3446 revhunksfilter = None
3445 displayer.show(ctx, copies=copies, matchfn=revmatchfn,
3447 displayer.show(ctx, copies=copies, matchfn=revmatchfn,
3446 hunksfilterfn=revhunksfilter)
3448 hunksfilterfn=revhunksfilter)
3447 if displayer.flush(ctx):
3449 if displayer.flush(ctx):
3448 count += 1
3450 count += 1
3449
3451
3450 displayer.close()
3452 displayer.close()
3451
3453
3452 @command('manifest',
3454 @command('manifest',
3453 [('r', 'rev', '', _('revision to display'), _('REV')),
3455 [('r', 'rev', '', _('revision to display'), _('REV')),
3454 ('', 'all', False, _("list files from all revisions"))]
3456 ('', 'all', False, _("list files from all revisions"))]
3455 + formatteropts,
3457 + formatteropts,
3456 _('[-r REV]'), cmdtype=readonly)
3458 _('[-r REV]'), cmdtype=readonly)
3457 def manifest(ui, repo, node=None, rev=None, **opts):
3459 def manifest(ui, repo, node=None, rev=None, **opts):
3458 """output the current or given revision of the project manifest
3460 """output the current or given revision of the project manifest
3459
3461
3460 Print a list of version controlled files for the given revision.
3462 Print a list of version controlled files for the given revision.
3461 If no revision is given, the first parent of the working directory
3463 If no revision is given, the first parent of the working directory
3462 is used, or the null revision if no revision is checked out.
3464 is used, or the null revision if no revision is checked out.
3463
3465
3464 With -v, print file permissions, symlink and executable bits.
3466 With -v, print file permissions, symlink and executable bits.
3465 With --debug, print file revision hashes.
3467 With --debug, print file revision hashes.
3466
3468
3467 If option --all is specified, the list of all files from all revisions
3469 If option --all is specified, the list of all files from all revisions
3468 is printed. This includes deleted and renamed files.
3470 is printed. This includes deleted and renamed files.
3469
3471
3470 Returns 0 on success.
3472 Returns 0 on success.
3471 """
3473 """
3472 opts = pycompat.byteskwargs(opts)
3474 opts = pycompat.byteskwargs(opts)
3473 fm = ui.formatter('manifest', opts)
3475 fm = ui.formatter('manifest', opts)
3474
3476
3475 if opts.get('all'):
3477 if opts.get('all'):
3476 if rev or node:
3478 if rev or node:
3477 raise error.Abort(_("can't specify a revision with --all"))
3479 raise error.Abort(_("can't specify a revision with --all"))
3478
3480
3479 res = []
3481 res = []
3480 prefix = "data/"
3482 prefix = "data/"
3481 suffix = ".i"
3483 suffix = ".i"
3482 plen = len(prefix)
3484 plen = len(prefix)
3483 slen = len(suffix)
3485 slen = len(suffix)
3484 with repo.lock():
3486 with repo.lock():
3485 for fn, b, size in repo.store.datafiles():
3487 for fn, b, size in repo.store.datafiles():
3486 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
3488 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
3487 res.append(fn[plen:-slen])
3489 res.append(fn[plen:-slen])
3488 ui.pager('manifest')
3490 ui.pager('manifest')
3489 for f in res:
3491 for f in res:
3490 fm.startitem()
3492 fm.startitem()
3491 fm.write("path", '%s\n', f)
3493 fm.write("path", '%s\n', f)
3492 fm.end()
3494 fm.end()
3493 return
3495 return
3494
3496
3495 if rev and node:
3497 if rev and node:
3496 raise error.Abort(_("please specify just one revision"))
3498 raise error.Abort(_("please specify just one revision"))
3497
3499
3498 if not node:
3500 if not node:
3499 node = rev
3501 node = rev
3500
3502
3501 char = {'l': '@', 'x': '*', '': ''}
3503 char = {'l': '@', 'x': '*', '': ''}
3502 mode = {'l': '644', 'x': '755', '': '644'}
3504 mode = {'l': '644', 'x': '755', '': '644'}
3503 ctx = scmutil.revsingle(repo, node)
3505 ctx = scmutil.revsingle(repo, node)
3504 mf = ctx.manifest()
3506 mf = ctx.manifest()
3505 ui.pager('manifest')
3507 ui.pager('manifest')
3506 for f in ctx:
3508 for f in ctx:
3507 fm.startitem()
3509 fm.startitem()
3508 fl = ctx[f].flags()
3510 fl = ctx[f].flags()
3509 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
3511 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
3510 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
3512 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
3511 fm.write('path', '%s\n', f)
3513 fm.write('path', '%s\n', f)
3512 fm.end()
3514 fm.end()
3513
3515
3514 @command('^merge',
3516 @command('^merge',
3515 [('f', 'force', None,
3517 [('f', 'force', None,
3516 _('force a merge including outstanding changes (DEPRECATED)')),
3518 _('force a merge including outstanding changes (DEPRECATED)')),
3517 ('r', 'rev', '', _('revision to merge'), _('REV')),
3519 ('r', 'rev', '', _('revision to merge'), _('REV')),
3518 ('P', 'preview', None,
3520 ('P', 'preview', None,
3519 _('review revisions to merge (no merge is performed)'))
3521 _('review revisions to merge (no merge is performed)'))
3520 ] + mergetoolopts,
3522 ] + mergetoolopts,
3521 _('[-P] [[-r] REV]'))
3523 _('[-P] [[-r] REV]'))
3522 def merge(ui, repo, node=None, **opts):
3524 def merge(ui, repo, node=None, **opts):
3523 """merge another revision into working directory
3525 """merge another revision into working directory
3524
3526
3525 The current working directory is updated with all changes made in
3527 The current working directory is updated with all changes made in
3526 the requested revision since the last common predecessor revision.
3528 the requested revision since the last common predecessor revision.
3527
3529
3528 Files that changed between either parent are marked as changed for
3530 Files that changed between either parent are marked as changed for
3529 the next commit and a commit must be performed before any further
3531 the next commit and a commit must be performed before any further
3530 updates to the repository are allowed. The next commit will have
3532 updates to the repository are allowed. The next commit will have
3531 two parents.
3533 two parents.
3532
3534
3533 ``--tool`` can be used to specify the merge tool used for file
3535 ``--tool`` can be used to specify the merge tool used for file
3534 merges. It overrides the HGMERGE environment variable and your
3536 merges. It overrides the HGMERGE environment variable and your
3535 configuration files. See :hg:`help merge-tools` for options.
3537 configuration files. See :hg:`help merge-tools` for options.
3536
3538
3537 If no revision is specified, the working directory's parent is a
3539 If no revision is specified, the working directory's parent is a
3538 head revision, and the current branch contains exactly one other
3540 head revision, and the current branch contains exactly one other
3539 head, the other head is merged with by default. Otherwise, an
3541 head, the other head is merged with by default. Otherwise, an
3540 explicit revision with which to merge with must be provided.
3542 explicit revision with which to merge with must be provided.
3541
3543
3542 See :hg:`help resolve` for information on handling file conflicts.
3544 See :hg:`help resolve` for information on handling file conflicts.
3543
3545
3544 To undo an uncommitted merge, use :hg:`update --clean .` which
3546 To undo an uncommitted merge, use :hg:`update --clean .` which
3545 will check out a clean copy of the original merge parent, losing
3547 will check out a clean copy of the original merge parent, losing
3546 all changes.
3548 all changes.
3547
3549
3548 Returns 0 on success, 1 if there are unresolved files.
3550 Returns 0 on success, 1 if there are unresolved files.
3549 """
3551 """
3550
3552
3551 opts = pycompat.byteskwargs(opts)
3553 opts = pycompat.byteskwargs(opts)
3552 if opts.get('rev') and node:
3554 if opts.get('rev') and node:
3553 raise error.Abort(_("please specify just one revision"))
3555 raise error.Abort(_("please specify just one revision"))
3554 if not node:
3556 if not node:
3555 node = opts.get('rev')
3557 node = opts.get('rev')
3556
3558
3557 if node:
3559 if node:
3558 node = scmutil.revsingle(repo, node).node()
3560 node = scmutil.revsingle(repo, node).node()
3559
3561
3560 if not node:
3562 if not node:
3561 node = repo[destutil.destmerge(repo)].node()
3563 node = repo[destutil.destmerge(repo)].node()
3562
3564
3563 if opts.get('preview'):
3565 if opts.get('preview'):
3564 # find nodes that are ancestors of p2 but not of p1
3566 # find nodes that are ancestors of p2 but not of p1
3565 p1 = repo.lookup('.')
3567 p1 = repo.lookup('.')
3566 p2 = repo.lookup(node)
3568 p2 = repo.lookup(node)
3567 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
3569 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
3568
3570
3569 displayer = cmdutil.show_changeset(ui, repo, opts)
3571 displayer = cmdutil.show_changeset(ui, repo, opts)
3570 for node in nodes:
3572 for node in nodes:
3571 displayer.show(repo[node])
3573 displayer.show(repo[node])
3572 displayer.close()
3574 displayer.close()
3573 return 0
3575 return 0
3574
3576
3575 try:
3577 try:
3576 # ui.forcemerge is an internal variable, do not document
3578 # ui.forcemerge is an internal variable, do not document
3577 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
3579 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
3578 force = opts.get('force')
3580 force = opts.get('force')
3579 labels = ['working copy', 'merge rev']
3581 labels = ['working copy', 'merge rev']
3580 return hg.merge(repo, node, force=force, mergeforce=force,
3582 return hg.merge(repo, node, force=force, mergeforce=force,
3581 labels=labels)
3583 labels=labels)
3582 finally:
3584 finally:
3583 ui.setconfig('ui', 'forcemerge', '', 'merge')
3585 ui.setconfig('ui', 'forcemerge', '', 'merge')
3584
3586
3585 @command('outgoing|out',
3587 @command('outgoing|out',
3586 [('f', 'force', None, _('run even when the destination is unrelated')),
3588 [('f', 'force', None, _('run even when the destination is unrelated')),
3587 ('r', 'rev', [],
3589 ('r', 'rev', [],
3588 _('a changeset intended to be included in the destination'), _('REV')),
3590 _('a changeset intended to be included in the destination'), _('REV')),
3589 ('n', 'newest-first', None, _('show newest record first')),
3591 ('n', 'newest-first', None, _('show newest record first')),
3590 ('B', 'bookmarks', False, _('compare bookmarks')),
3592 ('B', 'bookmarks', False, _('compare bookmarks')),
3591 ('b', 'branch', [], _('a specific branch you would like to push'),
3593 ('b', 'branch', [], _('a specific branch you would like to push'),
3592 _('BRANCH')),
3594 _('BRANCH')),
3593 ] + logopts + remoteopts + subrepoopts,
3595 ] + logopts + remoteopts + subrepoopts,
3594 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
3596 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
3595 def outgoing(ui, repo, dest=None, **opts):
3597 def outgoing(ui, repo, dest=None, **opts):
3596 """show changesets not found in the destination
3598 """show changesets not found in the destination
3597
3599
3598 Show changesets not found in the specified destination repository
3600 Show changesets not found in the specified destination repository
3599 or the default push location. These are the changesets that would
3601 or the default push location. These are the changesets that would
3600 be pushed if a push was requested.
3602 be pushed if a push was requested.
3601
3603
3602 See pull for details of valid destination formats.
3604 See pull for details of valid destination formats.
3603
3605
3604 .. container:: verbose
3606 .. container:: verbose
3605
3607
3606 With -B/--bookmarks, the result of bookmark comparison between
3608 With -B/--bookmarks, the result of bookmark comparison between
3607 local and remote repositories is displayed. With -v/--verbose,
3609 local and remote repositories is displayed. With -v/--verbose,
3608 status is also displayed for each bookmark like below::
3610 status is also displayed for each bookmark like below::
3609
3611
3610 BM1 01234567890a added
3612 BM1 01234567890a added
3611 BM2 deleted
3613 BM2 deleted
3612 BM3 234567890abc advanced
3614 BM3 234567890abc advanced
3613 BM4 34567890abcd diverged
3615 BM4 34567890abcd diverged
3614 BM5 4567890abcde changed
3616 BM5 4567890abcde changed
3615
3617
3616 The action taken when pushing depends on the
3618 The action taken when pushing depends on the
3617 status of each bookmark:
3619 status of each bookmark:
3618
3620
3619 :``added``: push with ``-B`` will create it
3621 :``added``: push with ``-B`` will create it
3620 :``deleted``: push with ``-B`` will delete it
3622 :``deleted``: push with ``-B`` will delete it
3621 :``advanced``: push will update it
3623 :``advanced``: push will update it
3622 :``diverged``: push with ``-B`` will update it
3624 :``diverged``: push with ``-B`` will update it
3623 :``changed``: push with ``-B`` will update it
3625 :``changed``: push with ``-B`` will update it
3624
3626
3625 From the point of view of pushing behavior, bookmarks
3627 From the point of view of pushing behavior, bookmarks
3626 existing only in the remote repository are treated as
3628 existing only in the remote repository are treated as
3627 ``deleted``, even if it is in fact added remotely.
3629 ``deleted``, even if it is in fact added remotely.
3628
3630
3629 Returns 0 if there are outgoing changes, 1 otherwise.
3631 Returns 0 if there are outgoing changes, 1 otherwise.
3630 """
3632 """
3631 opts = pycompat.byteskwargs(opts)
3633 opts = pycompat.byteskwargs(opts)
3632 if opts.get('graph'):
3634 if opts.get('graph'):
3633 cmdutil.checkunsupportedgraphflags([], opts)
3635 cmdutil.checkunsupportedgraphflags([], opts)
3634 o, other = hg._outgoing(ui, repo, dest, opts)
3636 o, other = hg._outgoing(ui, repo, dest, opts)
3635 if not o:
3637 if not o:
3636 cmdutil.outgoinghooks(ui, repo, other, opts, o)
3638 cmdutil.outgoinghooks(ui, repo, other, opts, o)
3637 return
3639 return
3638
3640
3639 revdag = cmdutil.graphrevs(repo, o, opts)
3641 revdag = cmdutil.graphrevs(repo, o, opts)
3640 ui.pager('outgoing')
3642 ui.pager('outgoing')
3641 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
3643 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
3642 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
3644 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
3643 cmdutil.outgoinghooks(ui, repo, other, opts, o)
3645 cmdutil.outgoinghooks(ui, repo, other, opts, o)
3644 return 0
3646 return 0
3645
3647
3646 if opts.get('bookmarks'):
3648 if opts.get('bookmarks'):
3647 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3649 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3648 dest, branches = hg.parseurl(dest, opts.get('branch'))
3650 dest, branches = hg.parseurl(dest, opts.get('branch'))
3649 other = hg.peer(repo, opts, dest)
3651 other = hg.peer(repo, opts, dest)
3650 if 'bookmarks' not in other.listkeys('namespaces'):
3652 if 'bookmarks' not in other.listkeys('namespaces'):
3651 ui.warn(_("remote doesn't support bookmarks\n"))
3653 ui.warn(_("remote doesn't support bookmarks\n"))
3652 return 0
3654 return 0
3653 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
3655 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
3654 ui.pager('outgoing')
3656 ui.pager('outgoing')
3655 return bookmarks.outgoing(ui, repo, other)
3657 return bookmarks.outgoing(ui, repo, other)
3656
3658
3657 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
3659 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
3658 try:
3660 try:
3659 return hg.outgoing(ui, repo, dest, opts)
3661 return hg.outgoing(ui, repo, dest, opts)
3660 finally:
3662 finally:
3661 del repo._subtoppath
3663 del repo._subtoppath
3662
3664
3663 @command('parents',
3665 @command('parents',
3664 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
3666 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
3665 ] + templateopts,
3667 ] + templateopts,
3666 _('[-r REV] [FILE]'),
3668 _('[-r REV] [FILE]'),
3667 inferrepo=True)
3669 inferrepo=True)
3668 def parents(ui, repo, file_=None, **opts):
3670 def parents(ui, repo, file_=None, **opts):
3669 """show the parents of the working directory or revision (DEPRECATED)
3671 """show the parents of the working directory or revision (DEPRECATED)
3670
3672
3671 Print the working directory's parent revisions. If a revision is
3673 Print the working directory's parent revisions. If a revision is
3672 given via -r/--rev, the parent of that revision will be printed.
3674 given via -r/--rev, the parent of that revision will be printed.
3673 If a file argument is given, the revision in which the file was
3675 If a file argument is given, the revision in which the file was
3674 last changed (before the working directory revision or the
3676 last changed (before the working directory revision or the
3675 argument to --rev if given) is printed.
3677 argument to --rev if given) is printed.
3676
3678
3677 This command is equivalent to::
3679 This command is equivalent to::
3678
3680
3679 hg log -r "p1()+p2()" or
3681 hg log -r "p1()+p2()" or
3680 hg log -r "p1(REV)+p2(REV)" or
3682 hg log -r "p1(REV)+p2(REV)" or
3681 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
3683 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
3682 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
3684 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
3683
3685
3684 See :hg:`summary` and :hg:`help revsets` for related information.
3686 See :hg:`summary` and :hg:`help revsets` for related information.
3685
3687
3686 Returns 0 on success.
3688 Returns 0 on success.
3687 """
3689 """
3688
3690
3689 opts = pycompat.byteskwargs(opts)
3691 opts = pycompat.byteskwargs(opts)
3690 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3692 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3691
3693
3692 if file_:
3694 if file_:
3693 m = scmutil.match(ctx, (file_,), opts)
3695 m = scmutil.match(ctx, (file_,), opts)
3694 if m.anypats() or len(m.files()) != 1:
3696 if m.anypats() or len(m.files()) != 1:
3695 raise error.Abort(_('can only specify an explicit filename'))
3697 raise error.Abort(_('can only specify an explicit filename'))
3696 file_ = m.files()[0]
3698 file_ = m.files()[0]
3697 filenodes = []
3699 filenodes = []
3698 for cp in ctx.parents():
3700 for cp in ctx.parents():
3699 if not cp:
3701 if not cp:
3700 continue
3702 continue
3701 try:
3703 try:
3702 filenodes.append(cp.filenode(file_))
3704 filenodes.append(cp.filenode(file_))
3703 except error.LookupError:
3705 except error.LookupError:
3704 pass
3706 pass
3705 if not filenodes:
3707 if not filenodes:
3706 raise error.Abort(_("'%s' not found in manifest!") % file_)
3708 raise error.Abort(_("'%s' not found in manifest!") % file_)
3707 p = []
3709 p = []
3708 for fn in filenodes:
3710 for fn in filenodes:
3709 fctx = repo.filectx(file_, fileid=fn)
3711 fctx = repo.filectx(file_, fileid=fn)
3710 p.append(fctx.node())
3712 p.append(fctx.node())
3711 else:
3713 else:
3712 p = [cp.node() for cp in ctx.parents()]
3714 p = [cp.node() for cp in ctx.parents()]
3713
3715
3714 displayer = cmdutil.show_changeset(ui, repo, opts)
3716 displayer = cmdutil.show_changeset(ui, repo, opts)
3715 for n in p:
3717 for n in p:
3716 if n != nullid:
3718 if n != nullid:
3717 displayer.show(repo[n])
3719 displayer.show(repo[n])
3718 displayer.close()
3720 displayer.close()
3719
3721
3720 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True,
3722 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True,
3721 cmdtype=readonly)
3723 cmdtype=readonly)
3722 def paths(ui, repo, search=None, **opts):
3724 def paths(ui, repo, search=None, **opts):
3723 """show aliases for remote repositories
3725 """show aliases for remote repositories
3724
3726
3725 Show definition of symbolic path name NAME. If no name is given,
3727 Show definition of symbolic path name NAME. If no name is given,
3726 show definition of all available names.
3728 show definition of all available names.
3727
3729
3728 Option -q/--quiet suppresses all output when searching for NAME
3730 Option -q/--quiet suppresses all output when searching for NAME
3729 and shows only the path names when listing all definitions.
3731 and shows only the path names when listing all definitions.
3730
3732
3731 Path names are defined in the [paths] section of your
3733 Path names are defined in the [paths] section of your
3732 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
3734 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
3733 repository, ``.hg/hgrc`` is used, too.
3735 repository, ``.hg/hgrc`` is used, too.
3734
3736
3735 The path names ``default`` and ``default-push`` have a special
3737 The path names ``default`` and ``default-push`` have a special
3736 meaning. When performing a push or pull operation, they are used
3738 meaning. When performing a push or pull operation, they are used
3737 as fallbacks if no location is specified on the command-line.
3739 as fallbacks if no location is specified on the command-line.
3738 When ``default-push`` is set, it will be used for push and
3740 When ``default-push`` is set, it will be used for push and
3739 ``default`` will be used for pull; otherwise ``default`` is used
3741 ``default`` will be used for pull; otherwise ``default`` is used
3740 as the fallback for both. When cloning a repository, the clone
3742 as the fallback for both. When cloning a repository, the clone
3741 source is written as ``default`` in ``.hg/hgrc``.
3743 source is written as ``default`` in ``.hg/hgrc``.
3742
3744
3743 .. note::
3745 .. note::
3744
3746
3745 ``default`` and ``default-push`` apply to all inbound (e.g.
3747 ``default`` and ``default-push`` apply to all inbound (e.g.
3746 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
3748 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
3747 and :hg:`bundle`) operations.
3749 and :hg:`bundle`) operations.
3748
3750
3749 See :hg:`help urls` for more information.
3751 See :hg:`help urls` for more information.
3750
3752
3751 Returns 0 on success.
3753 Returns 0 on success.
3752 """
3754 """
3753
3755
3754 opts = pycompat.byteskwargs(opts)
3756 opts = pycompat.byteskwargs(opts)
3755 ui.pager('paths')
3757 ui.pager('paths')
3756 if search:
3758 if search:
3757 pathitems = [(name, path) for name, path in ui.paths.iteritems()
3759 pathitems = [(name, path) for name, path in ui.paths.iteritems()
3758 if name == search]
3760 if name == search]
3759 else:
3761 else:
3760 pathitems = sorted(ui.paths.iteritems())
3762 pathitems = sorted(ui.paths.iteritems())
3761
3763
3762 fm = ui.formatter('paths', opts)
3764 fm = ui.formatter('paths', opts)
3763 if fm.isplain():
3765 if fm.isplain():
3764 hidepassword = util.hidepassword
3766 hidepassword = util.hidepassword
3765 else:
3767 else:
3766 hidepassword = str
3768 hidepassword = str
3767 if ui.quiet:
3769 if ui.quiet:
3768 namefmt = '%s\n'
3770 namefmt = '%s\n'
3769 else:
3771 else:
3770 namefmt = '%s = '
3772 namefmt = '%s = '
3771 showsubopts = not search and not ui.quiet
3773 showsubopts = not search and not ui.quiet
3772
3774
3773 for name, path in pathitems:
3775 for name, path in pathitems:
3774 fm.startitem()
3776 fm.startitem()
3775 fm.condwrite(not search, 'name', namefmt, name)
3777 fm.condwrite(not search, 'name', namefmt, name)
3776 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
3778 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
3777 for subopt, value in sorted(path.suboptions.items()):
3779 for subopt, value in sorted(path.suboptions.items()):
3778 assert subopt not in ('name', 'url')
3780 assert subopt not in ('name', 'url')
3779 if showsubopts:
3781 if showsubopts:
3780 fm.plain('%s:%s = ' % (name, subopt))
3782 fm.plain('%s:%s = ' % (name, subopt))
3781 fm.condwrite(showsubopts, subopt, '%s\n', value)
3783 fm.condwrite(showsubopts, subopt, '%s\n', value)
3782
3784
3783 fm.end()
3785 fm.end()
3784
3786
3785 if search and not pathitems:
3787 if search and not pathitems:
3786 if not ui.quiet:
3788 if not ui.quiet:
3787 ui.warn(_("not found!\n"))
3789 ui.warn(_("not found!\n"))
3788 return 1
3790 return 1
3789 else:
3791 else:
3790 return 0
3792 return 0
3791
3793
3792 @command('phase',
3794 @command('phase',
3793 [('p', 'public', False, _('set changeset phase to public')),
3795 [('p', 'public', False, _('set changeset phase to public')),
3794 ('d', 'draft', False, _('set changeset phase to draft')),
3796 ('d', 'draft', False, _('set changeset phase to draft')),
3795 ('s', 'secret', False, _('set changeset phase to secret')),
3797 ('s', 'secret', False, _('set changeset phase to secret')),
3796 ('f', 'force', False, _('allow to move boundary backward')),
3798 ('f', 'force', False, _('allow to move boundary backward')),
3797 ('r', 'rev', [], _('target revision'), _('REV')),
3799 ('r', 'rev', [], _('target revision'), _('REV')),
3798 ],
3800 ],
3799 _('[-p|-d|-s] [-f] [-r] [REV...]'))
3801 _('[-p|-d|-s] [-f] [-r] [REV...]'))
3800 def phase(ui, repo, *revs, **opts):
3802 def phase(ui, repo, *revs, **opts):
3801 """set or show the current phase name
3803 """set or show the current phase name
3802
3804
3803 With no argument, show the phase name of the current revision(s).
3805 With no argument, show the phase name of the current revision(s).
3804
3806
3805 With one of -p/--public, -d/--draft or -s/--secret, change the
3807 With one of -p/--public, -d/--draft or -s/--secret, change the
3806 phase value of the specified revisions.
3808 phase value of the specified revisions.
3807
3809
3808 Unless -f/--force is specified, :hg:`phase` won't move changesets from a
3810 Unless -f/--force is specified, :hg:`phase` won't move changesets from a
3809 lower phase to a higher phase. Phases are ordered as follows::
3811 lower phase to a higher phase. Phases are ordered as follows::
3810
3812
3811 public < draft < secret
3813 public < draft < secret
3812
3814
3813 Returns 0 on success, 1 if some phases could not be changed.
3815 Returns 0 on success, 1 if some phases could not be changed.
3814
3816
3815 (For more information about the phases concept, see :hg:`help phases`.)
3817 (For more information about the phases concept, see :hg:`help phases`.)
3816 """
3818 """
3817 opts = pycompat.byteskwargs(opts)
3819 opts = pycompat.byteskwargs(opts)
3818 # search for a unique phase argument
3820 # search for a unique phase argument
3819 targetphase = None
3821 targetphase = None
3820 for idx, name in enumerate(phases.phasenames):
3822 for idx, name in enumerate(phases.phasenames):
3821 if opts[name]:
3823 if opts[name]:
3822 if targetphase is not None:
3824 if targetphase is not None:
3823 raise error.Abort(_('only one phase can be specified'))
3825 raise error.Abort(_('only one phase can be specified'))
3824 targetphase = idx
3826 targetphase = idx
3825
3827
3826 # look for specified revision
3828 # look for specified revision
3827 revs = list(revs)
3829 revs = list(revs)
3828 revs.extend(opts['rev'])
3830 revs.extend(opts['rev'])
3829 if not revs:
3831 if not revs:
3830 # display both parents as the second parent phase can influence
3832 # display both parents as the second parent phase can influence
3831 # the phase of a merge commit
3833 # the phase of a merge commit
3832 revs = [c.rev() for c in repo[None].parents()]
3834 revs = [c.rev() for c in repo[None].parents()]
3833
3835
3834 revs = scmutil.revrange(repo, revs)
3836 revs = scmutil.revrange(repo, revs)
3835
3837
3836 lock = None
3838 lock = None
3837 ret = 0
3839 ret = 0
3838 if targetphase is None:
3840 if targetphase is None:
3839 # display
3841 # display
3840 for r in revs:
3842 for r in revs:
3841 ctx = repo[r]
3843 ctx = repo[r]
3842 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
3844 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
3843 else:
3845 else:
3844 tr = None
3846 tr = None
3845 lock = repo.lock()
3847 lock = repo.lock()
3846 try:
3848 try:
3847 tr = repo.transaction("phase")
3849 tr = repo.transaction("phase")
3848 # set phase
3850 # set phase
3849 if not revs:
3851 if not revs:
3850 raise error.Abort(_('empty revision set'))
3852 raise error.Abort(_('empty revision set'))
3851 nodes = [repo[r].node() for r in revs]
3853 nodes = [repo[r].node() for r in revs]
3852 # moving revision from public to draft may hide them
3854 # moving revision from public to draft may hide them
3853 # We have to check result on an unfiltered repository
3855 # We have to check result on an unfiltered repository
3854 unfi = repo.unfiltered()
3856 unfi = repo.unfiltered()
3855 getphase = unfi._phasecache.phase
3857 getphase = unfi._phasecache.phase
3856 olddata = [getphase(unfi, r) for r in unfi]
3858 olddata = [getphase(unfi, r) for r in unfi]
3857 phases.advanceboundary(repo, tr, targetphase, nodes)
3859 phases.advanceboundary(repo, tr, targetphase, nodes)
3858 if opts['force']:
3860 if opts['force']:
3859 phases.retractboundary(repo, tr, targetphase, nodes)
3861 phases.retractboundary(repo, tr, targetphase, nodes)
3860 tr.close()
3862 tr.close()
3861 finally:
3863 finally:
3862 if tr is not None:
3864 if tr is not None:
3863 tr.release()
3865 tr.release()
3864 lock.release()
3866 lock.release()
3865 getphase = unfi._phasecache.phase
3867 getphase = unfi._phasecache.phase
3866 newdata = [getphase(unfi, r) for r in unfi]
3868 newdata = [getphase(unfi, r) for r in unfi]
3867 changes = sum(newdata[r] != olddata[r] for r in unfi)
3869 changes = sum(newdata[r] != olddata[r] for r in unfi)
3868 cl = unfi.changelog
3870 cl = unfi.changelog
3869 rejected = [n for n in nodes
3871 rejected = [n for n in nodes
3870 if newdata[cl.rev(n)] < targetphase]
3872 if newdata[cl.rev(n)] < targetphase]
3871 if rejected:
3873 if rejected:
3872 ui.warn(_('cannot move %i changesets to a higher '
3874 ui.warn(_('cannot move %i changesets to a higher '
3873 'phase, use --force\n') % len(rejected))
3875 'phase, use --force\n') % len(rejected))
3874 ret = 1
3876 ret = 1
3875 if changes:
3877 if changes:
3876 msg = _('phase changed for %i changesets\n') % changes
3878 msg = _('phase changed for %i changesets\n') % changes
3877 if ret:
3879 if ret:
3878 ui.status(msg)
3880 ui.status(msg)
3879 else:
3881 else:
3880 ui.note(msg)
3882 ui.note(msg)
3881 else:
3883 else:
3882 ui.warn(_('no phases changed\n'))
3884 ui.warn(_('no phases changed\n'))
3883 return ret
3885 return ret
3884
3886
3885 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
3887 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
3886 """Run after a changegroup has been added via pull/unbundle
3888 """Run after a changegroup has been added via pull/unbundle
3887
3889
3888 This takes arguments below:
3890 This takes arguments below:
3889
3891
3890 :modheads: change of heads by pull/unbundle
3892 :modheads: change of heads by pull/unbundle
3891 :optupdate: updating working directory is needed or not
3893 :optupdate: updating working directory is needed or not
3892 :checkout: update destination revision (or None to default destination)
3894 :checkout: update destination revision (or None to default destination)
3893 :brev: a name, which might be a bookmark to be activated after updating
3895 :brev: a name, which might be a bookmark to be activated after updating
3894 """
3896 """
3895 if modheads == 0:
3897 if modheads == 0:
3896 return
3898 return
3897 if optupdate:
3899 if optupdate:
3898 try:
3900 try:
3899 return hg.updatetotally(ui, repo, checkout, brev)
3901 return hg.updatetotally(ui, repo, checkout, brev)
3900 except error.UpdateAbort as inst:
3902 except error.UpdateAbort as inst:
3901 msg = _("not updating: %s") % str(inst)
3903 msg = _("not updating: %s") % str(inst)
3902 hint = inst.hint
3904 hint = inst.hint
3903 raise error.UpdateAbort(msg, hint=hint)
3905 raise error.UpdateAbort(msg, hint=hint)
3904 if modheads > 1:
3906 if modheads > 1:
3905 currentbranchheads = len(repo.branchheads())
3907 currentbranchheads = len(repo.branchheads())
3906 if currentbranchheads == modheads:
3908 if currentbranchheads == modheads:
3907 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
3909 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
3908 elif currentbranchheads > 1:
3910 elif currentbranchheads > 1:
3909 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
3911 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
3910 "merge)\n"))
3912 "merge)\n"))
3911 else:
3913 else:
3912 ui.status(_("(run 'hg heads' to see heads)\n"))
3914 ui.status(_("(run 'hg heads' to see heads)\n"))
3913 elif not ui.configbool('commands', 'update.requiredest'):
3915 elif not ui.configbool('commands', 'update.requiredest'):
3914 ui.status(_("(run 'hg update' to get a working copy)\n"))
3916 ui.status(_("(run 'hg update' to get a working copy)\n"))
3915
3917
3916 @command('^pull',
3918 @command('^pull',
3917 [('u', 'update', None,
3919 [('u', 'update', None,
3918 _('update to new branch head if new descendants were pulled')),
3920 _('update to new branch head if new descendants were pulled')),
3919 ('f', 'force', None, _('run even when remote repository is unrelated')),
3921 ('f', 'force', None, _('run even when remote repository is unrelated')),
3920 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3922 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3921 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
3923 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
3922 ('b', 'branch', [], _('a specific branch you would like to pull'),
3924 ('b', 'branch', [], _('a specific branch you would like to pull'),
3923 _('BRANCH')),
3925 _('BRANCH')),
3924 ] + remoteopts,
3926 ] + remoteopts,
3925 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
3927 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
3926 def pull(ui, repo, source="default", **opts):
3928 def pull(ui, repo, source="default", **opts):
3927 """pull changes from the specified source
3929 """pull changes from the specified source
3928
3930
3929 Pull changes from a remote repository to a local one.
3931 Pull changes from a remote repository to a local one.
3930
3932
3931 This finds all changes from the repository at the specified path
3933 This finds all changes from the repository at the specified path
3932 or URL and adds them to a local repository (the current one unless
3934 or URL and adds them to a local repository (the current one unless
3933 -R is specified). By default, this does not update the copy of the
3935 -R is specified). By default, this does not update the copy of the
3934 project in the working directory.
3936 project in the working directory.
3935
3937
3936 Use :hg:`incoming` if you want to see what would have been added
3938 Use :hg:`incoming` if you want to see what would have been added
3937 by a pull at the time you issued this command. If you then decide
3939 by a pull at the time you issued this command. If you then decide
3938 to add those changes to the repository, you should use :hg:`pull
3940 to add those changes to the repository, you should use :hg:`pull
3939 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
3941 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
3940
3942
3941 If SOURCE is omitted, the 'default' path will be used.
3943 If SOURCE is omitted, the 'default' path will be used.
3942 See :hg:`help urls` for more information.
3944 See :hg:`help urls` for more information.
3943
3945
3944 Specifying bookmark as ``.`` is equivalent to specifying the active
3946 Specifying bookmark as ``.`` is equivalent to specifying the active
3945 bookmark's name.
3947 bookmark's name.
3946
3948
3947 Returns 0 on success, 1 if an update had unresolved files.
3949 Returns 0 on success, 1 if an update had unresolved files.
3948 """
3950 """
3949
3951
3950 opts = pycompat.byteskwargs(opts)
3952 opts = pycompat.byteskwargs(opts)
3951 if ui.configbool('commands', 'update.requiredest') and opts.get('update'):
3953 if ui.configbool('commands', 'update.requiredest') and opts.get('update'):
3952 msg = _('update destination required by configuration')
3954 msg = _('update destination required by configuration')
3953 hint = _('use hg pull followed by hg update DEST')
3955 hint = _('use hg pull followed by hg update DEST')
3954 raise error.Abort(msg, hint=hint)
3956 raise error.Abort(msg, hint=hint)
3955
3957
3956 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
3958 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
3957 ui.status(_('pulling from %s\n') % util.hidepassword(source))
3959 ui.status(_('pulling from %s\n') % util.hidepassword(source))
3958 other = hg.peer(repo, opts, source)
3960 other = hg.peer(repo, opts, source)
3959 try:
3961 try:
3960 revs, checkout = hg.addbranchrevs(repo, other, branches,
3962 revs, checkout = hg.addbranchrevs(repo, other, branches,
3961 opts.get('rev'))
3963 opts.get('rev'))
3962
3964
3963
3965
3964 pullopargs = {}
3966 pullopargs = {}
3965 if opts.get('bookmark'):
3967 if opts.get('bookmark'):
3966 if not revs:
3968 if not revs:
3967 revs = []
3969 revs = []
3968 # The list of bookmark used here is not the one used to actually
3970 # The list of bookmark used here is not the one used to actually
3969 # update the bookmark name. This can result in the revision pulled
3971 # update the bookmark name. This can result in the revision pulled
3970 # not ending up with the name of the bookmark because of a race
3972 # not ending up with the name of the bookmark because of a race
3971 # condition on the server. (See issue 4689 for details)
3973 # condition on the server. (See issue 4689 for details)
3972 remotebookmarks = other.listkeys('bookmarks')
3974 remotebookmarks = other.listkeys('bookmarks')
3973 remotebookmarks = bookmarks.unhexlifybookmarks(remotebookmarks)
3975 remotebookmarks = bookmarks.unhexlifybookmarks(remotebookmarks)
3974 pullopargs['remotebookmarks'] = remotebookmarks
3976 pullopargs['remotebookmarks'] = remotebookmarks
3975 for b in opts['bookmark']:
3977 for b in opts['bookmark']:
3976 b = repo._bookmarks.expandname(b)
3978 b = repo._bookmarks.expandname(b)
3977 if b not in remotebookmarks:
3979 if b not in remotebookmarks:
3978 raise error.Abort(_('remote bookmark %s not found!') % b)
3980 raise error.Abort(_('remote bookmark %s not found!') % b)
3979 revs.append(hex(remotebookmarks[b]))
3981 revs.append(hex(remotebookmarks[b]))
3980
3982
3981 if revs:
3983 if revs:
3982 try:
3984 try:
3983 # When 'rev' is a bookmark name, we cannot guarantee that it
3985 # When 'rev' is a bookmark name, we cannot guarantee that it
3984 # will be updated with that name because of a race condition
3986 # will be updated with that name because of a race condition
3985 # server side. (See issue 4689 for details)
3987 # server side. (See issue 4689 for details)
3986 oldrevs = revs
3988 oldrevs = revs
3987 revs = [] # actually, nodes
3989 revs = [] # actually, nodes
3988 for r in oldrevs:
3990 for r in oldrevs:
3989 node = other.lookup(r)
3991 node = other.lookup(r)
3990 revs.append(node)
3992 revs.append(node)
3991 if r == checkout:
3993 if r == checkout:
3992 checkout = node
3994 checkout = node
3993 except error.CapabilityError:
3995 except error.CapabilityError:
3994 err = _("other repository doesn't support revision lookup, "
3996 err = _("other repository doesn't support revision lookup, "
3995 "so a rev cannot be specified.")
3997 "so a rev cannot be specified.")
3996 raise error.Abort(err)
3998 raise error.Abort(err)
3997
3999
3998 pullopargs.update(opts.get('opargs', {}))
4000 pullopargs.update(opts.get('opargs', {}))
3999 modheads = exchange.pull(repo, other, heads=revs,
4001 modheads = exchange.pull(repo, other, heads=revs,
4000 force=opts.get('force'),
4002 force=opts.get('force'),
4001 bookmarks=opts.get('bookmark', ()),
4003 bookmarks=opts.get('bookmark', ()),
4002 opargs=pullopargs).cgresult
4004 opargs=pullopargs).cgresult
4003
4005
4004 # brev is a name, which might be a bookmark to be activated at
4006 # brev is a name, which might be a bookmark to be activated at
4005 # the end of the update. In other words, it is an explicit
4007 # the end of the update. In other words, it is an explicit
4006 # destination of the update
4008 # destination of the update
4007 brev = None
4009 brev = None
4008
4010
4009 if checkout:
4011 if checkout:
4010 checkout = str(repo.changelog.rev(checkout))
4012 checkout = str(repo.changelog.rev(checkout))
4011
4013
4012 # order below depends on implementation of
4014 # order below depends on implementation of
4013 # hg.addbranchrevs(). opts['bookmark'] is ignored,
4015 # hg.addbranchrevs(). opts['bookmark'] is ignored,
4014 # because 'checkout' is determined without it.
4016 # because 'checkout' is determined without it.
4015 if opts.get('rev'):
4017 if opts.get('rev'):
4016 brev = opts['rev'][0]
4018 brev = opts['rev'][0]
4017 elif opts.get('branch'):
4019 elif opts.get('branch'):
4018 brev = opts['branch'][0]
4020 brev = opts['branch'][0]
4019 else:
4021 else:
4020 brev = branches[0]
4022 brev = branches[0]
4021 repo._subtoppath = source
4023 repo._subtoppath = source
4022 try:
4024 try:
4023 ret = postincoming(ui, repo, modheads, opts.get('update'),
4025 ret = postincoming(ui, repo, modheads, opts.get('update'),
4024 checkout, brev)
4026 checkout, brev)
4025
4027
4026 finally:
4028 finally:
4027 del repo._subtoppath
4029 del repo._subtoppath
4028
4030
4029 finally:
4031 finally:
4030 other.close()
4032 other.close()
4031 return ret
4033 return ret
4032
4034
4033 @command('^push',
4035 @command('^push',
4034 [('f', 'force', None, _('force push')),
4036 [('f', 'force', None, _('force push')),
4035 ('r', 'rev', [],
4037 ('r', 'rev', [],
4036 _('a changeset intended to be included in the destination'),
4038 _('a changeset intended to be included in the destination'),
4037 _('REV')),
4039 _('REV')),
4038 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4040 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4039 ('b', 'branch', [],
4041 ('b', 'branch', [],
4040 _('a specific branch you would like to push'), _('BRANCH')),
4042 _('a specific branch you would like to push'), _('BRANCH')),
4041 ('', 'new-branch', False, _('allow pushing a new branch')),
4043 ('', 'new-branch', False, _('allow pushing a new branch')),
4042 ('', 'pushvars', [], _('variables that can be sent to server (ADVANCED)')),
4044 ('', 'pushvars', [], _('variables that can be sent to server (ADVANCED)')),
4043 ] + remoteopts,
4045 ] + remoteopts,
4044 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4046 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4045 def push(ui, repo, dest=None, **opts):
4047 def push(ui, repo, dest=None, **opts):
4046 """push changes to the specified destination
4048 """push changes to the specified destination
4047
4049
4048 Push changesets from the local repository to the specified
4050 Push changesets from the local repository to the specified
4049 destination.
4051 destination.
4050
4052
4051 This operation is symmetrical to pull: it is identical to a pull
4053 This operation is symmetrical to pull: it is identical to a pull
4052 in the destination repository from the current one.
4054 in the destination repository from the current one.
4053
4055
4054 By default, push will not allow creation of new heads at the
4056 By default, push will not allow creation of new heads at the
4055 destination, since multiple heads would make it unclear which head
4057 destination, since multiple heads would make it unclear which head
4056 to use. In this situation, it is recommended to pull and merge
4058 to use. In this situation, it is recommended to pull and merge
4057 before pushing.
4059 before pushing.
4058
4060
4059 Use --new-branch if you want to allow push to create a new named
4061 Use --new-branch if you want to allow push to create a new named
4060 branch that is not present at the destination. This allows you to
4062 branch that is not present at the destination. This allows you to
4061 only create a new branch without forcing other changes.
4063 only create a new branch without forcing other changes.
4062
4064
4063 .. note::
4065 .. note::
4064
4066
4065 Extra care should be taken with the -f/--force option,
4067 Extra care should be taken with the -f/--force option,
4066 which will push all new heads on all branches, an action which will
4068 which will push all new heads on all branches, an action which will
4067 almost always cause confusion for collaborators.
4069 almost always cause confusion for collaborators.
4068
4070
4069 If -r/--rev is used, the specified revision and all its ancestors
4071 If -r/--rev is used, the specified revision and all its ancestors
4070 will be pushed to the remote repository.
4072 will be pushed to the remote repository.
4071
4073
4072 If -B/--bookmark is used, the specified bookmarked revision, its
4074 If -B/--bookmark is used, the specified bookmarked revision, its
4073 ancestors, and the bookmark will be pushed to the remote
4075 ancestors, and the bookmark will be pushed to the remote
4074 repository. Specifying ``.`` is equivalent to specifying the active
4076 repository. Specifying ``.`` is equivalent to specifying the active
4075 bookmark's name.
4077 bookmark's name.
4076
4078
4077 Please see :hg:`help urls` for important details about ``ssh://``
4079 Please see :hg:`help urls` for important details about ``ssh://``
4078 URLs. If DESTINATION is omitted, a default path will be used.
4080 URLs. If DESTINATION is omitted, a default path will be used.
4079
4081
4080 .. container:: verbose
4082 .. container:: verbose
4081
4083
4082 The --pushvars option sends strings to the server that become
4084 The --pushvars option sends strings to the server that become
4083 environment variables prepended with ``HG_USERVAR_``. For example,
4085 environment variables prepended with ``HG_USERVAR_``. For example,
4084 ``--pushvars ENABLE_FEATURE=true``, provides the server side hooks with
4086 ``--pushvars ENABLE_FEATURE=true``, provides the server side hooks with
4085 ``HG_USERVAR_ENABLE_FEATURE=true`` as part of their environment.
4087 ``HG_USERVAR_ENABLE_FEATURE=true`` as part of their environment.
4086
4088
4087 pushvars can provide for user-overridable hooks as well as set debug
4089 pushvars can provide for user-overridable hooks as well as set debug
4088 levels. One example is having a hook that blocks commits containing
4090 levels. One example is having a hook that blocks commits containing
4089 conflict markers, but enables the user to override the hook if the file
4091 conflict markers, but enables the user to override the hook if the file
4090 is using conflict markers for testing purposes or the file format has
4092 is using conflict markers for testing purposes or the file format has
4091 strings that look like conflict markers.
4093 strings that look like conflict markers.
4092
4094
4093 By default, servers will ignore `--pushvars`. To enable it add the
4095 By default, servers will ignore `--pushvars`. To enable it add the
4094 following to your configuration file::
4096 following to your configuration file::
4095
4097
4096 [push]
4098 [push]
4097 pushvars.server = true
4099 pushvars.server = true
4098
4100
4099 Returns 0 if push was successful, 1 if nothing to push.
4101 Returns 0 if push was successful, 1 if nothing to push.
4100 """
4102 """
4101
4103
4102 opts = pycompat.byteskwargs(opts)
4104 opts = pycompat.byteskwargs(opts)
4103 if opts.get('bookmark'):
4105 if opts.get('bookmark'):
4104 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
4106 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
4105 for b in opts['bookmark']:
4107 for b in opts['bookmark']:
4106 # translate -B options to -r so changesets get pushed
4108 # translate -B options to -r so changesets get pushed
4107 b = repo._bookmarks.expandname(b)
4109 b = repo._bookmarks.expandname(b)
4108 if b in repo._bookmarks:
4110 if b in repo._bookmarks:
4109 opts.setdefault('rev', []).append(b)
4111 opts.setdefault('rev', []).append(b)
4110 else:
4112 else:
4111 # if we try to push a deleted bookmark, translate it to null
4113 # if we try to push a deleted bookmark, translate it to null
4112 # this lets simultaneous -r, -b options continue working
4114 # this lets simultaneous -r, -b options continue working
4113 opts.setdefault('rev', []).append("null")
4115 opts.setdefault('rev', []).append("null")
4114
4116
4115 path = ui.paths.getpath(dest, default=('default-push', 'default'))
4117 path = ui.paths.getpath(dest, default=('default-push', 'default'))
4116 if not path:
4118 if not path:
4117 raise error.Abort(_('default repository not configured!'),
4119 raise error.Abort(_('default repository not configured!'),
4118 hint=_("see 'hg help config.paths'"))
4120 hint=_("see 'hg help config.paths'"))
4119 dest = path.pushloc or path.loc
4121 dest = path.pushloc or path.loc
4120 branches = (path.branch, opts.get('branch') or [])
4122 branches = (path.branch, opts.get('branch') or [])
4121 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4123 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4122 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4124 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4123 other = hg.peer(repo, opts, dest)
4125 other = hg.peer(repo, opts, dest)
4124
4126
4125 if revs:
4127 if revs:
4126 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4128 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4127 if not revs:
4129 if not revs:
4128 raise error.Abort(_("specified revisions evaluate to an empty set"),
4130 raise error.Abort(_("specified revisions evaluate to an empty set"),
4129 hint=_("use different revision arguments"))
4131 hint=_("use different revision arguments"))
4130 elif path.pushrev:
4132 elif path.pushrev:
4131 # It doesn't make any sense to specify ancestor revisions. So limit
4133 # It doesn't make any sense to specify ancestor revisions. So limit
4132 # to DAG heads to make discovery simpler.
4134 # to DAG heads to make discovery simpler.
4133 expr = revsetlang.formatspec('heads(%r)', path.pushrev)
4135 expr = revsetlang.formatspec('heads(%r)', path.pushrev)
4134 revs = scmutil.revrange(repo, [expr])
4136 revs = scmutil.revrange(repo, [expr])
4135 revs = [repo[rev].node() for rev in revs]
4137 revs = [repo[rev].node() for rev in revs]
4136 if not revs:
4138 if not revs:
4137 raise error.Abort(_('default push revset for path evaluates to an '
4139 raise error.Abort(_('default push revset for path evaluates to an '
4138 'empty set'))
4140 'empty set'))
4139
4141
4140 repo._subtoppath = dest
4142 repo._subtoppath = dest
4141 try:
4143 try:
4142 # push subrepos depth-first for coherent ordering
4144 # push subrepos depth-first for coherent ordering
4143 c = repo['']
4145 c = repo['']
4144 subs = c.substate # only repos that are committed
4146 subs = c.substate # only repos that are committed
4145 for s in sorted(subs):
4147 for s in sorted(subs):
4146 result = c.sub(s).push(opts)
4148 result = c.sub(s).push(opts)
4147 if result == 0:
4149 if result == 0:
4148 return not result
4150 return not result
4149 finally:
4151 finally:
4150 del repo._subtoppath
4152 del repo._subtoppath
4151
4153
4152 opargs = dict(opts.get('opargs', {})) # copy opargs since we may mutate it
4154 opargs = dict(opts.get('opargs', {})) # copy opargs since we may mutate it
4153 opargs.setdefault('pushvars', []).extend(opts.get('pushvars', []))
4155 opargs.setdefault('pushvars', []).extend(opts.get('pushvars', []))
4154
4156
4155 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
4157 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
4156 newbranch=opts.get('new_branch'),
4158 newbranch=opts.get('new_branch'),
4157 bookmarks=opts.get('bookmark', ()),
4159 bookmarks=opts.get('bookmark', ()),
4158 opargs=opargs)
4160 opargs=opargs)
4159
4161
4160 result = not pushop.cgresult
4162 result = not pushop.cgresult
4161
4163
4162 if pushop.bkresult is not None:
4164 if pushop.bkresult is not None:
4163 if pushop.bkresult == 2:
4165 if pushop.bkresult == 2:
4164 result = 2
4166 result = 2
4165 elif not result and pushop.bkresult:
4167 elif not result and pushop.bkresult:
4166 result = 2
4168 result = 2
4167
4169
4168 return result
4170 return result
4169
4171
4170 @command('recover', [])
4172 @command('recover', [])
4171 def recover(ui, repo):
4173 def recover(ui, repo):
4172 """roll back an interrupted transaction
4174 """roll back an interrupted transaction
4173
4175
4174 Recover from an interrupted commit or pull.
4176 Recover from an interrupted commit or pull.
4175
4177
4176 This command tries to fix the repository status after an
4178 This command tries to fix the repository status after an
4177 interrupted operation. It should only be necessary when Mercurial
4179 interrupted operation. It should only be necessary when Mercurial
4178 suggests it.
4180 suggests it.
4179
4181
4180 Returns 0 if successful, 1 if nothing to recover or verify fails.
4182 Returns 0 if successful, 1 if nothing to recover or verify fails.
4181 """
4183 """
4182 if repo.recover():
4184 if repo.recover():
4183 return hg.verify(repo)
4185 return hg.verify(repo)
4184 return 1
4186 return 1
4185
4187
4186 @command('^remove|rm',
4188 @command('^remove|rm',
4187 [('A', 'after', None, _('record delete for missing files')),
4189 [('A', 'after', None, _('record delete for missing files')),
4188 ('f', 'force', None,
4190 ('f', 'force', None,
4189 _('forget added files, delete modified files')),
4191 _('forget added files, delete modified files')),
4190 ] + subrepoopts + walkopts,
4192 ] + subrepoopts + walkopts,
4191 _('[OPTION]... FILE...'),
4193 _('[OPTION]... FILE...'),
4192 inferrepo=True)
4194 inferrepo=True)
4193 def remove(ui, repo, *pats, **opts):
4195 def remove(ui, repo, *pats, **opts):
4194 """remove the specified files on the next commit
4196 """remove the specified files on the next commit
4195
4197
4196 Schedule the indicated files for removal from the current branch.
4198 Schedule the indicated files for removal from the current branch.
4197
4199
4198 This command schedules the files to be removed at the next commit.
4200 This command schedules the files to be removed at the next commit.
4199 To undo a remove before that, see :hg:`revert`. To undo added
4201 To undo a remove before that, see :hg:`revert`. To undo added
4200 files, see :hg:`forget`.
4202 files, see :hg:`forget`.
4201
4203
4202 .. container:: verbose
4204 .. container:: verbose
4203
4205
4204 -A/--after can be used to remove only files that have already
4206 -A/--after can be used to remove only files that have already
4205 been deleted, -f/--force can be used to force deletion, and -Af
4207 been deleted, -f/--force can be used to force deletion, and -Af
4206 can be used to remove files from the next revision without
4208 can be used to remove files from the next revision without
4207 deleting them from the working directory.
4209 deleting them from the working directory.
4208
4210
4209 The following table details the behavior of remove for different
4211 The following table details the behavior of remove for different
4210 file states (columns) and option combinations (rows). The file
4212 file states (columns) and option combinations (rows). The file
4211 states are Added [A], Clean [C], Modified [M] and Missing [!]
4213 states are Added [A], Clean [C], Modified [M] and Missing [!]
4212 (as reported by :hg:`status`). The actions are Warn, Remove
4214 (as reported by :hg:`status`). The actions are Warn, Remove
4213 (from branch) and Delete (from disk):
4215 (from branch) and Delete (from disk):
4214
4216
4215 ========= == == == ==
4217 ========= == == == ==
4216 opt/state A C M !
4218 opt/state A C M !
4217 ========= == == == ==
4219 ========= == == == ==
4218 none W RD W R
4220 none W RD W R
4219 -f R RD RD R
4221 -f R RD RD R
4220 -A W W W R
4222 -A W W W R
4221 -Af R R R R
4223 -Af R R R R
4222 ========= == == == ==
4224 ========= == == == ==
4223
4225
4224 .. note::
4226 .. note::
4225
4227
4226 :hg:`remove` never deletes files in Added [A] state from the
4228 :hg:`remove` never deletes files in Added [A] state from the
4227 working directory, not even if ``--force`` is specified.
4229 working directory, not even if ``--force`` is specified.
4228
4230
4229 Returns 0 on success, 1 if any warnings encountered.
4231 Returns 0 on success, 1 if any warnings encountered.
4230 """
4232 """
4231
4233
4232 opts = pycompat.byteskwargs(opts)
4234 opts = pycompat.byteskwargs(opts)
4233 after, force = opts.get('after'), opts.get('force')
4235 after, force = opts.get('after'), opts.get('force')
4234 if not pats and not after:
4236 if not pats and not after:
4235 raise error.Abort(_('no files specified'))
4237 raise error.Abort(_('no files specified'))
4236
4238
4237 m = scmutil.match(repo[None], pats, opts)
4239 m = scmutil.match(repo[None], pats, opts)
4238 subrepos = opts.get('subrepos')
4240 subrepos = opts.get('subrepos')
4239 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
4241 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
4240
4242
4241 @command('rename|move|mv',
4243 @command('rename|move|mv',
4242 [('A', 'after', None, _('record a rename that has already occurred')),
4244 [('A', 'after', None, _('record a rename that has already occurred')),
4243 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4245 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4244 ] + walkopts + dryrunopts,
4246 ] + walkopts + dryrunopts,
4245 _('[OPTION]... SOURCE... DEST'))
4247 _('[OPTION]... SOURCE... DEST'))
4246 def rename(ui, repo, *pats, **opts):
4248 def rename(ui, repo, *pats, **opts):
4247 """rename files; equivalent of copy + remove
4249 """rename files; equivalent of copy + remove
4248
4250
4249 Mark dest as copies of sources; mark sources for deletion. If dest
4251 Mark dest as copies of sources; mark sources for deletion. If dest
4250 is a directory, copies are put in that directory. If dest is a
4252 is a directory, copies are put in that directory. If dest is a
4251 file, there can only be one source.
4253 file, there can only be one source.
4252
4254
4253 By default, this command copies the contents of files as they
4255 By default, this command copies the contents of files as they
4254 exist in the working directory. If invoked with -A/--after, the
4256 exist in the working directory. If invoked with -A/--after, the
4255 operation is recorded, but no copying is performed.
4257 operation is recorded, but no copying is performed.
4256
4258
4257 This command takes effect at the next commit. To undo a rename
4259 This command takes effect at the next commit. To undo a rename
4258 before that, see :hg:`revert`.
4260 before that, see :hg:`revert`.
4259
4261
4260 Returns 0 on success, 1 if errors are encountered.
4262 Returns 0 on success, 1 if errors are encountered.
4261 """
4263 """
4262 opts = pycompat.byteskwargs(opts)
4264 opts = pycompat.byteskwargs(opts)
4263 with repo.wlock(False):
4265 with repo.wlock(False):
4264 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4266 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4265
4267
4266 @command('resolve',
4268 @command('resolve',
4267 [('a', 'all', None, _('select all unresolved files')),
4269 [('a', 'all', None, _('select all unresolved files')),
4268 ('l', 'list', None, _('list state of files needing merge')),
4270 ('l', 'list', None, _('list state of files needing merge')),
4269 ('m', 'mark', None, _('mark files as resolved')),
4271 ('m', 'mark', None, _('mark files as resolved')),
4270 ('u', 'unmark', None, _('mark files as unresolved')),
4272 ('u', 'unmark', None, _('mark files as unresolved')),
4271 ('n', 'no-status', None, _('hide status prefix'))]
4273 ('n', 'no-status', None, _('hide status prefix'))]
4272 + mergetoolopts + walkopts + formatteropts,
4274 + mergetoolopts + walkopts + formatteropts,
4273 _('[OPTION]... [FILE]...'),
4275 _('[OPTION]... [FILE]...'),
4274 inferrepo=True)
4276 inferrepo=True)
4275 def resolve(ui, repo, *pats, **opts):
4277 def resolve(ui, repo, *pats, **opts):
4276 """redo merges or set/view the merge status of files
4278 """redo merges or set/view the merge status of files
4277
4279
4278 Merges with unresolved conflicts are often the result of
4280 Merges with unresolved conflicts are often the result of
4279 non-interactive merging using the ``internal:merge`` configuration
4281 non-interactive merging using the ``internal:merge`` configuration
4280 setting, or a command-line merge tool like ``diff3``. The resolve
4282 setting, or a command-line merge tool like ``diff3``. The resolve
4281 command is used to manage the files involved in a merge, after
4283 command is used to manage the files involved in a merge, after
4282 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4284 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4283 working directory must have two parents). See :hg:`help
4285 working directory must have two parents). See :hg:`help
4284 merge-tools` for information on configuring merge tools.
4286 merge-tools` for information on configuring merge tools.
4285
4287
4286 The resolve command can be used in the following ways:
4288 The resolve command can be used in the following ways:
4287
4289
4288 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4290 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4289 files, discarding any previous merge attempts. Re-merging is not
4291 files, discarding any previous merge attempts. Re-merging is not
4290 performed for files already marked as resolved. Use ``--all/-a``
4292 performed for files already marked as resolved. Use ``--all/-a``
4291 to select all unresolved files. ``--tool`` can be used to specify
4293 to select all unresolved files. ``--tool`` can be used to specify
4292 the merge tool used for the given files. It overrides the HGMERGE
4294 the merge tool used for the given files. It overrides the HGMERGE
4293 environment variable and your configuration files. Previous file
4295 environment variable and your configuration files. Previous file
4294 contents are saved with a ``.orig`` suffix.
4296 contents are saved with a ``.orig`` suffix.
4295
4297
4296 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4298 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4297 (e.g. after having manually fixed-up the files). The default is
4299 (e.g. after having manually fixed-up the files). The default is
4298 to mark all unresolved files.
4300 to mark all unresolved files.
4299
4301
4300 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4302 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4301 default is to mark all resolved files.
4303 default is to mark all resolved files.
4302
4304
4303 - :hg:`resolve -l`: list files which had or still have conflicts.
4305 - :hg:`resolve -l`: list files which had or still have conflicts.
4304 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4306 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4305 You can use ``set:unresolved()`` or ``set:resolved()`` to filter
4307 You can use ``set:unresolved()`` or ``set:resolved()`` to filter
4306 the list. See :hg:`help filesets` for details.
4308 the list. See :hg:`help filesets` for details.
4307
4309
4308 .. note::
4310 .. note::
4309
4311
4310 Mercurial will not let you commit files with unresolved merge
4312 Mercurial will not let you commit files with unresolved merge
4311 conflicts. You must use :hg:`resolve -m ...` before you can
4313 conflicts. You must use :hg:`resolve -m ...` before you can
4312 commit after a conflicting merge.
4314 commit after a conflicting merge.
4313
4315
4314 Returns 0 on success, 1 if any files fail a resolve attempt.
4316 Returns 0 on success, 1 if any files fail a resolve attempt.
4315 """
4317 """
4316
4318
4317 opts = pycompat.byteskwargs(opts)
4319 opts = pycompat.byteskwargs(opts)
4318 flaglist = 'all mark unmark list no_status'.split()
4320 flaglist = 'all mark unmark list no_status'.split()
4319 all, mark, unmark, show, nostatus = \
4321 all, mark, unmark, show, nostatus = \
4320 [opts.get(o) for o in flaglist]
4322 [opts.get(o) for o in flaglist]
4321
4323
4322 if (show and (mark or unmark)) or (mark and unmark):
4324 if (show and (mark or unmark)) or (mark and unmark):
4323 raise error.Abort(_("too many options specified"))
4325 raise error.Abort(_("too many options specified"))
4324 if pats and all:
4326 if pats and all:
4325 raise error.Abort(_("can't specify --all and patterns"))
4327 raise error.Abort(_("can't specify --all and patterns"))
4326 if not (all or pats or show or mark or unmark):
4328 if not (all or pats or show or mark or unmark):
4327 raise error.Abort(_('no files or directories specified'),
4329 raise error.Abort(_('no files or directories specified'),
4328 hint=('use --all to re-merge all unresolved files'))
4330 hint=('use --all to re-merge all unresolved files'))
4329
4331
4330 if show:
4332 if show:
4331 ui.pager('resolve')
4333 ui.pager('resolve')
4332 fm = ui.formatter('resolve', opts)
4334 fm = ui.formatter('resolve', opts)
4333 ms = mergemod.mergestate.read(repo)
4335 ms = mergemod.mergestate.read(repo)
4334 m = scmutil.match(repo[None], pats, opts)
4336 m = scmutil.match(repo[None], pats, opts)
4335
4337
4336 # Labels and keys based on merge state. Unresolved path conflicts show
4338 # Labels and keys based on merge state. Unresolved path conflicts show
4337 # as 'P'. Resolved path conflicts show as 'R', the same as normal
4339 # as 'P'. Resolved path conflicts show as 'R', the same as normal
4338 # resolved conflicts.
4340 # resolved conflicts.
4339 mergestateinfo = {
4341 mergestateinfo = {
4340 'u': ('resolve.unresolved', 'U'),
4342 'u': ('resolve.unresolved', 'U'),
4341 'r': ('resolve.resolved', 'R'),
4343 'r': ('resolve.resolved', 'R'),
4342 'pu': ('resolve.unresolved', 'P'),
4344 'pu': ('resolve.unresolved', 'P'),
4343 'pr': ('resolve.resolved', 'R'),
4345 'pr': ('resolve.resolved', 'R'),
4344 'd': ('resolve.driverresolved', 'D'),
4346 'd': ('resolve.driverresolved', 'D'),
4345 }
4347 }
4346
4348
4347 for f in ms:
4349 for f in ms:
4348 if not m(f):
4350 if not m(f):
4349 continue
4351 continue
4350
4352
4351 label, key = mergestateinfo[ms[f]]
4353 label, key = mergestateinfo[ms[f]]
4352 fm.startitem()
4354 fm.startitem()
4353 fm.condwrite(not nostatus, 'status', '%s ', key, label=label)
4355 fm.condwrite(not nostatus, 'status', '%s ', key, label=label)
4354 fm.write('path', '%s\n', f, label=label)
4356 fm.write('path', '%s\n', f, label=label)
4355 fm.end()
4357 fm.end()
4356 return 0
4358 return 0
4357
4359
4358 with repo.wlock():
4360 with repo.wlock():
4359 ms = mergemod.mergestate.read(repo)
4361 ms = mergemod.mergestate.read(repo)
4360
4362
4361 if not (ms.active() or repo.dirstate.p2() != nullid):
4363 if not (ms.active() or repo.dirstate.p2() != nullid):
4362 raise error.Abort(
4364 raise error.Abort(
4363 _('resolve command not applicable when not merging'))
4365 _('resolve command not applicable when not merging'))
4364
4366
4365 wctx = repo[None]
4367 wctx = repo[None]
4366
4368
4367 if ms.mergedriver and ms.mdstate() == 'u':
4369 if ms.mergedriver and ms.mdstate() == 'u':
4368 proceed = mergemod.driverpreprocess(repo, ms, wctx)
4370 proceed = mergemod.driverpreprocess(repo, ms, wctx)
4369 ms.commit()
4371 ms.commit()
4370 # allow mark and unmark to go through
4372 # allow mark and unmark to go through
4371 if not mark and not unmark and not proceed:
4373 if not mark and not unmark and not proceed:
4372 return 1
4374 return 1
4373
4375
4374 m = scmutil.match(wctx, pats, opts)
4376 m = scmutil.match(wctx, pats, opts)
4375 ret = 0
4377 ret = 0
4376 didwork = False
4378 didwork = False
4377 runconclude = False
4379 runconclude = False
4378
4380
4379 tocomplete = []
4381 tocomplete = []
4380 for f in ms:
4382 for f in ms:
4381 if not m(f):
4383 if not m(f):
4382 continue
4384 continue
4383
4385
4384 didwork = True
4386 didwork = True
4385
4387
4386 # don't let driver-resolved files be marked, and run the conclude
4388 # don't let driver-resolved files be marked, and run the conclude
4387 # step if asked to resolve
4389 # step if asked to resolve
4388 if ms[f] == "d":
4390 if ms[f] == "d":
4389 exact = m.exact(f)
4391 exact = m.exact(f)
4390 if mark:
4392 if mark:
4391 if exact:
4393 if exact:
4392 ui.warn(_('not marking %s as it is driver-resolved\n')
4394 ui.warn(_('not marking %s as it is driver-resolved\n')
4393 % f)
4395 % f)
4394 elif unmark:
4396 elif unmark:
4395 if exact:
4397 if exact:
4396 ui.warn(_('not unmarking %s as it is driver-resolved\n')
4398 ui.warn(_('not unmarking %s as it is driver-resolved\n')
4397 % f)
4399 % f)
4398 else:
4400 else:
4399 runconclude = True
4401 runconclude = True
4400 continue
4402 continue
4401
4403
4402 # path conflicts must be resolved manually
4404 # path conflicts must be resolved manually
4403 if ms[f] in ("pu", "pr"):
4405 if ms[f] in ("pu", "pr"):
4404 if mark:
4406 if mark:
4405 ms.mark(f, "pr")
4407 ms.mark(f, "pr")
4406 elif unmark:
4408 elif unmark:
4407 ms.mark(f, "pu")
4409 ms.mark(f, "pu")
4408 elif ms[f] == "pu":
4410 elif ms[f] == "pu":
4409 ui.warn(_('%s: path conflict must be resolved manually\n')
4411 ui.warn(_('%s: path conflict must be resolved manually\n')
4410 % f)
4412 % f)
4411 continue
4413 continue
4412
4414
4413 if mark:
4415 if mark:
4414 ms.mark(f, "r")
4416 ms.mark(f, "r")
4415 elif unmark:
4417 elif unmark:
4416 ms.mark(f, "u")
4418 ms.mark(f, "u")
4417 else:
4419 else:
4418 # backup pre-resolve (merge uses .orig for its own purposes)
4420 # backup pre-resolve (merge uses .orig for its own purposes)
4419 a = repo.wjoin(f)
4421 a = repo.wjoin(f)
4420 try:
4422 try:
4421 util.copyfile(a, a + ".resolve")
4423 util.copyfile(a, a + ".resolve")
4422 except (IOError, OSError) as inst:
4424 except (IOError, OSError) as inst:
4423 if inst.errno != errno.ENOENT:
4425 if inst.errno != errno.ENOENT:
4424 raise
4426 raise
4425
4427
4426 try:
4428 try:
4427 # preresolve file
4429 # preresolve file
4428 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4430 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4429 'resolve')
4431 'resolve')
4430 complete, r = ms.preresolve(f, wctx)
4432 complete, r = ms.preresolve(f, wctx)
4431 if not complete:
4433 if not complete:
4432 tocomplete.append(f)
4434 tocomplete.append(f)
4433 elif r:
4435 elif r:
4434 ret = 1
4436 ret = 1
4435 finally:
4437 finally:
4436 ui.setconfig('ui', 'forcemerge', '', 'resolve')
4438 ui.setconfig('ui', 'forcemerge', '', 'resolve')
4437 ms.commit()
4439 ms.commit()
4438
4440
4439 # replace filemerge's .orig file with our resolve file, but only
4441 # replace filemerge's .orig file with our resolve file, but only
4440 # for merges that are complete
4442 # for merges that are complete
4441 if complete:
4443 if complete:
4442 try:
4444 try:
4443 util.rename(a + ".resolve",
4445 util.rename(a + ".resolve",
4444 scmutil.origpath(ui, repo, a))
4446 scmutil.origpath(ui, repo, a))
4445 except OSError as inst:
4447 except OSError as inst:
4446 if inst.errno != errno.ENOENT:
4448 if inst.errno != errno.ENOENT:
4447 raise
4449 raise
4448
4450
4449 for f in tocomplete:
4451 for f in tocomplete:
4450 try:
4452 try:
4451 # resolve file
4453 # resolve file
4452 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4454 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4453 'resolve')
4455 'resolve')
4454 r = ms.resolve(f, wctx)
4456 r = ms.resolve(f, wctx)
4455 if r:
4457 if r:
4456 ret = 1
4458 ret = 1
4457 finally:
4459 finally:
4458 ui.setconfig('ui', 'forcemerge', '', 'resolve')
4460 ui.setconfig('ui', 'forcemerge', '', 'resolve')
4459 ms.commit()
4461 ms.commit()
4460
4462
4461 # replace filemerge's .orig file with our resolve file
4463 # replace filemerge's .orig file with our resolve file
4462 a = repo.wjoin(f)
4464 a = repo.wjoin(f)
4463 try:
4465 try:
4464 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
4466 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
4465 except OSError as inst:
4467 except OSError as inst:
4466 if inst.errno != errno.ENOENT:
4468 if inst.errno != errno.ENOENT:
4467 raise
4469 raise
4468
4470
4469 ms.commit()
4471 ms.commit()
4470 ms.recordactions()
4472 ms.recordactions()
4471
4473
4472 if not didwork and pats:
4474 if not didwork and pats:
4473 hint = None
4475 hint = None
4474 if not any([p for p in pats if p.find(':') >= 0]):
4476 if not any([p for p in pats if p.find(':') >= 0]):
4475 pats = ['path:%s' % p for p in pats]
4477 pats = ['path:%s' % p for p in pats]
4476 m = scmutil.match(wctx, pats, opts)
4478 m = scmutil.match(wctx, pats, opts)
4477 for f in ms:
4479 for f in ms:
4478 if not m(f):
4480 if not m(f):
4479 continue
4481 continue
4480 flags = ''.join(['-%s ' % o[0] for o in flaglist
4482 flags = ''.join(['-%s ' % o[0] for o in flaglist
4481 if opts.get(o)])
4483 if opts.get(o)])
4482 hint = _("(try: hg resolve %s%s)\n") % (
4484 hint = _("(try: hg resolve %s%s)\n") % (
4483 flags,
4485 flags,
4484 ' '.join(pats))
4486 ' '.join(pats))
4485 break
4487 break
4486 ui.warn(_("arguments do not match paths that need resolving\n"))
4488 ui.warn(_("arguments do not match paths that need resolving\n"))
4487 if hint:
4489 if hint:
4488 ui.warn(hint)
4490 ui.warn(hint)
4489 elif ms.mergedriver and ms.mdstate() != 's':
4491 elif ms.mergedriver and ms.mdstate() != 's':
4490 # run conclude step when either a driver-resolved file is requested
4492 # run conclude step when either a driver-resolved file is requested
4491 # or there are no driver-resolved files
4493 # or there are no driver-resolved files
4492 # we can't use 'ret' to determine whether any files are unresolved
4494 # we can't use 'ret' to determine whether any files are unresolved
4493 # because we might not have tried to resolve some
4495 # because we might not have tried to resolve some
4494 if ((runconclude or not list(ms.driverresolved()))
4496 if ((runconclude or not list(ms.driverresolved()))
4495 and not list(ms.unresolved())):
4497 and not list(ms.unresolved())):
4496 proceed = mergemod.driverconclude(repo, ms, wctx)
4498 proceed = mergemod.driverconclude(repo, ms, wctx)
4497 ms.commit()
4499 ms.commit()
4498 if not proceed:
4500 if not proceed:
4499 return 1
4501 return 1
4500
4502
4501 # Nudge users into finishing an unfinished operation
4503 # Nudge users into finishing an unfinished operation
4502 unresolvedf = list(ms.unresolved())
4504 unresolvedf = list(ms.unresolved())
4503 driverresolvedf = list(ms.driverresolved())
4505 driverresolvedf = list(ms.driverresolved())
4504 if not unresolvedf and not driverresolvedf:
4506 if not unresolvedf and not driverresolvedf:
4505 ui.status(_('(no more unresolved files)\n'))
4507 ui.status(_('(no more unresolved files)\n'))
4506 cmdutil.checkafterresolved(repo)
4508 cmdutil.checkafterresolved(repo)
4507 elif not unresolvedf:
4509 elif not unresolvedf:
4508 ui.status(_('(no more unresolved files -- '
4510 ui.status(_('(no more unresolved files -- '
4509 'run "hg resolve --all" to conclude)\n'))
4511 'run "hg resolve --all" to conclude)\n'))
4510
4512
4511 return ret
4513 return ret
4512
4514
4513 @command('revert',
4515 @command('revert',
4514 [('a', 'all', None, _('revert all changes when no arguments given')),
4516 [('a', 'all', None, _('revert all changes when no arguments given')),
4515 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4517 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4516 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4518 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4517 ('C', 'no-backup', None, _('do not save backup copies of files')),
4519 ('C', 'no-backup', None, _('do not save backup copies of files')),
4518 ('i', 'interactive', None, _('interactively select the changes')),
4520 ('i', 'interactive', None, _('interactively select the changes')),
4519 ] + walkopts + dryrunopts,
4521 ] + walkopts + dryrunopts,
4520 _('[OPTION]... [-r REV] [NAME]...'))
4522 _('[OPTION]... [-r REV] [NAME]...'))
4521 def revert(ui, repo, *pats, **opts):
4523 def revert(ui, repo, *pats, **opts):
4522 """restore files to their checkout state
4524 """restore files to their checkout state
4523
4525
4524 .. note::
4526 .. note::
4525
4527
4526 To check out earlier revisions, you should use :hg:`update REV`.
4528 To check out earlier revisions, you should use :hg:`update REV`.
4527 To cancel an uncommitted merge (and lose your changes),
4529 To cancel an uncommitted merge (and lose your changes),
4528 use :hg:`update --clean .`.
4530 use :hg:`update --clean .`.
4529
4531
4530 With no revision specified, revert the specified files or directories
4532 With no revision specified, revert the specified files or directories
4531 to the contents they had in the parent of the working directory.
4533 to the contents they had in the parent of the working directory.
4532 This restores the contents of files to an unmodified
4534 This restores the contents of files to an unmodified
4533 state and unschedules adds, removes, copies, and renames. If the
4535 state and unschedules adds, removes, copies, and renames. If the
4534 working directory has two parents, you must explicitly specify a
4536 working directory has two parents, you must explicitly specify a
4535 revision.
4537 revision.
4536
4538
4537 Using the -r/--rev or -d/--date options, revert the given files or
4539 Using the -r/--rev or -d/--date options, revert the given files or
4538 directories to their states as of a specific revision. Because
4540 directories to their states as of a specific revision. Because
4539 revert does not change the working directory parents, this will
4541 revert does not change the working directory parents, this will
4540 cause these files to appear modified. This can be helpful to "back
4542 cause these files to appear modified. This can be helpful to "back
4541 out" some or all of an earlier change. See :hg:`backout` for a
4543 out" some or all of an earlier change. See :hg:`backout` for a
4542 related method.
4544 related method.
4543
4545
4544 Modified files are saved with a .orig suffix before reverting.
4546 Modified files are saved with a .orig suffix before reverting.
4545 To disable these backups, use --no-backup. It is possible to store
4547 To disable these backups, use --no-backup. It is possible to store
4546 the backup files in a custom directory relative to the root of the
4548 the backup files in a custom directory relative to the root of the
4547 repository by setting the ``ui.origbackuppath`` configuration
4549 repository by setting the ``ui.origbackuppath`` configuration
4548 option.
4550 option.
4549
4551
4550 See :hg:`help dates` for a list of formats valid for -d/--date.
4552 See :hg:`help dates` for a list of formats valid for -d/--date.
4551
4553
4552 See :hg:`help backout` for a way to reverse the effect of an
4554 See :hg:`help backout` for a way to reverse the effect of an
4553 earlier changeset.
4555 earlier changeset.
4554
4556
4555 Returns 0 on success.
4557 Returns 0 on success.
4556 """
4558 """
4557
4559
4558 opts = pycompat.byteskwargs(opts)
4560 opts = pycompat.byteskwargs(opts)
4559 if opts.get("date"):
4561 if opts.get("date"):
4560 if opts.get("rev"):
4562 if opts.get("rev"):
4561 raise error.Abort(_("you can't specify a revision and a date"))
4563 raise error.Abort(_("you can't specify a revision and a date"))
4562 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4564 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4563
4565
4564 parent, p2 = repo.dirstate.parents()
4566 parent, p2 = repo.dirstate.parents()
4565 if not opts.get('rev') and p2 != nullid:
4567 if not opts.get('rev') and p2 != nullid:
4566 # revert after merge is a trap for new users (issue2915)
4568 # revert after merge is a trap for new users (issue2915)
4567 raise error.Abort(_('uncommitted merge with no revision specified'),
4569 raise error.Abort(_('uncommitted merge with no revision specified'),
4568 hint=_("use 'hg update' or see 'hg help revert'"))
4570 hint=_("use 'hg update' or see 'hg help revert'"))
4569
4571
4570 ctx = scmutil.revsingle(repo, opts.get('rev'))
4572 ctx = scmutil.revsingle(repo, opts.get('rev'))
4571
4573
4572 if (not (pats or opts.get('include') or opts.get('exclude') or
4574 if (not (pats or opts.get('include') or opts.get('exclude') or
4573 opts.get('all') or opts.get('interactive'))):
4575 opts.get('all') or opts.get('interactive'))):
4574 msg = _("no files or directories specified")
4576 msg = _("no files or directories specified")
4575 if p2 != nullid:
4577 if p2 != nullid:
4576 hint = _("uncommitted merge, use --all to discard all changes,"
4578 hint = _("uncommitted merge, use --all to discard all changes,"
4577 " or 'hg update -C .' to abort the merge")
4579 " or 'hg update -C .' to abort the merge")
4578 raise error.Abort(msg, hint=hint)
4580 raise error.Abort(msg, hint=hint)
4579 dirty = any(repo.status())
4581 dirty = any(repo.status())
4580 node = ctx.node()
4582 node = ctx.node()
4581 if node != parent:
4583 if node != parent:
4582 if dirty:
4584 if dirty:
4583 hint = _("uncommitted changes, use --all to discard all"
4585 hint = _("uncommitted changes, use --all to discard all"
4584 " changes, or 'hg update %s' to update") % ctx.rev()
4586 " changes, or 'hg update %s' to update") % ctx.rev()
4585 else:
4587 else:
4586 hint = _("use --all to revert all files,"
4588 hint = _("use --all to revert all files,"
4587 " or 'hg update %s' to update") % ctx.rev()
4589 " or 'hg update %s' to update") % ctx.rev()
4588 elif dirty:
4590 elif dirty:
4589 hint = _("uncommitted changes, use --all to discard all changes")
4591 hint = _("uncommitted changes, use --all to discard all changes")
4590 else:
4592 else:
4591 hint = _("use --all to revert all files")
4593 hint = _("use --all to revert all files")
4592 raise error.Abort(msg, hint=hint)
4594 raise error.Abort(msg, hint=hint)
4593
4595
4594 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats,
4596 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats,
4595 **pycompat.strkwargs(opts))
4597 **pycompat.strkwargs(opts))
4596
4598
4597 @command('rollback', dryrunopts +
4599 @command('rollback', dryrunopts +
4598 [('f', 'force', False, _('ignore safety measures'))])
4600 [('f', 'force', False, _('ignore safety measures'))])
4599 def rollback(ui, repo, **opts):
4601 def rollback(ui, repo, **opts):
4600 """roll back the last transaction (DANGEROUS) (DEPRECATED)
4602 """roll back the last transaction (DANGEROUS) (DEPRECATED)
4601
4603
4602 Please use :hg:`commit --amend` instead of rollback to correct
4604 Please use :hg:`commit --amend` instead of rollback to correct
4603 mistakes in the last commit.
4605 mistakes in the last commit.
4604
4606
4605 This command should be used with care. There is only one level of
4607 This command should be used with care. There is only one level of
4606 rollback, and there is no way to undo a rollback. It will also
4608 rollback, and there is no way to undo a rollback. It will also
4607 restore the dirstate at the time of the last transaction, losing
4609 restore the dirstate at the time of the last transaction, losing
4608 any dirstate changes since that time. This command does not alter
4610 any dirstate changes since that time. This command does not alter
4609 the working directory.
4611 the working directory.
4610
4612
4611 Transactions are used to encapsulate the effects of all commands
4613 Transactions are used to encapsulate the effects of all commands
4612 that create new changesets or propagate existing changesets into a
4614 that create new changesets or propagate existing changesets into a
4613 repository.
4615 repository.
4614
4616
4615 .. container:: verbose
4617 .. container:: verbose
4616
4618
4617 For example, the following commands are transactional, and their
4619 For example, the following commands are transactional, and their
4618 effects can be rolled back:
4620 effects can be rolled back:
4619
4621
4620 - commit
4622 - commit
4621 - import
4623 - import
4622 - pull
4624 - pull
4623 - push (with this repository as the destination)
4625 - push (with this repository as the destination)
4624 - unbundle
4626 - unbundle
4625
4627
4626 To avoid permanent data loss, rollback will refuse to rollback a
4628 To avoid permanent data loss, rollback will refuse to rollback a
4627 commit transaction if it isn't checked out. Use --force to
4629 commit transaction if it isn't checked out. Use --force to
4628 override this protection.
4630 override this protection.
4629
4631
4630 The rollback command can be entirely disabled by setting the
4632 The rollback command can be entirely disabled by setting the
4631 ``ui.rollback`` configuration setting to false. If you're here
4633 ``ui.rollback`` configuration setting to false. If you're here
4632 because you want to use rollback and it's disabled, you can
4634 because you want to use rollback and it's disabled, you can
4633 re-enable the command by setting ``ui.rollback`` to true.
4635 re-enable the command by setting ``ui.rollback`` to true.
4634
4636
4635 This command is not intended for use on public repositories. Once
4637 This command is not intended for use on public repositories. Once
4636 changes are visible for pull by other users, rolling a transaction
4638 changes are visible for pull by other users, rolling a transaction
4637 back locally is ineffective (someone else may already have pulled
4639 back locally is ineffective (someone else may already have pulled
4638 the changes). Furthermore, a race is possible with readers of the
4640 the changes). Furthermore, a race is possible with readers of the
4639 repository; for example an in-progress pull from the repository
4641 repository; for example an in-progress pull from the repository
4640 may fail if a rollback is performed.
4642 may fail if a rollback is performed.
4641
4643
4642 Returns 0 on success, 1 if no rollback data is available.
4644 Returns 0 on success, 1 if no rollback data is available.
4643 """
4645 """
4644 if not ui.configbool('ui', 'rollback'):
4646 if not ui.configbool('ui', 'rollback'):
4645 raise error.Abort(_('rollback is disabled because it is unsafe'),
4647 raise error.Abort(_('rollback is disabled because it is unsafe'),
4646 hint=('see `hg help -v rollback` for information'))
4648 hint=('see `hg help -v rollback` for information'))
4647 return repo.rollback(dryrun=opts.get(r'dry_run'),
4649 return repo.rollback(dryrun=opts.get(r'dry_run'),
4648 force=opts.get(r'force'))
4650 force=opts.get(r'force'))
4649
4651
4650 @command('root', [], cmdtype=readonly)
4652 @command('root', [], cmdtype=readonly)
4651 def root(ui, repo):
4653 def root(ui, repo):
4652 """print the root (top) of the current working directory
4654 """print the root (top) of the current working directory
4653
4655
4654 Print the root directory of the current repository.
4656 Print the root directory of the current repository.
4655
4657
4656 Returns 0 on success.
4658 Returns 0 on success.
4657 """
4659 """
4658 ui.write(repo.root + "\n")
4660 ui.write(repo.root + "\n")
4659
4661
4660 @command('^serve',
4662 @command('^serve',
4661 [('A', 'accesslog', '', _('name of access log file to write to'),
4663 [('A', 'accesslog', '', _('name of access log file to write to'),
4662 _('FILE')),
4664 _('FILE')),
4663 ('d', 'daemon', None, _('run server in background')),
4665 ('d', 'daemon', None, _('run server in background')),
4664 ('', 'daemon-postexec', [], _('used internally by daemon mode')),
4666 ('', 'daemon-postexec', [], _('used internally by daemon mode')),
4665 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4667 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4666 # use string type, then we can check if something was passed
4668 # use string type, then we can check if something was passed
4667 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4669 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4668 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4670 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4669 _('ADDR')),
4671 _('ADDR')),
4670 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4672 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4671 _('PREFIX')),
4673 _('PREFIX')),
4672 ('n', 'name', '',
4674 ('n', 'name', '',
4673 _('name to show in web pages (default: working directory)'), _('NAME')),
4675 _('name to show in web pages (default: working directory)'), _('NAME')),
4674 ('', 'web-conf', '',
4676 ('', 'web-conf', '',
4675 _("name of the hgweb config file (see 'hg help hgweb')"), _('FILE')),
4677 _("name of the hgweb config file (see 'hg help hgweb')"), _('FILE')),
4676 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4678 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4677 _('FILE')),
4679 _('FILE')),
4678 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4680 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4679 ('', 'stdio', None, _('for remote clients (ADVANCED)')),
4681 ('', 'stdio', None, _('for remote clients (ADVANCED)')),
4680 ('', 'cmdserver', '', _('for remote clients (ADVANCED)'), _('MODE')),
4682 ('', 'cmdserver', '', _('for remote clients (ADVANCED)'), _('MODE')),
4681 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4683 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4682 ('', 'style', '', _('template style to use'), _('STYLE')),
4684 ('', 'style', '', _('template style to use'), _('STYLE')),
4683 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4685 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4684 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))]
4686 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))]
4685 + subrepoopts,
4687 + subrepoopts,
4686 _('[OPTION]...'),
4688 _('[OPTION]...'),
4687 optionalrepo=True)
4689 optionalrepo=True)
4688 def serve(ui, repo, **opts):
4690 def serve(ui, repo, **opts):
4689 """start stand-alone webserver
4691 """start stand-alone webserver
4690
4692
4691 Start a local HTTP repository browser and pull server. You can use
4693 Start a local HTTP repository browser and pull server. You can use
4692 this for ad-hoc sharing and browsing of repositories. It is
4694 this for ad-hoc sharing and browsing of repositories. It is
4693 recommended to use a real web server to serve a repository for
4695 recommended to use a real web server to serve a repository for
4694 longer periods of time.
4696 longer periods of time.
4695
4697
4696 Please note that the server does not implement access control.
4698 Please note that the server does not implement access control.
4697 This means that, by default, anybody can read from the server and
4699 This means that, by default, anybody can read from the server and
4698 nobody can write to it by default. Set the ``web.allow-push``
4700 nobody can write to it by default. Set the ``web.allow-push``
4699 option to ``*`` to allow everybody to push to the server. You
4701 option to ``*`` to allow everybody to push to the server. You
4700 should use a real web server if you need to authenticate users.
4702 should use a real web server if you need to authenticate users.
4701
4703
4702 By default, the server logs accesses to stdout and errors to
4704 By default, the server logs accesses to stdout and errors to
4703 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
4705 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
4704 files.
4706 files.
4705
4707
4706 To have the server choose a free port number to listen on, specify
4708 To have the server choose a free port number to listen on, specify
4707 a port number of 0; in this case, the server will print the port
4709 a port number of 0; in this case, the server will print the port
4708 number it uses.
4710 number it uses.
4709
4711
4710 Returns 0 on success.
4712 Returns 0 on success.
4711 """
4713 """
4712
4714
4713 opts = pycompat.byteskwargs(opts)
4715 opts = pycompat.byteskwargs(opts)
4714 if opts["stdio"] and opts["cmdserver"]:
4716 if opts["stdio"] and opts["cmdserver"]:
4715 raise error.Abort(_("cannot use --stdio with --cmdserver"))
4717 raise error.Abort(_("cannot use --stdio with --cmdserver"))
4716
4718
4717 if opts["stdio"]:
4719 if opts["stdio"]:
4718 if repo is None:
4720 if repo is None:
4719 raise error.RepoError(_("there is no Mercurial repository here"
4721 raise error.RepoError(_("there is no Mercurial repository here"
4720 " (.hg not found)"))
4722 " (.hg not found)"))
4721 s = sshserver.sshserver(ui, repo)
4723 s = sshserver.sshserver(ui, repo)
4722 s.serve_forever()
4724 s.serve_forever()
4723
4725
4724 service = server.createservice(ui, repo, opts)
4726 service = server.createservice(ui, repo, opts)
4725 return server.runservice(opts, initfn=service.init, runfn=service.run)
4727 return server.runservice(opts, initfn=service.init, runfn=service.run)
4726
4728
4727 @command('^status|st',
4729 @command('^status|st',
4728 [('A', 'all', None, _('show status of all files')),
4730 [('A', 'all', None, _('show status of all files')),
4729 ('m', 'modified', None, _('show only modified files')),
4731 ('m', 'modified', None, _('show only modified files')),
4730 ('a', 'added', None, _('show only added files')),
4732 ('a', 'added', None, _('show only added files')),
4731 ('r', 'removed', None, _('show only removed files')),
4733 ('r', 'removed', None, _('show only removed files')),
4732 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4734 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4733 ('c', 'clean', None, _('show only files without changes')),
4735 ('c', 'clean', None, _('show only files without changes')),
4734 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4736 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4735 ('i', 'ignored', None, _('show only ignored files')),
4737 ('i', 'ignored', None, _('show only ignored files')),
4736 ('n', 'no-status', None, _('hide status prefix')),
4738 ('n', 'no-status', None, _('hide status prefix')),
4737 ('t', 'terse', '', _('show the terse output (EXPERIMENTAL)')),
4739 ('t', 'terse', '', _('show the terse output (EXPERIMENTAL)')),
4738 ('C', 'copies', None, _('show source of copied files')),
4740 ('C', 'copies', None, _('show source of copied files')),
4739 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4741 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4740 ('', 'rev', [], _('show difference from revision'), _('REV')),
4742 ('', 'rev', [], _('show difference from revision'), _('REV')),
4741 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
4743 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
4742 ] + walkopts + subrepoopts + formatteropts,
4744 ] + walkopts + subrepoopts + formatteropts,
4743 _('[OPTION]... [FILE]...'),
4745 _('[OPTION]... [FILE]...'),
4744 inferrepo=True, cmdtype=readonly)
4746 inferrepo=True, cmdtype=readonly)
4745 def status(ui, repo, *pats, **opts):
4747 def status(ui, repo, *pats, **opts):
4746 """show changed files in the working directory
4748 """show changed files in the working directory
4747
4749
4748 Show status of files in the repository. If names are given, only
4750 Show status of files in the repository. If names are given, only
4749 files that match are shown. Files that are clean or ignored or
4751 files that match are shown. Files that are clean or ignored or
4750 the source of a copy/move operation, are not listed unless
4752 the source of a copy/move operation, are not listed unless
4751 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
4753 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
4752 Unless options described with "show only ..." are given, the
4754 Unless options described with "show only ..." are given, the
4753 options -mardu are used.
4755 options -mardu are used.
4754
4756
4755 Option -q/--quiet hides untracked (unknown and ignored) files
4757 Option -q/--quiet hides untracked (unknown and ignored) files
4756 unless explicitly requested with -u/--unknown or -i/--ignored.
4758 unless explicitly requested with -u/--unknown or -i/--ignored.
4757
4759
4758 .. note::
4760 .. note::
4759
4761
4760 :hg:`status` may appear to disagree with diff if permissions have
4762 :hg:`status` may appear to disagree with diff if permissions have
4761 changed or a merge has occurred. The standard diff format does
4763 changed or a merge has occurred. The standard diff format does
4762 not report permission changes and diff only reports changes
4764 not report permission changes and diff only reports changes
4763 relative to one merge parent.
4765 relative to one merge parent.
4764
4766
4765 If one revision is given, it is used as the base revision.
4767 If one revision is given, it is used as the base revision.
4766 If two revisions are given, the differences between them are
4768 If two revisions are given, the differences between them are
4767 shown. The --change option can also be used as a shortcut to list
4769 shown. The --change option can also be used as a shortcut to list
4768 the changed files of a revision from its first parent.
4770 the changed files of a revision from its first parent.
4769
4771
4770 The codes used to show the status of files are::
4772 The codes used to show the status of files are::
4771
4773
4772 M = modified
4774 M = modified
4773 A = added
4775 A = added
4774 R = removed
4776 R = removed
4775 C = clean
4777 C = clean
4776 ! = missing (deleted by non-hg command, but still tracked)
4778 ! = missing (deleted by non-hg command, but still tracked)
4777 ? = not tracked
4779 ? = not tracked
4778 I = ignored
4780 I = ignored
4779 = origin of the previous file (with --copies)
4781 = origin of the previous file (with --copies)
4780
4782
4781 .. container:: verbose
4783 .. container:: verbose
4782
4784
4783 The -t/--terse option abbreviates the output by showing only the directory
4785 The -t/--terse option abbreviates the output by showing only the directory
4784 name if all the files in it share the same status. The option takes an
4786 name if all the files in it share the same status. The option takes an
4785 argument indicating the statuses to abbreviate: 'm' for 'modified', 'a'
4787 argument indicating the statuses to abbreviate: 'm' for 'modified', 'a'
4786 for 'added', 'r' for 'removed', 'd' for 'deleted', 'u' for 'unknown', 'i'
4788 for 'added', 'r' for 'removed', 'd' for 'deleted', 'u' for 'unknown', 'i'
4787 for 'ignored' and 'c' for clean.
4789 for 'ignored' and 'c' for clean.
4788
4790
4789 It abbreviates only those statuses which are passed. Note that clean and
4791 It abbreviates only those statuses which are passed. Note that clean and
4790 ignored files are not displayed with '--terse ic' unless the -c/--clean
4792 ignored files are not displayed with '--terse ic' unless the -c/--clean
4791 and -i/--ignored options are also used.
4793 and -i/--ignored options are also used.
4792
4794
4793 The -v/--verbose option shows information when the repository is in an
4795 The -v/--verbose option shows information when the repository is in an
4794 unfinished merge, shelve, rebase state etc. You can have this behavior
4796 unfinished merge, shelve, rebase state etc. You can have this behavior
4795 turned on by default by enabling the ``commands.status.verbose`` option.
4797 turned on by default by enabling the ``commands.status.verbose`` option.
4796
4798
4797 You can skip displaying some of these states by setting
4799 You can skip displaying some of these states by setting
4798 ``commands.status.skipstates`` to one or more of: 'bisect', 'graft',
4800 ``commands.status.skipstates`` to one or more of: 'bisect', 'graft',
4799 'histedit', 'merge', 'rebase', or 'unshelve'.
4801 'histedit', 'merge', 'rebase', or 'unshelve'.
4800
4802
4801 Examples:
4803 Examples:
4802
4804
4803 - show changes in the working directory relative to a
4805 - show changes in the working directory relative to a
4804 changeset::
4806 changeset::
4805
4807
4806 hg status --rev 9353
4808 hg status --rev 9353
4807
4809
4808 - show changes in the working directory relative to the
4810 - show changes in the working directory relative to the
4809 current directory (see :hg:`help patterns` for more information)::
4811 current directory (see :hg:`help patterns` for more information)::
4810
4812
4811 hg status re:
4813 hg status re:
4812
4814
4813 - show all changes including copies in an existing changeset::
4815 - show all changes including copies in an existing changeset::
4814
4816
4815 hg status --copies --change 9353
4817 hg status --copies --change 9353
4816
4818
4817 - get a NUL separated list of added files, suitable for xargs::
4819 - get a NUL separated list of added files, suitable for xargs::
4818
4820
4819 hg status -an0
4821 hg status -an0
4820
4822
4821 - show more information about the repository status, abbreviating
4823 - show more information about the repository status, abbreviating
4822 added, removed, modified, deleted, and untracked paths::
4824 added, removed, modified, deleted, and untracked paths::
4823
4825
4824 hg status -v -t mardu
4826 hg status -v -t mardu
4825
4827
4826 Returns 0 on success.
4828 Returns 0 on success.
4827
4829
4828 """
4830 """
4829
4831
4830 opts = pycompat.byteskwargs(opts)
4832 opts = pycompat.byteskwargs(opts)
4831 revs = opts.get('rev')
4833 revs = opts.get('rev')
4832 change = opts.get('change')
4834 change = opts.get('change')
4833 terse = opts.get('terse')
4835 terse = opts.get('terse')
4834
4836
4835 if revs and change:
4837 if revs and change:
4836 msg = _('cannot specify --rev and --change at the same time')
4838 msg = _('cannot specify --rev and --change at the same time')
4837 raise error.Abort(msg)
4839 raise error.Abort(msg)
4838 elif revs and terse:
4840 elif revs and terse:
4839 msg = _('cannot use --terse with --rev')
4841 msg = _('cannot use --terse with --rev')
4840 raise error.Abort(msg)
4842 raise error.Abort(msg)
4841 elif change:
4843 elif change:
4842 node2 = scmutil.revsingle(repo, change, None).node()
4844 node2 = scmutil.revsingle(repo, change, None).node()
4843 node1 = repo[node2].p1().node()
4845 node1 = repo[node2].p1().node()
4844 else:
4846 else:
4845 node1, node2 = scmutil.revpair(repo, revs)
4847 node1, node2 = scmutil.revpair(repo, revs)
4846
4848
4847 if pats or ui.configbool('commands', 'status.relative'):
4849 if pats or ui.configbool('commands', 'status.relative'):
4848 cwd = repo.getcwd()
4850 cwd = repo.getcwd()
4849 else:
4851 else:
4850 cwd = ''
4852 cwd = ''
4851
4853
4852 if opts.get('print0'):
4854 if opts.get('print0'):
4853 end = '\0'
4855 end = '\0'
4854 else:
4856 else:
4855 end = '\n'
4857 end = '\n'
4856 copy = {}
4858 copy = {}
4857 states = 'modified added removed deleted unknown ignored clean'.split()
4859 states = 'modified added removed deleted unknown ignored clean'.split()
4858 show = [k for k in states if opts.get(k)]
4860 show = [k for k in states if opts.get(k)]
4859 if opts.get('all'):
4861 if opts.get('all'):
4860 show += ui.quiet and (states[:4] + ['clean']) or states
4862 show += ui.quiet and (states[:4] + ['clean']) or states
4861
4863
4862 if not show:
4864 if not show:
4863 if ui.quiet:
4865 if ui.quiet:
4864 show = states[:4]
4866 show = states[:4]
4865 else:
4867 else:
4866 show = states[:5]
4868 show = states[:5]
4867
4869
4868 m = scmutil.match(repo[node2], pats, opts)
4870 m = scmutil.match(repo[node2], pats, opts)
4869 if terse:
4871 if terse:
4870 # we need to compute clean and unknown to terse
4872 # we need to compute clean and unknown to terse
4871 stat = repo.status(node1, node2, m,
4873 stat = repo.status(node1, node2, m,
4872 'ignored' in show or 'i' in terse,
4874 'ignored' in show or 'i' in terse,
4873 True, True, opts.get('subrepos'))
4875 True, True, opts.get('subrepos'))
4874
4876
4875 stat = cmdutil.tersedir(stat, terse)
4877 stat = cmdutil.tersedir(stat, terse)
4876 else:
4878 else:
4877 stat = repo.status(node1, node2, m,
4879 stat = repo.status(node1, node2, m,
4878 'ignored' in show, 'clean' in show,
4880 'ignored' in show, 'clean' in show,
4879 'unknown' in show, opts.get('subrepos'))
4881 'unknown' in show, opts.get('subrepos'))
4880
4882
4881 changestates = zip(states, pycompat.iterbytestr('MAR!?IC'), stat)
4883 changestates = zip(states, pycompat.iterbytestr('MAR!?IC'), stat)
4882
4884
4883 if (opts.get('all') or opts.get('copies')
4885 if (opts.get('all') or opts.get('copies')
4884 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
4886 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
4885 copy = copies.pathcopies(repo[node1], repo[node2], m)
4887 copy = copies.pathcopies(repo[node1], repo[node2], m)
4886
4888
4887 ui.pager('status')
4889 ui.pager('status')
4888 fm = ui.formatter('status', opts)
4890 fm = ui.formatter('status', opts)
4889 fmt = '%s' + end
4891 fmt = '%s' + end
4890 showchar = not opts.get('no_status')
4892 showchar = not opts.get('no_status')
4891
4893
4892 for state, char, files in changestates:
4894 for state, char, files in changestates:
4893 if state in show:
4895 if state in show:
4894 label = 'status.' + state
4896 label = 'status.' + state
4895 for f in files:
4897 for f in files:
4896 fm.startitem()
4898 fm.startitem()
4897 fm.condwrite(showchar, 'status', '%s ', char, label=label)
4899 fm.condwrite(showchar, 'status', '%s ', char, label=label)
4898 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
4900 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
4899 if f in copy:
4901 if f in copy:
4900 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
4902 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
4901 label='status.copied')
4903 label='status.copied')
4902
4904
4903 if ((ui.verbose or ui.configbool('commands', 'status.verbose'))
4905 if ((ui.verbose or ui.configbool('commands', 'status.verbose'))
4904 and not ui.plain()):
4906 and not ui.plain()):
4905 cmdutil.morestatus(repo, fm)
4907 cmdutil.morestatus(repo, fm)
4906 fm.end()
4908 fm.end()
4907
4909
4908 @command('^summary|sum',
4910 @command('^summary|sum',
4909 [('', 'remote', None, _('check for push and pull'))],
4911 [('', 'remote', None, _('check for push and pull'))],
4910 '[--remote]', cmdtype=readonly)
4912 '[--remote]', cmdtype=readonly)
4911 def summary(ui, repo, **opts):
4913 def summary(ui, repo, **opts):
4912 """summarize working directory state
4914 """summarize working directory state
4913
4915
4914 This generates a brief summary of the working directory state,
4916 This generates a brief summary of the working directory state,
4915 including parents, branch, commit status, phase and available updates.
4917 including parents, branch, commit status, phase and available updates.
4916
4918
4917 With the --remote option, this will check the default paths for
4919 With the --remote option, this will check the default paths for
4918 incoming and outgoing changes. This can be time-consuming.
4920 incoming and outgoing changes. This can be time-consuming.
4919
4921
4920 Returns 0 on success.
4922 Returns 0 on success.
4921 """
4923 """
4922
4924
4923 opts = pycompat.byteskwargs(opts)
4925 opts = pycompat.byteskwargs(opts)
4924 ui.pager('summary')
4926 ui.pager('summary')
4925 ctx = repo[None]
4927 ctx = repo[None]
4926 parents = ctx.parents()
4928 parents = ctx.parents()
4927 pnode = parents[0].node()
4929 pnode = parents[0].node()
4928 marks = []
4930 marks = []
4929
4931
4930 ms = None
4932 ms = None
4931 try:
4933 try:
4932 ms = mergemod.mergestate.read(repo)
4934 ms = mergemod.mergestate.read(repo)
4933 except error.UnsupportedMergeRecords as e:
4935 except error.UnsupportedMergeRecords as e:
4934 s = ' '.join(e.recordtypes)
4936 s = ' '.join(e.recordtypes)
4935 ui.warn(
4937 ui.warn(
4936 _('warning: merge state has unsupported record types: %s\n') % s)
4938 _('warning: merge state has unsupported record types: %s\n') % s)
4937 unresolved = []
4939 unresolved = []
4938 else:
4940 else:
4939 unresolved = list(ms.unresolved())
4941 unresolved = list(ms.unresolved())
4940
4942
4941 for p in parents:
4943 for p in parents:
4942 # label with log.changeset (instead of log.parent) since this
4944 # label with log.changeset (instead of log.parent) since this
4943 # shows a working directory parent *changeset*:
4945 # shows a working directory parent *changeset*:
4944 # i18n: column positioning for "hg summary"
4946 # i18n: column positioning for "hg summary"
4945 ui.write(_('parent: %d:%s ') % (p.rev(), p),
4947 ui.write(_('parent: %d:%s ') % (p.rev(), p),
4946 label=cmdutil._changesetlabels(p))
4948 label=cmdutil._changesetlabels(p))
4947 ui.write(' '.join(p.tags()), label='log.tag')
4949 ui.write(' '.join(p.tags()), label='log.tag')
4948 if p.bookmarks():
4950 if p.bookmarks():
4949 marks.extend(p.bookmarks())
4951 marks.extend(p.bookmarks())
4950 if p.rev() == -1:
4952 if p.rev() == -1:
4951 if not len(repo):
4953 if not len(repo):
4952 ui.write(_(' (empty repository)'))
4954 ui.write(_(' (empty repository)'))
4953 else:
4955 else:
4954 ui.write(_(' (no revision checked out)'))
4956 ui.write(_(' (no revision checked out)'))
4955 if p.obsolete():
4957 if p.obsolete():
4956 ui.write(_(' (obsolete)'))
4958 ui.write(_(' (obsolete)'))
4957 if p.isunstable():
4959 if p.isunstable():
4958 instabilities = (ui.label(instability, 'trouble.%s' % instability)
4960 instabilities = (ui.label(instability, 'trouble.%s' % instability)
4959 for instability in p.instabilities())
4961 for instability in p.instabilities())
4960 ui.write(' ('
4962 ui.write(' ('
4961 + ', '.join(instabilities)
4963 + ', '.join(instabilities)
4962 + ')')
4964 + ')')
4963 ui.write('\n')
4965 ui.write('\n')
4964 if p.description():
4966 if p.description():
4965 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
4967 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
4966 label='log.summary')
4968 label='log.summary')
4967
4969
4968 branch = ctx.branch()
4970 branch = ctx.branch()
4969 bheads = repo.branchheads(branch)
4971 bheads = repo.branchheads(branch)
4970 # i18n: column positioning for "hg summary"
4972 # i18n: column positioning for "hg summary"
4971 m = _('branch: %s\n') % branch
4973 m = _('branch: %s\n') % branch
4972 if branch != 'default':
4974 if branch != 'default':
4973 ui.write(m, label='log.branch')
4975 ui.write(m, label='log.branch')
4974 else:
4976 else:
4975 ui.status(m, label='log.branch')
4977 ui.status(m, label='log.branch')
4976
4978
4977 if marks:
4979 if marks:
4978 active = repo._activebookmark
4980 active = repo._activebookmark
4979 # i18n: column positioning for "hg summary"
4981 # i18n: column positioning for "hg summary"
4980 ui.write(_('bookmarks:'), label='log.bookmark')
4982 ui.write(_('bookmarks:'), label='log.bookmark')
4981 if active is not None:
4983 if active is not None:
4982 if active in marks:
4984 if active in marks:
4983 ui.write(' *' + active, label=bookmarks.activebookmarklabel)
4985 ui.write(' *' + active, label=bookmarks.activebookmarklabel)
4984 marks.remove(active)
4986 marks.remove(active)
4985 else:
4987 else:
4986 ui.write(' [%s]' % active, label=bookmarks.activebookmarklabel)
4988 ui.write(' [%s]' % active, label=bookmarks.activebookmarklabel)
4987 for m in marks:
4989 for m in marks:
4988 ui.write(' ' + m, label='log.bookmark')
4990 ui.write(' ' + m, label='log.bookmark')
4989 ui.write('\n', label='log.bookmark')
4991 ui.write('\n', label='log.bookmark')
4990
4992
4991 status = repo.status(unknown=True)
4993 status = repo.status(unknown=True)
4992
4994
4993 c = repo.dirstate.copies()
4995 c = repo.dirstate.copies()
4994 copied, renamed = [], []
4996 copied, renamed = [], []
4995 for d, s in c.iteritems():
4997 for d, s in c.iteritems():
4996 if s in status.removed:
4998 if s in status.removed:
4997 status.removed.remove(s)
4999 status.removed.remove(s)
4998 renamed.append(d)
5000 renamed.append(d)
4999 else:
5001 else:
5000 copied.append(d)
5002 copied.append(d)
5001 if d in status.added:
5003 if d in status.added:
5002 status.added.remove(d)
5004 status.added.remove(d)
5003
5005
5004 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5006 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5005
5007
5006 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
5008 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
5007 (ui.label(_('%d added'), 'status.added'), status.added),
5009 (ui.label(_('%d added'), 'status.added'), status.added),
5008 (ui.label(_('%d removed'), 'status.removed'), status.removed),
5010 (ui.label(_('%d removed'), 'status.removed'), status.removed),
5009 (ui.label(_('%d renamed'), 'status.copied'), renamed),
5011 (ui.label(_('%d renamed'), 'status.copied'), renamed),
5010 (ui.label(_('%d copied'), 'status.copied'), copied),
5012 (ui.label(_('%d copied'), 'status.copied'), copied),
5011 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
5013 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
5012 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
5014 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
5013 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
5015 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
5014 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
5016 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
5015 t = []
5017 t = []
5016 for l, s in labels:
5018 for l, s in labels:
5017 if s:
5019 if s:
5018 t.append(l % len(s))
5020 t.append(l % len(s))
5019
5021
5020 t = ', '.join(t)
5022 t = ', '.join(t)
5021 cleanworkdir = False
5023 cleanworkdir = False
5022
5024
5023 if repo.vfs.exists('graftstate'):
5025 if repo.vfs.exists('graftstate'):
5024 t += _(' (graft in progress)')
5026 t += _(' (graft in progress)')
5025 if repo.vfs.exists('updatestate'):
5027 if repo.vfs.exists('updatestate'):
5026 t += _(' (interrupted update)')
5028 t += _(' (interrupted update)')
5027 elif len(parents) > 1:
5029 elif len(parents) > 1:
5028 t += _(' (merge)')
5030 t += _(' (merge)')
5029 elif branch != parents[0].branch():
5031 elif branch != parents[0].branch():
5030 t += _(' (new branch)')
5032 t += _(' (new branch)')
5031 elif (parents[0].closesbranch() and
5033 elif (parents[0].closesbranch() and
5032 pnode in repo.branchheads(branch, closed=True)):
5034 pnode in repo.branchheads(branch, closed=True)):
5033 t += _(' (head closed)')
5035 t += _(' (head closed)')
5034 elif not (status.modified or status.added or status.removed or renamed or
5036 elif not (status.modified or status.added or status.removed or renamed or
5035 copied or subs):
5037 copied or subs):
5036 t += _(' (clean)')
5038 t += _(' (clean)')
5037 cleanworkdir = True
5039 cleanworkdir = True
5038 elif pnode not in bheads:
5040 elif pnode not in bheads:
5039 t += _(' (new branch head)')
5041 t += _(' (new branch head)')
5040
5042
5041 if parents:
5043 if parents:
5042 pendingphase = max(p.phase() for p in parents)
5044 pendingphase = max(p.phase() for p in parents)
5043 else:
5045 else:
5044 pendingphase = phases.public
5046 pendingphase = phases.public
5045
5047
5046 if pendingphase > phases.newcommitphase(ui):
5048 if pendingphase > phases.newcommitphase(ui):
5047 t += ' (%s)' % phases.phasenames[pendingphase]
5049 t += ' (%s)' % phases.phasenames[pendingphase]
5048
5050
5049 if cleanworkdir:
5051 if cleanworkdir:
5050 # i18n: column positioning for "hg summary"
5052 # i18n: column positioning for "hg summary"
5051 ui.status(_('commit: %s\n') % t.strip())
5053 ui.status(_('commit: %s\n') % t.strip())
5052 else:
5054 else:
5053 # i18n: column positioning for "hg summary"
5055 # i18n: column positioning for "hg summary"
5054 ui.write(_('commit: %s\n') % t.strip())
5056 ui.write(_('commit: %s\n') % t.strip())
5055
5057
5056 # all ancestors of branch heads - all ancestors of parent = new csets
5058 # all ancestors of branch heads - all ancestors of parent = new csets
5057 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
5059 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
5058 bheads))
5060 bheads))
5059
5061
5060 if new == 0:
5062 if new == 0:
5061 # i18n: column positioning for "hg summary"
5063 # i18n: column positioning for "hg summary"
5062 ui.status(_('update: (current)\n'))
5064 ui.status(_('update: (current)\n'))
5063 elif pnode not in bheads:
5065 elif pnode not in bheads:
5064 # i18n: column positioning for "hg summary"
5066 # i18n: column positioning for "hg summary"
5065 ui.write(_('update: %d new changesets (update)\n') % new)
5067 ui.write(_('update: %d new changesets (update)\n') % new)
5066 else:
5068 else:
5067 # i18n: column positioning for "hg summary"
5069 # i18n: column positioning for "hg summary"
5068 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5070 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5069 (new, len(bheads)))
5071 (new, len(bheads)))
5070
5072
5071 t = []
5073 t = []
5072 draft = len(repo.revs('draft()'))
5074 draft = len(repo.revs('draft()'))
5073 if draft:
5075 if draft:
5074 t.append(_('%d draft') % draft)
5076 t.append(_('%d draft') % draft)
5075 secret = len(repo.revs('secret()'))
5077 secret = len(repo.revs('secret()'))
5076 if secret:
5078 if secret:
5077 t.append(_('%d secret') % secret)
5079 t.append(_('%d secret') % secret)
5078
5080
5079 if draft or secret:
5081 if draft or secret:
5080 ui.status(_('phases: %s\n') % ', '.join(t))
5082 ui.status(_('phases: %s\n') % ', '.join(t))
5081
5083
5082 if obsolete.isenabled(repo, obsolete.createmarkersopt):
5084 if obsolete.isenabled(repo, obsolete.createmarkersopt):
5083 for trouble in ("orphan", "contentdivergent", "phasedivergent"):
5085 for trouble in ("orphan", "contentdivergent", "phasedivergent"):
5084 numtrouble = len(repo.revs(trouble + "()"))
5086 numtrouble = len(repo.revs(trouble + "()"))
5085 # We write all the possibilities to ease translation
5087 # We write all the possibilities to ease translation
5086 troublemsg = {
5088 troublemsg = {
5087 "orphan": _("orphan: %d changesets"),
5089 "orphan": _("orphan: %d changesets"),
5088 "contentdivergent": _("content-divergent: %d changesets"),
5090 "contentdivergent": _("content-divergent: %d changesets"),
5089 "phasedivergent": _("phase-divergent: %d changesets"),
5091 "phasedivergent": _("phase-divergent: %d changesets"),
5090 }
5092 }
5091 if numtrouble > 0:
5093 if numtrouble > 0:
5092 ui.status(troublemsg[trouble] % numtrouble + "\n")
5094 ui.status(troublemsg[trouble] % numtrouble + "\n")
5093
5095
5094 cmdutil.summaryhooks(ui, repo)
5096 cmdutil.summaryhooks(ui, repo)
5095
5097
5096 if opts.get('remote'):
5098 if opts.get('remote'):
5097 needsincoming, needsoutgoing = True, True
5099 needsincoming, needsoutgoing = True, True
5098 else:
5100 else:
5099 needsincoming, needsoutgoing = False, False
5101 needsincoming, needsoutgoing = False, False
5100 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5102 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5101 if i:
5103 if i:
5102 needsincoming = True
5104 needsincoming = True
5103 if o:
5105 if o:
5104 needsoutgoing = True
5106 needsoutgoing = True
5105 if not needsincoming and not needsoutgoing:
5107 if not needsincoming and not needsoutgoing:
5106 return
5108 return
5107
5109
5108 def getincoming():
5110 def getincoming():
5109 source, branches = hg.parseurl(ui.expandpath('default'))
5111 source, branches = hg.parseurl(ui.expandpath('default'))
5110 sbranch = branches[0]
5112 sbranch = branches[0]
5111 try:
5113 try:
5112 other = hg.peer(repo, {}, source)
5114 other = hg.peer(repo, {}, source)
5113 except error.RepoError:
5115 except error.RepoError:
5114 if opts.get('remote'):
5116 if opts.get('remote'):
5115 raise
5117 raise
5116 return source, sbranch, None, None, None
5118 return source, sbranch, None, None, None
5117 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5119 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5118 if revs:
5120 if revs:
5119 revs = [other.lookup(rev) for rev in revs]
5121 revs = [other.lookup(rev) for rev in revs]
5120 ui.debug('comparing with %s\n' % util.hidepassword(source))
5122 ui.debug('comparing with %s\n' % util.hidepassword(source))
5121 repo.ui.pushbuffer()
5123 repo.ui.pushbuffer()
5122 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5124 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5123 repo.ui.popbuffer()
5125 repo.ui.popbuffer()
5124 return source, sbranch, other, commoninc, commoninc[1]
5126 return source, sbranch, other, commoninc, commoninc[1]
5125
5127
5126 if needsincoming:
5128 if needsincoming:
5127 source, sbranch, sother, commoninc, incoming = getincoming()
5129 source, sbranch, sother, commoninc, incoming = getincoming()
5128 else:
5130 else:
5129 source = sbranch = sother = commoninc = incoming = None
5131 source = sbranch = sother = commoninc = incoming = None
5130
5132
5131 def getoutgoing():
5133 def getoutgoing():
5132 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5134 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5133 dbranch = branches[0]
5135 dbranch = branches[0]
5134 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5136 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5135 if source != dest:
5137 if source != dest:
5136 try:
5138 try:
5137 dother = hg.peer(repo, {}, dest)
5139 dother = hg.peer(repo, {}, dest)
5138 except error.RepoError:
5140 except error.RepoError:
5139 if opts.get('remote'):
5141 if opts.get('remote'):
5140 raise
5142 raise
5141 return dest, dbranch, None, None
5143 return dest, dbranch, None, None
5142 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5144 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5143 elif sother is None:
5145 elif sother is None:
5144 # there is no explicit destination peer, but source one is invalid
5146 # there is no explicit destination peer, but source one is invalid
5145 return dest, dbranch, None, None
5147 return dest, dbranch, None, None
5146 else:
5148 else:
5147 dother = sother
5149 dother = sother
5148 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5150 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5149 common = None
5151 common = None
5150 else:
5152 else:
5151 common = commoninc
5153 common = commoninc
5152 if revs:
5154 if revs:
5153 revs = [repo.lookup(rev) for rev in revs]
5155 revs = [repo.lookup(rev) for rev in revs]
5154 repo.ui.pushbuffer()
5156 repo.ui.pushbuffer()
5155 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5157 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5156 commoninc=common)
5158 commoninc=common)
5157 repo.ui.popbuffer()
5159 repo.ui.popbuffer()
5158 return dest, dbranch, dother, outgoing
5160 return dest, dbranch, dother, outgoing
5159
5161
5160 if needsoutgoing:
5162 if needsoutgoing:
5161 dest, dbranch, dother, outgoing = getoutgoing()
5163 dest, dbranch, dother, outgoing = getoutgoing()
5162 else:
5164 else:
5163 dest = dbranch = dother = outgoing = None
5165 dest = dbranch = dother = outgoing = None
5164
5166
5165 if opts.get('remote'):
5167 if opts.get('remote'):
5166 t = []
5168 t = []
5167 if incoming:
5169 if incoming:
5168 t.append(_('1 or more incoming'))
5170 t.append(_('1 or more incoming'))
5169 o = outgoing.missing
5171 o = outgoing.missing
5170 if o:
5172 if o:
5171 t.append(_('%d outgoing') % len(o))
5173 t.append(_('%d outgoing') % len(o))
5172 other = dother or sother
5174 other = dother or sother
5173 if 'bookmarks' in other.listkeys('namespaces'):
5175 if 'bookmarks' in other.listkeys('namespaces'):
5174 counts = bookmarks.summary(repo, other)
5176 counts = bookmarks.summary(repo, other)
5175 if counts[0] > 0:
5177 if counts[0] > 0:
5176 t.append(_('%d incoming bookmarks') % counts[0])
5178 t.append(_('%d incoming bookmarks') % counts[0])
5177 if counts[1] > 0:
5179 if counts[1] > 0:
5178 t.append(_('%d outgoing bookmarks') % counts[1])
5180 t.append(_('%d outgoing bookmarks') % counts[1])
5179
5181
5180 if t:
5182 if t:
5181 # i18n: column positioning for "hg summary"
5183 # i18n: column positioning for "hg summary"
5182 ui.write(_('remote: %s\n') % (', '.join(t)))
5184 ui.write(_('remote: %s\n') % (', '.join(t)))
5183 else:
5185 else:
5184 # i18n: column positioning for "hg summary"
5186 # i18n: column positioning for "hg summary"
5185 ui.status(_('remote: (synced)\n'))
5187 ui.status(_('remote: (synced)\n'))
5186
5188
5187 cmdutil.summaryremotehooks(ui, repo, opts,
5189 cmdutil.summaryremotehooks(ui, repo, opts,
5188 ((source, sbranch, sother, commoninc),
5190 ((source, sbranch, sother, commoninc),
5189 (dest, dbranch, dother, outgoing)))
5191 (dest, dbranch, dother, outgoing)))
5190
5192
5191 @command('tag',
5193 @command('tag',
5192 [('f', 'force', None, _('force tag')),
5194 [('f', 'force', None, _('force tag')),
5193 ('l', 'local', None, _('make the tag local')),
5195 ('l', 'local', None, _('make the tag local')),
5194 ('r', 'rev', '', _('revision to tag'), _('REV')),
5196 ('r', 'rev', '', _('revision to tag'), _('REV')),
5195 ('', 'remove', None, _('remove a tag')),
5197 ('', 'remove', None, _('remove a tag')),
5196 # -l/--local is already there, commitopts cannot be used
5198 # -l/--local is already there, commitopts cannot be used
5197 ('e', 'edit', None, _('invoke editor on commit messages')),
5199 ('e', 'edit', None, _('invoke editor on commit messages')),
5198 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5200 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5199 ] + commitopts2,
5201 ] + commitopts2,
5200 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5202 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5201 def tag(ui, repo, name1, *names, **opts):
5203 def tag(ui, repo, name1, *names, **opts):
5202 """add one or more tags for the current or given revision
5204 """add one or more tags for the current or given revision
5203
5205
5204 Name a particular revision using <name>.
5206 Name a particular revision using <name>.
5205
5207
5206 Tags are used to name particular revisions of the repository and are
5208 Tags are used to name particular revisions of the repository and are
5207 very useful to compare different revisions, to go back to significant
5209 very useful to compare different revisions, to go back to significant
5208 earlier versions or to mark branch points as releases, etc. Changing
5210 earlier versions or to mark branch points as releases, etc. Changing
5209 an existing tag is normally disallowed; use -f/--force to override.
5211 an existing tag is normally disallowed; use -f/--force to override.
5210
5212
5211 If no revision is given, the parent of the working directory is
5213 If no revision is given, the parent of the working directory is
5212 used.
5214 used.
5213
5215
5214 To facilitate version control, distribution, and merging of tags,
5216 To facilitate version control, distribution, and merging of tags,
5215 they are stored as a file named ".hgtags" which is managed similarly
5217 they are stored as a file named ".hgtags" which is managed similarly
5216 to other project files and can be hand-edited if necessary. This
5218 to other project files and can be hand-edited if necessary. This
5217 also means that tagging creates a new commit. The file
5219 also means that tagging creates a new commit. The file
5218 ".hg/localtags" is used for local tags (not shared among
5220 ".hg/localtags" is used for local tags (not shared among
5219 repositories).
5221 repositories).
5220
5222
5221 Tag commits are usually made at the head of a branch. If the parent
5223 Tag commits are usually made at the head of a branch. If the parent
5222 of the working directory is not a branch head, :hg:`tag` aborts; use
5224 of the working directory is not a branch head, :hg:`tag` aborts; use
5223 -f/--force to force the tag commit to be based on a non-head
5225 -f/--force to force the tag commit to be based on a non-head
5224 changeset.
5226 changeset.
5225
5227
5226 See :hg:`help dates` for a list of formats valid for -d/--date.
5228 See :hg:`help dates` for a list of formats valid for -d/--date.
5227
5229
5228 Since tag names have priority over branch names during revision
5230 Since tag names have priority over branch names during revision
5229 lookup, using an existing branch name as a tag name is discouraged.
5231 lookup, using an existing branch name as a tag name is discouraged.
5230
5232
5231 Returns 0 on success.
5233 Returns 0 on success.
5232 """
5234 """
5233 opts = pycompat.byteskwargs(opts)
5235 opts = pycompat.byteskwargs(opts)
5234 wlock = lock = None
5236 wlock = lock = None
5235 try:
5237 try:
5236 wlock = repo.wlock()
5238 wlock = repo.wlock()
5237 lock = repo.lock()
5239 lock = repo.lock()
5238 rev_ = "."
5240 rev_ = "."
5239 names = [t.strip() for t in (name1,) + names]
5241 names = [t.strip() for t in (name1,) + names]
5240 if len(names) != len(set(names)):
5242 if len(names) != len(set(names)):
5241 raise error.Abort(_('tag names must be unique'))
5243 raise error.Abort(_('tag names must be unique'))
5242 for n in names:
5244 for n in names:
5243 scmutil.checknewlabel(repo, n, 'tag')
5245 scmutil.checknewlabel(repo, n, 'tag')
5244 if not n:
5246 if not n:
5245 raise error.Abort(_('tag names cannot consist entirely of '
5247 raise error.Abort(_('tag names cannot consist entirely of '
5246 'whitespace'))
5248 'whitespace'))
5247 if opts.get('rev') and opts.get('remove'):
5249 if opts.get('rev') and opts.get('remove'):
5248 raise error.Abort(_("--rev and --remove are incompatible"))
5250 raise error.Abort(_("--rev and --remove are incompatible"))
5249 if opts.get('rev'):
5251 if opts.get('rev'):
5250 rev_ = opts['rev']
5252 rev_ = opts['rev']
5251 message = opts.get('message')
5253 message = opts.get('message')
5252 if opts.get('remove'):
5254 if opts.get('remove'):
5253 if opts.get('local'):
5255 if opts.get('local'):
5254 expectedtype = 'local'
5256 expectedtype = 'local'
5255 else:
5257 else:
5256 expectedtype = 'global'
5258 expectedtype = 'global'
5257
5259
5258 for n in names:
5260 for n in names:
5259 if not repo.tagtype(n):
5261 if not repo.tagtype(n):
5260 raise error.Abort(_("tag '%s' does not exist") % n)
5262 raise error.Abort(_("tag '%s' does not exist") % n)
5261 if repo.tagtype(n) != expectedtype:
5263 if repo.tagtype(n) != expectedtype:
5262 if expectedtype == 'global':
5264 if expectedtype == 'global':
5263 raise error.Abort(_("tag '%s' is not a global tag") % n)
5265 raise error.Abort(_("tag '%s' is not a global tag") % n)
5264 else:
5266 else:
5265 raise error.Abort(_("tag '%s' is not a local tag") % n)
5267 raise error.Abort(_("tag '%s' is not a local tag") % n)
5266 rev_ = 'null'
5268 rev_ = 'null'
5267 if not message:
5269 if not message:
5268 # we don't translate commit messages
5270 # we don't translate commit messages
5269 message = 'Removed tag %s' % ', '.join(names)
5271 message = 'Removed tag %s' % ', '.join(names)
5270 elif not opts.get('force'):
5272 elif not opts.get('force'):
5271 for n in names:
5273 for n in names:
5272 if n in repo.tags():
5274 if n in repo.tags():
5273 raise error.Abort(_("tag '%s' already exists "
5275 raise error.Abort(_("tag '%s' already exists "
5274 "(use -f to force)") % n)
5276 "(use -f to force)") % n)
5275 if not opts.get('local'):
5277 if not opts.get('local'):
5276 p1, p2 = repo.dirstate.parents()
5278 p1, p2 = repo.dirstate.parents()
5277 if p2 != nullid:
5279 if p2 != nullid:
5278 raise error.Abort(_('uncommitted merge'))
5280 raise error.Abort(_('uncommitted merge'))
5279 bheads = repo.branchheads()
5281 bheads = repo.branchheads()
5280 if not opts.get('force') and bheads and p1 not in bheads:
5282 if not opts.get('force') and bheads and p1 not in bheads:
5281 raise error.Abort(_('working directory is not at a branch head '
5283 raise error.Abort(_('working directory is not at a branch head '
5282 '(use -f to force)'))
5284 '(use -f to force)'))
5283 r = scmutil.revsingle(repo, rev_).node()
5285 r = scmutil.revsingle(repo, rev_).node()
5284
5286
5285 if not message:
5287 if not message:
5286 # we don't translate commit messages
5288 # we don't translate commit messages
5287 message = ('Added tag %s for changeset %s' %
5289 message = ('Added tag %s for changeset %s' %
5288 (', '.join(names), short(r)))
5290 (', '.join(names), short(r)))
5289
5291
5290 date = opts.get('date')
5292 date = opts.get('date')
5291 if date:
5293 if date:
5292 date = util.parsedate(date)
5294 date = util.parsedate(date)
5293
5295
5294 if opts.get('remove'):
5296 if opts.get('remove'):
5295 editform = 'tag.remove'
5297 editform = 'tag.remove'
5296 else:
5298 else:
5297 editform = 'tag.add'
5299 editform = 'tag.add'
5298 editor = cmdutil.getcommiteditor(editform=editform,
5300 editor = cmdutil.getcommiteditor(editform=editform,
5299 **pycompat.strkwargs(opts))
5301 **pycompat.strkwargs(opts))
5300
5302
5301 # don't allow tagging the null rev
5303 # don't allow tagging the null rev
5302 if (not opts.get('remove') and
5304 if (not opts.get('remove') and
5303 scmutil.revsingle(repo, rev_).rev() == nullrev):
5305 scmutil.revsingle(repo, rev_).rev() == nullrev):
5304 raise error.Abort(_("cannot tag null revision"))
5306 raise error.Abort(_("cannot tag null revision"))
5305
5307
5306 tagsmod.tag(repo, names, r, message, opts.get('local'),
5308 tagsmod.tag(repo, names, r, message, opts.get('local'),
5307 opts.get('user'), date, editor=editor)
5309 opts.get('user'), date, editor=editor)
5308 finally:
5310 finally:
5309 release(lock, wlock)
5311 release(lock, wlock)
5310
5312
5311 @command('tags', formatteropts, '', cmdtype=readonly)
5313 @command('tags', formatteropts, '', cmdtype=readonly)
5312 def tags(ui, repo, **opts):
5314 def tags(ui, repo, **opts):
5313 """list repository tags
5315 """list repository tags
5314
5316
5315 This lists both regular and local tags. When the -v/--verbose
5317 This lists both regular and local tags. When the -v/--verbose
5316 switch is used, a third column "local" is printed for local tags.
5318 switch is used, a third column "local" is printed for local tags.
5317 When the -q/--quiet switch is used, only the tag name is printed.
5319 When the -q/--quiet switch is used, only the tag name is printed.
5318
5320
5319 Returns 0 on success.
5321 Returns 0 on success.
5320 """
5322 """
5321
5323
5322 opts = pycompat.byteskwargs(opts)
5324 opts = pycompat.byteskwargs(opts)
5323 ui.pager('tags')
5325 ui.pager('tags')
5324 fm = ui.formatter('tags', opts)
5326 fm = ui.formatter('tags', opts)
5325 hexfunc = fm.hexfunc
5327 hexfunc = fm.hexfunc
5326 tagtype = ""
5328 tagtype = ""
5327
5329
5328 for t, n in reversed(repo.tagslist()):
5330 for t, n in reversed(repo.tagslist()):
5329 hn = hexfunc(n)
5331 hn = hexfunc(n)
5330 label = 'tags.normal'
5332 label = 'tags.normal'
5331 tagtype = ''
5333 tagtype = ''
5332 if repo.tagtype(t) == 'local':
5334 if repo.tagtype(t) == 'local':
5333 label = 'tags.local'
5335 label = 'tags.local'
5334 tagtype = 'local'
5336 tagtype = 'local'
5335
5337
5336 fm.startitem()
5338 fm.startitem()
5337 fm.write('tag', '%s', t, label=label)
5339 fm.write('tag', '%s', t, label=label)
5338 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5340 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5339 fm.condwrite(not ui.quiet, 'rev node', fmt,
5341 fm.condwrite(not ui.quiet, 'rev node', fmt,
5340 repo.changelog.rev(n), hn, label=label)
5342 repo.changelog.rev(n), hn, label=label)
5341 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5343 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5342 tagtype, label=label)
5344 tagtype, label=label)
5343 fm.plain('\n')
5345 fm.plain('\n')
5344 fm.end()
5346 fm.end()
5345
5347
5346 @command('tip',
5348 @command('tip',
5347 [('p', 'patch', None, _('show patch')),
5349 [('p', 'patch', None, _('show patch')),
5348 ('g', 'git', None, _('use git extended diff format')),
5350 ('g', 'git', None, _('use git extended diff format')),
5349 ] + templateopts,
5351 ] + templateopts,
5350 _('[-p] [-g]'))
5352 _('[-p] [-g]'))
5351 def tip(ui, repo, **opts):
5353 def tip(ui, repo, **opts):
5352 """show the tip revision (DEPRECATED)
5354 """show the tip revision (DEPRECATED)
5353
5355
5354 The tip revision (usually just called the tip) is the changeset
5356 The tip revision (usually just called the tip) is the changeset
5355 most recently added to the repository (and therefore the most
5357 most recently added to the repository (and therefore the most
5356 recently changed head).
5358 recently changed head).
5357
5359
5358 If you have just made a commit, that commit will be the tip. If
5360 If you have just made a commit, that commit will be the tip. If
5359 you have just pulled changes from another repository, the tip of
5361 you have just pulled changes from another repository, the tip of
5360 that repository becomes the current tip. The "tip" tag is special
5362 that repository becomes the current tip. The "tip" tag is special
5361 and cannot be renamed or assigned to a different changeset.
5363 and cannot be renamed or assigned to a different changeset.
5362
5364
5363 This command is deprecated, please use :hg:`heads` instead.
5365 This command is deprecated, please use :hg:`heads` instead.
5364
5366
5365 Returns 0 on success.
5367 Returns 0 on success.
5366 """
5368 """
5367 opts = pycompat.byteskwargs(opts)
5369 opts = pycompat.byteskwargs(opts)
5368 displayer = cmdutil.show_changeset(ui, repo, opts)
5370 displayer = cmdutil.show_changeset(ui, repo, opts)
5369 displayer.show(repo['tip'])
5371 displayer.show(repo['tip'])
5370 displayer.close()
5372 displayer.close()
5371
5373
5372 @command('unbundle',
5374 @command('unbundle',
5373 [('u', 'update', None,
5375 [('u', 'update', None,
5374 _('update to new branch head if changesets were unbundled'))],
5376 _('update to new branch head if changesets were unbundled'))],
5375 _('[-u] FILE...'))
5377 _('[-u] FILE...'))
5376 def unbundle(ui, repo, fname1, *fnames, **opts):
5378 def unbundle(ui, repo, fname1, *fnames, **opts):
5377 """apply one or more bundle files
5379 """apply one or more bundle files
5378
5380
5379 Apply one or more bundle files generated by :hg:`bundle`.
5381 Apply one or more bundle files generated by :hg:`bundle`.
5380
5382
5381 Returns 0 on success, 1 if an update has unresolved files.
5383 Returns 0 on success, 1 if an update has unresolved files.
5382 """
5384 """
5383 fnames = (fname1,) + fnames
5385 fnames = (fname1,) + fnames
5384
5386
5385 with repo.lock():
5387 with repo.lock():
5386 for fname in fnames:
5388 for fname in fnames:
5387 f = hg.openpath(ui, fname)
5389 f = hg.openpath(ui, fname)
5388 gen = exchange.readbundle(ui, f, fname)
5390 gen = exchange.readbundle(ui, f, fname)
5389 if isinstance(gen, streamclone.streamcloneapplier):
5391 if isinstance(gen, streamclone.streamcloneapplier):
5390 raise error.Abort(
5392 raise error.Abort(
5391 _('packed bundles cannot be applied with '
5393 _('packed bundles cannot be applied with '
5392 '"hg unbundle"'),
5394 '"hg unbundle"'),
5393 hint=_('use "hg debugapplystreamclonebundle"'))
5395 hint=_('use "hg debugapplystreamclonebundle"'))
5394 url = 'bundle:' + fname
5396 url = 'bundle:' + fname
5395 try:
5397 try:
5396 txnname = 'unbundle'
5398 txnname = 'unbundle'
5397 if not isinstance(gen, bundle2.unbundle20):
5399 if not isinstance(gen, bundle2.unbundle20):
5398 txnname = 'unbundle\n%s' % util.hidepassword(url)
5400 txnname = 'unbundle\n%s' % util.hidepassword(url)
5399 with repo.transaction(txnname) as tr:
5401 with repo.transaction(txnname) as tr:
5400 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
5402 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
5401 url=url)
5403 url=url)
5402 except error.BundleUnknownFeatureError as exc:
5404 except error.BundleUnknownFeatureError as exc:
5403 raise error.Abort(
5405 raise error.Abort(
5404 _('%s: unknown bundle feature, %s') % (fname, exc),
5406 _('%s: unknown bundle feature, %s') % (fname, exc),
5405 hint=_("see https://mercurial-scm.org/"
5407 hint=_("see https://mercurial-scm.org/"
5406 "wiki/BundleFeature for more "
5408 "wiki/BundleFeature for more "
5407 "information"))
5409 "information"))
5408 modheads = bundle2.combinechangegroupresults(op)
5410 modheads = bundle2.combinechangegroupresults(op)
5409
5411
5410 return postincoming(ui, repo, modheads, opts.get(r'update'), None, None)
5412 return postincoming(ui, repo, modheads, opts.get(r'update'), None, None)
5411
5413
5412 @command('^update|up|checkout|co',
5414 @command('^update|up|checkout|co',
5413 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5415 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5414 ('c', 'check', None, _('require clean working directory')),
5416 ('c', 'check', None, _('require clean working directory')),
5415 ('m', 'merge', None, _('merge uncommitted changes')),
5417 ('m', 'merge', None, _('merge uncommitted changes')),
5416 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5418 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5417 ('r', 'rev', '', _('revision'), _('REV'))
5419 ('r', 'rev', '', _('revision'), _('REV'))
5418 ] + mergetoolopts,
5420 ] + mergetoolopts,
5419 _('[-C|-c|-m] [-d DATE] [[-r] REV]'))
5421 _('[-C|-c|-m] [-d DATE] [[-r] REV]'))
5420 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
5422 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
5421 merge=None, tool=None):
5423 merge=None, tool=None):
5422 """update working directory (or switch revisions)
5424 """update working directory (or switch revisions)
5423
5425
5424 Update the repository's working directory to the specified
5426 Update the repository's working directory to the specified
5425 changeset. If no changeset is specified, update to the tip of the
5427 changeset. If no changeset is specified, update to the tip of the
5426 current named branch and move the active bookmark (see :hg:`help
5428 current named branch and move the active bookmark (see :hg:`help
5427 bookmarks`).
5429 bookmarks`).
5428
5430
5429 Update sets the working directory's parent revision to the specified
5431 Update sets the working directory's parent revision to the specified
5430 changeset (see :hg:`help parents`).
5432 changeset (see :hg:`help parents`).
5431
5433
5432 If the changeset is not a descendant or ancestor of the working
5434 If the changeset is not a descendant or ancestor of the working
5433 directory's parent and there are uncommitted changes, the update is
5435 directory's parent and there are uncommitted changes, the update is
5434 aborted. With the -c/--check option, the working directory is checked
5436 aborted. With the -c/--check option, the working directory is checked
5435 for uncommitted changes; if none are found, the working directory is
5437 for uncommitted changes; if none are found, the working directory is
5436 updated to the specified changeset.
5438 updated to the specified changeset.
5437
5439
5438 .. container:: verbose
5440 .. container:: verbose
5439
5441
5440 The -C/--clean, -c/--check, and -m/--merge options control what
5442 The -C/--clean, -c/--check, and -m/--merge options control what
5441 happens if the working directory contains uncommitted changes.
5443 happens if the working directory contains uncommitted changes.
5442 At most of one of them can be specified.
5444 At most of one of them can be specified.
5443
5445
5444 1. If no option is specified, and if
5446 1. If no option is specified, and if
5445 the requested changeset is an ancestor or descendant of
5447 the requested changeset is an ancestor or descendant of
5446 the working directory's parent, the uncommitted changes
5448 the working directory's parent, the uncommitted changes
5447 are merged into the requested changeset and the merged
5449 are merged into the requested changeset and the merged
5448 result is left uncommitted. If the requested changeset is
5450 result is left uncommitted. If the requested changeset is
5449 not an ancestor or descendant (that is, it is on another
5451 not an ancestor or descendant (that is, it is on another
5450 branch), the update is aborted and the uncommitted changes
5452 branch), the update is aborted and the uncommitted changes
5451 are preserved.
5453 are preserved.
5452
5454
5453 2. With the -m/--merge option, the update is allowed even if the
5455 2. With the -m/--merge option, the update is allowed even if the
5454 requested changeset is not an ancestor or descendant of
5456 requested changeset is not an ancestor or descendant of
5455 the working directory's parent.
5457 the working directory's parent.
5456
5458
5457 3. With the -c/--check option, the update is aborted and the
5459 3. With the -c/--check option, the update is aborted and the
5458 uncommitted changes are preserved.
5460 uncommitted changes are preserved.
5459
5461
5460 4. With the -C/--clean option, uncommitted changes are discarded and
5462 4. With the -C/--clean option, uncommitted changes are discarded and
5461 the working directory is updated to the requested changeset.
5463 the working directory is updated to the requested changeset.
5462
5464
5463 To cancel an uncommitted merge (and lose your changes), use
5465 To cancel an uncommitted merge (and lose your changes), use
5464 :hg:`update --clean .`.
5466 :hg:`update --clean .`.
5465
5467
5466 Use null as the changeset to remove the working directory (like
5468 Use null as the changeset to remove the working directory (like
5467 :hg:`clone -U`).
5469 :hg:`clone -U`).
5468
5470
5469 If you want to revert just one file to an older revision, use
5471 If you want to revert just one file to an older revision, use
5470 :hg:`revert [-r REV] NAME`.
5472 :hg:`revert [-r REV] NAME`.
5471
5473
5472 See :hg:`help dates` for a list of formats valid for -d/--date.
5474 See :hg:`help dates` for a list of formats valid for -d/--date.
5473
5475
5474 Returns 0 on success, 1 if there are unresolved files.
5476 Returns 0 on success, 1 if there are unresolved files.
5475 """
5477 """
5476 if rev and node:
5478 if rev and node:
5477 raise error.Abort(_("please specify just one revision"))
5479 raise error.Abort(_("please specify just one revision"))
5478
5480
5479 if ui.configbool('commands', 'update.requiredest'):
5481 if ui.configbool('commands', 'update.requiredest'):
5480 if not node and not rev and not date:
5482 if not node and not rev and not date:
5481 raise error.Abort(_('you must specify a destination'),
5483 raise error.Abort(_('you must specify a destination'),
5482 hint=_('for example: hg update ".::"'))
5484 hint=_('for example: hg update ".::"'))
5483
5485
5484 if rev is None or rev == '':
5486 if rev is None or rev == '':
5485 rev = node
5487 rev = node
5486
5488
5487 if date and rev is not None:
5489 if date and rev is not None:
5488 raise error.Abort(_("you can't specify a revision and a date"))
5490 raise error.Abort(_("you can't specify a revision and a date"))
5489
5491
5490 if len([x for x in (clean, check, merge) if x]) > 1:
5492 if len([x for x in (clean, check, merge) if x]) > 1:
5491 raise error.Abort(_("can only specify one of -C/--clean, -c/--check, "
5493 raise error.Abort(_("can only specify one of -C/--clean, -c/--check, "
5492 "or -m/--merge"))
5494 "or -m/--merge"))
5493
5495
5494 updatecheck = None
5496 updatecheck = None
5495 if check:
5497 if check:
5496 updatecheck = 'abort'
5498 updatecheck = 'abort'
5497 elif merge:
5499 elif merge:
5498 updatecheck = 'none'
5500 updatecheck = 'none'
5499
5501
5500 with repo.wlock():
5502 with repo.wlock():
5501 cmdutil.clearunfinished(repo)
5503 cmdutil.clearunfinished(repo)
5502
5504
5503 if date:
5505 if date:
5504 rev = cmdutil.finddate(ui, repo, date)
5506 rev = cmdutil.finddate(ui, repo, date)
5505
5507
5506 # if we defined a bookmark, we have to remember the original name
5508 # if we defined a bookmark, we have to remember the original name
5507 brev = rev
5509 brev = rev
5508 rev = scmutil.revsingle(repo, rev, rev).rev()
5510 rev = scmutil.revsingle(repo, rev, rev).rev()
5509
5511
5510 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
5512 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
5511
5513
5512 return hg.updatetotally(ui, repo, rev, brev, clean=clean,
5514 return hg.updatetotally(ui, repo, rev, brev, clean=clean,
5513 updatecheck=updatecheck)
5515 updatecheck=updatecheck)
5514
5516
5515 @command('verify', [])
5517 @command('verify', [])
5516 def verify(ui, repo):
5518 def verify(ui, repo):
5517 """verify the integrity of the repository
5519 """verify the integrity of the repository
5518
5520
5519 Verify the integrity of the current repository.
5521 Verify the integrity of the current repository.
5520
5522
5521 This will perform an extensive check of the repository's
5523 This will perform an extensive check of the repository's
5522 integrity, validating the hashes and checksums of each entry in
5524 integrity, validating the hashes and checksums of each entry in
5523 the changelog, manifest, and tracked files, as well as the
5525 the changelog, manifest, and tracked files, as well as the
5524 integrity of their crosslinks and indices.
5526 integrity of their crosslinks and indices.
5525
5527
5526 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
5528 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
5527 for more information about recovery from corruption of the
5529 for more information about recovery from corruption of the
5528 repository.
5530 repository.
5529
5531
5530 Returns 0 on success, 1 if errors are encountered.
5532 Returns 0 on success, 1 if errors are encountered.
5531 """
5533 """
5532 return hg.verify(repo)
5534 return hg.verify(repo)
5533
5535
5534 @command('version', [] + formatteropts, norepo=True, cmdtype=readonly)
5536 @command('version', [] + formatteropts, norepo=True, cmdtype=readonly)
5535 def version_(ui, **opts):
5537 def version_(ui, **opts):
5536 """output version and copyright information"""
5538 """output version and copyright information"""
5537 opts = pycompat.byteskwargs(opts)
5539 opts = pycompat.byteskwargs(opts)
5538 if ui.verbose:
5540 if ui.verbose:
5539 ui.pager('version')
5541 ui.pager('version')
5540 fm = ui.formatter("version", opts)
5542 fm = ui.formatter("version", opts)
5541 fm.startitem()
5543 fm.startitem()
5542 fm.write("ver", _("Mercurial Distributed SCM (version %s)\n"),
5544 fm.write("ver", _("Mercurial Distributed SCM (version %s)\n"),
5543 util.version())
5545 util.version())
5544 license = _(
5546 license = _(
5545 "(see https://mercurial-scm.org for more information)\n"
5547 "(see https://mercurial-scm.org for more information)\n"
5546 "\nCopyright (C) 2005-2017 Matt Mackall and others\n"
5548 "\nCopyright (C) 2005-2017 Matt Mackall and others\n"
5547 "This is free software; see the source for copying conditions. "
5549 "This is free software; see the source for copying conditions. "
5548 "There is NO\nwarranty; "
5550 "There is NO\nwarranty; "
5549 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5551 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5550 )
5552 )
5551 if not ui.quiet:
5553 if not ui.quiet:
5552 fm.plain(license)
5554 fm.plain(license)
5553
5555
5554 if ui.verbose:
5556 if ui.verbose:
5555 fm.plain(_("\nEnabled extensions:\n\n"))
5557 fm.plain(_("\nEnabled extensions:\n\n"))
5556 # format names and versions into columns
5558 # format names and versions into columns
5557 names = []
5559 names = []
5558 vers = []
5560 vers = []
5559 isinternals = []
5561 isinternals = []
5560 for name, module in extensions.extensions():
5562 for name, module in extensions.extensions():
5561 names.append(name)
5563 names.append(name)
5562 vers.append(extensions.moduleversion(module) or None)
5564 vers.append(extensions.moduleversion(module) or None)
5563 isinternals.append(extensions.ismoduleinternal(module))
5565 isinternals.append(extensions.ismoduleinternal(module))
5564 fn = fm.nested("extensions")
5566 fn = fm.nested("extensions")
5565 if names:
5567 if names:
5566 namefmt = " %%-%ds " % max(len(n) for n in names)
5568 namefmt = " %%-%ds " % max(len(n) for n in names)
5567 places = [_("external"), _("internal")]
5569 places = [_("external"), _("internal")]
5568 for n, v, p in zip(names, vers, isinternals):
5570 for n, v, p in zip(names, vers, isinternals):
5569 fn.startitem()
5571 fn.startitem()
5570 fn.condwrite(ui.verbose, "name", namefmt, n)
5572 fn.condwrite(ui.verbose, "name", namefmt, n)
5571 if ui.verbose:
5573 if ui.verbose:
5572 fn.plain("%s " % places[p])
5574 fn.plain("%s " % places[p])
5573 fn.data(bundled=p)
5575 fn.data(bundled=p)
5574 fn.condwrite(ui.verbose and v, "ver", "%s", v)
5576 fn.condwrite(ui.verbose and v, "ver", "%s", v)
5575 if ui.verbose:
5577 if ui.verbose:
5576 fn.plain("\n")
5578 fn.plain("\n")
5577 fn.end()
5579 fn.end()
5578 fm.end()
5580 fm.end()
5579
5581
5580 def loadcmdtable(ui, name, cmdtable):
5582 def loadcmdtable(ui, name, cmdtable):
5581 """Load command functions from specified cmdtable
5583 """Load command functions from specified cmdtable
5582 """
5584 """
5583 overrides = [cmd for cmd in cmdtable if cmd in table]
5585 overrides = [cmd for cmd in cmdtable if cmd in table]
5584 if overrides:
5586 if overrides:
5585 ui.warn(_("extension '%s' overrides commands: %s\n")
5587 ui.warn(_("extension '%s' overrides commands: %s\n")
5586 % (name, " ".join(overrides)))
5588 % (name, " ".join(overrides)))
5587 table.update(cmdtable)
5589 table.update(cmdtable)
General Comments 0
You need to be logged in to leave comments. Login now