##// END OF EJS Templates
commands: pass include and exclude options to hg.clone()...
Gregory Szorc -
r39588:4c807ec0 default
parent child Browse files
Show More
@@ -1,5906 +1,5923 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 filemerge,
38 filemerge,
39 formatter,
39 formatter,
40 graphmod,
40 graphmod,
41 hbisect,
41 hbisect,
42 help,
42 help,
43 hg,
43 hg,
44 logcmdutil,
44 logcmdutil,
45 merge as mergemod,
45 merge as mergemod,
46 narrowspec,
46 obsolete,
47 obsolete,
47 obsutil,
48 obsutil,
48 patch,
49 patch,
49 phases,
50 phases,
50 pycompat,
51 pycompat,
51 rcutil,
52 rcutil,
52 registrar,
53 registrar,
53 repair,
54 repair,
54 revsetlang,
55 revsetlang,
55 rewriteutil,
56 rewriteutil,
56 scmutil,
57 scmutil,
57 server,
58 server,
58 state as statemod,
59 state as statemod,
59 streamclone,
60 streamclone,
60 tags as tagsmod,
61 tags as tagsmod,
61 templatekw,
62 templatekw,
62 ui as uimod,
63 ui as uimod,
63 util,
64 util,
64 wireprotoserver,
65 wireprotoserver,
65 )
66 )
66 from .utils import (
67 from .utils import (
67 dateutil,
68 dateutil,
68 stringutil,
69 stringutil,
69 )
70 )
70
71
71 table = {}
72 table = {}
72 table.update(debugcommandsmod.command._table)
73 table.update(debugcommandsmod.command._table)
73
74
74 command = registrar.command(table)
75 command = registrar.command(table)
75 INTENT_READONLY = registrar.INTENT_READONLY
76 INTENT_READONLY = registrar.INTENT_READONLY
76
77
77 # common command options
78 # common command options
78
79
79 globalopts = [
80 globalopts = [
80 ('R', 'repository', '',
81 ('R', 'repository', '',
81 _('repository root directory or name of overlay bundle file'),
82 _('repository root directory or name of overlay bundle file'),
82 _('REPO')),
83 _('REPO')),
83 ('', 'cwd', '',
84 ('', 'cwd', '',
84 _('change working directory'), _('DIR')),
85 _('change working directory'), _('DIR')),
85 ('y', 'noninteractive', None,
86 ('y', 'noninteractive', None,
86 _('do not prompt, automatically pick the first choice for all prompts')),
87 _('do not prompt, automatically pick the first choice for all prompts')),
87 ('q', 'quiet', None, _('suppress output')),
88 ('q', 'quiet', None, _('suppress output')),
88 ('v', 'verbose', None, _('enable additional output')),
89 ('v', 'verbose', None, _('enable additional output')),
89 ('', 'color', '',
90 ('', 'color', '',
90 # i18n: 'always', 'auto', 'never', and 'debug' are keywords
91 # i18n: 'always', 'auto', 'never', and 'debug' are keywords
91 # and should not be translated
92 # and should not be translated
92 _("when to colorize (boolean, always, auto, never, or debug)"),
93 _("when to colorize (boolean, always, auto, never, or debug)"),
93 _('TYPE')),
94 _('TYPE')),
94 ('', 'config', [],
95 ('', 'config', [],
95 _('set/override config option (use \'section.name=value\')'),
96 _('set/override config option (use \'section.name=value\')'),
96 _('CONFIG')),
97 _('CONFIG')),
97 ('', 'debug', None, _('enable debugging output')),
98 ('', 'debug', None, _('enable debugging output')),
98 ('', 'debugger', None, _('start debugger')),
99 ('', 'debugger', None, _('start debugger')),
99 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
100 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
100 _('ENCODE')),
101 _('ENCODE')),
101 ('', 'encodingmode', encoding.encodingmode,
102 ('', 'encodingmode', encoding.encodingmode,
102 _('set the charset encoding mode'), _('MODE')),
103 _('set the charset encoding mode'), _('MODE')),
103 ('', 'traceback', None, _('always print a traceback on exception')),
104 ('', 'traceback', None, _('always print a traceback on exception')),
104 ('', 'time', None, _('time how long the command takes')),
105 ('', 'time', None, _('time how long the command takes')),
105 ('', 'profile', None, _('print command execution profile')),
106 ('', 'profile', None, _('print command execution profile')),
106 ('', 'version', None, _('output version information and exit')),
107 ('', 'version', None, _('output version information and exit')),
107 ('h', 'help', None, _('display help and exit')),
108 ('h', 'help', None, _('display help and exit')),
108 ('', 'hidden', False, _('consider hidden changesets')),
109 ('', 'hidden', False, _('consider hidden changesets')),
109 ('', 'pager', 'auto',
110 ('', 'pager', 'auto',
110 _("when to paginate (boolean, always, auto, or never)"), _('TYPE')),
111 _("when to paginate (boolean, always, auto, or never)"), _('TYPE')),
111 ]
112 ]
112
113
113 dryrunopts = cmdutil.dryrunopts
114 dryrunopts = cmdutil.dryrunopts
114 remoteopts = cmdutil.remoteopts
115 remoteopts = cmdutil.remoteopts
115 walkopts = cmdutil.walkopts
116 walkopts = cmdutil.walkopts
116 commitopts = cmdutil.commitopts
117 commitopts = cmdutil.commitopts
117 commitopts2 = cmdutil.commitopts2
118 commitopts2 = cmdutil.commitopts2
118 formatteropts = cmdutil.formatteropts
119 formatteropts = cmdutil.formatteropts
119 templateopts = cmdutil.templateopts
120 templateopts = cmdutil.templateopts
120 logopts = cmdutil.logopts
121 logopts = cmdutil.logopts
121 diffopts = cmdutil.diffopts
122 diffopts = cmdutil.diffopts
122 diffwsopts = cmdutil.diffwsopts
123 diffwsopts = cmdutil.diffwsopts
123 diffopts2 = cmdutil.diffopts2
124 diffopts2 = cmdutil.diffopts2
124 mergetoolopts = cmdutil.mergetoolopts
125 mergetoolopts = cmdutil.mergetoolopts
125 similarityopts = cmdutil.similarityopts
126 similarityopts = cmdutil.similarityopts
126 subrepoopts = cmdutil.subrepoopts
127 subrepoopts = cmdutil.subrepoopts
127 debugrevlogopts = cmdutil.debugrevlogopts
128 debugrevlogopts = cmdutil.debugrevlogopts
128
129
129 # Commands start here, listed alphabetically
130 # Commands start here, listed alphabetically
130
131
131 @command('^add',
132 @command('^add',
132 walkopts + subrepoopts + dryrunopts,
133 walkopts + subrepoopts + dryrunopts,
133 _('[OPTION]... [FILE]...'),
134 _('[OPTION]... [FILE]...'),
134 inferrepo=True)
135 inferrepo=True)
135 def add(ui, repo, *pats, **opts):
136 def add(ui, repo, *pats, **opts):
136 """add the specified files on the next commit
137 """add the specified files on the next commit
137
138
138 Schedule files to be version controlled and added to the
139 Schedule files to be version controlled and added to the
139 repository.
140 repository.
140
141
141 The files will be added to the repository at the next commit. To
142 The files will be added to the repository at the next commit. To
142 undo an add before that, see :hg:`forget`.
143 undo an add before that, see :hg:`forget`.
143
144
144 If no names are given, add all files to the repository (except
145 If no names are given, add all files to the repository (except
145 files matching ``.hgignore``).
146 files matching ``.hgignore``).
146
147
147 .. container:: verbose
148 .. container:: verbose
148
149
149 Examples:
150 Examples:
150
151
151 - New (unknown) files are added
152 - New (unknown) files are added
152 automatically by :hg:`add`::
153 automatically by :hg:`add`::
153
154
154 $ ls
155 $ ls
155 foo.c
156 foo.c
156 $ hg status
157 $ hg status
157 ? foo.c
158 ? foo.c
158 $ hg add
159 $ hg add
159 adding foo.c
160 adding foo.c
160 $ hg status
161 $ hg status
161 A foo.c
162 A foo.c
162
163
163 - Specific files to be added can be specified::
164 - Specific files to be added can be specified::
164
165
165 $ ls
166 $ ls
166 bar.c foo.c
167 bar.c foo.c
167 $ hg status
168 $ hg status
168 ? bar.c
169 ? bar.c
169 ? foo.c
170 ? foo.c
170 $ hg add bar.c
171 $ hg add bar.c
171 $ hg status
172 $ hg status
172 A bar.c
173 A bar.c
173 ? foo.c
174 ? foo.c
174
175
175 Returns 0 if all files are successfully added.
176 Returns 0 if all files are successfully added.
176 """
177 """
177
178
178 m = scmutil.match(repo[None], pats, pycompat.byteskwargs(opts))
179 m = scmutil.match(repo[None], pats, pycompat.byteskwargs(opts))
179 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
180 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
180 return rejected and 1 or 0
181 return rejected and 1 or 0
181
182
182 @command('addremove',
183 @command('addremove',
183 similarityopts + subrepoopts + walkopts + dryrunopts,
184 similarityopts + subrepoopts + walkopts + dryrunopts,
184 _('[OPTION]... [FILE]...'),
185 _('[OPTION]... [FILE]...'),
185 inferrepo=True)
186 inferrepo=True)
186 def addremove(ui, repo, *pats, **opts):
187 def addremove(ui, repo, *pats, **opts):
187 """add all new files, delete all missing files
188 """add all new files, delete all missing files
188
189
189 Add all new files and remove all missing files from the
190 Add all new files and remove all missing files from the
190 repository.
191 repository.
191
192
192 Unless names are given, new files are ignored if they match any of
193 Unless names are given, new files are ignored if they match any of
193 the patterns in ``.hgignore``. As with add, these changes take
194 the patterns in ``.hgignore``. As with add, these changes take
194 effect at the next commit.
195 effect at the next commit.
195
196
196 Use the -s/--similarity option to detect renamed files. This
197 Use the -s/--similarity option to detect renamed files. This
197 option takes a percentage between 0 (disabled) and 100 (files must
198 option takes a percentage between 0 (disabled) and 100 (files must
198 be identical) as its parameter. With a parameter greater than 0,
199 be identical) as its parameter. With a parameter greater than 0,
199 this compares every removed file with every added file and records
200 this compares every removed file with every added file and records
200 those similar enough as renames. Detecting renamed files this way
201 those similar enough as renames. Detecting renamed files this way
201 can be expensive. After using this option, :hg:`status -C` can be
202 can be expensive. After using this option, :hg:`status -C` can be
202 used to check which files were identified as moved or renamed. If
203 used to check which files were identified as moved or renamed. If
203 not specified, -s/--similarity defaults to 100 and only renames of
204 not specified, -s/--similarity defaults to 100 and only renames of
204 identical files are detected.
205 identical files are detected.
205
206
206 .. container:: verbose
207 .. container:: verbose
207
208
208 Examples:
209 Examples:
209
210
210 - A number of files (bar.c and foo.c) are new,
211 - A number of files (bar.c and foo.c) are new,
211 while foobar.c has been removed (without using :hg:`remove`)
212 while foobar.c has been removed (without using :hg:`remove`)
212 from the repository::
213 from the repository::
213
214
214 $ ls
215 $ ls
215 bar.c foo.c
216 bar.c foo.c
216 $ hg status
217 $ hg status
217 ! foobar.c
218 ! foobar.c
218 ? bar.c
219 ? bar.c
219 ? foo.c
220 ? foo.c
220 $ hg addremove
221 $ hg addremove
221 adding bar.c
222 adding bar.c
222 adding foo.c
223 adding foo.c
223 removing foobar.c
224 removing foobar.c
224 $ hg status
225 $ hg status
225 A bar.c
226 A bar.c
226 A foo.c
227 A foo.c
227 R foobar.c
228 R foobar.c
228
229
229 - A file foobar.c was moved to foo.c without using :hg:`rename`.
230 - A file foobar.c was moved to foo.c without using :hg:`rename`.
230 Afterwards, it was edited slightly::
231 Afterwards, it was edited slightly::
231
232
232 $ ls
233 $ ls
233 foo.c
234 foo.c
234 $ hg status
235 $ hg status
235 ! foobar.c
236 ! foobar.c
236 ? foo.c
237 ? foo.c
237 $ hg addremove --similarity 90
238 $ hg addremove --similarity 90
238 removing foobar.c
239 removing foobar.c
239 adding foo.c
240 adding foo.c
240 recording removal of foobar.c as rename to foo.c (94% similar)
241 recording removal of foobar.c as rename to foo.c (94% similar)
241 $ hg status -C
242 $ hg status -C
242 A foo.c
243 A foo.c
243 foobar.c
244 foobar.c
244 R foobar.c
245 R foobar.c
245
246
246 Returns 0 if all files are successfully added.
247 Returns 0 if all files are successfully added.
247 """
248 """
248 opts = pycompat.byteskwargs(opts)
249 opts = pycompat.byteskwargs(opts)
249 if not opts.get('similarity'):
250 if not opts.get('similarity'):
250 opts['similarity'] = '100'
251 opts['similarity'] = '100'
251 matcher = scmutil.match(repo[None], pats, opts)
252 matcher = scmutil.match(repo[None], pats, opts)
252 return scmutil.addremove(repo, matcher, "", opts)
253 return scmutil.addremove(repo, matcher, "", opts)
253
254
254 @command('^annotate|blame',
255 @command('^annotate|blame',
255 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
256 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
256 ('', 'follow', None,
257 ('', 'follow', None,
257 _('follow copies/renames and list the filename (DEPRECATED)')),
258 _('follow copies/renames and list the filename (DEPRECATED)')),
258 ('', 'no-follow', None, _("don't follow copies and renames")),
259 ('', 'no-follow', None, _("don't follow copies and renames")),
259 ('a', 'text', None, _('treat all files as text')),
260 ('a', 'text', None, _('treat all files as text')),
260 ('u', 'user', None, _('list the author (long with -v)')),
261 ('u', 'user', None, _('list the author (long with -v)')),
261 ('f', 'file', None, _('list the filename')),
262 ('f', 'file', None, _('list the filename')),
262 ('d', 'date', None, _('list the date (short with -q)')),
263 ('d', 'date', None, _('list the date (short with -q)')),
263 ('n', 'number', None, _('list the revision number (default)')),
264 ('n', 'number', None, _('list the revision number (default)')),
264 ('c', 'changeset', None, _('list the changeset')),
265 ('c', 'changeset', None, _('list the changeset')),
265 ('l', 'line-number', None, _('show line number at the first appearance')),
266 ('l', 'line-number', None, _('show line number at the first appearance')),
266 ('', 'skip', [], _('revision to not display (EXPERIMENTAL)'), _('REV')),
267 ('', 'skip', [], _('revision to not display (EXPERIMENTAL)'), _('REV')),
267 ] + diffwsopts + walkopts + formatteropts,
268 ] + diffwsopts + walkopts + formatteropts,
268 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
269 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
269 inferrepo=True)
270 inferrepo=True)
270 def annotate(ui, repo, *pats, **opts):
271 def annotate(ui, repo, *pats, **opts):
271 """show changeset information by line for each file
272 """show changeset information by line for each file
272
273
273 List changes in files, showing the revision id responsible for
274 List changes in files, showing the revision id responsible for
274 each line.
275 each line.
275
276
276 This command is useful for discovering when a change was made and
277 This command is useful for discovering when a change was made and
277 by whom.
278 by whom.
278
279
279 If you include --file, --user, or --date, the revision number is
280 If you include --file, --user, or --date, the revision number is
280 suppressed unless you also include --number.
281 suppressed unless you also include --number.
281
282
282 Without the -a/--text option, annotate will avoid processing files
283 Without the -a/--text option, annotate will avoid processing files
283 it detects as binary. With -a, annotate will annotate the file
284 it detects as binary. With -a, annotate will annotate the file
284 anyway, although the results will probably be neither useful
285 anyway, although the results will probably be neither useful
285 nor desirable.
286 nor desirable.
286
287
287 Returns 0 on success.
288 Returns 0 on success.
288 """
289 """
289 opts = pycompat.byteskwargs(opts)
290 opts = pycompat.byteskwargs(opts)
290 if not pats:
291 if not pats:
291 raise error.Abort(_('at least one filename or pattern is required'))
292 raise error.Abort(_('at least one filename or pattern is required'))
292
293
293 if opts.get('follow'):
294 if opts.get('follow'):
294 # --follow is deprecated and now just an alias for -f/--file
295 # --follow is deprecated and now just an alias for -f/--file
295 # to mimic the behavior of Mercurial before version 1.5
296 # to mimic the behavior of Mercurial before version 1.5
296 opts['file'] = True
297 opts['file'] = True
297
298
298 rev = opts.get('rev')
299 rev = opts.get('rev')
299 if rev:
300 if rev:
300 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
301 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
301 ctx = scmutil.revsingle(repo, rev)
302 ctx = scmutil.revsingle(repo, rev)
302
303
303 rootfm = ui.formatter('annotate', opts)
304 rootfm = ui.formatter('annotate', opts)
304 if ui.quiet:
305 if ui.quiet:
305 datefunc = dateutil.shortdate
306 datefunc = dateutil.shortdate
306 else:
307 else:
307 datefunc = dateutil.datestr
308 datefunc = dateutil.datestr
308 if ctx.rev() is None:
309 if ctx.rev() is None:
309 def hexfn(node):
310 def hexfn(node):
310 if node is None:
311 if node is None:
311 return None
312 return None
312 else:
313 else:
313 return rootfm.hexfunc(node)
314 return rootfm.hexfunc(node)
314 if opts.get('changeset'):
315 if opts.get('changeset'):
315 # omit "+" suffix which is appended to node hex
316 # omit "+" suffix which is appended to node hex
316 def formatrev(rev):
317 def formatrev(rev):
317 if rev is None:
318 if rev is None:
318 return '%d' % ctx.p1().rev()
319 return '%d' % ctx.p1().rev()
319 else:
320 else:
320 return '%d' % rev
321 return '%d' % rev
321 else:
322 else:
322 def formatrev(rev):
323 def formatrev(rev):
323 if rev is None:
324 if rev is None:
324 return '%d+' % ctx.p1().rev()
325 return '%d+' % ctx.p1().rev()
325 else:
326 else:
326 return '%d ' % rev
327 return '%d ' % rev
327 def formathex(hex):
328 def formathex(hex):
328 if hex is None:
329 if hex is None:
329 return '%s+' % rootfm.hexfunc(ctx.p1().node())
330 return '%s+' % rootfm.hexfunc(ctx.p1().node())
330 else:
331 else:
331 return '%s ' % hex
332 return '%s ' % hex
332 else:
333 else:
333 hexfn = rootfm.hexfunc
334 hexfn = rootfm.hexfunc
334 formatrev = formathex = pycompat.bytestr
335 formatrev = formathex = pycompat.bytestr
335
336
336 opmap = [('user', ' ', lambda x: x.fctx.user(), ui.shortuser),
337 opmap = [('user', ' ', lambda x: x.fctx.user(), ui.shortuser),
337 ('rev', ' ', lambda x: x.fctx.rev(), formatrev),
338 ('rev', ' ', lambda x: x.fctx.rev(), formatrev),
338 ('node', ' ', lambda x: hexfn(x.fctx.node()), formathex),
339 ('node', ' ', lambda x: hexfn(x.fctx.node()), formathex),
339 ('date', ' ', lambda x: x.fctx.date(), util.cachefunc(datefunc)),
340 ('date', ' ', lambda x: x.fctx.date(), util.cachefunc(datefunc)),
340 ('path', ' ', lambda x: x.fctx.path(), pycompat.bytestr),
341 ('path', ' ', lambda x: x.fctx.path(), pycompat.bytestr),
341 ('line_number', ':', lambda x: x.lineno, pycompat.bytestr),
342 ('line_number', ':', lambda x: x.lineno, pycompat.bytestr),
342 ]
343 ]
343 opnamemap = {'rev': 'number', 'node': 'changeset', 'path': 'file'}
344 opnamemap = {'rev': 'number', 'node': 'changeset', 'path': 'file'}
344
345
345 if (not opts.get('user') and not opts.get('changeset')
346 if (not opts.get('user') and not opts.get('changeset')
346 and not opts.get('date') and not opts.get('file')):
347 and not opts.get('date') and not opts.get('file')):
347 opts['number'] = True
348 opts['number'] = True
348
349
349 linenumber = opts.get('line_number') is not None
350 linenumber = opts.get('line_number') is not None
350 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
351 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
351 raise error.Abort(_('at least one of -n/-c is required for -l'))
352 raise error.Abort(_('at least one of -n/-c is required for -l'))
352
353
353 ui.pager('annotate')
354 ui.pager('annotate')
354
355
355 if rootfm.isplain():
356 if rootfm.isplain():
356 def makefunc(get, fmt):
357 def makefunc(get, fmt):
357 return lambda x: fmt(get(x))
358 return lambda x: fmt(get(x))
358 else:
359 else:
359 def makefunc(get, fmt):
360 def makefunc(get, fmt):
360 return get
361 return get
361 datahint = rootfm.datahint()
362 datahint = rootfm.datahint()
362 funcmap = [(makefunc(get, fmt), sep) for fn, sep, get, fmt in opmap
363 funcmap = [(makefunc(get, fmt), sep) for fn, sep, get, fmt in opmap
363 if opts.get(opnamemap.get(fn, fn)) or fn in datahint]
364 if opts.get(opnamemap.get(fn, fn)) or fn in datahint]
364 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
365 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
365 fields = ' '.join(fn for fn, sep, get, fmt in opmap
366 fields = ' '.join(fn for fn, sep, get, fmt in opmap
366 if opts.get(opnamemap.get(fn, fn)) or fn in datahint)
367 if opts.get(opnamemap.get(fn, fn)) or fn in datahint)
367
368
368 def bad(x, y):
369 def bad(x, y):
369 raise error.Abort("%s: %s" % (x, y))
370 raise error.Abort("%s: %s" % (x, y))
370
371
371 m = scmutil.match(ctx, pats, opts, badfn=bad)
372 m = scmutil.match(ctx, pats, opts, badfn=bad)
372
373
373 follow = not opts.get('no_follow')
374 follow = not opts.get('no_follow')
374 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
375 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
375 whitespace=True)
376 whitespace=True)
376 skiprevs = opts.get('skip')
377 skiprevs = opts.get('skip')
377 if skiprevs:
378 if skiprevs:
378 skiprevs = scmutil.revrange(repo, skiprevs)
379 skiprevs = scmutil.revrange(repo, skiprevs)
379
380
380 for abs in ctx.walk(m):
381 for abs in ctx.walk(m):
381 fctx = ctx[abs]
382 fctx = ctx[abs]
382 rootfm.startitem()
383 rootfm.startitem()
383 rootfm.data(path=abs)
384 rootfm.data(path=abs)
384 if not opts.get('text') and fctx.isbinary():
385 if not opts.get('text') and fctx.isbinary():
385 rootfm.plain(_("%s: binary file\n")
386 rootfm.plain(_("%s: binary file\n")
386 % ((pats and m.rel(abs)) or abs))
387 % ((pats and m.rel(abs)) or abs))
387 continue
388 continue
388
389
389 fm = rootfm.nested('lines', tmpl='{rev}: {line}')
390 fm = rootfm.nested('lines', tmpl='{rev}: {line}')
390 lines = fctx.annotate(follow=follow, skiprevs=skiprevs,
391 lines = fctx.annotate(follow=follow, skiprevs=skiprevs,
391 diffopts=diffopts)
392 diffopts=diffopts)
392 if not lines:
393 if not lines:
393 fm.end()
394 fm.end()
394 continue
395 continue
395 formats = []
396 formats = []
396 pieces = []
397 pieces = []
397
398
398 for f, sep in funcmap:
399 for f, sep in funcmap:
399 l = [f(n) for n in lines]
400 l = [f(n) for n in lines]
400 if fm.isplain():
401 if fm.isplain():
401 sizes = [encoding.colwidth(x) for x in l]
402 sizes = [encoding.colwidth(x) for x in l]
402 ml = max(sizes)
403 ml = max(sizes)
403 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
404 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
404 else:
405 else:
405 formats.append(['%s' for x in l])
406 formats.append(['%s' for x in l])
406 pieces.append(l)
407 pieces.append(l)
407
408
408 for f, p, n in zip(zip(*formats), zip(*pieces), lines):
409 for f, p, n in zip(zip(*formats), zip(*pieces), lines):
409 fm.startitem()
410 fm.startitem()
410 fm.context(fctx=n.fctx)
411 fm.context(fctx=n.fctx)
411 fm.write(fields, "".join(f), *p)
412 fm.write(fields, "".join(f), *p)
412 if n.skip:
413 if n.skip:
413 fmt = "* %s"
414 fmt = "* %s"
414 else:
415 else:
415 fmt = ": %s"
416 fmt = ": %s"
416 fm.write('line', fmt, n.text)
417 fm.write('line', fmt, n.text)
417
418
418 if not lines[-1].text.endswith('\n'):
419 if not lines[-1].text.endswith('\n'):
419 fm.plain('\n')
420 fm.plain('\n')
420 fm.end()
421 fm.end()
421
422
422 rootfm.end()
423 rootfm.end()
423
424
424 @command('archive',
425 @command('archive',
425 [('', 'no-decode', None, _('do not pass files through decoders')),
426 [('', 'no-decode', None, _('do not pass files through decoders')),
426 ('p', 'prefix', '', _('directory prefix for files in archive'),
427 ('p', 'prefix', '', _('directory prefix for files in archive'),
427 _('PREFIX')),
428 _('PREFIX')),
428 ('r', 'rev', '', _('revision to distribute'), _('REV')),
429 ('r', 'rev', '', _('revision to distribute'), _('REV')),
429 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
430 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
430 ] + subrepoopts + walkopts,
431 ] + subrepoopts + walkopts,
431 _('[OPTION]... DEST'))
432 _('[OPTION]... DEST'))
432 def archive(ui, repo, dest, **opts):
433 def archive(ui, repo, dest, **opts):
433 '''create an unversioned archive of a repository revision
434 '''create an unversioned archive of a repository revision
434
435
435 By default, the revision used is the parent of the working
436 By default, the revision used is the parent of the working
436 directory; use -r/--rev to specify a different revision.
437 directory; use -r/--rev to specify a different revision.
437
438
438 The archive type is automatically detected based on file
439 The archive type is automatically detected based on file
439 extension (to override, use -t/--type).
440 extension (to override, use -t/--type).
440
441
441 .. container:: verbose
442 .. container:: verbose
442
443
443 Examples:
444 Examples:
444
445
445 - create a zip file containing the 1.0 release::
446 - create a zip file containing the 1.0 release::
446
447
447 hg archive -r 1.0 project-1.0.zip
448 hg archive -r 1.0 project-1.0.zip
448
449
449 - create a tarball excluding .hg files::
450 - create a tarball excluding .hg files::
450
451
451 hg archive project.tar.gz -X ".hg*"
452 hg archive project.tar.gz -X ".hg*"
452
453
453 Valid types are:
454 Valid types are:
454
455
455 :``files``: a directory full of files (default)
456 :``files``: a directory full of files (default)
456 :``tar``: tar archive, uncompressed
457 :``tar``: tar archive, uncompressed
457 :``tbz2``: tar archive, compressed using bzip2
458 :``tbz2``: tar archive, compressed using bzip2
458 :``tgz``: tar archive, compressed using gzip
459 :``tgz``: tar archive, compressed using gzip
459 :``uzip``: zip archive, uncompressed
460 :``uzip``: zip archive, uncompressed
460 :``zip``: zip archive, compressed using deflate
461 :``zip``: zip archive, compressed using deflate
461
462
462 The exact name of the destination archive or directory is given
463 The exact name of the destination archive or directory is given
463 using a format string; see :hg:`help export` for details.
464 using a format string; see :hg:`help export` for details.
464
465
465 Each member added to an archive file has a directory prefix
466 Each member added to an archive file has a directory prefix
466 prepended. Use -p/--prefix to specify a format string for the
467 prepended. Use -p/--prefix to specify a format string for the
467 prefix. The default is the basename of the archive, with suffixes
468 prefix. The default is the basename of the archive, with suffixes
468 removed.
469 removed.
469
470
470 Returns 0 on success.
471 Returns 0 on success.
471 '''
472 '''
472
473
473 opts = pycompat.byteskwargs(opts)
474 opts = pycompat.byteskwargs(opts)
474 rev = opts.get('rev')
475 rev = opts.get('rev')
475 if rev:
476 if rev:
476 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
477 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
477 ctx = scmutil.revsingle(repo, rev)
478 ctx = scmutil.revsingle(repo, rev)
478 if not ctx:
479 if not ctx:
479 raise error.Abort(_('no working directory: please specify a revision'))
480 raise error.Abort(_('no working directory: please specify a revision'))
480 node = ctx.node()
481 node = ctx.node()
481 dest = cmdutil.makefilename(ctx, dest)
482 dest = cmdutil.makefilename(ctx, dest)
482 if os.path.realpath(dest) == repo.root:
483 if os.path.realpath(dest) == repo.root:
483 raise error.Abort(_('repository root cannot be destination'))
484 raise error.Abort(_('repository root cannot be destination'))
484
485
485 kind = opts.get('type') or archival.guesskind(dest) or 'files'
486 kind = opts.get('type') or archival.guesskind(dest) or 'files'
486 prefix = opts.get('prefix')
487 prefix = opts.get('prefix')
487
488
488 if dest == '-':
489 if dest == '-':
489 if kind == 'files':
490 if kind == 'files':
490 raise error.Abort(_('cannot archive plain files to stdout'))
491 raise error.Abort(_('cannot archive plain files to stdout'))
491 dest = cmdutil.makefileobj(ctx, dest)
492 dest = cmdutil.makefileobj(ctx, dest)
492 if not prefix:
493 if not prefix:
493 prefix = os.path.basename(repo.root) + '-%h'
494 prefix = os.path.basename(repo.root) + '-%h'
494
495
495 prefix = cmdutil.makefilename(ctx, prefix)
496 prefix = cmdutil.makefilename(ctx, prefix)
496 match = scmutil.match(ctx, [], opts)
497 match = scmutil.match(ctx, [], opts)
497 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
498 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
498 match, prefix, subrepos=opts.get('subrepos'))
499 match, prefix, subrepos=opts.get('subrepos'))
499
500
500 @command('backout',
501 @command('backout',
501 [('', 'merge', None, _('merge with old dirstate parent after backout')),
502 [('', 'merge', None, _('merge with old dirstate parent after backout')),
502 ('', 'commit', None,
503 ('', 'commit', None,
503 _('commit if no conflicts were encountered (DEPRECATED)')),
504 _('commit if no conflicts were encountered (DEPRECATED)')),
504 ('', 'no-commit', None, _('do not commit')),
505 ('', 'no-commit', None, _('do not commit')),
505 ('', 'parent', '',
506 ('', 'parent', '',
506 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
507 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
507 ('r', 'rev', '', _('revision to backout'), _('REV')),
508 ('r', 'rev', '', _('revision to backout'), _('REV')),
508 ('e', 'edit', False, _('invoke editor on commit messages')),
509 ('e', 'edit', False, _('invoke editor on commit messages')),
509 ] + mergetoolopts + walkopts + commitopts + commitopts2,
510 ] + mergetoolopts + walkopts + commitopts + commitopts2,
510 _('[OPTION]... [-r] REV'))
511 _('[OPTION]... [-r] REV'))
511 def backout(ui, repo, node=None, rev=None, **opts):
512 def backout(ui, repo, node=None, rev=None, **opts):
512 '''reverse effect of earlier changeset
513 '''reverse effect of earlier changeset
513
514
514 Prepare a new changeset with the effect of REV undone in the
515 Prepare a new changeset with the effect of REV undone in the
515 current working directory. If no conflicts were encountered,
516 current working directory. If no conflicts were encountered,
516 it will be committed immediately.
517 it will be committed immediately.
517
518
518 If REV is the parent of the working directory, then this new changeset
519 If REV is the parent of the working directory, then this new changeset
519 is committed automatically (unless --no-commit is specified).
520 is committed automatically (unless --no-commit is specified).
520
521
521 .. note::
522 .. note::
522
523
523 :hg:`backout` cannot be used to fix either an unwanted or
524 :hg:`backout` cannot be used to fix either an unwanted or
524 incorrect merge.
525 incorrect merge.
525
526
526 .. container:: verbose
527 .. container:: verbose
527
528
528 Examples:
529 Examples:
529
530
530 - Reverse the effect of the parent of the working directory.
531 - Reverse the effect of the parent of the working directory.
531 This backout will be committed immediately::
532 This backout will be committed immediately::
532
533
533 hg backout -r .
534 hg backout -r .
534
535
535 - Reverse the effect of previous bad revision 23::
536 - Reverse the effect of previous bad revision 23::
536
537
537 hg backout -r 23
538 hg backout -r 23
538
539
539 - Reverse the effect of previous bad revision 23 and
540 - Reverse the effect of previous bad revision 23 and
540 leave changes uncommitted::
541 leave changes uncommitted::
541
542
542 hg backout -r 23 --no-commit
543 hg backout -r 23 --no-commit
543 hg commit -m "Backout revision 23"
544 hg commit -m "Backout revision 23"
544
545
545 By default, the pending changeset will have one parent,
546 By default, the pending changeset will have one parent,
546 maintaining a linear history. With --merge, the pending
547 maintaining a linear history. With --merge, the pending
547 changeset will instead have two parents: the old parent of the
548 changeset will instead have two parents: the old parent of the
548 working directory and a new child of REV that simply undoes REV.
549 working directory and a new child of REV that simply undoes REV.
549
550
550 Before version 1.7, the behavior without --merge was equivalent
551 Before version 1.7, the behavior without --merge was equivalent
551 to specifying --merge followed by :hg:`update --clean .` to
552 to specifying --merge followed by :hg:`update --clean .` to
552 cancel the merge and leave the child of REV as a head to be
553 cancel the merge and leave the child of REV as a head to be
553 merged separately.
554 merged separately.
554
555
555 See :hg:`help dates` for a list of formats valid for -d/--date.
556 See :hg:`help dates` for a list of formats valid for -d/--date.
556
557
557 See :hg:`help revert` for a way to restore files to the state
558 See :hg:`help revert` for a way to restore files to the state
558 of another revision.
559 of another revision.
559
560
560 Returns 0 on success, 1 if nothing to backout or there are unresolved
561 Returns 0 on success, 1 if nothing to backout or there are unresolved
561 files.
562 files.
562 '''
563 '''
563 with repo.wlock(), repo.lock():
564 with repo.wlock(), repo.lock():
564 return _dobackout(ui, repo, node, rev, **opts)
565 return _dobackout(ui, repo, node, rev, **opts)
565
566
566 def _dobackout(ui, repo, node=None, rev=None, **opts):
567 def _dobackout(ui, repo, node=None, rev=None, **opts):
567 opts = pycompat.byteskwargs(opts)
568 opts = pycompat.byteskwargs(opts)
568 if opts.get('commit') and opts.get('no_commit'):
569 if opts.get('commit') and opts.get('no_commit'):
569 raise error.Abort(_("cannot use --commit with --no-commit"))
570 raise error.Abort(_("cannot use --commit with --no-commit"))
570 if opts.get('merge') and opts.get('no_commit'):
571 if opts.get('merge') and opts.get('no_commit'):
571 raise error.Abort(_("cannot use --merge with --no-commit"))
572 raise error.Abort(_("cannot use --merge with --no-commit"))
572
573
573 if rev and node:
574 if rev and node:
574 raise error.Abort(_("please specify just one revision"))
575 raise error.Abort(_("please specify just one revision"))
575
576
576 if not rev:
577 if not rev:
577 rev = node
578 rev = node
578
579
579 if not rev:
580 if not rev:
580 raise error.Abort(_("please specify a revision to backout"))
581 raise error.Abort(_("please specify a revision to backout"))
581
582
582 date = opts.get('date')
583 date = opts.get('date')
583 if date:
584 if date:
584 opts['date'] = dateutil.parsedate(date)
585 opts['date'] = dateutil.parsedate(date)
585
586
586 cmdutil.checkunfinished(repo)
587 cmdutil.checkunfinished(repo)
587 cmdutil.bailifchanged(repo)
588 cmdutil.bailifchanged(repo)
588 node = scmutil.revsingle(repo, rev).node()
589 node = scmutil.revsingle(repo, rev).node()
589
590
590 op1, op2 = repo.dirstate.parents()
591 op1, op2 = repo.dirstate.parents()
591 if not repo.changelog.isancestor(node, op1):
592 if not repo.changelog.isancestor(node, op1):
592 raise error.Abort(_('cannot backout change that is not an ancestor'))
593 raise error.Abort(_('cannot backout change that is not an ancestor'))
593
594
594 p1, p2 = repo.changelog.parents(node)
595 p1, p2 = repo.changelog.parents(node)
595 if p1 == nullid:
596 if p1 == nullid:
596 raise error.Abort(_('cannot backout a change with no parents'))
597 raise error.Abort(_('cannot backout a change with no parents'))
597 if p2 != nullid:
598 if p2 != nullid:
598 if not opts.get('parent'):
599 if not opts.get('parent'):
599 raise error.Abort(_('cannot backout a merge changeset'))
600 raise error.Abort(_('cannot backout a merge changeset'))
600 p = repo.lookup(opts['parent'])
601 p = repo.lookup(opts['parent'])
601 if p not in (p1, p2):
602 if p not in (p1, p2):
602 raise error.Abort(_('%s is not a parent of %s') %
603 raise error.Abort(_('%s is not a parent of %s') %
603 (short(p), short(node)))
604 (short(p), short(node)))
604 parent = p
605 parent = p
605 else:
606 else:
606 if opts.get('parent'):
607 if opts.get('parent'):
607 raise error.Abort(_('cannot use --parent on non-merge changeset'))
608 raise error.Abort(_('cannot use --parent on non-merge changeset'))
608 parent = p1
609 parent = p1
609
610
610 # the backout should appear on the same branch
611 # the backout should appear on the same branch
611 branch = repo.dirstate.branch()
612 branch = repo.dirstate.branch()
612 bheads = repo.branchheads(branch)
613 bheads = repo.branchheads(branch)
613 rctx = scmutil.revsingle(repo, hex(parent))
614 rctx = scmutil.revsingle(repo, hex(parent))
614 if not opts.get('merge') and op1 != node:
615 if not opts.get('merge') and op1 != node:
615 with dirstateguard.dirstateguard(repo, 'backout'):
616 with dirstateguard.dirstateguard(repo, 'backout'):
616 overrides = {('ui', 'forcemerge'): opts.get('tool', '')}
617 overrides = {('ui', 'forcemerge'): opts.get('tool', '')}
617 with ui.configoverride(overrides, 'backout'):
618 with ui.configoverride(overrides, 'backout'):
618 stats = mergemod.update(repo, parent, True, True, node, False)
619 stats = mergemod.update(repo, parent, True, True, node, False)
619 repo.setparents(op1, op2)
620 repo.setparents(op1, op2)
620 hg._showstats(repo, stats)
621 hg._showstats(repo, stats)
621 if stats.unresolvedcount:
622 if stats.unresolvedcount:
622 repo.ui.status(_("use 'hg resolve' to retry unresolved "
623 repo.ui.status(_("use 'hg resolve' to retry unresolved "
623 "file merges\n"))
624 "file merges\n"))
624 return 1
625 return 1
625 else:
626 else:
626 hg.clean(repo, node, show_stats=False)
627 hg.clean(repo, node, show_stats=False)
627 repo.dirstate.setbranch(branch)
628 repo.dirstate.setbranch(branch)
628 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
629 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
629
630
630 if opts.get('no_commit'):
631 if opts.get('no_commit'):
631 msg = _("changeset %s backed out, "
632 msg = _("changeset %s backed out, "
632 "don't forget to commit.\n")
633 "don't forget to commit.\n")
633 ui.status(msg % short(node))
634 ui.status(msg % short(node))
634 return 0
635 return 0
635
636
636 def commitfunc(ui, repo, message, match, opts):
637 def commitfunc(ui, repo, message, match, opts):
637 editform = 'backout'
638 editform = 'backout'
638 e = cmdutil.getcommiteditor(editform=editform,
639 e = cmdutil.getcommiteditor(editform=editform,
639 **pycompat.strkwargs(opts))
640 **pycompat.strkwargs(opts))
640 if not message:
641 if not message:
641 # we don't translate commit messages
642 # we don't translate commit messages
642 message = "Backed out changeset %s" % short(node)
643 message = "Backed out changeset %s" % short(node)
643 e = cmdutil.getcommiteditor(edit=True, editform=editform)
644 e = cmdutil.getcommiteditor(edit=True, editform=editform)
644 return repo.commit(message, opts.get('user'), opts.get('date'),
645 return repo.commit(message, opts.get('user'), opts.get('date'),
645 match, editor=e)
646 match, editor=e)
646 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
647 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
647 if not newnode:
648 if not newnode:
648 ui.status(_("nothing changed\n"))
649 ui.status(_("nothing changed\n"))
649 return 1
650 return 1
650 cmdutil.commitstatus(repo, newnode, branch, bheads)
651 cmdutil.commitstatus(repo, newnode, branch, bheads)
651
652
652 def nice(node):
653 def nice(node):
653 return '%d:%s' % (repo.changelog.rev(node), short(node))
654 return '%d:%s' % (repo.changelog.rev(node), short(node))
654 ui.status(_('changeset %s backs out changeset %s\n') %
655 ui.status(_('changeset %s backs out changeset %s\n') %
655 (nice(repo.changelog.tip()), nice(node)))
656 (nice(repo.changelog.tip()), nice(node)))
656 if opts.get('merge') and op1 != node:
657 if opts.get('merge') and op1 != node:
657 hg.clean(repo, op1, show_stats=False)
658 hg.clean(repo, op1, show_stats=False)
658 ui.status(_('merging with changeset %s\n')
659 ui.status(_('merging with changeset %s\n')
659 % nice(repo.changelog.tip()))
660 % nice(repo.changelog.tip()))
660 overrides = {('ui', 'forcemerge'): opts.get('tool', '')}
661 overrides = {('ui', 'forcemerge'): opts.get('tool', '')}
661 with ui.configoverride(overrides, 'backout'):
662 with ui.configoverride(overrides, 'backout'):
662 return hg.merge(repo, hex(repo.changelog.tip()))
663 return hg.merge(repo, hex(repo.changelog.tip()))
663 return 0
664 return 0
664
665
665 @command('bisect',
666 @command('bisect',
666 [('r', 'reset', False, _('reset bisect state')),
667 [('r', 'reset', False, _('reset bisect state')),
667 ('g', 'good', False, _('mark changeset good')),
668 ('g', 'good', False, _('mark changeset good')),
668 ('b', 'bad', False, _('mark changeset bad')),
669 ('b', 'bad', False, _('mark changeset bad')),
669 ('s', 'skip', False, _('skip testing changeset')),
670 ('s', 'skip', False, _('skip testing changeset')),
670 ('e', 'extend', False, _('extend the bisect range')),
671 ('e', 'extend', False, _('extend the bisect range')),
671 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
672 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
672 ('U', 'noupdate', False, _('do not update to target'))],
673 ('U', 'noupdate', False, _('do not update to target'))],
673 _("[-gbsr] [-U] [-c CMD] [REV]"))
674 _("[-gbsr] [-U] [-c CMD] [REV]"))
674 def bisect(ui, repo, rev=None, extra=None, command=None,
675 def bisect(ui, repo, rev=None, extra=None, command=None,
675 reset=None, good=None, bad=None, skip=None, extend=None,
676 reset=None, good=None, bad=None, skip=None, extend=None,
676 noupdate=None):
677 noupdate=None):
677 """subdivision search of changesets
678 """subdivision search of changesets
678
679
679 This command helps to find changesets which introduce problems. To
680 This command helps to find changesets which introduce problems. To
680 use, mark the earliest changeset you know exhibits the problem as
681 use, mark the earliest changeset you know exhibits the problem as
681 bad, then mark the latest changeset which is free from the problem
682 bad, then mark the latest changeset which is free from the problem
682 as good. Bisect will update your working directory to a revision
683 as good. Bisect will update your working directory to a revision
683 for testing (unless the -U/--noupdate option is specified). Once
684 for testing (unless the -U/--noupdate option is specified). Once
684 you have performed tests, mark the working directory as good or
685 you have performed tests, mark the working directory as good or
685 bad, and bisect will either update to another candidate changeset
686 bad, and bisect will either update to another candidate changeset
686 or announce that it has found the bad revision.
687 or announce that it has found the bad revision.
687
688
688 As a shortcut, you can also use the revision argument to mark a
689 As a shortcut, you can also use the revision argument to mark a
689 revision as good or bad without checking it out first.
690 revision as good or bad without checking it out first.
690
691
691 If you supply a command, it will be used for automatic bisection.
692 If you supply a command, it will be used for automatic bisection.
692 The environment variable HG_NODE will contain the ID of the
693 The environment variable HG_NODE will contain the ID of the
693 changeset being tested. The exit status of the command will be
694 changeset being tested. The exit status of the command will be
694 used to mark revisions as good or bad: status 0 means good, 125
695 used to mark revisions as good or bad: status 0 means good, 125
695 means to skip the revision, 127 (command not found) will abort the
696 means to skip the revision, 127 (command not found) will abort the
696 bisection, and any other non-zero exit status means the revision
697 bisection, and any other non-zero exit status means the revision
697 is bad.
698 is bad.
698
699
699 .. container:: verbose
700 .. container:: verbose
700
701
701 Some examples:
702 Some examples:
702
703
703 - start a bisection with known bad revision 34, and good revision 12::
704 - start a bisection with known bad revision 34, and good revision 12::
704
705
705 hg bisect --bad 34
706 hg bisect --bad 34
706 hg bisect --good 12
707 hg bisect --good 12
707
708
708 - advance the current bisection by marking current revision as good or
709 - advance the current bisection by marking current revision as good or
709 bad::
710 bad::
710
711
711 hg bisect --good
712 hg bisect --good
712 hg bisect --bad
713 hg bisect --bad
713
714
714 - mark the current revision, or a known revision, to be skipped (e.g. if
715 - mark the current revision, or a known revision, to be skipped (e.g. if
715 that revision is not usable because of another issue)::
716 that revision is not usable because of another issue)::
716
717
717 hg bisect --skip
718 hg bisect --skip
718 hg bisect --skip 23
719 hg bisect --skip 23
719
720
720 - skip all revisions that do not touch directories ``foo`` or ``bar``::
721 - skip all revisions that do not touch directories ``foo`` or ``bar``::
721
722
722 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
723 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
723
724
724 - forget the current bisection::
725 - forget the current bisection::
725
726
726 hg bisect --reset
727 hg bisect --reset
727
728
728 - use 'make && make tests' to automatically find the first broken
729 - use 'make && make tests' to automatically find the first broken
729 revision::
730 revision::
730
731
731 hg bisect --reset
732 hg bisect --reset
732 hg bisect --bad 34
733 hg bisect --bad 34
733 hg bisect --good 12
734 hg bisect --good 12
734 hg bisect --command "make && make tests"
735 hg bisect --command "make && make tests"
735
736
736 - see all changesets whose states are already known in the current
737 - see all changesets whose states are already known in the current
737 bisection::
738 bisection::
738
739
739 hg log -r "bisect(pruned)"
740 hg log -r "bisect(pruned)"
740
741
741 - see the changeset currently being bisected (especially useful
742 - see the changeset currently being bisected (especially useful
742 if running with -U/--noupdate)::
743 if running with -U/--noupdate)::
743
744
744 hg log -r "bisect(current)"
745 hg log -r "bisect(current)"
745
746
746 - see all changesets that took part in the current bisection::
747 - see all changesets that took part in the current bisection::
747
748
748 hg log -r "bisect(range)"
749 hg log -r "bisect(range)"
749
750
750 - you can even get a nice graph::
751 - you can even get a nice graph::
751
752
752 hg log --graph -r "bisect(range)"
753 hg log --graph -r "bisect(range)"
753
754
754 See :hg:`help revisions.bisect` for more about the `bisect()` predicate.
755 See :hg:`help revisions.bisect` for more about the `bisect()` predicate.
755
756
756 Returns 0 on success.
757 Returns 0 on success.
757 """
758 """
758 # backward compatibility
759 # backward compatibility
759 if rev in "good bad reset init".split():
760 if rev in "good bad reset init".split():
760 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
761 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
761 cmd, rev, extra = rev, extra, None
762 cmd, rev, extra = rev, extra, None
762 if cmd == "good":
763 if cmd == "good":
763 good = True
764 good = True
764 elif cmd == "bad":
765 elif cmd == "bad":
765 bad = True
766 bad = True
766 else:
767 else:
767 reset = True
768 reset = True
768 elif extra:
769 elif extra:
769 raise error.Abort(_('incompatible arguments'))
770 raise error.Abort(_('incompatible arguments'))
770
771
771 incompatibles = {
772 incompatibles = {
772 '--bad': bad,
773 '--bad': bad,
773 '--command': bool(command),
774 '--command': bool(command),
774 '--extend': extend,
775 '--extend': extend,
775 '--good': good,
776 '--good': good,
776 '--reset': reset,
777 '--reset': reset,
777 '--skip': skip,
778 '--skip': skip,
778 }
779 }
779
780
780 enabled = [x for x in incompatibles if incompatibles[x]]
781 enabled = [x for x in incompatibles if incompatibles[x]]
781
782
782 if len(enabled) > 1:
783 if len(enabled) > 1:
783 raise error.Abort(_('%s and %s are incompatible') %
784 raise error.Abort(_('%s and %s are incompatible') %
784 tuple(sorted(enabled)[0:2]))
785 tuple(sorted(enabled)[0:2]))
785
786
786 if reset:
787 if reset:
787 hbisect.resetstate(repo)
788 hbisect.resetstate(repo)
788 return
789 return
789
790
790 state = hbisect.load_state(repo)
791 state = hbisect.load_state(repo)
791
792
792 # update state
793 # update state
793 if good or bad or skip:
794 if good or bad or skip:
794 if rev:
795 if rev:
795 nodes = [repo[i].node() for i in scmutil.revrange(repo, [rev])]
796 nodes = [repo[i].node() for i in scmutil.revrange(repo, [rev])]
796 else:
797 else:
797 nodes = [repo.lookup('.')]
798 nodes = [repo.lookup('.')]
798 if good:
799 if good:
799 state['good'] += nodes
800 state['good'] += nodes
800 elif bad:
801 elif bad:
801 state['bad'] += nodes
802 state['bad'] += nodes
802 elif skip:
803 elif skip:
803 state['skip'] += nodes
804 state['skip'] += nodes
804 hbisect.save_state(repo, state)
805 hbisect.save_state(repo, state)
805 if not (state['good'] and state['bad']):
806 if not (state['good'] and state['bad']):
806 return
807 return
807
808
808 def mayupdate(repo, node, show_stats=True):
809 def mayupdate(repo, node, show_stats=True):
809 """common used update sequence"""
810 """common used update sequence"""
810 if noupdate:
811 if noupdate:
811 return
812 return
812 cmdutil.checkunfinished(repo)
813 cmdutil.checkunfinished(repo)
813 cmdutil.bailifchanged(repo)
814 cmdutil.bailifchanged(repo)
814 return hg.clean(repo, node, show_stats=show_stats)
815 return hg.clean(repo, node, show_stats=show_stats)
815
816
816 displayer = logcmdutil.changesetdisplayer(ui, repo, {})
817 displayer = logcmdutil.changesetdisplayer(ui, repo, {})
817
818
818 if command:
819 if command:
819 changesets = 1
820 changesets = 1
820 if noupdate:
821 if noupdate:
821 try:
822 try:
822 node = state['current'][0]
823 node = state['current'][0]
823 except LookupError:
824 except LookupError:
824 raise error.Abort(_('current bisect revision is unknown - '
825 raise error.Abort(_('current bisect revision is unknown - '
825 'start a new bisect to fix'))
826 'start a new bisect to fix'))
826 else:
827 else:
827 node, p2 = repo.dirstate.parents()
828 node, p2 = repo.dirstate.parents()
828 if p2 != nullid:
829 if p2 != nullid:
829 raise error.Abort(_('current bisect revision is a merge'))
830 raise error.Abort(_('current bisect revision is a merge'))
830 if rev:
831 if rev:
831 node = repo[scmutil.revsingle(repo, rev, node)].node()
832 node = repo[scmutil.revsingle(repo, rev, node)].node()
832 try:
833 try:
833 while changesets:
834 while changesets:
834 # update state
835 # update state
835 state['current'] = [node]
836 state['current'] = [node]
836 hbisect.save_state(repo, state)
837 hbisect.save_state(repo, state)
837 status = ui.system(command, environ={'HG_NODE': hex(node)},
838 status = ui.system(command, environ={'HG_NODE': hex(node)},
838 blockedtag='bisect_check')
839 blockedtag='bisect_check')
839 if status == 125:
840 if status == 125:
840 transition = "skip"
841 transition = "skip"
841 elif status == 0:
842 elif status == 0:
842 transition = "good"
843 transition = "good"
843 # status < 0 means process was killed
844 # status < 0 means process was killed
844 elif status == 127:
845 elif status == 127:
845 raise error.Abort(_("failed to execute %s") % command)
846 raise error.Abort(_("failed to execute %s") % command)
846 elif status < 0:
847 elif status < 0:
847 raise error.Abort(_("%s killed") % command)
848 raise error.Abort(_("%s killed") % command)
848 else:
849 else:
849 transition = "bad"
850 transition = "bad"
850 state[transition].append(node)
851 state[transition].append(node)
851 ctx = repo[node]
852 ctx = repo[node]
852 ui.status(_('changeset %d:%s: %s\n') % (ctx.rev(), ctx,
853 ui.status(_('changeset %d:%s: %s\n') % (ctx.rev(), ctx,
853 transition))
854 transition))
854 hbisect.checkstate(state)
855 hbisect.checkstate(state)
855 # bisect
856 # bisect
856 nodes, changesets, bgood = hbisect.bisect(repo, state)
857 nodes, changesets, bgood = hbisect.bisect(repo, state)
857 # update to next check
858 # update to next check
858 node = nodes[0]
859 node = nodes[0]
859 mayupdate(repo, node, show_stats=False)
860 mayupdate(repo, node, show_stats=False)
860 finally:
861 finally:
861 state['current'] = [node]
862 state['current'] = [node]
862 hbisect.save_state(repo, state)
863 hbisect.save_state(repo, state)
863 hbisect.printresult(ui, repo, state, displayer, nodes, bgood)
864 hbisect.printresult(ui, repo, state, displayer, nodes, bgood)
864 return
865 return
865
866
866 hbisect.checkstate(state)
867 hbisect.checkstate(state)
867
868
868 # actually bisect
869 # actually bisect
869 nodes, changesets, good = hbisect.bisect(repo, state)
870 nodes, changesets, good = hbisect.bisect(repo, state)
870 if extend:
871 if extend:
871 if not changesets:
872 if not changesets:
872 extendnode = hbisect.extendrange(repo, state, nodes, good)
873 extendnode = hbisect.extendrange(repo, state, nodes, good)
873 if extendnode is not None:
874 if extendnode is not None:
874 ui.write(_("Extending search to changeset %d:%s\n")
875 ui.write(_("Extending search to changeset %d:%s\n")
875 % (extendnode.rev(), extendnode))
876 % (extendnode.rev(), extendnode))
876 state['current'] = [extendnode.node()]
877 state['current'] = [extendnode.node()]
877 hbisect.save_state(repo, state)
878 hbisect.save_state(repo, state)
878 return mayupdate(repo, extendnode.node())
879 return mayupdate(repo, extendnode.node())
879 raise error.Abort(_("nothing to extend"))
880 raise error.Abort(_("nothing to extend"))
880
881
881 if changesets == 0:
882 if changesets == 0:
882 hbisect.printresult(ui, repo, state, displayer, nodes, good)
883 hbisect.printresult(ui, repo, state, displayer, nodes, good)
883 else:
884 else:
884 assert len(nodes) == 1 # only a single node can be tested next
885 assert len(nodes) == 1 # only a single node can be tested next
885 node = nodes[0]
886 node = nodes[0]
886 # compute the approximate number of remaining tests
887 # compute the approximate number of remaining tests
887 tests, size = 0, 2
888 tests, size = 0, 2
888 while size <= changesets:
889 while size <= changesets:
889 tests, size = tests + 1, size * 2
890 tests, size = tests + 1, size * 2
890 rev = repo.changelog.rev(node)
891 rev = repo.changelog.rev(node)
891 ui.write(_("Testing changeset %d:%s "
892 ui.write(_("Testing changeset %d:%s "
892 "(%d changesets remaining, ~%d tests)\n")
893 "(%d changesets remaining, ~%d tests)\n")
893 % (rev, short(node), changesets, tests))
894 % (rev, short(node), changesets, tests))
894 state['current'] = [node]
895 state['current'] = [node]
895 hbisect.save_state(repo, state)
896 hbisect.save_state(repo, state)
896 return mayupdate(repo, node)
897 return mayupdate(repo, node)
897
898
898 @command('bookmarks|bookmark',
899 @command('bookmarks|bookmark',
899 [('f', 'force', False, _('force')),
900 [('f', 'force', False, _('force')),
900 ('r', 'rev', '', _('revision for bookmark action'), _('REV')),
901 ('r', 'rev', '', _('revision for bookmark action'), _('REV')),
901 ('d', 'delete', False, _('delete a given bookmark')),
902 ('d', 'delete', False, _('delete a given bookmark')),
902 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
903 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
903 ('i', 'inactive', False, _('mark a bookmark inactive')),
904 ('i', 'inactive', False, _('mark a bookmark inactive')),
904 ('', 'active', False, _('display the active bookmark')),
905 ('', 'active', False, _('display the active bookmark')),
905 ] + formatteropts,
906 ] + formatteropts,
906 _('hg bookmarks [OPTIONS]... [NAME]...'))
907 _('hg bookmarks [OPTIONS]... [NAME]...'))
907 def bookmark(ui, repo, *names, **opts):
908 def bookmark(ui, repo, *names, **opts):
908 '''create a new bookmark or list existing bookmarks
909 '''create a new bookmark or list existing bookmarks
909
910
910 Bookmarks are labels on changesets to help track lines of development.
911 Bookmarks are labels on changesets to help track lines of development.
911 Bookmarks are unversioned and can be moved, renamed and deleted.
912 Bookmarks are unversioned and can be moved, renamed and deleted.
912 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.
913
914
914 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'.
915 The active bookmark is indicated with a '*'.
916 The active bookmark is indicated with a '*'.
916 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.
917 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.
918 Updating away from a bookmark will cause it to be deactivated.
919 Updating away from a bookmark will cause it to be deactivated.
919
920
920 Bookmarks can be pushed and pulled between repositories (see
921 Bookmarks can be pushed and pulled between repositories (see
921 :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
922 diverged, a new 'divergent bookmark' of the form 'name@path' will
923 diverged, a new 'divergent bookmark' of the form 'name@path' will
923 be created. Using :hg:`merge` will resolve the divergence.
924 be created. Using :hg:`merge` will resolve the divergence.
924
925
925 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
926 the active bookmark's name.
927 the active bookmark's name.
927
928
928 A bookmark named '@' has the special property that :hg:`clone` will
929 A bookmark named '@' has the special property that :hg:`clone` will
929 check it out by default if it exists.
930 check it out by default if it exists.
930
931
931 The '--active' flag will display the current bookmark or return non-zero,
932 The '--active' flag will display the current bookmark or return non-zero,
932 if combined with other action, they will be performed on the active
933 if combined with other action, they will be performed on the active
933 bookmark.
934 bookmark.
934
935
935 .. container:: verbose
936 .. container:: verbose
936
937
937 Examples:
938 Examples:
938
939
939 - create an active bookmark for a new line of development::
940 - create an active bookmark for a new line of development::
940
941
941 hg book new-feature
942 hg book new-feature
942
943
943 - create an inactive bookmark as a place marker::
944 - create an inactive bookmark as a place marker::
944
945
945 hg book -i reviewed
946 hg book -i reviewed
946
947
947 - create an inactive bookmark on another changeset::
948 - create an inactive bookmark on another changeset::
948
949
949 hg book -r .^ tested
950 hg book -r .^ tested
950
951
951 - rename bookmark turkey to dinner::
952 - rename bookmark turkey to dinner::
952
953
953 hg book -m turkey dinner
954 hg book -m turkey dinner
954
955
955 - move the '@' bookmark from another branch::
956 - move the '@' bookmark from another branch::
956
957
957 hg book -f @
958 hg book -f @
958 '''
959 '''
959 force = opts.get(r'force')
960 force = opts.get(r'force')
960 rev = opts.get(r'rev')
961 rev = opts.get(r'rev')
961 delete = opts.get(r'delete')
962 delete = opts.get(r'delete')
962 rename = opts.get(r'rename')
963 rename = opts.get(r'rename')
963 inactive = opts.get(r'inactive')
964 inactive = opts.get(r'inactive')
964 active = opts.get(r'active')
965 active = opts.get(r'active')
965
966
966 if delete and rename:
967 if delete and rename:
967 raise error.Abort(_("--delete and --rename are incompatible"))
968 raise error.Abort(_("--delete and --rename are incompatible"))
968 if delete and rev:
969 if delete and rev:
969 raise error.Abort(_("--rev is incompatible with --delete"))
970 raise error.Abort(_("--rev is incompatible with --delete"))
970 if rename and rev:
971 if rename and rev:
971 raise error.Abort(_("--rev is incompatible with --rename"))
972 raise error.Abort(_("--rev is incompatible with --rename"))
972 if delete and active:
973 if delete and active:
973 raise error.Abort(_("--delete is incompatible with --active"))
974 raise error.Abort(_("--delete is incompatible with --active"))
974 if rev and active:
975 if rev and active:
975 raise error.Abort(_("--rev is incompatible with --active"))
976 raise error.Abort(_("--rev is incompatible with --active"))
976 if rename and active:
977 if rename and active:
977 raise error.Abort(_("--rename is incompatible with --active"))
978 raise error.Abort(_("--rename is incompatible with --active"))
978 if names and active:
979 if names and active:
979 raise error.Abort(_("NAMES is incompatible with --active"))
980 raise error.Abort(_("NAMES is incompatible with --active"))
980 if inactive and active:
981 if inactive and active:
981 raise error.Abort(_("--inactive is incompatible with --active"))
982 raise error.Abort(_("--inactive is incompatible with --active"))
982 if not names and (delete or rev):
983 if not names and (delete or rev):
983 raise error.Abort(_("bookmark name required"))
984 raise error.Abort(_("bookmark name required"))
984
985
985 if delete or rename or names or inactive:
986 if delete or rename or names or inactive:
986 with repo.wlock(), repo.lock(), repo.transaction('bookmark') as tr:
987 with repo.wlock(), repo.lock(), repo.transaction('bookmark') as tr:
987 if delete:
988 if delete:
988 names = pycompat.maplist(repo._bookmarks.expandname, names)
989 names = pycompat.maplist(repo._bookmarks.expandname, names)
989 bookmarks.delete(repo, tr, names)
990 bookmarks.delete(repo, tr, names)
990 elif rename:
991 elif rename:
991 if not names:
992 if not names:
992 raise error.Abort(_("new bookmark name required"))
993 raise error.Abort(_("new bookmark name required"))
993 elif len(names) > 1:
994 elif len(names) > 1:
994 raise error.Abort(_("only one new bookmark name allowed"))
995 raise error.Abort(_("only one new bookmark name allowed"))
995 rename = repo._bookmarks.expandname(rename)
996 rename = repo._bookmarks.expandname(rename)
996 bookmarks.rename(repo, tr, rename, names[0], force, inactive)
997 bookmarks.rename(repo, tr, rename, names[0], force, inactive)
997 elif names:
998 elif names:
998 bookmarks.addbookmarks(repo, tr, names, rev, force, inactive)
999 bookmarks.addbookmarks(repo, tr, names, rev, force, inactive)
999 elif inactive:
1000 elif inactive:
1000 if len(repo._bookmarks) == 0:
1001 if len(repo._bookmarks) == 0:
1001 ui.status(_("no bookmarks set\n"))
1002 ui.status(_("no bookmarks set\n"))
1002 elif not repo._activebookmark:
1003 elif not repo._activebookmark:
1003 ui.status(_("no active bookmark\n"))
1004 ui.status(_("no active bookmark\n"))
1004 else:
1005 else:
1005 bookmarks.deactivate(repo)
1006 bookmarks.deactivate(repo)
1006 elif active:
1007 elif active:
1007 book = repo._activebookmark
1008 book = repo._activebookmark
1008 if book is None:
1009 if book is None:
1009 return 1
1010 return 1
1010 ui.write("%s\n" % book, label=bookmarks.activebookmarklabel)
1011 ui.write("%s\n" % book, label=bookmarks.activebookmarklabel)
1011 else: # show bookmarks
1012 else: # show bookmarks
1012 bookmarks.printbookmarks(ui, repo, **opts)
1013 bookmarks.printbookmarks(ui, repo, **opts)
1013
1014
1014 @command('branch',
1015 @command('branch',
1015 [('f', 'force', None,
1016 [('f', 'force', None,
1016 _('set branch name even if it shadows an existing branch')),
1017 _('set branch name even if it shadows an existing branch')),
1017 ('C', 'clean', None, _('reset branch name to parent branch name')),
1018 ('C', 'clean', None, _('reset branch name to parent branch name')),
1018 ('r', 'rev', [], _('change branches of the given revs (EXPERIMENTAL)')),
1019 ('r', 'rev', [], _('change branches of the given revs (EXPERIMENTAL)')),
1019 ],
1020 ],
1020 _('[-fC] [NAME]'))
1021 _('[-fC] [NAME]'))
1021 def branch(ui, repo, label=None, **opts):
1022 def branch(ui, repo, label=None, **opts):
1022 """set or show the current branch name
1023 """set or show the current branch name
1023
1024
1024 .. note::
1025 .. note::
1025
1026
1026 Branch names are permanent and global. Use :hg:`bookmark` to create a
1027 Branch names are permanent and global. Use :hg:`bookmark` to create a
1027 light-weight bookmark instead. See :hg:`help glossary` for more
1028 light-weight bookmark instead. See :hg:`help glossary` for more
1028 information about named branches and bookmarks.
1029 information about named branches and bookmarks.
1029
1030
1030 With no argument, show the current branch name. With one argument,
1031 With no argument, show the current branch name. With one argument,
1031 set the working directory branch name (the branch will not exist
1032 set the working directory branch name (the branch will not exist
1032 in the repository until the next commit). Standard practice
1033 in the repository until the next commit). Standard practice
1033 recommends that primary development take place on the 'default'
1034 recommends that primary development take place on the 'default'
1034 branch.
1035 branch.
1035
1036
1036 Unless -f/--force is specified, branch will not let you set a
1037 Unless -f/--force is specified, branch will not let you set a
1037 branch name that already exists.
1038 branch name that already exists.
1038
1039
1039 Use -C/--clean to reset the working directory branch to that of
1040 Use -C/--clean to reset the working directory branch to that of
1040 the parent of the working directory, negating a previous branch
1041 the parent of the working directory, negating a previous branch
1041 change.
1042 change.
1042
1043
1043 Use the command :hg:`update` to switch to an existing branch. Use
1044 Use the command :hg:`update` to switch to an existing branch. Use
1044 :hg:`commit --close-branch` to mark this branch head as closed.
1045 :hg:`commit --close-branch` to mark this branch head as closed.
1045 When all heads of a branch are closed, the branch will be
1046 When all heads of a branch are closed, the branch will be
1046 considered closed.
1047 considered closed.
1047
1048
1048 Returns 0 on success.
1049 Returns 0 on success.
1049 """
1050 """
1050 opts = pycompat.byteskwargs(opts)
1051 opts = pycompat.byteskwargs(opts)
1051 revs = opts.get('rev')
1052 revs = opts.get('rev')
1052 if label:
1053 if label:
1053 label = label.strip()
1054 label = label.strip()
1054
1055
1055 if not opts.get('clean') and not label:
1056 if not opts.get('clean') and not label:
1056 if revs:
1057 if revs:
1057 raise error.Abort(_("no branch name specified for the revisions"))
1058 raise error.Abort(_("no branch name specified for the revisions"))
1058 ui.write("%s\n" % repo.dirstate.branch())
1059 ui.write("%s\n" % repo.dirstate.branch())
1059 return
1060 return
1060
1061
1061 with repo.wlock():
1062 with repo.wlock():
1062 if opts.get('clean'):
1063 if opts.get('clean'):
1063 label = repo[None].p1().branch()
1064 label = repo[None].p1().branch()
1064 repo.dirstate.setbranch(label)
1065 repo.dirstate.setbranch(label)
1065 ui.status(_('reset working directory to branch %s\n') % label)
1066 ui.status(_('reset working directory to branch %s\n') % label)
1066 elif label:
1067 elif label:
1067
1068
1068 scmutil.checknewlabel(repo, label, 'branch')
1069 scmutil.checknewlabel(repo, label, 'branch')
1069 if revs:
1070 if revs:
1070 return cmdutil.changebranch(ui, repo, revs, label)
1071 return cmdutil.changebranch(ui, repo, revs, label)
1071
1072
1072 if not opts.get('force') and label in repo.branchmap():
1073 if not opts.get('force') and label in repo.branchmap():
1073 if label not in [p.branch() for p in repo[None].parents()]:
1074 if label not in [p.branch() for p in repo[None].parents()]:
1074 raise error.Abort(_('a branch of the same name already'
1075 raise error.Abort(_('a branch of the same name already'
1075 ' exists'),
1076 ' exists'),
1076 # i18n: "it" refers to an existing branch
1077 # i18n: "it" refers to an existing branch
1077 hint=_("use 'hg update' to switch to it"))
1078 hint=_("use 'hg update' to switch to it"))
1078
1079
1079 repo.dirstate.setbranch(label)
1080 repo.dirstate.setbranch(label)
1080 ui.status(_('marked working directory as branch %s\n') % label)
1081 ui.status(_('marked working directory as branch %s\n') % label)
1081
1082
1082 # find any open named branches aside from default
1083 # find any open named branches aside from default
1083 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1084 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1084 if n != "default" and not c]
1085 if n != "default" and not c]
1085 if not others:
1086 if not others:
1086 ui.status(_('(branches are permanent and global, '
1087 ui.status(_('(branches are permanent and global, '
1087 'did you want a bookmark?)\n'))
1088 'did you want a bookmark?)\n'))
1088
1089
1089 @command('branches',
1090 @command('branches',
1090 [('a', 'active', False,
1091 [('a', 'active', False,
1091 _('show only branches that have unmerged heads (DEPRECATED)')),
1092 _('show only branches that have unmerged heads (DEPRECATED)')),
1092 ('c', 'closed', False, _('show normal and closed branches')),
1093 ('c', 'closed', False, _('show normal and closed branches')),
1093 ] + formatteropts,
1094 ] + formatteropts,
1094 _('[-c]'),
1095 _('[-c]'),
1095 intents={INTENT_READONLY})
1096 intents={INTENT_READONLY})
1096 def branches(ui, repo, active=False, closed=False, **opts):
1097 def branches(ui, repo, active=False, closed=False, **opts):
1097 """list repository named branches
1098 """list repository named branches
1098
1099
1099 List the repository's named branches, indicating which ones are
1100 List the repository's named branches, indicating which ones are
1100 inactive. If -c/--closed is specified, also list branches which have
1101 inactive. If -c/--closed is specified, also list branches which have
1101 been marked closed (see :hg:`commit --close-branch`).
1102 been marked closed (see :hg:`commit --close-branch`).
1102
1103
1103 Use the command :hg:`update` to switch to an existing branch.
1104 Use the command :hg:`update` to switch to an existing branch.
1104
1105
1105 Returns 0.
1106 Returns 0.
1106 """
1107 """
1107
1108
1108 opts = pycompat.byteskwargs(opts)
1109 opts = pycompat.byteskwargs(opts)
1109 ui.pager('branches')
1110 ui.pager('branches')
1110 fm = ui.formatter('branches', opts)
1111 fm = ui.formatter('branches', opts)
1111 hexfunc = fm.hexfunc
1112 hexfunc = fm.hexfunc
1112
1113
1113 allheads = set(repo.heads())
1114 allheads = set(repo.heads())
1114 branches = []
1115 branches = []
1115 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1116 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1116 isactive = False
1117 isactive = False
1117 if not isclosed:
1118 if not isclosed:
1118 openheads = set(repo.branchmap().iteropen(heads))
1119 openheads = set(repo.branchmap().iteropen(heads))
1119 isactive = bool(openheads & allheads)
1120 isactive = bool(openheads & allheads)
1120 branches.append((tag, repo[tip], isactive, not isclosed))
1121 branches.append((tag, repo[tip], isactive, not isclosed))
1121 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1122 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1122 reverse=True)
1123 reverse=True)
1123
1124
1124 for tag, ctx, isactive, isopen in branches:
1125 for tag, ctx, isactive, isopen in branches:
1125 if active and not isactive:
1126 if active and not isactive:
1126 continue
1127 continue
1127 if isactive:
1128 if isactive:
1128 label = 'branches.active'
1129 label = 'branches.active'
1129 notice = ''
1130 notice = ''
1130 elif not isopen:
1131 elif not isopen:
1131 if not closed:
1132 if not closed:
1132 continue
1133 continue
1133 label = 'branches.closed'
1134 label = 'branches.closed'
1134 notice = _(' (closed)')
1135 notice = _(' (closed)')
1135 else:
1136 else:
1136 label = 'branches.inactive'
1137 label = 'branches.inactive'
1137 notice = _(' (inactive)')
1138 notice = _(' (inactive)')
1138 current = (tag == repo.dirstate.branch())
1139 current = (tag == repo.dirstate.branch())
1139 if current:
1140 if current:
1140 label = 'branches.current'
1141 label = 'branches.current'
1141
1142
1142 fm.startitem()
1143 fm.startitem()
1143 fm.write('branch', '%s', tag, label=label)
1144 fm.write('branch', '%s', tag, label=label)
1144 rev = ctx.rev()
1145 rev = ctx.rev()
1145 padsize = max(31 - len("%d" % rev) - encoding.colwidth(tag), 0)
1146 padsize = max(31 - len("%d" % rev) - encoding.colwidth(tag), 0)
1146 fmt = ' ' * padsize + ' %d:%s'
1147 fmt = ' ' * padsize + ' %d:%s'
1147 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1148 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1148 label='log.changeset changeset.%s' % ctx.phasestr())
1149 label='log.changeset changeset.%s' % ctx.phasestr())
1149 fm.context(ctx=ctx)
1150 fm.context(ctx=ctx)
1150 fm.data(active=isactive, closed=not isopen, current=current)
1151 fm.data(active=isactive, closed=not isopen, current=current)
1151 if not ui.quiet:
1152 if not ui.quiet:
1152 fm.plain(notice)
1153 fm.plain(notice)
1153 fm.plain('\n')
1154 fm.plain('\n')
1154 fm.end()
1155 fm.end()
1155
1156
1156 @command('bundle',
1157 @command('bundle',
1157 [('f', 'force', None, _('run even when the destination is unrelated')),
1158 [('f', 'force', None, _('run even when the destination is unrelated')),
1158 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1159 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1159 _('REV')),
1160 _('REV')),
1160 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1161 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1161 _('BRANCH')),
1162 _('BRANCH')),
1162 ('', 'base', [],
1163 ('', 'base', [],
1163 _('a base changeset assumed to be available at the destination'),
1164 _('a base changeset assumed to be available at the destination'),
1164 _('REV')),
1165 _('REV')),
1165 ('a', 'all', None, _('bundle all changesets in the repository')),
1166 ('a', 'all', None, _('bundle all changesets in the repository')),
1166 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1167 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1167 ] + remoteopts,
1168 ] + remoteopts,
1168 _('[-f] [-t BUNDLESPEC] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1169 _('[-f] [-t BUNDLESPEC] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1169 def bundle(ui, repo, fname, dest=None, **opts):
1170 def bundle(ui, repo, fname, dest=None, **opts):
1170 """create a bundle file
1171 """create a bundle file
1171
1172
1172 Generate a bundle file containing data to be transferred to another
1173 Generate a bundle file containing data to be transferred to another
1173 repository.
1174 repository.
1174
1175
1175 To create a bundle containing all changesets, use -a/--all
1176 To create a bundle containing all changesets, use -a/--all
1176 (or --base null). Otherwise, hg assumes the destination will have
1177 (or --base null). Otherwise, hg assumes the destination will have
1177 all the nodes you specify with --base parameters. Otherwise, hg
1178 all the nodes you specify with --base parameters. Otherwise, hg
1178 will assume the repository has all the nodes in destination, or
1179 will assume the repository has all the nodes in destination, or
1179 default-push/default if no destination is specified, where destination
1180 default-push/default if no destination is specified, where destination
1180 is the repository you provide through DEST option.
1181 is the repository you provide through DEST option.
1181
1182
1182 You can change bundle format with the -t/--type option. See
1183 You can change bundle format with the -t/--type option. See
1183 :hg:`help bundlespec` for documentation on this format. By default,
1184 :hg:`help bundlespec` for documentation on this format. By default,
1184 the most appropriate format is used and compression defaults to
1185 the most appropriate format is used and compression defaults to
1185 bzip2.
1186 bzip2.
1186
1187
1187 The bundle file can then be transferred using conventional means
1188 The bundle file can then be transferred using conventional means
1188 and applied to another repository with the unbundle or pull
1189 and applied to another repository with the unbundle or pull
1189 command. This is useful when direct push and pull are not
1190 command. This is useful when direct push and pull are not
1190 available or when exporting an entire repository is undesirable.
1191 available or when exporting an entire repository is undesirable.
1191
1192
1192 Applying bundles preserves all changeset contents including
1193 Applying bundles preserves all changeset contents including
1193 permissions, copy/rename information, and revision history.
1194 permissions, copy/rename information, and revision history.
1194
1195
1195 Returns 0 on success, 1 if no changes found.
1196 Returns 0 on success, 1 if no changes found.
1196 """
1197 """
1197 opts = pycompat.byteskwargs(opts)
1198 opts = pycompat.byteskwargs(opts)
1198 revs = None
1199 revs = None
1199 if 'rev' in opts:
1200 if 'rev' in opts:
1200 revstrings = opts['rev']
1201 revstrings = opts['rev']
1201 revs = scmutil.revrange(repo, revstrings)
1202 revs = scmutil.revrange(repo, revstrings)
1202 if revstrings and not revs:
1203 if revstrings and not revs:
1203 raise error.Abort(_('no commits to bundle'))
1204 raise error.Abort(_('no commits to bundle'))
1204
1205
1205 bundletype = opts.get('type', 'bzip2').lower()
1206 bundletype = opts.get('type', 'bzip2').lower()
1206 try:
1207 try:
1207 bundlespec = exchange.parsebundlespec(repo, bundletype, strict=False)
1208 bundlespec = exchange.parsebundlespec(repo, bundletype, strict=False)
1208 except error.UnsupportedBundleSpecification as e:
1209 except error.UnsupportedBundleSpecification as e:
1209 raise error.Abort(pycompat.bytestr(e),
1210 raise error.Abort(pycompat.bytestr(e),
1210 hint=_("see 'hg help bundlespec' for supported "
1211 hint=_("see 'hg help bundlespec' for supported "
1211 "values for --type"))
1212 "values for --type"))
1212 cgversion = bundlespec.contentopts["cg.version"]
1213 cgversion = bundlespec.contentopts["cg.version"]
1213
1214
1214 # Packed bundles are a pseudo bundle format for now.
1215 # Packed bundles are a pseudo bundle format for now.
1215 if cgversion == 's1':
1216 if cgversion == 's1':
1216 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1217 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1217 hint=_("use 'hg debugcreatestreamclonebundle'"))
1218 hint=_("use 'hg debugcreatestreamclonebundle'"))
1218
1219
1219 if opts.get('all'):
1220 if opts.get('all'):
1220 if dest:
1221 if dest:
1221 raise error.Abort(_("--all is incompatible with specifying "
1222 raise error.Abort(_("--all is incompatible with specifying "
1222 "a destination"))
1223 "a destination"))
1223 if opts.get('base'):
1224 if opts.get('base'):
1224 ui.warn(_("ignoring --base because --all was specified\n"))
1225 ui.warn(_("ignoring --base because --all was specified\n"))
1225 base = ['null']
1226 base = ['null']
1226 else:
1227 else:
1227 base = scmutil.revrange(repo, opts.get('base'))
1228 base = scmutil.revrange(repo, opts.get('base'))
1228 if cgversion not in changegroup.supportedoutgoingversions(repo):
1229 if cgversion not in changegroup.supportedoutgoingversions(repo):
1229 raise error.Abort(_("repository does not support bundle version %s") %
1230 raise error.Abort(_("repository does not support bundle version %s") %
1230 cgversion)
1231 cgversion)
1231
1232
1232 if base:
1233 if base:
1233 if dest:
1234 if dest:
1234 raise error.Abort(_("--base is incompatible with specifying "
1235 raise error.Abort(_("--base is incompatible with specifying "
1235 "a destination"))
1236 "a destination"))
1236 common = [repo[rev].node() for rev in base]
1237 common = [repo[rev].node() for rev in base]
1237 heads = [repo[r].node() for r in revs] if revs else None
1238 heads = [repo[r].node() for r in revs] if revs else None
1238 outgoing = discovery.outgoing(repo, common, heads)
1239 outgoing = discovery.outgoing(repo, common, heads)
1239 else:
1240 else:
1240 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1241 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1241 dest, branches = hg.parseurl(dest, opts.get('branch'))
1242 dest, branches = hg.parseurl(dest, opts.get('branch'))
1242 other = hg.peer(repo, opts, dest)
1243 other = hg.peer(repo, opts, dest)
1243 revs = [repo[r].hex() for r in revs]
1244 revs = [repo[r].hex() for r in revs]
1244 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1245 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1245 heads = revs and pycompat.maplist(repo.lookup, revs) or revs
1246 heads = revs and pycompat.maplist(repo.lookup, revs) or revs
1246 outgoing = discovery.findcommonoutgoing(repo, other,
1247 outgoing = discovery.findcommonoutgoing(repo, other,
1247 onlyheads=heads,
1248 onlyheads=heads,
1248 force=opts.get('force'),
1249 force=opts.get('force'),
1249 portable=True)
1250 portable=True)
1250
1251
1251 if not outgoing.missing:
1252 if not outgoing.missing:
1252 scmutil.nochangesfound(ui, repo, not base and outgoing.excluded)
1253 scmutil.nochangesfound(ui, repo, not base and outgoing.excluded)
1253 return 1
1254 return 1
1254
1255
1255 if cgversion == '01': #bundle1
1256 if cgversion == '01': #bundle1
1256 bversion = 'HG10' + bundlespec.wirecompression
1257 bversion = 'HG10' + bundlespec.wirecompression
1257 bcompression = None
1258 bcompression = None
1258 elif cgversion in ('02', '03'):
1259 elif cgversion in ('02', '03'):
1259 bversion = 'HG20'
1260 bversion = 'HG20'
1260 bcompression = bundlespec.wirecompression
1261 bcompression = bundlespec.wirecompression
1261 else:
1262 else:
1262 raise error.ProgrammingError(
1263 raise error.ProgrammingError(
1263 'bundle: unexpected changegroup version %s' % cgversion)
1264 'bundle: unexpected changegroup version %s' % cgversion)
1264
1265
1265 # TODO compression options should be derived from bundlespec parsing.
1266 # TODO compression options should be derived from bundlespec parsing.
1266 # This is a temporary hack to allow adjusting bundle compression
1267 # This is a temporary hack to allow adjusting bundle compression
1267 # level without a) formalizing the bundlespec changes to declare it
1268 # level without a) formalizing the bundlespec changes to declare it
1268 # b) introducing a command flag.
1269 # b) introducing a command flag.
1269 compopts = {}
1270 compopts = {}
1270 complevel = ui.configint('experimental',
1271 complevel = ui.configint('experimental',
1271 'bundlecomplevel.' + bundlespec.compression)
1272 'bundlecomplevel.' + bundlespec.compression)
1272 if complevel is None:
1273 if complevel is None:
1273 complevel = ui.configint('experimental', 'bundlecomplevel')
1274 complevel = ui.configint('experimental', 'bundlecomplevel')
1274 if complevel is not None:
1275 if complevel is not None:
1275 compopts['level'] = complevel
1276 compopts['level'] = complevel
1276
1277
1277 # Allow overriding the bundling of obsmarker in phases through
1278 # Allow overriding the bundling of obsmarker in phases through
1278 # configuration while we don't have a bundle version that include them
1279 # configuration while we don't have a bundle version that include them
1279 if repo.ui.configbool('experimental', 'evolution.bundle-obsmarker'):
1280 if repo.ui.configbool('experimental', 'evolution.bundle-obsmarker'):
1280 bundlespec.contentopts['obsolescence'] = True
1281 bundlespec.contentopts['obsolescence'] = True
1281 if repo.ui.configbool('experimental', 'bundle-phases'):
1282 if repo.ui.configbool('experimental', 'bundle-phases'):
1282 bundlespec.contentopts['phases'] = True
1283 bundlespec.contentopts['phases'] = True
1283
1284
1284 bundle2.writenewbundle(ui, repo, 'bundle', fname, bversion, outgoing,
1285 bundle2.writenewbundle(ui, repo, 'bundle', fname, bversion, outgoing,
1285 bundlespec.contentopts, compression=bcompression,
1286 bundlespec.contentopts, compression=bcompression,
1286 compopts=compopts)
1287 compopts=compopts)
1287
1288
1288 @command('cat',
1289 @command('cat',
1289 [('o', 'output', '',
1290 [('o', 'output', '',
1290 _('print output to file with formatted name'), _('FORMAT')),
1291 _('print output to file with formatted name'), _('FORMAT')),
1291 ('r', 'rev', '', _('print the given revision'), _('REV')),
1292 ('r', 'rev', '', _('print the given revision'), _('REV')),
1292 ('', 'decode', None, _('apply any matching decode filter')),
1293 ('', 'decode', None, _('apply any matching decode filter')),
1293 ] + walkopts + formatteropts,
1294 ] + walkopts + formatteropts,
1294 _('[OPTION]... FILE...'),
1295 _('[OPTION]... FILE...'),
1295 inferrepo=True,
1296 inferrepo=True,
1296 intents={INTENT_READONLY})
1297 intents={INTENT_READONLY})
1297 def cat(ui, repo, file1, *pats, **opts):
1298 def cat(ui, repo, file1, *pats, **opts):
1298 """output the current or given revision of files
1299 """output the current or given revision of files
1299
1300
1300 Print the specified files as they were at the given revision. If
1301 Print the specified files as they were at the given revision. If
1301 no revision is given, the parent of the working directory is used.
1302 no revision is given, the parent of the working directory is used.
1302
1303
1303 Output may be to a file, in which case the name of the file is
1304 Output may be to a file, in which case the name of the file is
1304 given using a template string. See :hg:`help templates`. In addition
1305 given using a template string. See :hg:`help templates`. In addition
1305 to the common template keywords, the following formatting rules are
1306 to the common template keywords, the following formatting rules are
1306 supported:
1307 supported:
1307
1308
1308 :``%%``: literal "%" character
1309 :``%%``: literal "%" character
1309 :``%s``: basename of file being printed
1310 :``%s``: basename of file being printed
1310 :``%d``: dirname of file being printed, or '.' if in repository root
1311 :``%d``: dirname of file being printed, or '.' if in repository root
1311 :``%p``: root-relative path name of file being printed
1312 :``%p``: root-relative path name of file being printed
1312 :``%H``: changeset hash (40 hexadecimal digits)
1313 :``%H``: changeset hash (40 hexadecimal digits)
1313 :``%R``: changeset revision number
1314 :``%R``: changeset revision number
1314 :``%h``: short-form changeset hash (12 hexadecimal digits)
1315 :``%h``: short-form changeset hash (12 hexadecimal digits)
1315 :``%r``: zero-padded changeset revision number
1316 :``%r``: zero-padded changeset revision number
1316 :``%b``: basename of the exporting repository
1317 :``%b``: basename of the exporting repository
1317 :``\\``: literal "\\" character
1318 :``\\``: literal "\\" character
1318
1319
1319 Returns 0 on success.
1320 Returns 0 on success.
1320 """
1321 """
1321 opts = pycompat.byteskwargs(opts)
1322 opts = pycompat.byteskwargs(opts)
1322 rev = opts.get('rev')
1323 rev = opts.get('rev')
1323 if rev:
1324 if rev:
1324 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
1325 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
1325 ctx = scmutil.revsingle(repo, rev)
1326 ctx = scmutil.revsingle(repo, rev)
1326 m = scmutil.match(ctx, (file1,) + pats, opts)
1327 m = scmutil.match(ctx, (file1,) + pats, opts)
1327 fntemplate = opts.pop('output', '')
1328 fntemplate = opts.pop('output', '')
1328 if cmdutil.isstdiofilename(fntemplate):
1329 if cmdutil.isstdiofilename(fntemplate):
1329 fntemplate = ''
1330 fntemplate = ''
1330
1331
1331 if fntemplate:
1332 if fntemplate:
1332 fm = formatter.nullformatter(ui, 'cat', opts)
1333 fm = formatter.nullformatter(ui, 'cat', opts)
1333 else:
1334 else:
1334 ui.pager('cat')
1335 ui.pager('cat')
1335 fm = ui.formatter('cat', opts)
1336 fm = ui.formatter('cat', opts)
1336 with fm:
1337 with fm:
1337 return cmdutil.cat(ui, repo, ctx, m, fm, fntemplate, '',
1338 return cmdutil.cat(ui, repo, ctx, m, fm, fntemplate, '',
1338 **pycompat.strkwargs(opts))
1339 **pycompat.strkwargs(opts))
1339
1340
1340 @command('^clone',
1341 @command('^clone',
1341 [('U', 'noupdate', None, _('the clone will include an empty working '
1342 [('U', 'noupdate', None, _('the clone will include an empty working '
1342 'directory (only a repository)')),
1343 'directory (only a repository)')),
1343 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1344 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1344 _('REV')),
1345 _('REV')),
1345 ('r', 'rev', [], _('do not clone everything, but include this changeset'
1346 ('r', 'rev', [], _('do not clone everything, but include this changeset'
1346 ' and its ancestors'), _('REV')),
1347 ' and its ancestors'), _('REV')),
1347 ('b', 'branch', [], _('do not clone everything, but include this branch\'s'
1348 ('b', 'branch', [], _('do not clone everything, but include this branch\'s'
1348 ' changesets and their ancestors'), _('BRANCH')),
1349 ' changesets and their ancestors'), _('BRANCH')),
1349 ('', 'pull', None, _('use pull protocol to copy metadata')),
1350 ('', 'pull', None, _('use pull protocol to copy metadata')),
1350 ('', 'uncompressed', None,
1351 ('', 'uncompressed', None,
1351 _('an alias to --stream (DEPRECATED)')),
1352 _('an alias to --stream (DEPRECATED)')),
1352 ('', 'stream', None,
1353 ('', 'stream', None,
1353 _('clone with minimal data processing')),
1354 _('clone with minimal data processing')),
1354 ] + remoteopts,
1355 ] + remoteopts,
1355 _('[OPTION]... SOURCE [DEST]'),
1356 _('[OPTION]... SOURCE [DEST]'),
1356 norepo=True)
1357 norepo=True)
1357 def clone(ui, source, dest=None, **opts):
1358 def clone(ui, source, dest=None, **opts):
1358 """make a copy of an existing repository
1359 """make a copy of an existing repository
1359
1360
1360 Create a copy of an existing repository in a new directory.
1361 Create a copy of an existing repository in a new directory.
1361
1362
1362 If no destination directory name is specified, it defaults to the
1363 If no destination directory name is specified, it defaults to the
1363 basename of the source.
1364 basename of the source.
1364
1365
1365 The location of the source is added to the new repository's
1366 The location of the source is added to the new repository's
1366 ``.hg/hgrc`` file, as the default to be used for future pulls.
1367 ``.hg/hgrc`` file, as the default to be used for future pulls.
1367
1368
1368 Only local paths and ``ssh://`` URLs are supported as
1369 Only local paths and ``ssh://`` URLs are supported as
1369 destinations. For ``ssh://`` destinations, no working directory or
1370 destinations. For ``ssh://`` destinations, no working directory or
1370 ``.hg/hgrc`` will be created on the remote side.
1371 ``.hg/hgrc`` will be created on the remote side.
1371
1372
1372 If the source repository has a bookmark called '@' set, that
1373 If the source repository has a bookmark called '@' set, that
1373 revision will be checked out in the new repository by default.
1374 revision will be checked out in the new repository by default.
1374
1375
1375 To check out a particular version, use -u/--update, or
1376 To check out a particular version, use -u/--update, or
1376 -U/--noupdate to create a clone with no working directory.
1377 -U/--noupdate to create a clone with no working directory.
1377
1378
1378 To pull only a subset of changesets, specify one or more revisions
1379 To pull only a subset of changesets, specify one or more revisions
1379 identifiers with -r/--rev or branches with -b/--branch. The
1380 identifiers with -r/--rev or branches with -b/--branch. The
1380 resulting clone will contain only the specified changesets and
1381 resulting clone will contain only the specified changesets and
1381 their ancestors. These options (or 'clone src#rev dest') imply
1382 their ancestors. These options (or 'clone src#rev dest') imply
1382 --pull, even for local source repositories.
1383 --pull, even for local source repositories.
1383
1384
1384 In normal clone mode, the remote normalizes repository data into a common
1385 In normal clone mode, the remote normalizes repository data into a common
1385 exchange format and the receiving end translates this data into its local
1386 exchange format and the receiving end translates this data into its local
1386 storage format. --stream activates a different clone mode that essentially
1387 storage format. --stream activates a different clone mode that essentially
1387 copies repository files from the remote with minimal data processing. This
1388 copies repository files from the remote with minimal data processing. This
1388 significantly reduces the CPU cost of a clone both remotely and locally.
1389 significantly reduces the CPU cost of a clone both remotely and locally.
1389 However, it often increases the transferred data size by 30-40%. This can
1390 However, it often increases the transferred data size by 30-40%. This can
1390 result in substantially faster clones where I/O throughput is plentiful,
1391 result in substantially faster clones where I/O throughput is plentiful,
1391 especially for larger repositories. A side-effect of --stream clones is
1392 especially for larger repositories. A side-effect of --stream clones is
1392 that storage settings and requirements on the remote are applied locally:
1393 that storage settings and requirements on the remote are applied locally:
1393 a modern client may inherit legacy or inefficient storage used by the
1394 a modern client may inherit legacy or inefficient storage used by the
1394 remote or a legacy Mercurial client may not be able to clone from a
1395 remote or a legacy Mercurial client may not be able to clone from a
1395 modern Mercurial remote.
1396 modern Mercurial remote.
1396
1397
1397 .. note::
1398 .. note::
1398
1399
1399 Specifying a tag will include the tagged changeset but not the
1400 Specifying a tag will include the tagged changeset but not the
1400 changeset containing the tag.
1401 changeset containing the tag.
1401
1402
1402 .. container:: verbose
1403 .. container:: verbose
1403
1404
1404 For efficiency, hardlinks are used for cloning whenever the
1405 For efficiency, hardlinks are used for cloning whenever the
1405 source and destination are on the same filesystem (note this
1406 source and destination are on the same filesystem (note this
1406 applies only to the repository data, not to the working
1407 applies only to the repository data, not to the working
1407 directory). Some filesystems, such as AFS, implement hardlinking
1408 directory). Some filesystems, such as AFS, implement hardlinking
1408 incorrectly, but do not report errors. In these cases, use the
1409 incorrectly, but do not report errors. In these cases, use the
1409 --pull option to avoid hardlinking.
1410 --pull option to avoid hardlinking.
1410
1411
1411 Mercurial will update the working directory to the first applicable
1412 Mercurial will update the working directory to the first applicable
1412 revision from this list:
1413 revision from this list:
1413
1414
1414 a) null if -U or the source repository has no changesets
1415 a) null if -U or the source repository has no changesets
1415 b) if -u . and the source repository is local, the first parent of
1416 b) if -u . and the source repository is local, the first parent of
1416 the source repository's working directory
1417 the source repository's working directory
1417 c) the changeset specified with -u (if a branch name, this means the
1418 c) the changeset specified with -u (if a branch name, this means the
1418 latest head of that branch)
1419 latest head of that branch)
1419 d) the changeset specified with -r
1420 d) the changeset specified with -r
1420 e) the tipmost head specified with -b
1421 e) the tipmost head specified with -b
1421 f) the tipmost head specified with the url#branch source syntax
1422 f) the tipmost head specified with the url#branch source syntax
1422 g) the revision marked with the '@' bookmark, if present
1423 g) the revision marked with the '@' bookmark, if present
1423 h) the tipmost head of the default branch
1424 h) the tipmost head of the default branch
1424 i) tip
1425 i) tip
1425
1426
1426 When cloning from servers that support it, Mercurial may fetch
1427 When cloning from servers that support it, Mercurial may fetch
1427 pre-generated data from a server-advertised URL or inline from the
1428 pre-generated data from a server-advertised URL or inline from the
1428 same stream. When this is done, hooks operating on incoming changesets
1429 same stream. When this is done, hooks operating on incoming changesets
1429 and changegroups may fire more than once, once for each pre-generated
1430 and changegroups may fire more than once, once for each pre-generated
1430 bundle and as well as for any additional remaining data. In addition,
1431 bundle and as well as for any additional remaining data. In addition,
1431 if an error occurs, the repository may be rolled back to a partial
1432 if an error occurs, the repository may be rolled back to a partial
1432 clone. This behavior may change in future releases.
1433 clone. This behavior may change in future releases.
1433 See :hg:`help -e clonebundles` for more.
1434 See :hg:`help -e clonebundles` for more.
1434
1435
1435 Examples:
1436 Examples:
1436
1437
1437 - clone a remote repository to a new directory named hg/::
1438 - clone a remote repository to a new directory named hg/::
1438
1439
1439 hg clone https://www.mercurial-scm.org/repo/hg/
1440 hg clone https://www.mercurial-scm.org/repo/hg/
1440
1441
1441 - create a lightweight local clone::
1442 - create a lightweight local clone::
1442
1443
1443 hg clone project/ project-feature/
1444 hg clone project/ project-feature/
1444
1445
1445 - clone from an absolute path on an ssh server (note double-slash)::
1446 - clone from an absolute path on an ssh server (note double-slash)::
1446
1447
1447 hg clone ssh://user@server//home/projects/alpha/
1448 hg clone ssh://user@server//home/projects/alpha/
1448
1449
1449 - do a streaming clone while checking out a specified version::
1450 - do a streaming clone while checking out a specified version::
1450
1451
1451 hg clone --stream http://server/repo -u 1.5
1452 hg clone --stream http://server/repo -u 1.5
1452
1453
1453 - create a repository without changesets after a particular revision::
1454 - create a repository without changesets after a particular revision::
1454
1455
1455 hg clone -r 04e544 experimental/ good/
1456 hg clone -r 04e544 experimental/ good/
1456
1457
1457 - clone (and track) a particular named branch::
1458 - clone (and track) a particular named branch::
1458
1459
1459 hg clone https://www.mercurial-scm.org/repo/hg/#stable
1460 hg clone https://www.mercurial-scm.org/repo/hg/#stable
1460
1461
1461 See :hg:`help urls` for details on specifying URLs.
1462 See :hg:`help urls` for details on specifying URLs.
1462
1463
1463 Returns 0 on success.
1464 Returns 0 on success.
1464 """
1465 """
1465 opts = pycompat.byteskwargs(opts)
1466 opts = pycompat.byteskwargs(opts)
1466 if opts.get('noupdate') and opts.get('updaterev'):
1467 if opts.get('noupdate') and opts.get('updaterev'):
1467 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1468 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1468
1469
1470 # --include/--exclude can come from narrow or sparse.
1471 includepats, excludepats = None, None
1472
1473 # hg.clone() differentiates between None and an empty set. So make sure
1474 # patterns are sets if narrow is requested without patterns.
1475 if opts.get('narrow'):
1476 includepats = set()
1477 excludepats = set()
1478
1479 if opts.get('include'):
1480 includepats = narrowspec.parsepatterns(opts.get('include'))
1481 if opts.get('exclude'):
1482 excludepats = narrowspec.parsepatterns(opts.get('exclude'))
1483
1469 r = hg.clone(ui, opts, source, dest,
1484 r = hg.clone(ui, opts, source, dest,
1470 pull=opts.get('pull'),
1485 pull=opts.get('pull'),
1471 stream=opts.get('stream') or opts.get('uncompressed'),
1486 stream=opts.get('stream') or opts.get('uncompressed'),
1472 revs=opts.get('rev'),
1487 revs=opts.get('rev'),
1473 update=opts.get('updaterev') or not opts.get('noupdate'),
1488 update=opts.get('updaterev') or not opts.get('noupdate'),
1474 branch=opts.get('branch'),
1489 branch=opts.get('branch'),
1475 shareopts=opts.get('shareopts'))
1490 shareopts=opts.get('shareopts'),
1491 storeincludepats=includepats,
1492 storeexcludepats=excludepats)
1476
1493
1477 return r is None
1494 return r is None
1478
1495
1479 @command('^commit|ci',
1496 @command('^commit|ci',
1480 [('A', 'addremove', None,
1497 [('A', 'addremove', None,
1481 _('mark new/missing files as added/removed before committing')),
1498 _('mark new/missing files as added/removed before committing')),
1482 ('', 'close-branch', None,
1499 ('', 'close-branch', None,
1483 _('mark a branch head as closed')),
1500 _('mark a branch head as closed')),
1484 ('', 'amend', None, _('amend the parent of the working directory')),
1501 ('', 'amend', None, _('amend the parent of the working directory')),
1485 ('s', 'secret', None, _('use the secret phase for committing')),
1502 ('s', 'secret', None, _('use the secret phase for committing')),
1486 ('e', 'edit', None, _('invoke editor on commit messages')),
1503 ('e', 'edit', None, _('invoke editor on commit messages')),
1487 ('i', 'interactive', None, _('use interactive mode')),
1504 ('i', 'interactive', None, _('use interactive mode')),
1488 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1505 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1489 _('[OPTION]... [FILE]...'),
1506 _('[OPTION]... [FILE]...'),
1490 inferrepo=True)
1507 inferrepo=True)
1491 def commit(ui, repo, *pats, **opts):
1508 def commit(ui, repo, *pats, **opts):
1492 """commit the specified files or all outstanding changes
1509 """commit the specified files or all outstanding changes
1493
1510
1494 Commit changes to the given files into the repository. Unlike a
1511 Commit changes to the given files into the repository. Unlike a
1495 centralized SCM, this operation is a local operation. See
1512 centralized SCM, this operation is a local operation. See
1496 :hg:`push` for a way to actively distribute your changes.
1513 :hg:`push` for a way to actively distribute your changes.
1497
1514
1498 If a list of files is omitted, all changes reported by :hg:`status`
1515 If a list of files is omitted, all changes reported by :hg:`status`
1499 will be committed.
1516 will be committed.
1500
1517
1501 If you are committing the result of a merge, do not provide any
1518 If you are committing the result of a merge, do not provide any
1502 filenames or -I/-X filters.
1519 filenames or -I/-X filters.
1503
1520
1504 If no commit message is specified, Mercurial starts your
1521 If no commit message is specified, Mercurial starts your
1505 configured editor where you can enter a message. In case your
1522 configured editor where you can enter a message. In case your
1506 commit fails, you will find a backup of your message in
1523 commit fails, you will find a backup of your message in
1507 ``.hg/last-message.txt``.
1524 ``.hg/last-message.txt``.
1508
1525
1509 The --close-branch flag can be used to mark the current branch
1526 The --close-branch flag can be used to mark the current branch
1510 head closed. When all heads of a branch are closed, the branch
1527 head closed. When all heads of a branch are closed, the branch
1511 will be considered closed and no longer listed.
1528 will be considered closed and no longer listed.
1512
1529
1513 The --amend flag can be used to amend the parent of the
1530 The --amend flag can be used to amend the parent of the
1514 working directory with a new commit that contains the changes
1531 working directory with a new commit that contains the changes
1515 in the parent in addition to those currently reported by :hg:`status`,
1532 in the parent in addition to those currently reported by :hg:`status`,
1516 if there are any. The old commit is stored in a backup bundle in
1533 if there are any. The old commit is stored in a backup bundle in
1517 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1534 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1518 on how to restore it).
1535 on how to restore it).
1519
1536
1520 Message, user and date are taken from the amended commit unless
1537 Message, user and date are taken from the amended commit unless
1521 specified. When a message isn't specified on the command line,
1538 specified. When a message isn't specified on the command line,
1522 the editor will open with the message of the amended commit.
1539 the editor will open with the message of the amended commit.
1523
1540
1524 It is not possible to amend public changesets (see :hg:`help phases`)
1541 It is not possible to amend public changesets (see :hg:`help phases`)
1525 or changesets that have children.
1542 or changesets that have children.
1526
1543
1527 See :hg:`help dates` for a list of formats valid for -d/--date.
1544 See :hg:`help dates` for a list of formats valid for -d/--date.
1528
1545
1529 Returns 0 on success, 1 if nothing changed.
1546 Returns 0 on success, 1 if nothing changed.
1530
1547
1531 .. container:: verbose
1548 .. container:: verbose
1532
1549
1533 Examples:
1550 Examples:
1534
1551
1535 - commit all files ending in .py::
1552 - commit all files ending in .py::
1536
1553
1537 hg commit --include "set:**.py"
1554 hg commit --include "set:**.py"
1538
1555
1539 - commit all non-binary files::
1556 - commit all non-binary files::
1540
1557
1541 hg commit --exclude "set:binary()"
1558 hg commit --exclude "set:binary()"
1542
1559
1543 - amend the current commit and set the date to now::
1560 - amend the current commit and set the date to now::
1544
1561
1545 hg commit --amend --date now
1562 hg commit --amend --date now
1546 """
1563 """
1547 with repo.wlock(), repo.lock():
1564 with repo.wlock(), repo.lock():
1548 return _docommit(ui, repo, *pats, **opts)
1565 return _docommit(ui, repo, *pats, **opts)
1549
1566
1550 def _docommit(ui, repo, *pats, **opts):
1567 def _docommit(ui, repo, *pats, **opts):
1551 if opts.get(r'interactive'):
1568 if opts.get(r'interactive'):
1552 opts.pop(r'interactive')
1569 opts.pop(r'interactive')
1553 ret = cmdutil.dorecord(ui, repo, commit, None, False,
1570 ret = cmdutil.dorecord(ui, repo, commit, None, False,
1554 cmdutil.recordfilter, *pats,
1571 cmdutil.recordfilter, *pats,
1555 **opts)
1572 **opts)
1556 # ret can be 0 (no changes to record) or the value returned by
1573 # ret can be 0 (no changes to record) or the value returned by
1557 # commit(), 1 if nothing changed or None on success.
1574 # commit(), 1 if nothing changed or None on success.
1558 return 1 if ret == 0 else ret
1575 return 1 if ret == 0 else ret
1559
1576
1560 opts = pycompat.byteskwargs(opts)
1577 opts = pycompat.byteskwargs(opts)
1561 if opts.get('subrepos'):
1578 if opts.get('subrepos'):
1562 if opts.get('amend'):
1579 if opts.get('amend'):
1563 raise error.Abort(_('cannot amend with --subrepos'))
1580 raise error.Abort(_('cannot amend with --subrepos'))
1564 # Let --subrepos on the command line override config setting.
1581 # Let --subrepos on the command line override config setting.
1565 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1582 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1566
1583
1567 cmdutil.checkunfinished(repo, commit=True)
1584 cmdutil.checkunfinished(repo, commit=True)
1568
1585
1569 branch = repo[None].branch()
1586 branch = repo[None].branch()
1570 bheads = repo.branchheads(branch)
1587 bheads = repo.branchheads(branch)
1571
1588
1572 extra = {}
1589 extra = {}
1573 if opts.get('close_branch'):
1590 if opts.get('close_branch'):
1574 extra['close'] = '1'
1591 extra['close'] = '1'
1575
1592
1576 if not bheads:
1593 if not bheads:
1577 raise error.Abort(_('can only close branch heads'))
1594 raise error.Abort(_('can only close branch heads'))
1578 elif opts.get('amend'):
1595 elif opts.get('amend'):
1579 if repo[None].parents()[0].p1().branch() != branch and \
1596 if repo[None].parents()[0].p1().branch() != branch and \
1580 repo[None].parents()[0].p2().branch() != branch:
1597 repo[None].parents()[0].p2().branch() != branch:
1581 raise error.Abort(_('can only close branch heads'))
1598 raise error.Abort(_('can only close branch heads'))
1582
1599
1583 if opts.get('amend'):
1600 if opts.get('amend'):
1584 if ui.configbool('ui', 'commitsubrepos'):
1601 if ui.configbool('ui', 'commitsubrepos'):
1585 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1602 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1586
1603
1587 old = repo['.']
1604 old = repo['.']
1588 rewriteutil.precheck(repo, [old.rev()], 'amend')
1605 rewriteutil.precheck(repo, [old.rev()], 'amend')
1589
1606
1590 # Currently histedit gets confused if an amend happens while histedit
1607 # Currently histedit gets confused if an amend happens while histedit
1591 # is in progress. Since we have a checkunfinished command, we are
1608 # is in progress. Since we have a checkunfinished command, we are
1592 # temporarily honoring it.
1609 # temporarily honoring it.
1593 #
1610 #
1594 # Note: eventually this guard will be removed. Please do not expect
1611 # Note: eventually this guard will be removed. Please do not expect
1595 # this behavior to remain.
1612 # this behavior to remain.
1596 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
1613 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
1597 cmdutil.checkunfinished(repo)
1614 cmdutil.checkunfinished(repo)
1598
1615
1599 node = cmdutil.amend(ui, repo, old, extra, pats, opts)
1616 node = cmdutil.amend(ui, repo, old, extra, pats, opts)
1600 if node == old.node():
1617 if node == old.node():
1601 ui.status(_("nothing changed\n"))
1618 ui.status(_("nothing changed\n"))
1602 return 1
1619 return 1
1603 else:
1620 else:
1604 def commitfunc(ui, repo, message, match, opts):
1621 def commitfunc(ui, repo, message, match, opts):
1605 overrides = {}
1622 overrides = {}
1606 if opts.get('secret'):
1623 if opts.get('secret'):
1607 overrides[('phases', 'new-commit')] = 'secret'
1624 overrides[('phases', 'new-commit')] = 'secret'
1608
1625
1609 baseui = repo.baseui
1626 baseui = repo.baseui
1610 with baseui.configoverride(overrides, 'commit'):
1627 with baseui.configoverride(overrides, 'commit'):
1611 with ui.configoverride(overrides, 'commit'):
1628 with ui.configoverride(overrides, 'commit'):
1612 editform = cmdutil.mergeeditform(repo[None],
1629 editform = cmdutil.mergeeditform(repo[None],
1613 'commit.normal')
1630 'commit.normal')
1614 editor = cmdutil.getcommiteditor(
1631 editor = cmdutil.getcommiteditor(
1615 editform=editform, **pycompat.strkwargs(opts))
1632 editform=editform, **pycompat.strkwargs(opts))
1616 return repo.commit(message,
1633 return repo.commit(message,
1617 opts.get('user'),
1634 opts.get('user'),
1618 opts.get('date'),
1635 opts.get('date'),
1619 match,
1636 match,
1620 editor=editor,
1637 editor=editor,
1621 extra=extra)
1638 extra=extra)
1622
1639
1623 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1640 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1624
1641
1625 if not node:
1642 if not node:
1626 stat = cmdutil.postcommitstatus(repo, pats, opts)
1643 stat = cmdutil.postcommitstatus(repo, pats, opts)
1627 if stat[3]:
1644 if stat[3]:
1628 ui.status(_("nothing changed (%d missing files, see "
1645 ui.status(_("nothing changed (%d missing files, see "
1629 "'hg status')\n") % len(stat[3]))
1646 "'hg status')\n") % len(stat[3]))
1630 else:
1647 else:
1631 ui.status(_("nothing changed\n"))
1648 ui.status(_("nothing changed\n"))
1632 return 1
1649 return 1
1633
1650
1634 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1651 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1635
1652
1636 @command('config|showconfig|debugconfig',
1653 @command('config|showconfig|debugconfig',
1637 [('u', 'untrusted', None, _('show untrusted configuration options')),
1654 [('u', 'untrusted', None, _('show untrusted configuration options')),
1638 ('e', 'edit', None, _('edit user config')),
1655 ('e', 'edit', None, _('edit user config')),
1639 ('l', 'local', None, _('edit repository config')),
1656 ('l', 'local', None, _('edit repository config')),
1640 ('g', 'global', None, _('edit global config'))] + formatteropts,
1657 ('g', 'global', None, _('edit global config'))] + formatteropts,
1641 _('[-u] [NAME]...'),
1658 _('[-u] [NAME]...'),
1642 optionalrepo=True,
1659 optionalrepo=True,
1643 intents={INTENT_READONLY})
1660 intents={INTENT_READONLY})
1644 def config(ui, repo, *values, **opts):
1661 def config(ui, repo, *values, **opts):
1645 """show combined config settings from all hgrc files
1662 """show combined config settings from all hgrc files
1646
1663
1647 With no arguments, print names and values of all config items.
1664 With no arguments, print names and values of all config items.
1648
1665
1649 With one argument of the form section.name, print just the value
1666 With one argument of the form section.name, print just the value
1650 of that config item.
1667 of that config item.
1651
1668
1652 With multiple arguments, print names and values of all config
1669 With multiple arguments, print names and values of all config
1653 items with matching section names or section.names.
1670 items with matching section names or section.names.
1654
1671
1655 With --edit, start an editor on the user-level config file. With
1672 With --edit, start an editor on the user-level config file. With
1656 --global, edit the system-wide config file. With --local, edit the
1673 --global, edit the system-wide config file. With --local, edit the
1657 repository-level config file.
1674 repository-level config file.
1658
1675
1659 With --debug, the source (filename and line number) is printed
1676 With --debug, the source (filename and line number) is printed
1660 for each config item.
1677 for each config item.
1661
1678
1662 See :hg:`help config` for more information about config files.
1679 See :hg:`help config` for more information about config files.
1663
1680
1664 Returns 0 on success, 1 if NAME does not exist.
1681 Returns 0 on success, 1 if NAME does not exist.
1665
1682
1666 """
1683 """
1667
1684
1668 opts = pycompat.byteskwargs(opts)
1685 opts = pycompat.byteskwargs(opts)
1669 if opts.get('edit') or opts.get('local') or opts.get('global'):
1686 if opts.get('edit') or opts.get('local') or opts.get('global'):
1670 if opts.get('local') and opts.get('global'):
1687 if opts.get('local') and opts.get('global'):
1671 raise error.Abort(_("can't use --local and --global together"))
1688 raise error.Abort(_("can't use --local and --global together"))
1672
1689
1673 if opts.get('local'):
1690 if opts.get('local'):
1674 if not repo:
1691 if not repo:
1675 raise error.Abort(_("can't use --local outside a repository"))
1692 raise error.Abort(_("can't use --local outside a repository"))
1676 paths = [repo.vfs.join('hgrc')]
1693 paths = [repo.vfs.join('hgrc')]
1677 elif opts.get('global'):
1694 elif opts.get('global'):
1678 paths = rcutil.systemrcpath()
1695 paths = rcutil.systemrcpath()
1679 else:
1696 else:
1680 paths = rcutil.userrcpath()
1697 paths = rcutil.userrcpath()
1681
1698
1682 for f in paths:
1699 for f in paths:
1683 if os.path.exists(f):
1700 if os.path.exists(f):
1684 break
1701 break
1685 else:
1702 else:
1686 if opts.get('global'):
1703 if opts.get('global'):
1687 samplehgrc = uimod.samplehgrcs['global']
1704 samplehgrc = uimod.samplehgrcs['global']
1688 elif opts.get('local'):
1705 elif opts.get('local'):
1689 samplehgrc = uimod.samplehgrcs['local']
1706 samplehgrc = uimod.samplehgrcs['local']
1690 else:
1707 else:
1691 samplehgrc = uimod.samplehgrcs['user']
1708 samplehgrc = uimod.samplehgrcs['user']
1692
1709
1693 f = paths[0]
1710 f = paths[0]
1694 fp = open(f, "wb")
1711 fp = open(f, "wb")
1695 fp.write(util.tonativeeol(samplehgrc))
1712 fp.write(util.tonativeeol(samplehgrc))
1696 fp.close()
1713 fp.close()
1697
1714
1698 editor = ui.geteditor()
1715 editor = ui.geteditor()
1699 ui.system("%s \"%s\"" % (editor, f),
1716 ui.system("%s \"%s\"" % (editor, f),
1700 onerr=error.Abort, errprefix=_("edit failed"),
1717 onerr=error.Abort, errprefix=_("edit failed"),
1701 blockedtag='config_edit')
1718 blockedtag='config_edit')
1702 return
1719 return
1703 ui.pager('config')
1720 ui.pager('config')
1704 fm = ui.formatter('config', opts)
1721 fm = ui.formatter('config', opts)
1705 for t, f in rcutil.rccomponents():
1722 for t, f in rcutil.rccomponents():
1706 if t == 'path':
1723 if t == 'path':
1707 ui.debug('read config from: %s\n' % f)
1724 ui.debug('read config from: %s\n' % f)
1708 elif t == 'items':
1725 elif t == 'items':
1709 for section, name, value, source in f:
1726 for section, name, value, source in f:
1710 ui.debug('set config by: %s\n' % source)
1727 ui.debug('set config by: %s\n' % source)
1711 else:
1728 else:
1712 raise error.ProgrammingError('unknown rctype: %s' % t)
1729 raise error.ProgrammingError('unknown rctype: %s' % t)
1713 untrusted = bool(opts.get('untrusted'))
1730 untrusted = bool(opts.get('untrusted'))
1714
1731
1715 selsections = selentries = []
1732 selsections = selentries = []
1716 if values:
1733 if values:
1717 selsections = [v for v in values if '.' not in v]
1734 selsections = [v for v in values if '.' not in v]
1718 selentries = [v for v in values if '.' in v]
1735 selentries = [v for v in values if '.' in v]
1719 uniquesel = (len(selentries) == 1 and not selsections)
1736 uniquesel = (len(selentries) == 1 and not selsections)
1720 selsections = set(selsections)
1737 selsections = set(selsections)
1721 selentries = set(selentries)
1738 selentries = set(selentries)
1722
1739
1723 matched = False
1740 matched = False
1724 for section, name, value in ui.walkconfig(untrusted=untrusted):
1741 for section, name, value in ui.walkconfig(untrusted=untrusted):
1725 source = ui.configsource(section, name, untrusted)
1742 source = ui.configsource(section, name, untrusted)
1726 value = pycompat.bytestr(value)
1743 value = pycompat.bytestr(value)
1727 if fm.isplain():
1744 if fm.isplain():
1728 source = source or 'none'
1745 source = source or 'none'
1729 value = value.replace('\n', '\\n')
1746 value = value.replace('\n', '\\n')
1730 entryname = section + '.' + name
1747 entryname = section + '.' + name
1731 if values and not (section in selsections or entryname in selentries):
1748 if values and not (section in selsections or entryname in selentries):
1732 continue
1749 continue
1733 fm.startitem()
1750 fm.startitem()
1734 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1751 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1735 if uniquesel:
1752 if uniquesel:
1736 fm.data(name=entryname)
1753 fm.data(name=entryname)
1737 fm.write('value', '%s\n', value)
1754 fm.write('value', '%s\n', value)
1738 else:
1755 else:
1739 fm.write('name value', '%s=%s\n', entryname, value)
1756 fm.write('name value', '%s=%s\n', entryname, value)
1740 matched = True
1757 matched = True
1741 fm.end()
1758 fm.end()
1742 if matched:
1759 if matched:
1743 return 0
1760 return 0
1744 return 1
1761 return 1
1745
1762
1746 @command('copy|cp',
1763 @command('copy|cp',
1747 [('A', 'after', None, _('record a copy that has already occurred')),
1764 [('A', 'after', None, _('record a copy that has already occurred')),
1748 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1765 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1749 ] + walkopts + dryrunopts,
1766 ] + walkopts + dryrunopts,
1750 _('[OPTION]... [SOURCE]... DEST'))
1767 _('[OPTION]... [SOURCE]... DEST'))
1751 def copy(ui, repo, *pats, **opts):
1768 def copy(ui, repo, *pats, **opts):
1752 """mark files as copied for the next commit
1769 """mark files as copied for the next commit
1753
1770
1754 Mark dest as having copies of source files. If dest is a
1771 Mark dest as having copies of source files. If dest is a
1755 directory, copies are put in that directory. If dest is a file,
1772 directory, copies are put in that directory. If dest is a file,
1756 the source must be a single file.
1773 the source must be a single file.
1757
1774
1758 By default, this command copies the contents of files as they
1775 By default, this command copies the contents of files as they
1759 exist in the working directory. If invoked with -A/--after, the
1776 exist in the working directory. If invoked with -A/--after, the
1760 operation is recorded, but no copying is performed.
1777 operation is recorded, but no copying is performed.
1761
1778
1762 This command takes effect with the next commit. To undo a copy
1779 This command takes effect with the next commit. To undo a copy
1763 before that, see :hg:`revert`.
1780 before that, see :hg:`revert`.
1764
1781
1765 Returns 0 on success, 1 if errors are encountered.
1782 Returns 0 on success, 1 if errors are encountered.
1766 """
1783 """
1767 opts = pycompat.byteskwargs(opts)
1784 opts = pycompat.byteskwargs(opts)
1768 with repo.wlock(False):
1785 with repo.wlock(False):
1769 return cmdutil.copy(ui, repo, pats, opts)
1786 return cmdutil.copy(ui, repo, pats, opts)
1770
1787
1771 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1788 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1772 def debugcommands(ui, cmd='', *args):
1789 def debugcommands(ui, cmd='', *args):
1773 """list all available commands and options"""
1790 """list all available commands and options"""
1774 for cmd, vals in sorted(table.iteritems()):
1791 for cmd, vals in sorted(table.iteritems()):
1775 cmd = cmd.split('|')[0].strip('^')
1792 cmd = cmd.split('|')[0].strip('^')
1776 opts = ', '.join([i[1] for i in vals[1]])
1793 opts = ', '.join([i[1] for i in vals[1]])
1777 ui.write('%s: %s\n' % (cmd, opts))
1794 ui.write('%s: %s\n' % (cmd, opts))
1778
1795
1779 @command('debugcomplete',
1796 @command('debugcomplete',
1780 [('o', 'options', None, _('show the command options'))],
1797 [('o', 'options', None, _('show the command options'))],
1781 _('[-o] CMD'),
1798 _('[-o] CMD'),
1782 norepo=True)
1799 norepo=True)
1783 def debugcomplete(ui, cmd='', **opts):
1800 def debugcomplete(ui, cmd='', **opts):
1784 """returns the completion list associated with the given command"""
1801 """returns the completion list associated with the given command"""
1785
1802
1786 if opts.get(r'options'):
1803 if opts.get(r'options'):
1787 options = []
1804 options = []
1788 otables = [globalopts]
1805 otables = [globalopts]
1789 if cmd:
1806 if cmd:
1790 aliases, entry = cmdutil.findcmd(cmd, table, False)
1807 aliases, entry = cmdutil.findcmd(cmd, table, False)
1791 otables.append(entry[1])
1808 otables.append(entry[1])
1792 for t in otables:
1809 for t in otables:
1793 for o in t:
1810 for o in t:
1794 if "(DEPRECATED)" in o[3]:
1811 if "(DEPRECATED)" in o[3]:
1795 continue
1812 continue
1796 if o[0]:
1813 if o[0]:
1797 options.append('-%s' % o[0])
1814 options.append('-%s' % o[0])
1798 options.append('--%s' % o[1])
1815 options.append('--%s' % o[1])
1799 ui.write("%s\n" % "\n".join(options))
1816 ui.write("%s\n" % "\n".join(options))
1800 return
1817 return
1801
1818
1802 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
1819 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
1803 if ui.verbose:
1820 if ui.verbose:
1804 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1821 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1805 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1822 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1806
1823
1807 @command('^diff',
1824 @command('^diff',
1808 [('r', 'rev', [], _('revision'), _('REV')),
1825 [('r', 'rev', [], _('revision'), _('REV')),
1809 ('c', 'change', '', _('change made by revision'), _('REV'))
1826 ('c', 'change', '', _('change made by revision'), _('REV'))
1810 ] + diffopts + diffopts2 + walkopts + subrepoopts,
1827 ] + diffopts + diffopts2 + walkopts + subrepoopts,
1811 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
1828 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
1812 inferrepo=True,
1829 inferrepo=True,
1813 intents={INTENT_READONLY})
1830 intents={INTENT_READONLY})
1814 def diff(ui, repo, *pats, **opts):
1831 def diff(ui, repo, *pats, **opts):
1815 """diff repository (or selected files)
1832 """diff repository (or selected files)
1816
1833
1817 Show differences between revisions for the specified files.
1834 Show differences between revisions for the specified files.
1818
1835
1819 Differences between files are shown using the unified diff format.
1836 Differences between files are shown using the unified diff format.
1820
1837
1821 .. note::
1838 .. note::
1822
1839
1823 :hg:`diff` may generate unexpected results for merges, as it will
1840 :hg:`diff` may generate unexpected results for merges, as it will
1824 default to comparing against the working directory's first
1841 default to comparing against the working directory's first
1825 parent changeset if no revisions are specified.
1842 parent changeset if no revisions are specified.
1826
1843
1827 When two revision arguments are given, then changes are shown
1844 When two revision arguments are given, then changes are shown
1828 between those revisions. If only one revision is specified then
1845 between those revisions. If only one revision is specified then
1829 that revision is compared to the working directory, and, when no
1846 that revision is compared to the working directory, and, when no
1830 revisions are specified, the working directory files are compared
1847 revisions are specified, the working directory files are compared
1831 to its first parent.
1848 to its first parent.
1832
1849
1833 Alternatively you can specify -c/--change with a revision to see
1850 Alternatively you can specify -c/--change with a revision to see
1834 the changes in that changeset relative to its first parent.
1851 the changes in that changeset relative to its first parent.
1835
1852
1836 Without the -a/--text option, diff will avoid generating diffs of
1853 Without the -a/--text option, diff will avoid generating diffs of
1837 files it detects as binary. With -a, diff will generate a diff
1854 files it detects as binary. With -a, diff will generate a diff
1838 anyway, probably with undesirable results.
1855 anyway, probably with undesirable results.
1839
1856
1840 Use the -g/--git option to generate diffs in the git extended diff
1857 Use the -g/--git option to generate diffs in the git extended diff
1841 format. For more information, read :hg:`help diffs`.
1858 format. For more information, read :hg:`help diffs`.
1842
1859
1843 .. container:: verbose
1860 .. container:: verbose
1844
1861
1845 Examples:
1862 Examples:
1846
1863
1847 - compare a file in the current working directory to its parent::
1864 - compare a file in the current working directory to its parent::
1848
1865
1849 hg diff foo.c
1866 hg diff foo.c
1850
1867
1851 - compare two historical versions of a directory, with rename info::
1868 - compare two historical versions of a directory, with rename info::
1852
1869
1853 hg diff --git -r 1.0:1.2 lib/
1870 hg diff --git -r 1.0:1.2 lib/
1854
1871
1855 - get change stats relative to the last change on some date::
1872 - get change stats relative to the last change on some date::
1856
1873
1857 hg diff --stat -r "date('may 2')"
1874 hg diff --stat -r "date('may 2')"
1858
1875
1859 - diff all newly-added files that contain a keyword::
1876 - diff all newly-added files that contain a keyword::
1860
1877
1861 hg diff "set:added() and grep(GNU)"
1878 hg diff "set:added() and grep(GNU)"
1862
1879
1863 - compare a revision and its parents::
1880 - compare a revision and its parents::
1864
1881
1865 hg diff -c 9353 # compare against first parent
1882 hg diff -c 9353 # compare against first parent
1866 hg diff -r 9353^:9353 # same using revset syntax
1883 hg diff -r 9353^:9353 # same using revset syntax
1867 hg diff -r 9353^2:9353 # compare against the second parent
1884 hg diff -r 9353^2:9353 # compare against the second parent
1868
1885
1869 Returns 0 on success.
1886 Returns 0 on success.
1870 """
1887 """
1871
1888
1872 opts = pycompat.byteskwargs(opts)
1889 opts = pycompat.byteskwargs(opts)
1873 revs = opts.get('rev')
1890 revs = opts.get('rev')
1874 change = opts.get('change')
1891 change = opts.get('change')
1875 stat = opts.get('stat')
1892 stat = opts.get('stat')
1876 reverse = opts.get('reverse')
1893 reverse = opts.get('reverse')
1877
1894
1878 if revs and change:
1895 if revs and change:
1879 msg = _('cannot specify --rev and --change at the same time')
1896 msg = _('cannot specify --rev and --change at the same time')
1880 raise error.Abort(msg)
1897 raise error.Abort(msg)
1881 elif change:
1898 elif change:
1882 repo = scmutil.unhidehashlikerevs(repo, [change], 'nowarn')
1899 repo = scmutil.unhidehashlikerevs(repo, [change], 'nowarn')
1883 ctx2 = scmutil.revsingle(repo, change, None)
1900 ctx2 = scmutil.revsingle(repo, change, None)
1884 ctx1 = ctx2.p1()
1901 ctx1 = ctx2.p1()
1885 else:
1902 else:
1886 repo = scmutil.unhidehashlikerevs(repo, revs, 'nowarn')
1903 repo = scmutil.unhidehashlikerevs(repo, revs, 'nowarn')
1887 ctx1, ctx2 = scmutil.revpair(repo, revs)
1904 ctx1, ctx2 = scmutil.revpair(repo, revs)
1888 node1, node2 = ctx1.node(), ctx2.node()
1905 node1, node2 = ctx1.node(), ctx2.node()
1889
1906
1890 if reverse:
1907 if reverse:
1891 node1, node2 = node2, node1
1908 node1, node2 = node2, node1
1892
1909
1893 diffopts = patch.diffallopts(ui, opts)
1910 diffopts = patch.diffallopts(ui, opts)
1894 m = scmutil.match(ctx2, pats, opts)
1911 m = scmutil.match(ctx2, pats, opts)
1895 ui.pager('diff')
1912 ui.pager('diff')
1896 logcmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
1913 logcmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
1897 listsubrepos=opts.get('subrepos'),
1914 listsubrepos=opts.get('subrepos'),
1898 root=opts.get('root'))
1915 root=opts.get('root'))
1899
1916
1900 @command('^export',
1917 @command('^export',
1901 [('B', 'bookmark', '',
1918 [('B', 'bookmark', '',
1902 _('export changes only reachable by given bookmark')),
1919 _('export changes only reachable by given bookmark')),
1903 ('o', 'output', '',
1920 ('o', 'output', '',
1904 _('print output to file with formatted name'), _('FORMAT')),
1921 _('print output to file with formatted name'), _('FORMAT')),
1905 ('', 'switch-parent', None, _('diff against the second parent')),
1922 ('', 'switch-parent', None, _('diff against the second parent')),
1906 ('r', 'rev', [], _('revisions to export'), _('REV')),
1923 ('r', 'rev', [], _('revisions to export'), _('REV')),
1907 ] + diffopts + formatteropts,
1924 ] + diffopts + formatteropts,
1908 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'),
1925 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'),
1909 intents={INTENT_READONLY})
1926 intents={INTENT_READONLY})
1910 def export(ui, repo, *changesets, **opts):
1927 def export(ui, repo, *changesets, **opts):
1911 """dump the header and diffs for one or more changesets
1928 """dump the header and diffs for one or more changesets
1912
1929
1913 Print the changeset header and diffs for one or more revisions.
1930 Print the changeset header and diffs for one or more revisions.
1914 If no revision is given, the parent of the working directory is used.
1931 If no revision is given, the parent of the working directory is used.
1915
1932
1916 The information shown in the changeset header is: author, date,
1933 The information shown in the changeset header is: author, date,
1917 branch name (if non-default), changeset hash, parent(s) and commit
1934 branch name (if non-default), changeset hash, parent(s) and commit
1918 comment.
1935 comment.
1919
1936
1920 .. note::
1937 .. note::
1921
1938
1922 :hg:`export` may generate unexpected diff output for merge
1939 :hg:`export` may generate unexpected diff output for merge
1923 changesets, as it will compare the merge changeset against its
1940 changesets, as it will compare the merge changeset against its
1924 first parent only.
1941 first parent only.
1925
1942
1926 Output may be to a file, in which case the name of the file is
1943 Output may be to a file, in which case the name of the file is
1927 given using a template string. See :hg:`help templates`. In addition
1944 given using a template string. See :hg:`help templates`. In addition
1928 to the common template keywords, the following formatting rules are
1945 to the common template keywords, the following formatting rules are
1929 supported:
1946 supported:
1930
1947
1931 :``%%``: literal "%" character
1948 :``%%``: literal "%" character
1932 :``%H``: changeset hash (40 hexadecimal digits)
1949 :``%H``: changeset hash (40 hexadecimal digits)
1933 :``%N``: number of patches being generated
1950 :``%N``: number of patches being generated
1934 :``%R``: changeset revision number
1951 :``%R``: changeset revision number
1935 :``%b``: basename of the exporting repository
1952 :``%b``: basename of the exporting repository
1936 :``%h``: short-form changeset hash (12 hexadecimal digits)
1953 :``%h``: short-form changeset hash (12 hexadecimal digits)
1937 :``%m``: first line of the commit message (only alphanumeric characters)
1954 :``%m``: first line of the commit message (only alphanumeric characters)
1938 :``%n``: zero-padded sequence number, starting at 1
1955 :``%n``: zero-padded sequence number, starting at 1
1939 :``%r``: zero-padded changeset revision number
1956 :``%r``: zero-padded changeset revision number
1940 :``\\``: literal "\\" character
1957 :``\\``: literal "\\" character
1941
1958
1942 Without the -a/--text option, export will avoid generating diffs
1959 Without the -a/--text option, export will avoid generating diffs
1943 of files it detects as binary. With -a, export will generate a
1960 of files it detects as binary. With -a, export will generate a
1944 diff anyway, probably with undesirable results.
1961 diff anyway, probably with undesirable results.
1945
1962
1946 With -B/--bookmark changesets reachable by the given bookmark are
1963 With -B/--bookmark changesets reachable by the given bookmark are
1947 selected.
1964 selected.
1948
1965
1949 Use the -g/--git option to generate diffs in the git extended diff
1966 Use the -g/--git option to generate diffs in the git extended diff
1950 format. See :hg:`help diffs` for more information.
1967 format. See :hg:`help diffs` for more information.
1951
1968
1952 With the --switch-parent option, the diff will be against the
1969 With the --switch-parent option, the diff will be against the
1953 second parent. It can be useful to review a merge.
1970 second parent. It can be useful to review a merge.
1954
1971
1955 .. container:: verbose
1972 .. container:: verbose
1956
1973
1957 Examples:
1974 Examples:
1958
1975
1959 - use export and import to transplant a bugfix to the current
1976 - use export and import to transplant a bugfix to the current
1960 branch::
1977 branch::
1961
1978
1962 hg export -r 9353 | hg import -
1979 hg export -r 9353 | hg import -
1963
1980
1964 - export all the changesets between two revisions to a file with
1981 - export all the changesets between two revisions to a file with
1965 rename information::
1982 rename information::
1966
1983
1967 hg export --git -r 123:150 > changes.txt
1984 hg export --git -r 123:150 > changes.txt
1968
1985
1969 - split outgoing changes into a series of patches with
1986 - split outgoing changes into a series of patches with
1970 descriptive names::
1987 descriptive names::
1971
1988
1972 hg export -r "outgoing()" -o "%n-%m.patch"
1989 hg export -r "outgoing()" -o "%n-%m.patch"
1973
1990
1974 Returns 0 on success.
1991 Returns 0 on success.
1975 """
1992 """
1976 opts = pycompat.byteskwargs(opts)
1993 opts = pycompat.byteskwargs(opts)
1977 bookmark = opts.get('bookmark')
1994 bookmark = opts.get('bookmark')
1978 changesets += tuple(opts.get('rev', []))
1995 changesets += tuple(opts.get('rev', []))
1979
1996
1980 if bookmark and changesets:
1997 if bookmark and changesets:
1981 raise error.Abort(_("-r and -B are mutually exclusive"))
1998 raise error.Abort(_("-r and -B are mutually exclusive"))
1982
1999
1983 if bookmark:
2000 if bookmark:
1984 if bookmark not in repo._bookmarks:
2001 if bookmark not in repo._bookmarks:
1985 raise error.Abort(_("bookmark '%s' not found") % bookmark)
2002 raise error.Abort(_("bookmark '%s' not found") % bookmark)
1986
2003
1987 revs = scmutil.bookmarkrevs(repo, bookmark)
2004 revs = scmutil.bookmarkrevs(repo, bookmark)
1988 else:
2005 else:
1989 if not changesets:
2006 if not changesets:
1990 changesets = ['.']
2007 changesets = ['.']
1991
2008
1992 repo = scmutil.unhidehashlikerevs(repo, changesets, 'nowarn')
2009 repo = scmutil.unhidehashlikerevs(repo, changesets, 'nowarn')
1993 revs = scmutil.revrange(repo, changesets)
2010 revs = scmutil.revrange(repo, changesets)
1994
2011
1995 if not revs:
2012 if not revs:
1996 raise error.Abort(_("export requires at least one changeset"))
2013 raise error.Abort(_("export requires at least one changeset"))
1997 if len(revs) > 1:
2014 if len(revs) > 1:
1998 ui.note(_('exporting patches:\n'))
2015 ui.note(_('exporting patches:\n'))
1999 else:
2016 else:
2000 ui.note(_('exporting patch:\n'))
2017 ui.note(_('exporting patch:\n'))
2001
2018
2002 fntemplate = opts.get('output')
2019 fntemplate = opts.get('output')
2003 if cmdutil.isstdiofilename(fntemplate):
2020 if cmdutil.isstdiofilename(fntemplate):
2004 fntemplate = ''
2021 fntemplate = ''
2005
2022
2006 if fntemplate:
2023 if fntemplate:
2007 fm = formatter.nullformatter(ui, 'export', opts)
2024 fm = formatter.nullformatter(ui, 'export', opts)
2008 else:
2025 else:
2009 ui.pager('export')
2026 ui.pager('export')
2010 fm = ui.formatter('export', opts)
2027 fm = ui.formatter('export', opts)
2011 with fm:
2028 with fm:
2012 cmdutil.export(repo, revs, fm, fntemplate=fntemplate,
2029 cmdutil.export(repo, revs, fm, fntemplate=fntemplate,
2013 switch_parent=opts.get('switch_parent'),
2030 switch_parent=opts.get('switch_parent'),
2014 opts=patch.diffallopts(ui, opts))
2031 opts=patch.diffallopts(ui, opts))
2015
2032
2016 @command('files',
2033 @command('files',
2017 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
2034 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
2018 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
2035 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
2019 ] + walkopts + formatteropts + subrepoopts,
2036 ] + walkopts + formatteropts + subrepoopts,
2020 _('[OPTION]... [FILE]...'),
2037 _('[OPTION]... [FILE]...'),
2021 intents={INTENT_READONLY})
2038 intents={INTENT_READONLY})
2022 def files(ui, repo, *pats, **opts):
2039 def files(ui, repo, *pats, **opts):
2023 """list tracked files
2040 """list tracked files
2024
2041
2025 Print files under Mercurial control in the working directory or
2042 Print files under Mercurial control in the working directory or
2026 specified revision for given files (excluding removed files).
2043 specified revision for given files (excluding removed files).
2027 Files can be specified as filenames or filesets.
2044 Files can be specified as filenames or filesets.
2028
2045
2029 If no files are given to match, this command prints the names
2046 If no files are given to match, this command prints the names
2030 of all files under Mercurial control.
2047 of all files under Mercurial control.
2031
2048
2032 .. container:: verbose
2049 .. container:: verbose
2033
2050
2034 Examples:
2051 Examples:
2035
2052
2036 - list all files under the current directory::
2053 - list all files under the current directory::
2037
2054
2038 hg files .
2055 hg files .
2039
2056
2040 - shows sizes and flags for current revision::
2057 - shows sizes and flags for current revision::
2041
2058
2042 hg files -vr .
2059 hg files -vr .
2043
2060
2044 - list all files named README::
2061 - list all files named README::
2045
2062
2046 hg files -I "**/README"
2063 hg files -I "**/README"
2047
2064
2048 - list all binary files::
2065 - list all binary files::
2049
2066
2050 hg files "set:binary()"
2067 hg files "set:binary()"
2051
2068
2052 - find files containing a regular expression::
2069 - find files containing a regular expression::
2053
2070
2054 hg files "set:grep('bob')"
2071 hg files "set:grep('bob')"
2055
2072
2056 - search tracked file contents with xargs and grep::
2073 - search tracked file contents with xargs and grep::
2057
2074
2058 hg files -0 | xargs -0 grep foo
2075 hg files -0 | xargs -0 grep foo
2059
2076
2060 See :hg:`help patterns` and :hg:`help filesets` for more information
2077 See :hg:`help patterns` and :hg:`help filesets` for more information
2061 on specifying file patterns.
2078 on specifying file patterns.
2062
2079
2063 Returns 0 if a match is found, 1 otherwise.
2080 Returns 0 if a match is found, 1 otherwise.
2064
2081
2065 """
2082 """
2066
2083
2067 opts = pycompat.byteskwargs(opts)
2084 opts = pycompat.byteskwargs(opts)
2068 rev = opts.get('rev')
2085 rev = opts.get('rev')
2069 if rev:
2086 if rev:
2070 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
2087 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
2071 ctx = scmutil.revsingle(repo, rev, None)
2088 ctx = scmutil.revsingle(repo, rev, None)
2072
2089
2073 end = '\n'
2090 end = '\n'
2074 if opts.get('print0'):
2091 if opts.get('print0'):
2075 end = '\0'
2092 end = '\0'
2076 fmt = '%s' + end
2093 fmt = '%s' + end
2077
2094
2078 m = scmutil.match(ctx, pats, opts)
2095 m = scmutil.match(ctx, pats, opts)
2079 ui.pager('files')
2096 ui.pager('files')
2080 with ui.formatter('files', opts) as fm:
2097 with ui.formatter('files', opts) as fm:
2081 return cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
2098 return cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
2082
2099
2083 @command(
2100 @command(
2084 '^forget',
2101 '^forget',
2085 [('i', 'interactive', None, _('use interactive mode')),
2102 [('i', 'interactive', None, _('use interactive mode')),
2086 ] + walkopts + dryrunopts,
2103 ] + walkopts + dryrunopts,
2087 _('[OPTION]... FILE...'), inferrepo=True)
2104 _('[OPTION]... FILE...'), inferrepo=True)
2088 def forget(ui, repo, *pats, **opts):
2105 def forget(ui, repo, *pats, **opts):
2089 """forget the specified files on the next commit
2106 """forget the specified files on the next commit
2090
2107
2091 Mark the specified files so they will no longer be tracked
2108 Mark the specified files so they will no longer be tracked
2092 after the next commit.
2109 after the next commit.
2093
2110
2094 This only removes files from the current branch, not from the
2111 This only removes files from the current branch, not from the
2095 entire project history, and it does not delete them from the
2112 entire project history, and it does not delete them from the
2096 working directory.
2113 working directory.
2097
2114
2098 To delete the file from the working directory, see :hg:`remove`.
2115 To delete the file from the working directory, see :hg:`remove`.
2099
2116
2100 To undo a forget before the next commit, see :hg:`add`.
2117 To undo a forget before the next commit, see :hg:`add`.
2101
2118
2102 .. container:: verbose
2119 .. container:: verbose
2103
2120
2104 Examples:
2121 Examples:
2105
2122
2106 - forget newly-added binary files::
2123 - forget newly-added binary files::
2107
2124
2108 hg forget "set:added() and binary()"
2125 hg forget "set:added() and binary()"
2109
2126
2110 - forget files that would be excluded by .hgignore::
2127 - forget files that would be excluded by .hgignore::
2111
2128
2112 hg forget "set:hgignore()"
2129 hg forget "set:hgignore()"
2113
2130
2114 Returns 0 on success.
2131 Returns 0 on success.
2115 """
2132 """
2116
2133
2117 opts = pycompat.byteskwargs(opts)
2134 opts = pycompat.byteskwargs(opts)
2118 if not pats:
2135 if not pats:
2119 raise error.Abort(_('no files specified'))
2136 raise error.Abort(_('no files specified'))
2120
2137
2121 m = scmutil.match(repo[None], pats, opts)
2138 m = scmutil.match(repo[None], pats, opts)
2122 dryrun, interactive = opts.get('dry_run'), opts.get('interactive')
2139 dryrun, interactive = opts.get('dry_run'), opts.get('interactive')
2123 rejected = cmdutil.forget(ui, repo, m, prefix="",
2140 rejected = cmdutil.forget(ui, repo, m, prefix="",
2124 explicitonly=False, dryrun=dryrun,
2141 explicitonly=False, dryrun=dryrun,
2125 interactive=interactive)[0]
2142 interactive=interactive)[0]
2126 return rejected and 1 or 0
2143 return rejected and 1 or 0
2127
2144
2128 @command(
2145 @command(
2129 'graft',
2146 'graft',
2130 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2147 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2131 ('c', 'continue', False, _('resume interrupted graft')),
2148 ('c', 'continue', False, _('resume interrupted graft')),
2132 ('', 'stop', False, _('stop interrupted graft')),
2149 ('', 'stop', False, _('stop interrupted graft')),
2133 ('', 'abort', False, _('abort interrupted graft')),
2150 ('', 'abort', False, _('abort interrupted graft')),
2134 ('e', 'edit', False, _('invoke editor on commit messages')),
2151 ('e', 'edit', False, _('invoke editor on commit messages')),
2135 ('', 'log', None, _('append graft info to log message')),
2152 ('', 'log', None, _('append graft info to log message')),
2136 ('', 'no-commit', None,
2153 ('', 'no-commit', None,
2137 _("don't commit, just apply the changes in working directory")),
2154 _("don't commit, just apply the changes in working directory")),
2138 ('f', 'force', False, _('force graft')),
2155 ('f', 'force', False, _('force graft')),
2139 ('D', 'currentdate', False,
2156 ('D', 'currentdate', False,
2140 _('record the current date as commit date')),
2157 _('record the current date as commit date')),
2141 ('U', 'currentuser', False,
2158 ('U', 'currentuser', False,
2142 _('record the current user as committer'), _('DATE'))]
2159 _('record the current user as committer'), _('DATE'))]
2143 + commitopts2 + mergetoolopts + dryrunopts,
2160 + commitopts2 + mergetoolopts + dryrunopts,
2144 _('[OPTION]... [-r REV]... REV...'))
2161 _('[OPTION]... [-r REV]... REV...'))
2145 def graft(ui, repo, *revs, **opts):
2162 def graft(ui, repo, *revs, **opts):
2146 '''copy changes from other branches onto the current branch
2163 '''copy changes from other branches onto the current branch
2147
2164
2148 This command uses Mercurial's merge logic to copy individual
2165 This command uses Mercurial's merge logic to copy individual
2149 changes from other branches without merging branches in the
2166 changes from other branches without merging branches in the
2150 history graph. This is sometimes known as 'backporting' or
2167 history graph. This is sometimes known as 'backporting' or
2151 'cherry-picking'. By default, graft will copy user, date, and
2168 'cherry-picking'. By default, graft will copy user, date, and
2152 description from the source changesets.
2169 description from the source changesets.
2153
2170
2154 Changesets that are ancestors of the current revision, that have
2171 Changesets that are ancestors of the current revision, that have
2155 already been grafted, or that are merges will be skipped.
2172 already been grafted, or that are merges will be skipped.
2156
2173
2157 If --log is specified, log messages will have a comment appended
2174 If --log is specified, log messages will have a comment appended
2158 of the form::
2175 of the form::
2159
2176
2160 (grafted from CHANGESETHASH)
2177 (grafted from CHANGESETHASH)
2161
2178
2162 If --force is specified, revisions will be grafted even if they
2179 If --force is specified, revisions will be grafted even if they
2163 are already ancestors of, or have been grafted to, the destination.
2180 are already ancestors of, or have been grafted to, the destination.
2164 This is useful when the revisions have since been backed out.
2181 This is useful when the revisions have since been backed out.
2165
2182
2166 If a graft merge results in conflicts, the graft process is
2183 If a graft merge results in conflicts, the graft process is
2167 interrupted so that the current merge can be manually resolved.
2184 interrupted so that the current merge can be manually resolved.
2168 Once all conflicts are addressed, the graft process can be
2185 Once all conflicts are addressed, the graft process can be
2169 continued with the -c/--continue option.
2186 continued with the -c/--continue option.
2170
2187
2171 The -c/--continue option reapplies all the earlier options.
2188 The -c/--continue option reapplies all the earlier options.
2172
2189
2173 .. container:: verbose
2190 .. container:: verbose
2174
2191
2175 Examples:
2192 Examples:
2176
2193
2177 - copy a single change to the stable branch and edit its description::
2194 - copy a single change to the stable branch and edit its description::
2178
2195
2179 hg update stable
2196 hg update stable
2180 hg graft --edit 9393
2197 hg graft --edit 9393
2181
2198
2182 - graft a range of changesets with one exception, updating dates::
2199 - graft a range of changesets with one exception, updating dates::
2183
2200
2184 hg graft -D "2085::2093 and not 2091"
2201 hg graft -D "2085::2093 and not 2091"
2185
2202
2186 - continue a graft after resolving conflicts::
2203 - continue a graft after resolving conflicts::
2187
2204
2188 hg graft -c
2205 hg graft -c
2189
2206
2190 - show the source of a grafted changeset::
2207 - show the source of a grafted changeset::
2191
2208
2192 hg log --debug -r .
2209 hg log --debug -r .
2193
2210
2194 - show revisions sorted by date::
2211 - show revisions sorted by date::
2195
2212
2196 hg log -r "sort(all(), date)"
2213 hg log -r "sort(all(), date)"
2197
2214
2198 See :hg:`help revisions` for more about specifying revisions.
2215 See :hg:`help revisions` for more about specifying revisions.
2199
2216
2200 Returns 0 on successful completion.
2217 Returns 0 on successful completion.
2201 '''
2218 '''
2202 with repo.wlock():
2219 with repo.wlock():
2203 return _dograft(ui, repo, *revs, **opts)
2220 return _dograft(ui, repo, *revs, **opts)
2204
2221
2205 def _dograft(ui, repo, *revs, **opts):
2222 def _dograft(ui, repo, *revs, **opts):
2206 opts = pycompat.byteskwargs(opts)
2223 opts = pycompat.byteskwargs(opts)
2207 if revs and opts.get('rev'):
2224 if revs and opts.get('rev'):
2208 ui.warn(_('warning: inconsistent use of --rev might give unexpected '
2225 ui.warn(_('warning: inconsistent use of --rev might give unexpected '
2209 'revision ordering!\n'))
2226 'revision ordering!\n'))
2210
2227
2211 revs = list(revs)
2228 revs = list(revs)
2212 revs.extend(opts.get('rev'))
2229 revs.extend(opts.get('rev'))
2213 # a dict of data to be stored in state file
2230 # a dict of data to be stored in state file
2214 statedata = {}
2231 statedata = {}
2215 # list of new nodes created by ongoing graft
2232 # list of new nodes created by ongoing graft
2216 statedata['newnodes'] = []
2233 statedata['newnodes'] = []
2217
2234
2218 if not opts.get('user') and opts.get('currentuser'):
2235 if not opts.get('user') and opts.get('currentuser'):
2219 opts['user'] = ui.username()
2236 opts['user'] = ui.username()
2220 if not opts.get('date') and opts.get('currentdate'):
2237 if not opts.get('date') and opts.get('currentdate'):
2221 opts['date'] = "%d %d" % dateutil.makedate()
2238 opts['date'] = "%d %d" % dateutil.makedate()
2222
2239
2223 editor = cmdutil.getcommiteditor(editform='graft',
2240 editor = cmdutil.getcommiteditor(editform='graft',
2224 **pycompat.strkwargs(opts))
2241 **pycompat.strkwargs(opts))
2225
2242
2226 cont = False
2243 cont = False
2227 if opts.get('no_commit'):
2244 if opts.get('no_commit'):
2228 if opts.get('edit'):
2245 if opts.get('edit'):
2229 raise error.Abort(_("cannot specify --no-commit and "
2246 raise error.Abort(_("cannot specify --no-commit and "
2230 "--edit together"))
2247 "--edit together"))
2231 if opts.get('currentuser'):
2248 if opts.get('currentuser'):
2232 raise error.Abort(_("cannot specify --no-commit and "
2249 raise error.Abort(_("cannot specify --no-commit and "
2233 "--currentuser together"))
2250 "--currentuser together"))
2234 if opts.get('currentdate'):
2251 if opts.get('currentdate'):
2235 raise error.Abort(_("cannot specify --no-commit and "
2252 raise error.Abort(_("cannot specify --no-commit and "
2236 "--currentdate together"))
2253 "--currentdate together"))
2237 if opts.get('log'):
2254 if opts.get('log'):
2238 raise error.Abort(_("cannot specify --no-commit and "
2255 raise error.Abort(_("cannot specify --no-commit and "
2239 "--log together"))
2256 "--log together"))
2240
2257
2241 graftstate = statemod.cmdstate(repo, 'graftstate')
2258 graftstate = statemod.cmdstate(repo, 'graftstate')
2242
2259
2243 if opts.get('stop'):
2260 if opts.get('stop'):
2244 if opts.get('continue'):
2261 if opts.get('continue'):
2245 raise error.Abort(_("cannot use '--continue' and "
2262 raise error.Abort(_("cannot use '--continue' and "
2246 "'--stop' together"))
2263 "'--stop' together"))
2247 if opts.get('abort'):
2264 if opts.get('abort'):
2248 raise error.Abort(_("cannot use '--abort' and '--stop' together"))
2265 raise error.Abort(_("cannot use '--abort' and '--stop' together"))
2249
2266
2250 if any((opts.get('edit'), opts.get('log'), opts.get('user'),
2267 if any((opts.get('edit'), opts.get('log'), opts.get('user'),
2251 opts.get('date'), opts.get('currentdate'),
2268 opts.get('date'), opts.get('currentdate'),
2252 opts.get('currentuser'), opts.get('rev'))):
2269 opts.get('currentuser'), opts.get('rev'))):
2253 raise error.Abort(_("cannot specify any other flag with '--stop'"))
2270 raise error.Abort(_("cannot specify any other flag with '--stop'"))
2254 return _stopgraft(ui, repo, graftstate)
2271 return _stopgraft(ui, repo, graftstate)
2255 elif opts.get('abort'):
2272 elif opts.get('abort'):
2256 if opts.get('continue'):
2273 if opts.get('continue'):
2257 raise error.Abort(_("cannot use '--continue' and "
2274 raise error.Abort(_("cannot use '--continue' and "
2258 "'--abort' together"))
2275 "'--abort' together"))
2259 if any((opts.get('edit'), opts.get('log'), opts.get('user'),
2276 if any((opts.get('edit'), opts.get('log'), opts.get('user'),
2260 opts.get('date'), opts.get('currentdate'),
2277 opts.get('date'), opts.get('currentdate'),
2261 opts.get('currentuser'), opts.get('rev'))):
2278 opts.get('currentuser'), opts.get('rev'))):
2262 raise error.Abort(_("cannot specify any other flag with '--abort'"))
2279 raise error.Abort(_("cannot specify any other flag with '--abort'"))
2263
2280
2264 return _abortgraft(ui, repo, graftstate)
2281 return _abortgraft(ui, repo, graftstate)
2265 elif opts.get('continue'):
2282 elif opts.get('continue'):
2266 cont = True
2283 cont = True
2267 if revs:
2284 if revs:
2268 raise error.Abort(_("can't specify --continue and revisions"))
2285 raise error.Abort(_("can't specify --continue and revisions"))
2269 # read in unfinished revisions
2286 # read in unfinished revisions
2270 if graftstate.exists():
2287 if graftstate.exists():
2271 statedata = _readgraftstate(repo, graftstate)
2288 statedata = _readgraftstate(repo, graftstate)
2272 if statedata.get('date'):
2289 if statedata.get('date'):
2273 opts['date'] = statedata['date']
2290 opts['date'] = statedata['date']
2274 if statedata.get('user'):
2291 if statedata.get('user'):
2275 opts['user'] = statedata['user']
2292 opts['user'] = statedata['user']
2276 if statedata.get('log'):
2293 if statedata.get('log'):
2277 opts['log'] = True
2294 opts['log'] = True
2278 if statedata.get('no_commit'):
2295 if statedata.get('no_commit'):
2279 opts['no_commit'] = statedata.get('no_commit')
2296 opts['no_commit'] = statedata.get('no_commit')
2280 nodes = statedata['nodes']
2297 nodes = statedata['nodes']
2281 revs = [repo[node].rev() for node in nodes]
2298 revs = [repo[node].rev() for node in nodes]
2282 else:
2299 else:
2283 cmdutil.wrongtooltocontinue(repo, _('graft'))
2300 cmdutil.wrongtooltocontinue(repo, _('graft'))
2284 else:
2301 else:
2285 if not revs:
2302 if not revs:
2286 raise error.Abort(_('no revisions specified'))
2303 raise error.Abort(_('no revisions specified'))
2287 cmdutil.checkunfinished(repo)
2304 cmdutil.checkunfinished(repo)
2288 cmdutil.bailifchanged(repo)
2305 cmdutil.bailifchanged(repo)
2289 revs = scmutil.revrange(repo, revs)
2306 revs = scmutil.revrange(repo, revs)
2290
2307
2291 skipped = set()
2308 skipped = set()
2292 # check for merges
2309 # check for merges
2293 for rev in repo.revs('%ld and merge()', revs):
2310 for rev in repo.revs('%ld and merge()', revs):
2294 ui.warn(_('skipping ungraftable merge revision %d\n') % rev)
2311 ui.warn(_('skipping ungraftable merge revision %d\n') % rev)
2295 skipped.add(rev)
2312 skipped.add(rev)
2296 revs = [r for r in revs if r not in skipped]
2313 revs = [r for r in revs if r not in skipped]
2297 if not revs:
2314 if not revs:
2298 return -1
2315 return -1
2299
2316
2300 # Don't check in the --continue case, in effect retaining --force across
2317 # Don't check in the --continue case, in effect retaining --force across
2301 # --continues. That's because without --force, any revisions we decided to
2318 # --continues. That's because without --force, any revisions we decided to
2302 # skip would have been filtered out here, so they wouldn't have made their
2319 # skip would have been filtered out here, so they wouldn't have made their
2303 # way to the graftstate. With --force, any revisions we would have otherwise
2320 # way to the graftstate. With --force, any revisions we would have otherwise
2304 # skipped would not have been filtered out, and if they hadn't been applied
2321 # skipped would not have been filtered out, and if they hadn't been applied
2305 # already, they'd have been in the graftstate.
2322 # already, they'd have been in the graftstate.
2306 if not (cont or opts.get('force')):
2323 if not (cont or opts.get('force')):
2307 # check for ancestors of dest branch
2324 # check for ancestors of dest branch
2308 crev = repo['.'].rev()
2325 crev = repo['.'].rev()
2309 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2326 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2310 # XXX make this lazy in the future
2327 # XXX make this lazy in the future
2311 # don't mutate while iterating, create a copy
2328 # don't mutate while iterating, create a copy
2312 for rev in list(revs):
2329 for rev in list(revs):
2313 if rev in ancestors:
2330 if rev in ancestors:
2314 ui.warn(_('skipping ancestor revision %d:%s\n') %
2331 ui.warn(_('skipping ancestor revision %d:%s\n') %
2315 (rev, repo[rev]))
2332 (rev, repo[rev]))
2316 # XXX remove on list is slow
2333 # XXX remove on list is slow
2317 revs.remove(rev)
2334 revs.remove(rev)
2318 if not revs:
2335 if not revs:
2319 return -1
2336 return -1
2320
2337
2321 # analyze revs for earlier grafts
2338 # analyze revs for earlier grafts
2322 ids = {}
2339 ids = {}
2323 for ctx in repo.set("%ld", revs):
2340 for ctx in repo.set("%ld", revs):
2324 ids[ctx.hex()] = ctx.rev()
2341 ids[ctx.hex()] = ctx.rev()
2325 n = ctx.extra().get('source')
2342 n = ctx.extra().get('source')
2326 if n:
2343 if n:
2327 ids[n] = ctx.rev()
2344 ids[n] = ctx.rev()
2328
2345
2329 # check ancestors for earlier grafts
2346 # check ancestors for earlier grafts
2330 ui.debug('scanning for duplicate grafts\n')
2347 ui.debug('scanning for duplicate grafts\n')
2331
2348
2332 # The only changesets we can be sure doesn't contain grafts of any
2349 # The only changesets we can be sure doesn't contain grafts of any
2333 # revs, are the ones that are common ancestors of *all* revs:
2350 # revs, are the ones that are common ancestors of *all* revs:
2334 for rev in repo.revs('only(%d,ancestor(%ld))', crev, revs):
2351 for rev in repo.revs('only(%d,ancestor(%ld))', crev, revs):
2335 ctx = repo[rev]
2352 ctx = repo[rev]
2336 n = ctx.extra().get('source')
2353 n = ctx.extra().get('source')
2337 if n in ids:
2354 if n in ids:
2338 try:
2355 try:
2339 r = repo[n].rev()
2356 r = repo[n].rev()
2340 except error.RepoLookupError:
2357 except error.RepoLookupError:
2341 r = None
2358 r = None
2342 if r in revs:
2359 if r in revs:
2343 ui.warn(_('skipping revision %d:%s '
2360 ui.warn(_('skipping revision %d:%s '
2344 '(already grafted to %d:%s)\n')
2361 '(already grafted to %d:%s)\n')
2345 % (r, repo[r], rev, ctx))
2362 % (r, repo[r], rev, ctx))
2346 revs.remove(r)
2363 revs.remove(r)
2347 elif ids[n] in revs:
2364 elif ids[n] in revs:
2348 if r is None:
2365 if r is None:
2349 ui.warn(_('skipping already grafted revision %d:%s '
2366 ui.warn(_('skipping already grafted revision %d:%s '
2350 '(%d:%s also has unknown origin %s)\n')
2367 '(%d:%s also has unknown origin %s)\n')
2351 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
2368 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
2352 else:
2369 else:
2353 ui.warn(_('skipping already grafted revision %d:%s '
2370 ui.warn(_('skipping already grafted revision %d:%s '
2354 '(%d:%s also has origin %d:%s)\n')
2371 '(%d:%s also has origin %d:%s)\n')
2355 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
2372 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
2356 revs.remove(ids[n])
2373 revs.remove(ids[n])
2357 elif ctx.hex() in ids:
2374 elif ctx.hex() in ids:
2358 r = ids[ctx.hex()]
2375 r = ids[ctx.hex()]
2359 ui.warn(_('skipping already grafted revision %d:%s '
2376 ui.warn(_('skipping already grafted revision %d:%s '
2360 '(was grafted from %d:%s)\n') %
2377 '(was grafted from %d:%s)\n') %
2361 (r, repo[r], rev, ctx))
2378 (r, repo[r], rev, ctx))
2362 revs.remove(r)
2379 revs.remove(r)
2363 if not revs:
2380 if not revs:
2364 return -1
2381 return -1
2365
2382
2366 if opts.get('no_commit'):
2383 if opts.get('no_commit'):
2367 statedata['no_commit'] = True
2384 statedata['no_commit'] = True
2368 for pos, ctx in enumerate(repo.set("%ld", revs)):
2385 for pos, ctx in enumerate(repo.set("%ld", revs)):
2369 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
2386 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
2370 ctx.description().split('\n', 1)[0])
2387 ctx.description().split('\n', 1)[0])
2371 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
2388 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
2372 if names:
2389 if names:
2373 desc += ' (%s)' % ' '.join(names)
2390 desc += ' (%s)' % ' '.join(names)
2374 ui.status(_('grafting %s\n') % desc)
2391 ui.status(_('grafting %s\n') % desc)
2375 if opts.get('dry_run'):
2392 if opts.get('dry_run'):
2376 continue
2393 continue
2377
2394
2378 source = ctx.extra().get('source')
2395 source = ctx.extra().get('source')
2379 extra = {}
2396 extra = {}
2380 if source:
2397 if source:
2381 extra['source'] = source
2398 extra['source'] = source
2382 extra['intermediate-source'] = ctx.hex()
2399 extra['intermediate-source'] = ctx.hex()
2383 else:
2400 else:
2384 extra['source'] = ctx.hex()
2401 extra['source'] = ctx.hex()
2385 user = ctx.user()
2402 user = ctx.user()
2386 if opts.get('user'):
2403 if opts.get('user'):
2387 user = opts['user']
2404 user = opts['user']
2388 statedata['user'] = user
2405 statedata['user'] = user
2389 date = ctx.date()
2406 date = ctx.date()
2390 if opts.get('date'):
2407 if opts.get('date'):
2391 date = opts['date']
2408 date = opts['date']
2392 statedata['date'] = date
2409 statedata['date'] = date
2393 message = ctx.description()
2410 message = ctx.description()
2394 if opts.get('log'):
2411 if opts.get('log'):
2395 message += '\n(grafted from %s)' % ctx.hex()
2412 message += '\n(grafted from %s)' % ctx.hex()
2396 statedata['log'] = True
2413 statedata['log'] = True
2397
2414
2398 # we don't merge the first commit when continuing
2415 # we don't merge the first commit when continuing
2399 if not cont:
2416 if not cont:
2400 # perform the graft merge with p1(rev) as 'ancestor'
2417 # perform the graft merge with p1(rev) as 'ancestor'
2401 overrides = {('ui', 'forcemerge'): opts.get('tool', '')}
2418 overrides = {('ui', 'forcemerge'): opts.get('tool', '')}
2402 with ui.configoverride(overrides, 'graft'):
2419 with ui.configoverride(overrides, 'graft'):
2403 stats = mergemod.graft(repo, ctx, ctx.p1(), ['local', 'graft'])
2420 stats = mergemod.graft(repo, ctx, ctx.p1(), ['local', 'graft'])
2404 # report any conflicts
2421 # report any conflicts
2405 if stats.unresolvedcount > 0:
2422 if stats.unresolvedcount > 0:
2406 # write out state for --continue
2423 # write out state for --continue
2407 nodes = [repo[rev].hex() for rev in revs[pos:]]
2424 nodes = [repo[rev].hex() for rev in revs[pos:]]
2408 statedata['nodes'] = nodes
2425 statedata['nodes'] = nodes
2409 stateversion = 1
2426 stateversion = 1
2410 graftstate.save(stateversion, statedata)
2427 graftstate.save(stateversion, statedata)
2411 hint = _("use 'hg resolve' and 'hg graft --continue'")
2428 hint = _("use 'hg resolve' and 'hg graft --continue'")
2412 raise error.Abort(
2429 raise error.Abort(
2413 _("unresolved conflicts, can't continue"),
2430 _("unresolved conflicts, can't continue"),
2414 hint=hint)
2431 hint=hint)
2415 else:
2432 else:
2416 cont = False
2433 cont = False
2417
2434
2418 # commit if --no-commit is false
2435 # commit if --no-commit is false
2419 if not opts.get('no_commit'):
2436 if not opts.get('no_commit'):
2420 node = repo.commit(text=message, user=user, date=date, extra=extra,
2437 node = repo.commit(text=message, user=user, date=date, extra=extra,
2421 editor=editor)
2438 editor=editor)
2422 if node is None:
2439 if node is None:
2423 ui.warn(
2440 ui.warn(
2424 _('note: graft of %d:%s created no changes to commit\n') %
2441 _('note: graft of %d:%s created no changes to commit\n') %
2425 (ctx.rev(), ctx))
2442 (ctx.rev(), ctx))
2426 # checking that newnodes exist because old state files won't have it
2443 # checking that newnodes exist because old state files won't have it
2427 elif statedata.get('newnodes') is not None:
2444 elif statedata.get('newnodes') is not None:
2428 statedata['newnodes'].append(node)
2445 statedata['newnodes'].append(node)
2429
2446
2430 # remove state when we complete successfully
2447 # remove state when we complete successfully
2431 if not opts.get('dry_run'):
2448 if not opts.get('dry_run'):
2432 graftstate.delete()
2449 graftstate.delete()
2433
2450
2434 return 0
2451 return 0
2435
2452
2436 def _abortgraft(ui, repo, graftstate):
2453 def _abortgraft(ui, repo, graftstate):
2437 """abort the interrupted graft and rollbacks to the state before interrupted
2454 """abort the interrupted graft and rollbacks to the state before interrupted
2438 graft"""
2455 graft"""
2439 if not graftstate.exists():
2456 if not graftstate.exists():
2440 raise error.Abort(_("no interrupted graft to abort"))
2457 raise error.Abort(_("no interrupted graft to abort"))
2441 statedata = _readgraftstate(repo, graftstate)
2458 statedata = _readgraftstate(repo, graftstate)
2442 newnodes = statedata.get('newnodes')
2459 newnodes = statedata.get('newnodes')
2443 if newnodes is None:
2460 if newnodes is None:
2444 # and old graft state which does not have all the data required to abort
2461 # and old graft state which does not have all the data required to abort
2445 # the graft
2462 # the graft
2446 raise error.Abort(_("cannot abort using an old graftstate"))
2463 raise error.Abort(_("cannot abort using an old graftstate"))
2447
2464
2448 # changeset from which graft operation was started
2465 # changeset from which graft operation was started
2449 startctx = None
2466 startctx = None
2450 if len(newnodes) > 0:
2467 if len(newnodes) > 0:
2451 startctx = repo[newnodes[0]].p1()
2468 startctx = repo[newnodes[0]].p1()
2452 else:
2469 else:
2453 startctx = repo['.']
2470 startctx = repo['.']
2454 # whether to strip or not
2471 # whether to strip or not
2455 cleanup = False
2472 cleanup = False
2456 if newnodes:
2473 if newnodes:
2457 newnodes = [repo[r].rev() for r in newnodes]
2474 newnodes = [repo[r].rev() for r in newnodes]
2458 cleanup = True
2475 cleanup = True
2459 # checking that none of the newnodes turned public or is public
2476 # checking that none of the newnodes turned public or is public
2460 immutable = [c for c in newnodes if not repo[c].mutable()]
2477 immutable = [c for c in newnodes if not repo[c].mutable()]
2461 if immutable:
2478 if immutable:
2462 repo.ui.warn(_("cannot clean up public changesets %s\n")
2479 repo.ui.warn(_("cannot clean up public changesets %s\n")
2463 % ', '.join(bytes(repo[r]) for r in immutable),
2480 % ', '.join(bytes(repo[r]) for r in immutable),
2464 hint=_("see 'hg help phases' for details"))
2481 hint=_("see 'hg help phases' for details"))
2465 cleanup = False
2482 cleanup = False
2466
2483
2467 # checking that no new nodes are created on top of grafted revs
2484 # checking that no new nodes are created on top of grafted revs
2468 desc = set(repo.changelog.descendants(newnodes))
2485 desc = set(repo.changelog.descendants(newnodes))
2469 if desc - set(newnodes):
2486 if desc - set(newnodes):
2470 repo.ui.warn(_("new changesets detected on destination "
2487 repo.ui.warn(_("new changesets detected on destination "
2471 "branch, can't strip\n"))
2488 "branch, can't strip\n"))
2472 cleanup = False
2489 cleanup = False
2473
2490
2474 if cleanup:
2491 if cleanup:
2475 with repo.wlock(), repo.lock():
2492 with repo.wlock(), repo.lock():
2476 hg.updaterepo(repo, startctx.node(), overwrite=True)
2493 hg.updaterepo(repo, startctx.node(), overwrite=True)
2477 # stripping the new nodes created
2494 # stripping the new nodes created
2478 strippoints = [c.node() for c in repo.set("roots(%ld)",
2495 strippoints = [c.node() for c in repo.set("roots(%ld)",
2479 newnodes)]
2496 newnodes)]
2480 repair.strip(repo.ui, repo, strippoints, backup=False)
2497 repair.strip(repo.ui, repo, strippoints, backup=False)
2481
2498
2482 if not cleanup:
2499 if not cleanup:
2483 # we don't update to the startnode if we can't strip
2500 # we don't update to the startnode if we can't strip
2484 startctx = repo['.']
2501 startctx = repo['.']
2485 hg.updaterepo(repo, startctx.node(), overwrite=True)
2502 hg.updaterepo(repo, startctx.node(), overwrite=True)
2486
2503
2487 ui.status(_("graft aborted\n"))
2504 ui.status(_("graft aborted\n"))
2488 ui.status(_("working directory is now at %s\n") % startctx.hex()[:12])
2505 ui.status(_("working directory is now at %s\n") % startctx.hex()[:12])
2489 graftstate.delete()
2506 graftstate.delete()
2490 return 0
2507 return 0
2491
2508
2492 def _readgraftstate(repo, graftstate):
2509 def _readgraftstate(repo, graftstate):
2493 """read the graft state file and return a dict of the data stored in it"""
2510 """read the graft state file and return a dict of the data stored in it"""
2494 try:
2511 try:
2495 return graftstate.read()
2512 return graftstate.read()
2496 except error.CorruptedState:
2513 except error.CorruptedState:
2497 nodes = repo.vfs.read('graftstate').splitlines()
2514 nodes = repo.vfs.read('graftstate').splitlines()
2498 return {'nodes': nodes}
2515 return {'nodes': nodes}
2499
2516
2500 def _stopgraft(ui, repo, graftstate):
2517 def _stopgraft(ui, repo, graftstate):
2501 """stop the interrupted graft"""
2518 """stop the interrupted graft"""
2502 if not graftstate.exists():
2519 if not graftstate.exists():
2503 raise error.Abort(_("no interrupted graft found"))
2520 raise error.Abort(_("no interrupted graft found"))
2504 pctx = repo['.']
2521 pctx = repo['.']
2505 hg.updaterepo(repo, pctx.node(), overwrite=True)
2522 hg.updaterepo(repo, pctx.node(), overwrite=True)
2506 graftstate.delete()
2523 graftstate.delete()
2507 ui.status(_("stopped the interrupted graft\n"))
2524 ui.status(_("stopped the interrupted graft\n"))
2508 ui.status(_("working directory is now at %s\n") % pctx.hex()[:12])
2525 ui.status(_("working directory is now at %s\n") % pctx.hex()[:12])
2509 return 0
2526 return 0
2510
2527
2511 @command('grep',
2528 @command('grep',
2512 [('0', 'print0', None, _('end fields with NUL')),
2529 [('0', 'print0', None, _('end fields with NUL')),
2513 ('', 'all', None, _('print all revisions that match (DEPRECATED) ')),
2530 ('', 'all', None, _('print all revisions that match (DEPRECATED) ')),
2514 ('', 'diff', None, _('print all revisions when the term was introduced '
2531 ('', 'diff', None, _('print all revisions when the term was introduced '
2515 'or removed')),
2532 'or removed')),
2516 ('a', 'text', None, _('treat all files as text')),
2533 ('a', 'text', None, _('treat all files as text')),
2517 ('f', 'follow', None,
2534 ('f', 'follow', None,
2518 _('follow changeset history,'
2535 _('follow changeset history,'
2519 ' or file history across copies and renames')),
2536 ' or file history across copies and renames')),
2520 ('i', 'ignore-case', None, _('ignore case when matching')),
2537 ('i', 'ignore-case', None, _('ignore case when matching')),
2521 ('l', 'files-with-matches', None,
2538 ('l', 'files-with-matches', None,
2522 _('print only filenames and revisions that match')),
2539 _('print only filenames and revisions that match')),
2523 ('n', 'line-number', None, _('print matching line numbers')),
2540 ('n', 'line-number', None, _('print matching line numbers')),
2524 ('r', 'rev', [],
2541 ('r', 'rev', [],
2525 _('only search files changed within revision range'), _('REV')),
2542 _('only search files changed within revision range'), _('REV')),
2526 ('', 'all-files', None,
2543 ('', 'all-files', None,
2527 _('include all files in the changeset while grepping (EXPERIMENTAL)')),
2544 _('include all files in the changeset while grepping (EXPERIMENTAL)')),
2528 ('u', 'user', None, _('list the author (long with -v)')),
2545 ('u', 'user', None, _('list the author (long with -v)')),
2529 ('d', 'date', None, _('list the date (short with -q)')),
2546 ('d', 'date', None, _('list the date (short with -q)')),
2530 ] + formatteropts + walkopts,
2547 ] + formatteropts + walkopts,
2531 _('[OPTION]... PATTERN [FILE]...'),
2548 _('[OPTION]... PATTERN [FILE]...'),
2532 inferrepo=True,
2549 inferrepo=True,
2533 intents={INTENT_READONLY})
2550 intents={INTENT_READONLY})
2534 def grep(ui, repo, pattern, *pats, **opts):
2551 def grep(ui, repo, pattern, *pats, **opts):
2535 """search revision history for a pattern in specified files
2552 """search revision history for a pattern in specified files
2536
2553
2537 Search revision history for a regular expression in the specified
2554 Search revision history for a regular expression in the specified
2538 files or the entire project.
2555 files or the entire project.
2539
2556
2540 By default, grep prints the most recent revision number for each
2557 By default, grep prints the most recent revision number for each
2541 file in which it finds a match. To get it to print every revision
2558 file in which it finds a match. To get it to print every revision
2542 that contains a change in match status ("-" for a match that becomes
2559 that contains a change in match status ("-" for a match that becomes
2543 a non-match, or "+" for a non-match that becomes a match), use the
2560 a non-match, or "+" for a non-match that becomes a match), use the
2544 --diff flag.
2561 --diff flag.
2545
2562
2546 PATTERN can be any Python (roughly Perl-compatible) regular
2563 PATTERN can be any Python (roughly Perl-compatible) regular
2547 expression.
2564 expression.
2548
2565
2549 If no FILEs are specified (and -f/--follow isn't set), all files in
2566 If no FILEs are specified (and -f/--follow isn't set), all files in
2550 the repository are searched, including those that don't exist in the
2567 the repository are searched, including those that don't exist in the
2551 current branch or have been deleted in a prior changeset.
2568 current branch or have been deleted in a prior changeset.
2552
2569
2553 Returns 0 if a match is found, 1 otherwise.
2570 Returns 0 if a match is found, 1 otherwise.
2554 """
2571 """
2555 opts = pycompat.byteskwargs(opts)
2572 opts = pycompat.byteskwargs(opts)
2556 diff = opts.get('all') or opts.get('diff')
2573 diff = opts.get('all') or opts.get('diff')
2557 all_files = opts.get('all_files')
2574 all_files = opts.get('all_files')
2558 if diff and opts.get('all_files'):
2575 if diff and opts.get('all_files'):
2559 raise error.Abort(_('--diff and --all-files are mutually exclusive'))
2576 raise error.Abort(_('--diff and --all-files are mutually exclusive'))
2560 # TODO: remove "not opts.get('rev')" if --all-files -rMULTIREV gets working
2577 # TODO: remove "not opts.get('rev')" if --all-files -rMULTIREV gets working
2561 if opts.get('all_files') is None and not opts.get('rev') and not diff:
2578 if opts.get('all_files') is None and not opts.get('rev') and not diff:
2562 # experimental config: commands.grep.all-files
2579 # experimental config: commands.grep.all-files
2563 opts['all_files'] = ui.configbool('commands', 'grep.all-files')
2580 opts['all_files'] = ui.configbool('commands', 'grep.all-files')
2564 plaingrep = opts.get('all_files') and not opts.get('rev')
2581 plaingrep = opts.get('all_files') and not opts.get('rev')
2565 if plaingrep:
2582 if plaingrep:
2566 opts['rev'] = ['wdir()']
2583 opts['rev'] = ['wdir()']
2567
2584
2568 reflags = re.M
2585 reflags = re.M
2569 if opts.get('ignore_case'):
2586 if opts.get('ignore_case'):
2570 reflags |= re.I
2587 reflags |= re.I
2571 try:
2588 try:
2572 regexp = util.re.compile(pattern, reflags)
2589 regexp = util.re.compile(pattern, reflags)
2573 except re.error as inst:
2590 except re.error as inst:
2574 ui.warn(_("grep: invalid match pattern: %s\n") % pycompat.bytestr(inst))
2591 ui.warn(_("grep: invalid match pattern: %s\n") % pycompat.bytestr(inst))
2575 return 1
2592 return 1
2576 sep, eol = ':', '\n'
2593 sep, eol = ':', '\n'
2577 if opts.get('print0'):
2594 if opts.get('print0'):
2578 sep = eol = '\0'
2595 sep = eol = '\0'
2579
2596
2580 getfile = util.lrucachefunc(repo.file)
2597 getfile = util.lrucachefunc(repo.file)
2581
2598
2582 def matchlines(body):
2599 def matchlines(body):
2583 begin = 0
2600 begin = 0
2584 linenum = 0
2601 linenum = 0
2585 while begin < len(body):
2602 while begin < len(body):
2586 match = regexp.search(body, begin)
2603 match = regexp.search(body, begin)
2587 if not match:
2604 if not match:
2588 break
2605 break
2589 mstart, mend = match.span()
2606 mstart, mend = match.span()
2590 linenum += body.count('\n', begin, mstart) + 1
2607 linenum += body.count('\n', begin, mstart) + 1
2591 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2608 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2592 begin = body.find('\n', mend) + 1 or len(body) + 1
2609 begin = body.find('\n', mend) + 1 or len(body) + 1
2593 lend = begin - 1
2610 lend = begin - 1
2594 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2611 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2595
2612
2596 class linestate(object):
2613 class linestate(object):
2597 def __init__(self, line, linenum, colstart, colend):
2614 def __init__(self, line, linenum, colstart, colend):
2598 self.line = line
2615 self.line = line
2599 self.linenum = linenum
2616 self.linenum = linenum
2600 self.colstart = colstart
2617 self.colstart = colstart
2601 self.colend = colend
2618 self.colend = colend
2602
2619
2603 def __hash__(self):
2620 def __hash__(self):
2604 return hash((self.linenum, self.line))
2621 return hash((self.linenum, self.line))
2605
2622
2606 def __eq__(self, other):
2623 def __eq__(self, other):
2607 return self.line == other.line
2624 return self.line == other.line
2608
2625
2609 def findpos(self):
2626 def findpos(self):
2610 """Iterate all (start, end) indices of matches"""
2627 """Iterate all (start, end) indices of matches"""
2611 yield self.colstart, self.colend
2628 yield self.colstart, self.colend
2612 p = self.colend
2629 p = self.colend
2613 while p < len(self.line):
2630 while p < len(self.line):
2614 m = regexp.search(self.line, p)
2631 m = regexp.search(self.line, p)
2615 if not m:
2632 if not m:
2616 break
2633 break
2617 yield m.span()
2634 yield m.span()
2618 p = m.end()
2635 p = m.end()
2619
2636
2620 matches = {}
2637 matches = {}
2621 copies = {}
2638 copies = {}
2622 def grepbody(fn, rev, body):
2639 def grepbody(fn, rev, body):
2623 matches[rev].setdefault(fn, [])
2640 matches[rev].setdefault(fn, [])
2624 m = matches[rev][fn]
2641 m = matches[rev][fn]
2625 for lnum, cstart, cend, line in matchlines(body):
2642 for lnum, cstart, cend, line in matchlines(body):
2626 s = linestate(line, lnum, cstart, cend)
2643 s = linestate(line, lnum, cstart, cend)
2627 m.append(s)
2644 m.append(s)
2628
2645
2629 def difflinestates(a, b):
2646 def difflinestates(a, b):
2630 sm = difflib.SequenceMatcher(None, a, b)
2647 sm = difflib.SequenceMatcher(None, a, b)
2631 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2648 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2632 if tag == r'insert':
2649 if tag == r'insert':
2633 for i in pycompat.xrange(blo, bhi):
2650 for i in pycompat.xrange(blo, bhi):
2634 yield ('+', b[i])
2651 yield ('+', b[i])
2635 elif tag == r'delete':
2652 elif tag == r'delete':
2636 for i in pycompat.xrange(alo, ahi):
2653 for i in pycompat.xrange(alo, ahi):
2637 yield ('-', a[i])
2654 yield ('-', a[i])
2638 elif tag == r'replace':
2655 elif tag == r'replace':
2639 for i in pycompat.xrange(alo, ahi):
2656 for i in pycompat.xrange(alo, ahi):
2640 yield ('-', a[i])
2657 yield ('-', a[i])
2641 for i in pycompat.xrange(blo, bhi):
2658 for i in pycompat.xrange(blo, bhi):
2642 yield ('+', b[i])
2659 yield ('+', b[i])
2643
2660
2644 def display(fm, fn, ctx, pstates, states):
2661 def display(fm, fn, ctx, pstates, states):
2645 rev = scmutil.intrev(ctx)
2662 rev = scmutil.intrev(ctx)
2646 if fm.isplain():
2663 if fm.isplain():
2647 formatuser = ui.shortuser
2664 formatuser = ui.shortuser
2648 else:
2665 else:
2649 formatuser = pycompat.bytestr
2666 formatuser = pycompat.bytestr
2650 if ui.quiet:
2667 if ui.quiet:
2651 datefmt = '%Y-%m-%d'
2668 datefmt = '%Y-%m-%d'
2652 else:
2669 else:
2653 datefmt = '%a %b %d %H:%M:%S %Y %1%2'
2670 datefmt = '%a %b %d %H:%M:%S %Y %1%2'
2654 found = False
2671 found = False
2655 @util.cachefunc
2672 @util.cachefunc
2656 def binary():
2673 def binary():
2657 flog = getfile(fn)
2674 flog = getfile(fn)
2658 try:
2675 try:
2659 return stringutil.binary(flog.read(ctx.filenode(fn)))
2676 return stringutil.binary(flog.read(ctx.filenode(fn)))
2660 except error.WdirUnsupported:
2677 except error.WdirUnsupported:
2661 return ctx[fn].isbinary()
2678 return ctx[fn].isbinary()
2662
2679
2663 fieldnamemap = {'filename': 'path', 'linenumber': 'line_number'}
2680 fieldnamemap = {'filename': 'path', 'linenumber': 'line_number'}
2664 if diff:
2681 if diff:
2665 iter = difflinestates(pstates, states)
2682 iter = difflinestates(pstates, states)
2666 else:
2683 else:
2667 iter = [('', l) for l in states]
2684 iter = [('', l) for l in states]
2668 for change, l in iter:
2685 for change, l in iter:
2669 fm.startitem()
2686 fm.startitem()
2670 fm.context(ctx=ctx)
2687 fm.context(ctx=ctx)
2671 fm.data(node=fm.hexfunc(scmutil.binnode(ctx)))
2688 fm.data(node=fm.hexfunc(scmutil.binnode(ctx)))
2672
2689
2673 cols = [
2690 cols = [
2674 ('filename', '%s', fn, True),
2691 ('filename', '%s', fn, True),
2675 ('rev', '%d', rev, not plaingrep),
2692 ('rev', '%d', rev, not plaingrep),
2676 ('linenumber', '%d', l.linenum, opts.get('line_number')),
2693 ('linenumber', '%d', l.linenum, opts.get('line_number')),
2677 ]
2694 ]
2678 if diff:
2695 if diff:
2679 cols.append(('change', '%s', change, True))
2696 cols.append(('change', '%s', change, True))
2680 cols.extend([
2697 cols.extend([
2681 ('user', '%s', formatuser(ctx.user()), opts.get('user')),
2698 ('user', '%s', formatuser(ctx.user()), opts.get('user')),
2682 ('date', '%s', fm.formatdate(ctx.date(), datefmt),
2699 ('date', '%s', fm.formatdate(ctx.date(), datefmt),
2683 opts.get('date')),
2700 opts.get('date')),
2684 ])
2701 ])
2685 lastcol = next(
2702 lastcol = next(
2686 name for name, fmt, data, cond in reversed(cols) if cond)
2703 name for name, fmt, data, cond in reversed(cols) if cond)
2687 for name, fmt, data, cond in cols:
2704 for name, fmt, data, cond in cols:
2688 field = fieldnamemap.get(name, name)
2705 field = fieldnamemap.get(name, name)
2689 fm.condwrite(cond, field, fmt, data, label='grep.%s' % name)
2706 fm.condwrite(cond, field, fmt, data, label='grep.%s' % name)
2690 if cond and name != lastcol:
2707 if cond and name != lastcol:
2691 fm.plain(sep, label='grep.sep')
2708 fm.plain(sep, label='grep.sep')
2692 if not opts.get('files_with_matches'):
2709 if not opts.get('files_with_matches'):
2693 fm.plain(sep, label='grep.sep')
2710 fm.plain(sep, label='grep.sep')
2694 if not opts.get('text') and binary():
2711 if not opts.get('text') and binary():
2695 fm.plain(_(" Binary file matches"))
2712 fm.plain(_(" Binary file matches"))
2696 else:
2713 else:
2697 displaymatches(fm.nested('texts', tmpl='{text}'), l)
2714 displaymatches(fm.nested('texts', tmpl='{text}'), l)
2698 fm.plain(eol)
2715 fm.plain(eol)
2699 found = True
2716 found = True
2700 if opts.get('files_with_matches'):
2717 if opts.get('files_with_matches'):
2701 break
2718 break
2702 return found
2719 return found
2703
2720
2704 def displaymatches(fm, l):
2721 def displaymatches(fm, l):
2705 p = 0
2722 p = 0
2706 for s, e in l.findpos():
2723 for s, e in l.findpos():
2707 if p < s:
2724 if p < s:
2708 fm.startitem()
2725 fm.startitem()
2709 fm.write('text', '%s', l.line[p:s])
2726 fm.write('text', '%s', l.line[p:s])
2710 fm.data(matched=False)
2727 fm.data(matched=False)
2711 fm.startitem()
2728 fm.startitem()
2712 fm.write('text', '%s', l.line[s:e], label='grep.match')
2729 fm.write('text', '%s', l.line[s:e], label='grep.match')
2713 fm.data(matched=True)
2730 fm.data(matched=True)
2714 p = e
2731 p = e
2715 if p < len(l.line):
2732 if p < len(l.line):
2716 fm.startitem()
2733 fm.startitem()
2717 fm.write('text', '%s', l.line[p:])
2734 fm.write('text', '%s', l.line[p:])
2718 fm.data(matched=False)
2735 fm.data(matched=False)
2719 fm.end()
2736 fm.end()
2720
2737
2721 skip = {}
2738 skip = {}
2722 revfiles = {}
2739 revfiles = {}
2723 match = scmutil.match(repo[None], pats, opts)
2740 match = scmutil.match(repo[None], pats, opts)
2724 found = False
2741 found = False
2725 follow = opts.get('follow')
2742 follow = opts.get('follow')
2726
2743
2727 def prep(ctx, fns):
2744 def prep(ctx, fns):
2728 rev = ctx.rev()
2745 rev = ctx.rev()
2729 pctx = ctx.p1()
2746 pctx = ctx.p1()
2730 parent = pctx.rev()
2747 parent = pctx.rev()
2731 matches.setdefault(rev, {})
2748 matches.setdefault(rev, {})
2732 matches.setdefault(parent, {})
2749 matches.setdefault(parent, {})
2733 files = revfiles.setdefault(rev, [])
2750 files = revfiles.setdefault(rev, [])
2734 for fn in fns:
2751 for fn in fns:
2735 flog = getfile(fn)
2752 flog = getfile(fn)
2736 try:
2753 try:
2737 fnode = ctx.filenode(fn)
2754 fnode = ctx.filenode(fn)
2738 except error.LookupError:
2755 except error.LookupError:
2739 continue
2756 continue
2740 try:
2757 try:
2741 copied = flog.renamed(fnode)
2758 copied = flog.renamed(fnode)
2742 except error.WdirUnsupported:
2759 except error.WdirUnsupported:
2743 copied = ctx[fn].renamed()
2760 copied = ctx[fn].renamed()
2744 copy = follow and copied and copied[0]
2761 copy = follow and copied and copied[0]
2745 if copy:
2762 if copy:
2746 copies.setdefault(rev, {})[fn] = copy
2763 copies.setdefault(rev, {})[fn] = copy
2747 if fn in skip:
2764 if fn in skip:
2748 if copy:
2765 if copy:
2749 skip[copy] = True
2766 skip[copy] = True
2750 continue
2767 continue
2751 files.append(fn)
2768 files.append(fn)
2752
2769
2753 if fn not in matches[rev]:
2770 if fn not in matches[rev]:
2754 try:
2771 try:
2755 content = flog.read(fnode)
2772 content = flog.read(fnode)
2756 except error.WdirUnsupported:
2773 except error.WdirUnsupported:
2757 content = ctx[fn].data()
2774 content = ctx[fn].data()
2758 grepbody(fn, rev, content)
2775 grepbody(fn, rev, content)
2759
2776
2760 pfn = copy or fn
2777 pfn = copy or fn
2761 if pfn not in matches[parent]:
2778 if pfn not in matches[parent]:
2762 try:
2779 try:
2763 fnode = pctx.filenode(pfn)
2780 fnode = pctx.filenode(pfn)
2764 grepbody(pfn, parent, flog.read(fnode))
2781 grepbody(pfn, parent, flog.read(fnode))
2765 except error.LookupError:
2782 except error.LookupError:
2766 pass
2783 pass
2767
2784
2768 ui.pager('grep')
2785 ui.pager('grep')
2769 fm = ui.formatter('grep', opts)
2786 fm = ui.formatter('grep', opts)
2770 for ctx in cmdutil.walkchangerevs(repo, match, opts, prep):
2787 for ctx in cmdutil.walkchangerevs(repo, match, opts, prep):
2771 rev = ctx.rev()
2788 rev = ctx.rev()
2772 parent = ctx.p1().rev()
2789 parent = ctx.p1().rev()
2773 for fn in sorted(revfiles.get(rev, [])):
2790 for fn in sorted(revfiles.get(rev, [])):
2774 states = matches[rev][fn]
2791 states = matches[rev][fn]
2775 copy = copies.get(rev, {}).get(fn)
2792 copy = copies.get(rev, {}).get(fn)
2776 if fn in skip:
2793 if fn in skip:
2777 if copy:
2794 if copy:
2778 skip[copy] = True
2795 skip[copy] = True
2779 continue
2796 continue
2780 pstates = matches.get(parent, {}).get(copy or fn, [])
2797 pstates = matches.get(parent, {}).get(copy or fn, [])
2781 if pstates or states:
2798 if pstates or states:
2782 r = display(fm, fn, ctx, pstates, states)
2799 r = display(fm, fn, ctx, pstates, states)
2783 found = found or r
2800 found = found or r
2784 if r and not diff and not all_files:
2801 if r and not diff and not all_files:
2785 skip[fn] = True
2802 skip[fn] = True
2786 if copy:
2803 if copy:
2787 skip[copy] = True
2804 skip[copy] = True
2788 del revfiles[rev]
2805 del revfiles[rev]
2789 # We will keep the matches dict for the duration of the window
2806 # We will keep the matches dict for the duration of the window
2790 # clear the matches dict once the window is over
2807 # clear the matches dict once the window is over
2791 if not revfiles:
2808 if not revfiles:
2792 matches.clear()
2809 matches.clear()
2793 fm.end()
2810 fm.end()
2794
2811
2795 return not found
2812 return not found
2796
2813
2797 @command('heads',
2814 @command('heads',
2798 [('r', 'rev', '',
2815 [('r', 'rev', '',
2799 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2816 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2800 ('t', 'topo', False, _('show topological heads only')),
2817 ('t', 'topo', False, _('show topological heads only')),
2801 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2818 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2802 ('c', 'closed', False, _('show normal and closed branch heads')),
2819 ('c', 'closed', False, _('show normal and closed branch heads')),
2803 ] + templateopts,
2820 ] + templateopts,
2804 _('[-ct] [-r STARTREV] [REV]...'),
2821 _('[-ct] [-r STARTREV] [REV]...'),
2805 intents={INTENT_READONLY})
2822 intents={INTENT_READONLY})
2806 def heads(ui, repo, *branchrevs, **opts):
2823 def heads(ui, repo, *branchrevs, **opts):
2807 """show branch heads
2824 """show branch heads
2808
2825
2809 With no arguments, show all open branch heads in the repository.
2826 With no arguments, show all open branch heads in the repository.
2810 Branch heads are changesets that have no descendants on the
2827 Branch heads are changesets that have no descendants on the
2811 same branch. They are where development generally takes place and
2828 same branch. They are where development generally takes place and
2812 are the usual targets for update and merge operations.
2829 are the usual targets for update and merge operations.
2813
2830
2814 If one or more REVs are given, only open branch heads on the
2831 If one or more REVs are given, only open branch heads on the
2815 branches associated with the specified changesets are shown. This
2832 branches associated with the specified changesets are shown. This
2816 means that you can use :hg:`heads .` to see the heads on the
2833 means that you can use :hg:`heads .` to see the heads on the
2817 currently checked-out branch.
2834 currently checked-out branch.
2818
2835
2819 If -c/--closed is specified, also show branch heads marked closed
2836 If -c/--closed is specified, also show branch heads marked closed
2820 (see :hg:`commit --close-branch`).
2837 (see :hg:`commit --close-branch`).
2821
2838
2822 If STARTREV is specified, only those heads that are descendants of
2839 If STARTREV is specified, only those heads that are descendants of
2823 STARTREV will be displayed.
2840 STARTREV will be displayed.
2824
2841
2825 If -t/--topo is specified, named branch mechanics will be ignored and only
2842 If -t/--topo is specified, named branch mechanics will be ignored and only
2826 topological heads (changesets with no children) will be shown.
2843 topological heads (changesets with no children) will be shown.
2827
2844
2828 Returns 0 if matching heads are found, 1 if not.
2845 Returns 0 if matching heads are found, 1 if not.
2829 """
2846 """
2830
2847
2831 opts = pycompat.byteskwargs(opts)
2848 opts = pycompat.byteskwargs(opts)
2832 start = None
2849 start = None
2833 rev = opts.get('rev')
2850 rev = opts.get('rev')
2834 if rev:
2851 if rev:
2835 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
2852 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
2836 start = scmutil.revsingle(repo, rev, None).node()
2853 start = scmutil.revsingle(repo, rev, None).node()
2837
2854
2838 if opts.get('topo'):
2855 if opts.get('topo'):
2839 heads = [repo[h] for h in repo.heads(start)]
2856 heads = [repo[h] for h in repo.heads(start)]
2840 else:
2857 else:
2841 heads = []
2858 heads = []
2842 for branch in repo.branchmap():
2859 for branch in repo.branchmap():
2843 heads += repo.branchheads(branch, start, opts.get('closed'))
2860 heads += repo.branchheads(branch, start, opts.get('closed'))
2844 heads = [repo[h] for h in heads]
2861 heads = [repo[h] for h in heads]
2845
2862
2846 if branchrevs:
2863 if branchrevs:
2847 branches = set(repo[r].branch()
2864 branches = set(repo[r].branch()
2848 for r in scmutil.revrange(repo, branchrevs))
2865 for r in scmutil.revrange(repo, branchrevs))
2849 heads = [h for h in heads if h.branch() in branches]
2866 heads = [h for h in heads if h.branch() in branches]
2850
2867
2851 if opts.get('active') and branchrevs:
2868 if opts.get('active') and branchrevs:
2852 dagheads = repo.heads(start)
2869 dagheads = repo.heads(start)
2853 heads = [h for h in heads if h.node() in dagheads]
2870 heads = [h for h in heads if h.node() in dagheads]
2854
2871
2855 if branchrevs:
2872 if branchrevs:
2856 haveheads = set(h.branch() for h in heads)
2873 haveheads = set(h.branch() for h in heads)
2857 if branches - haveheads:
2874 if branches - haveheads:
2858 headless = ', '.join(b for b in branches - haveheads)
2875 headless = ', '.join(b for b in branches - haveheads)
2859 msg = _('no open branch heads found on branches %s')
2876 msg = _('no open branch heads found on branches %s')
2860 if opts.get('rev'):
2877 if opts.get('rev'):
2861 msg += _(' (started at %s)') % opts['rev']
2878 msg += _(' (started at %s)') % opts['rev']
2862 ui.warn((msg + '\n') % headless)
2879 ui.warn((msg + '\n') % headless)
2863
2880
2864 if not heads:
2881 if not heads:
2865 return 1
2882 return 1
2866
2883
2867 ui.pager('heads')
2884 ui.pager('heads')
2868 heads = sorted(heads, key=lambda x: -x.rev())
2885 heads = sorted(heads, key=lambda x: -x.rev())
2869 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
2886 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
2870 for ctx in heads:
2887 for ctx in heads:
2871 displayer.show(ctx)
2888 displayer.show(ctx)
2872 displayer.close()
2889 displayer.close()
2873
2890
2874 @command('help',
2891 @command('help',
2875 [('e', 'extension', None, _('show only help for extensions')),
2892 [('e', 'extension', None, _('show only help for extensions')),
2876 ('c', 'command', None, _('show only help for commands')),
2893 ('c', 'command', None, _('show only help for commands')),
2877 ('k', 'keyword', None, _('show topics matching keyword')),
2894 ('k', 'keyword', None, _('show topics matching keyword')),
2878 ('s', 'system', [], _('show help for specific platform(s)')),
2895 ('s', 'system', [], _('show help for specific platform(s)')),
2879 ],
2896 ],
2880 _('[-ecks] [TOPIC]'),
2897 _('[-ecks] [TOPIC]'),
2881 norepo=True,
2898 norepo=True,
2882 intents={INTENT_READONLY})
2899 intents={INTENT_READONLY})
2883 def help_(ui, name=None, **opts):
2900 def help_(ui, name=None, **opts):
2884 """show help for a given topic or a help overview
2901 """show help for a given topic or a help overview
2885
2902
2886 With no arguments, print a list of commands with short help messages.
2903 With no arguments, print a list of commands with short help messages.
2887
2904
2888 Given a topic, extension, or command name, print help for that
2905 Given a topic, extension, or command name, print help for that
2889 topic.
2906 topic.
2890
2907
2891 Returns 0 if successful.
2908 Returns 0 if successful.
2892 """
2909 """
2893
2910
2894 keep = opts.get(r'system') or []
2911 keep = opts.get(r'system') or []
2895 if len(keep) == 0:
2912 if len(keep) == 0:
2896 if pycompat.sysplatform.startswith('win'):
2913 if pycompat.sysplatform.startswith('win'):
2897 keep.append('windows')
2914 keep.append('windows')
2898 elif pycompat.sysplatform == 'OpenVMS':
2915 elif pycompat.sysplatform == 'OpenVMS':
2899 keep.append('vms')
2916 keep.append('vms')
2900 elif pycompat.sysplatform == 'plan9':
2917 elif pycompat.sysplatform == 'plan9':
2901 keep.append('plan9')
2918 keep.append('plan9')
2902 else:
2919 else:
2903 keep.append('unix')
2920 keep.append('unix')
2904 keep.append(pycompat.sysplatform.lower())
2921 keep.append(pycompat.sysplatform.lower())
2905 if ui.verbose:
2922 if ui.verbose:
2906 keep.append('verbose')
2923 keep.append('verbose')
2907
2924
2908 commands = sys.modules[__name__]
2925 commands = sys.modules[__name__]
2909 formatted = help.formattedhelp(ui, commands, name, keep=keep, **opts)
2926 formatted = help.formattedhelp(ui, commands, name, keep=keep, **opts)
2910 ui.pager('help')
2927 ui.pager('help')
2911 ui.write(formatted)
2928 ui.write(formatted)
2912
2929
2913
2930
2914 @command('identify|id',
2931 @command('identify|id',
2915 [('r', 'rev', '',
2932 [('r', 'rev', '',
2916 _('identify the specified revision'), _('REV')),
2933 _('identify the specified revision'), _('REV')),
2917 ('n', 'num', None, _('show local revision number')),
2934 ('n', 'num', None, _('show local revision number')),
2918 ('i', 'id', None, _('show global revision id')),
2935 ('i', 'id', None, _('show global revision id')),
2919 ('b', 'branch', None, _('show branch')),
2936 ('b', 'branch', None, _('show branch')),
2920 ('t', 'tags', None, _('show tags')),
2937 ('t', 'tags', None, _('show tags')),
2921 ('B', 'bookmarks', None, _('show bookmarks')),
2938 ('B', 'bookmarks', None, _('show bookmarks')),
2922 ] + remoteopts + formatteropts,
2939 ] + remoteopts + formatteropts,
2923 _('[-nibtB] [-r REV] [SOURCE]'),
2940 _('[-nibtB] [-r REV] [SOURCE]'),
2924 optionalrepo=True,
2941 optionalrepo=True,
2925 intents={INTENT_READONLY})
2942 intents={INTENT_READONLY})
2926 def identify(ui, repo, source=None, rev=None,
2943 def identify(ui, repo, source=None, rev=None,
2927 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
2944 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
2928 """identify the working directory or specified revision
2945 """identify the working directory or specified revision
2929
2946
2930 Print a summary identifying the repository state at REV using one or
2947 Print a summary identifying the repository state at REV using one or
2931 two parent hash identifiers, followed by a "+" if the working
2948 two parent hash identifiers, followed by a "+" if the working
2932 directory has uncommitted changes, the branch name (if not default),
2949 directory has uncommitted changes, the branch name (if not default),
2933 a list of tags, and a list of bookmarks.
2950 a list of tags, and a list of bookmarks.
2934
2951
2935 When REV is not given, print a summary of the current state of the
2952 When REV is not given, print a summary of the current state of the
2936 repository including the working directory. Specify -r. to get information
2953 repository including the working directory. Specify -r. to get information
2937 of the working directory parent without scanning uncommitted changes.
2954 of the working directory parent without scanning uncommitted changes.
2938
2955
2939 Specifying a path to a repository root or Mercurial bundle will
2956 Specifying a path to a repository root or Mercurial bundle will
2940 cause lookup to operate on that repository/bundle.
2957 cause lookup to operate on that repository/bundle.
2941
2958
2942 .. container:: verbose
2959 .. container:: verbose
2943
2960
2944 Examples:
2961 Examples:
2945
2962
2946 - generate a build identifier for the working directory::
2963 - generate a build identifier for the working directory::
2947
2964
2948 hg id --id > build-id.dat
2965 hg id --id > build-id.dat
2949
2966
2950 - find the revision corresponding to a tag::
2967 - find the revision corresponding to a tag::
2951
2968
2952 hg id -n -r 1.3
2969 hg id -n -r 1.3
2953
2970
2954 - check the most recent revision of a remote repository::
2971 - check the most recent revision of a remote repository::
2955
2972
2956 hg id -r tip https://www.mercurial-scm.org/repo/hg/
2973 hg id -r tip https://www.mercurial-scm.org/repo/hg/
2957
2974
2958 See :hg:`log` for generating more information about specific revisions,
2975 See :hg:`log` for generating more information about specific revisions,
2959 including full hash identifiers.
2976 including full hash identifiers.
2960
2977
2961 Returns 0 if successful.
2978 Returns 0 if successful.
2962 """
2979 """
2963
2980
2964 opts = pycompat.byteskwargs(opts)
2981 opts = pycompat.byteskwargs(opts)
2965 if not repo and not source:
2982 if not repo and not source:
2966 raise error.Abort(_("there is no Mercurial repository here "
2983 raise error.Abort(_("there is no Mercurial repository here "
2967 "(.hg not found)"))
2984 "(.hg not found)"))
2968
2985
2969 if ui.debugflag:
2986 if ui.debugflag:
2970 hexfunc = hex
2987 hexfunc = hex
2971 else:
2988 else:
2972 hexfunc = short
2989 hexfunc = short
2973 default = not (num or id or branch or tags or bookmarks)
2990 default = not (num or id or branch or tags or bookmarks)
2974 output = []
2991 output = []
2975 revs = []
2992 revs = []
2976
2993
2977 if source:
2994 if source:
2978 source, branches = hg.parseurl(ui.expandpath(source))
2995 source, branches = hg.parseurl(ui.expandpath(source))
2979 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
2996 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
2980 repo = peer.local()
2997 repo = peer.local()
2981 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
2998 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
2982
2999
2983 fm = ui.formatter('identify', opts)
3000 fm = ui.formatter('identify', opts)
2984 fm.startitem()
3001 fm.startitem()
2985
3002
2986 if not repo:
3003 if not repo:
2987 if num or branch or tags:
3004 if num or branch or tags:
2988 raise error.Abort(
3005 raise error.Abort(
2989 _("can't query remote revision number, branch, or tags"))
3006 _("can't query remote revision number, branch, or tags"))
2990 if not rev and revs:
3007 if not rev and revs:
2991 rev = revs[0]
3008 rev = revs[0]
2992 if not rev:
3009 if not rev:
2993 rev = "tip"
3010 rev = "tip"
2994
3011
2995 remoterev = peer.lookup(rev)
3012 remoterev = peer.lookup(rev)
2996 hexrev = hexfunc(remoterev)
3013 hexrev = hexfunc(remoterev)
2997 if default or id:
3014 if default or id:
2998 output = [hexrev]
3015 output = [hexrev]
2999 fm.data(id=hexrev)
3016 fm.data(id=hexrev)
3000
3017
3001 def getbms():
3018 def getbms():
3002 bms = []
3019 bms = []
3003
3020
3004 if 'bookmarks' in peer.listkeys('namespaces'):
3021 if 'bookmarks' in peer.listkeys('namespaces'):
3005 hexremoterev = hex(remoterev)
3022 hexremoterev = hex(remoterev)
3006 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3023 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3007 if bmr == hexremoterev]
3024 if bmr == hexremoterev]
3008
3025
3009 return sorted(bms)
3026 return sorted(bms)
3010
3027
3011 bms = getbms()
3028 bms = getbms()
3012 if bookmarks:
3029 if bookmarks:
3013 output.extend(bms)
3030 output.extend(bms)
3014 elif default and not ui.quiet:
3031 elif default and not ui.quiet:
3015 # multiple bookmarks for a single parent separated by '/'
3032 # multiple bookmarks for a single parent separated by '/'
3016 bm = '/'.join(bms)
3033 bm = '/'.join(bms)
3017 if bm:
3034 if bm:
3018 output.append(bm)
3035 output.append(bm)
3019
3036
3020 fm.data(node=hex(remoterev))
3037 fm.data(node=hex(remoterev))
3021 fm.data(bookmarks=fm.formatlist(bms, name='bookmark'))
3038 fm.data(bookmarks=fm.formatlist(bms, name='bookmark'))
3022 else:
3039 else:
3023 if rev:
3040 if rev:
3024 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
3041 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
3025 ctx = scmutil.revsingle(repo, rev, None)
3042 ctx = scmutil.revsingle(repo, rev, None)
3026
3043
3027 if ctx.rev() is None:
3044 if ctx.rev() is None:
3028 ctx = repo[None]
3045 ctx = repo[None]
3029 parents = ctx.parents()
3046 parents = ctx.parents()
3030 taglist = []
3047 taglist = []
3031 for p in parents:
3048 for p in parents:
3032 taglist.extend(p.tags())
3049 taglist.extend(p.tags())
3033
3050
3034 dirty = ""
3051 dirty = ""
3035 if ctx.dirty(missing=True, merge=False, branch=False):
3052 if ctx.dirty(missing=True, merge=False, branch=False):
3036 dirty = '+'
3053 dirty = '+'
3037 fm.data(dirty=dirty)
3054 fm.data(dirty=dirty)
3038
3055
3039 hexoutput = [hexfunc(p.node()) for p in parents]
3056 hexoutput = [hexfunc(p.node()) for p in parents]
3040 if default or id:
3057 if default or id:
3041 output = ["%s%s" % ('+'.join(hexoutput), dirty)]
3058 output = ["%s%s" % ('+'.join(hexoutput), dirty)]
3042 fm.data(id="%s%s" % ('+'.join(hexoutput), dirty))
3059 fm.data(id="%s%s" % ('+'.join(hexoutput), dirty))
3043
3060
3044 if num:
3061 if num:
3045 numoutput = ["%d" % p.rev() for p in parents]
3062 numoutput = ["%d" % p.rev() for p in parents]
3046 output.append("%s%s" % ('+'.join(numoutput), dirty))
3063 output.append("%s%s" % ('+'.join(numoutput), dirty))
3047
3064
3048 fn = fm.nested('parents', tmpl='{rev}:{node|formatnode}', sep=' ')
3065 fn = fm.nested('parents', tmpl='{rev}:{node|formatnode}', sep=' ')
3049 for p in parents:
3066 for p in parents:
3050 fn.startitem()
3067 fn.startitem()
3051 fn.data(rev=p.rev())
3068 fn.data(rev=p.rev())
3052 fn.data(node=p.hex())
3069 fn.data(node=p.hex())
3053 fn.context(ctx=p)
3070 fn.context(ctx=p)
3054 fn.end()
3071 fn.end()
3055 else:
3072 else:
3056 hexoutput = hexfunc(ctx.node())
3073 hexoutput = hexfunc(ctx.node())
3057 if default or id:
3074 if default or id:
3058 output = [hexoutput]
3075 output = [hexoutput]
3059 fm.data(id=hexoutput)
3076 fm.data(id=hexoutput)
3060
3077
3061 if num:
3078 if num:
3062 output.append(pycompat.bytestr(ctx.rev()))
3079 output.append(pycompat.bytestr(ctx.rev()))
3063 taglist = ctx.tags()
3080 taglist = ctx.tags()
3064
3081
3065 if default and not ui.quiet:
3082 if default and not ui.quiet:
3066 b = ctx.branch()
3083 b = ctx.branch()
3067 if b != 'default':
3084 if b != 'default':
3068 output.append("(%s)" % b)
3085 output.append("(%s)" % b)
3069
3086
3070 # multiple tags for a single parent separated by '/'
3087 # multiple tags for a single parent separated by '/'
3071 t = '/'.join(taglist)
3088 t = '/'.join(taglist)
3072 if t:
3089 if t:
3073 output.append(t)
3090 output.append(t)
3074
3091
3075 # multiple bookmarks for a single parent separated by '/'
3092 # multiple bookmarks for a single parent separated by '/'
3076 bm = '/'.join(ctx.bookmarks())
3093 bm = '/'.join(ctx.bookmarks())
3077 if bm:
3094 if bm:
3078 output.append(bm)
3095 output.append(bm)
3079 else:
3096 else:
3080 if branch:
3097 if branch:
3081 output.append(ctx.branch())
3098 output.append(ctx.branch())
3082
3099
3083 if tags:
3100 if tags:
3084 output.extend(taglist)
3101 output.extend(taglist)
3085
3102
3086 if bookmarks:
3103 if bookmarks:
3087 output.extend(ctx.bookmarks())
3104 output.extend(ctx.bookmarks())
3088
3105
3089 fm.data(node=ctx.hex())
3106 fm.data(node=ctx.hex())
3090 fm.data(branch=ctx.branch())
3107 fm.data(branch=ctx.branch())
3091 fm.data(tags=fm.formatlist(taglist, name='tag', sep=':'))
3108 fm.data(tags=fm.formatlist(taglist, name='tag', sep=':'))
3092 fm.data(bookmarks=fm.formatlist(ctx.bookmarks(), name='bookmark'))
3109 fm.data(bookmarks=fm.formatlist(ctx.bookmarks(), name='bookmark'))
3093 fm.context(ctx=ctx)
3110 fm.context(ctx=ctx)
3094
3111
3095 fm.plain("%s\n" % ' '.join(output))
3112 fm.plain("%s\n" % ' '.join(output))
3096 fm.end()
3113 fm.end()
3097
3114
3098 @command('import|patch',
3115 @command('import|patch',
3099 [('p', 'strip', 1,
3116 [('p', 'strip', 1,
3100 _('directory strip option for patch. This has the same '
3117 _('directory strip option for patch. This has the same '
3101 'meaning as the corresponding patch option'), _('NUM')),
3118 'meaning as the corresponding patch option'), _('NUM')),
3102 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3119 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3103 ('e', 'edit', False, _('invoke editor on commit messages')),
3120 ('e', 'edit', False, _('invoke editor on commit messages')),
3104 ('f', 'force', None,
3121 ('f', 'force', None,
3105 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3122 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3106 ('', 'no-commit', None,
3123 ('', 'no-commit', None,
3107 _("don't commit, just update the working directory")),
3124 _("don't commit, just update the working directory")),
3108 ('', 'bypass', None,
3125 ('', 'bypass', None,
3109 _("apply patch without touching the working directory")),
3126 _("apply patch without touching the working directory")),
3110 ('', 'partial', None,
3127 ('', 'partial', None,
3111 _('commit even if some hunks fail')),
3128 _('commit even if some hunks fail')),
3112 ('', 'exact', None,
3129 ('', 'exact', None,
3113 _('abort if patch would apply lossily')),
3130 _('abort if patch would apply lossily')),
3114 ('', 'prefix', '',
3131 ('', 'prefix', '',
3115 _('apply patch to subdirectory'), _('DIR')),
3132 _('apply patch to subdirectory'), _('DIR')),
3116 ('', 'import-branch', None,
3133 ('', 'import-branch', None,
3117 _('use any branch information in patch (implied by --exact)'))] +
3134 _('use any branch information in patch (implied by --exact)'))] +
3118 commitopts + commitopts2 + similarityopts,
3135 commitopts + commitopts2 + similarityopts,
3119 _('[OPTION]... PATCH...'))
3136 _('[OPTION]... PATCH...'))
3120 def import_(ui, repo, patch1=None, *patches, **opts):
3137 def import_(ui, repo, patch1=None, *patches, **opts):
3121 """import an ordered set of patches
3138 """import an ordered set of patches
3122
3139
3123 Import a list of patches and commit them individually (unless
3140 Import a list of patches and commit them individually (unless
3124 --no-commit is specified).
3141 --no-commit is specified).
3125
3142
3126 To read a patch from standard input (stdin), use "-" as the patch
3143 To read a patch from standard input (stdin), use "-" as the patch
3127 name. If a URL is specified, the patch will be downloaded from
3144 name. If a URL is specified, the patch will be downloaded from
3128 there.
3145 there.
3129
3146
3130 Import first applies changes to the working directory (unless
3147 Import first applies changes to the working directory (unless
3131 --bypass is specified), import will abort if there are outstanding
3148 --bypass is specified), import will abort if there are outstanding
3132 changes.
3149 changes.
3133
3150
3134 Use --bypass to apply and commit patches directly to the
3151 Use --bypass to apply and commit patches directly to the
3135 repository, without affecting the working directory. Without
3152 repository, without affecting the working directory. Without
3136 --exact, patches will be applied on top of the working directory
3153 --exact, patches will be applied on top of the working directory
3137 parent revision.
3154 parent revision.
3138
3155
3139 You can import a patch straight from a mail message. Even patches
3156 You can import a patch straight from a mail message. Even patches
3140 as attachments work (to use the body part, it must have type
3157 as attachments work (to use the body part, it must have type
3141 text/plain or text/x-patch). From and Subject headers of email
3158 text/plain or text/x-patch). From and Subject headers of email
3142 message are used as default committer and commit message. All
3159 message are used as default committer and commit message. All
3143 text/plain body parts before first diff are added to the commit
3160 text/plain body parts before first diff are added to the commit
3144 message.
3161 message.
3145
3162
3146 If the imported patch was generated by :hg:`export`, user and
3163 If the imported patch was generated by :hg:`export`, user and
3147 description from patch override values from message headers and
3164 description from patch override values from message headers and
3148 body. Values given on command line with -m/--message and -u/--user
3165 body. Values given on command line with -m/--message and -u/--user
3149 override these.
3166 override these.
3150
3167
3151 If --exact is specified, import will set the working directory to
3168 If --exact is specified, import will set the working directory to
3152 the parent of each patch before applying it, and will abort if the
3169 the parent of each patch before applying it, and will abort if the
3153 resulting changeset has a different ID than the one recorded in
3170 resulting changeset has a different ID than the one recorded in
3154 the patch. This will guard against various ways that portable
3171 the patch. This will guard against various ways that portable
3155 patch formats and mail systems might fail to transfer Mercurial
3172 patch formats and mail systems might fail to transfer Mercurial
3156 data or metadata. See :hg:`bundle` for lossless transmission.
3173 data or metadata. See :hg:`bundle` for lossless transmission.
3157
3174
3158 Use --partial to ensure a changeset will be created from the patch
3175 Use --partial to ensure a changeset will be created from the patch
3159 even if some hunks fail to apply. Hunks that fail to apply will be
3176 even if some hunks fail to apply. Hunks that fail to apply will be
3160 written to a <target-file>.rej file. Conflicts can then be resolved
3177 written to a <target-file>.rej file. Conflicts can then be resolved
3161 by hand before :hg:`commit --amend` is run to update the created
3178 by hand before :hg:`commit --amend` is run to update the created
3162 changeset. This flag exists to let people import patches that
3179 changeset. This flag exists to let people import patches that
3163 partially apply without losing the associated metadata (author,
3180 partially apply without losing the associated metadata (author,
3164 date, description, ...).
3181 date, description, ...).
3165
3182
3166 .. note::
3183 .. note::
3167
3184
3168 When no hunks apply cleanly, :hg:`import --partial` will create
3185 When no hunks apply cleanly, :hg:`import --partial` will create
3169 an empty changeset, importing only the patch metadata.
3186 an empty changeset, importing only the patch metadata.
3170
3187
3171 With -s/--similarity, hg will attempt to discover renames and
3188 With -s/--similarity, hg will attempt to discover renames and
3172 copies in the patch in the same way as :hg:`addremove`.
3189 copies in the patch in the same way as :hg:`addremove`.
3173
3190
3174 It is possible to use external patch programs to perform the patch
3191 It is possible to use external patch programs to perform the patch
3175 by setting the ``ui.patch`` configuration option. For the default
3192 by setting the ``ui.patch`` configuration option. For the default
3176 internal tool, the fuzz can also be configured via ``patch.fuzz``.
3193 internal tool, the fuzz can also be configured via ``patch.fuzz``.
3177 See :hg:`help config` for more information about configuration
3194 See :hg:`help config` for more information about configuration
3178 files and how to use these options.
3195 files and how to use these options.
3179
3196
3180 See :hg:`help dates` for a list of formats valid for -d/--date.
3197 See :hg:`help dates` for a list of formats valid for -d/--date.
3181
3198
3182 .. container:: verbose
3199 .. container:: verbose
3183
3200
3184 Examples:
3201 Examples:
3185
3202
3186 - import a traditional patch from a website and detect renames::
3203 - import a traditional patch from a website and detect renames::
3187
3204
3188 hg import -s 80 http://example.com/bugfix.patch
3205 hg import -s 80 http://example.com/bugfix.patch
3189
3206
3190 - import a changeset from an hgweb server::
3207 - import a changeset from an hgweb server::
3191
3208
3192 hg import https://www.mercurial-scm.org/repo/hg/rev/5ca8c111e9aa
3209 hg import https://www.mercurial-scm.org/repo/hg/rev/5ca8c111e9aa
3193
3210
3194 - import all the patches in an Unix-style mbox::
3211 - import all the patches in an Unix-style mbox::
3195
3212
3196 hg import incoming-patches.mbox
3213 hg import incoming-patches.mbox
3197
3214
3198 - import patches from stdin::
3215 - import patches from stdin::
3199
3216
3200 hg import -
3217 hg import -
3201
3218
3202 - attempt to exactly restore an exported changeset (not always
3219 - attempt to exactly restore an exported changeset (not always
3203 possible)::
3220 possible)::
3204
3221
3205 hg import --exact proposed-fix.patch
3222 hg import --exact proposed-fix.patch
3206
3223
3207 - use an external tool to apply a patch which is too fuzzy for
3224 - use an external tool to apply a patch which is too fuzzy for
3208 the default internal tool.
3225 the default internal tool.
3209
3226
3210 hg import --config ui.patch="patch --merge" fuzzy.patch
3227 hg import --config ui.patch="patch --merge" fuzzy.patch
3211
3228
3212 - change the default fuzzing from 2 to a less strict 7
3229 - change the default fuzzing from 2 to a less strict 7
3213
3230
3214 hg import --config ui.fuzz=7 fuzz.patch
3231 hg import --config ui.fuzz=7 fuzz.patch
3215
3232
3216 Returns 0 on success, 1 on partial success (see --partial).
3233 Returns 0 on success, 1 on partial success (see --partial).
3217 """
3234 """
3218
3235
3219 opts = pycompat.byteskwargs(opts)
3236 opts = pycompat.byteskwargs(opts)
3220 if not patch1:
3237 if not patch1:
3221 raise error.Abort(_('need at least one patch to import'))
3238 raise error.Abort(_('need at least one patch to import'))
3222
3239
3223 patches = (patch1,) + patches
3240 patches = (patch1,) + patches
3224
3241
3225 date = opts.get('date')
3242 date = opts.get('date')
3226 if date:
3243 if date:
3227 opts['date'] = dateutil.parsedate(date)
3244 opts['date'] = dateutil.parsedate(date)
3228
3245
3229 exact = opts.get('exact')
3246 exact = opts.get('exact')
3230 update = not opts.get('bypass')
3247 update = not opts.get('bypass')
3231 if not update and opts.get('no_commit'):
3248 if not update and opts.get('no_commit'):
3232 raise error.Abort(_('cannot use --no-commit with --bypass'))
3249 raise error.Abort(_('cannot use --no-commit with --bypass'))
3233 try:
3250 try:
3234 sim = float(opts.get('similarity') or 0)
3251 sim = float(opts.get('similarity') or 0)
3235 except ValueError:
3252 except ValueError:
3236 raise error.Abort(_('similarity must be a number'))
3253 raise error.Abort(_('similarity must be a number'))
3237 if sim < 0 or sim > 100:
3254 if sim < 0 or sim > 100:
3238 raise error.Abort(_('similarity must be between 0 and 100'))
3255 raise error.Abort(_('similarity must be between 0 and 100'))
3239 if sim and not update:
3256 if sim and not update:
3240 raise error.Abort(_('cannot use --similarity with --bypass'))
3257 raise error.Abort(_('cannot use --similarity with --bypass'))
3241 if exact:
3258 if exact:
3242 if opts.get('edit'):
3259 if opts.get('edit'):
3243 raise error.Abort(_('cannot use --exact with --edit'))
3260 raise error.Abort(_('cannot use --exact with --edit'))
3244 if opts.get('prefix'):
3261 if opts.get('prefix'):
3245 raise error.Abort(_('cannot use --exact with --prefix'))
3262 raise error.Abort(_('cannot use --exact with --prefix'))
3246
3263
3247 base = opts["base"]
3264 base = opts["base"]
3248 msgs = []
3265 msgs = []
3249 ret = 0
3266 ret = 0
3250
3267
3251 with repo.wlock():
3268 with repo.wlock():
3252 if update:
3269 if update:
3253 cmdutil.checkunfinished(repo)
3270 cmdutil.checkunfinished(repo)
3254 if (exact or not opts.get('force')):
3271 if (exact or not opts.get('force')):
3255 cmdutil.bailifchanged(repo)
3272 cmdutil.bailifchanged(repo)
3256
3273
3257 if not opts.get('no_commit'):
3274 if not opts.get('no_commit'):
3258 lock = repo.lock
3275 lock = repo.lock
3259 tr = lambda: repo.transaction('import')
3276 tr = lambda: repo.transaction('import')
3260 dsguard = util.nullcontextmanager
3277 dsguard = util.nullcontextmanager
3261 else:
3278 else:
3262 lock = util.nullcontextmanager
3279 lock = util.nullcontextmanager
3263 tr = util.nullcontextmanager
3280 tr = util.nullcontextmanager
3264 dsguard = lambda: dirstateguard.dirstateguard(repo, 'import')
3281 dsguard = lambda: dirstateguard.dirstateguard(repo, 'import')
3265 with lock(), tr(), dsguard():
3282 with lock(), tr(), dsguard():
3266 parents = repo[None].parents()
3283 parents = repo[None].parents()
3267 for patchurl in patches:
3284 for patchurl in patches:
3268 if patchurl == '-':
3285 if patchurl == '-':
3269 ui.status(_('applying patch from stdin\n'))
3286 ui.status(_('applying patch from stdin\n'))
3270 patchfile = ui.fin
3287 patchfile = ui.fin
3271 patchurl = 'stdin' # for error message
3288 patchurl = 'stdin' # for error message
3272 else:
3289 else:
3273 patchurl = os.path.join(base, patchurl)
3290 patchurl = os.path.join(base, patchurl)
3274 ui.status(_('applying %s\n') % patchurl)
3291 ui.status(_('applying %s\n') % patchurl)
3275 patchfile = hg.openpath(ui, patchurl)
3292 patchfile = hg.openpath(ui, patchurl)
3276
3293
3277 haspatch = False
3294 haspatch = False
3278 for hunk in patch.split(patchfile):
3295 for hunk in patch.split(patchfile):
3279 with patch.extract(ui, hunk) as patchdata:
3296 with patch.extract(ui, hunk) as patchdata:
3280 msg, node, rej = cmdutil.tryimportone(ui, repo,
3297 msg, node, rej = cmdutil.tryimportone(ui, repo,
3281 patchdata,
3298 patchdata,
3282 parents, opts,
3299 parents, opts,
3283 msgs, hg.clean)
3300 msgs, hg.clean)
3284 if msg:
3301 if msg:
3285 haspatch = True
3302 haspatch = True
3286 ui.note(msg + '\n')
3303 ui.note(msg + '\n')
3287 if update or exact:
3304 if update or exact:
3288 parents = repo[None].parents()
3305 parents = repo[None].parents()
3289 else:
3306 else:
3290 parents = [repo[node]]
3307 parents = [repo[node]]
3291 if rej:
3308 if rej:
3292 ui.write_err(_("patch applied partially\n"))
3309 ui.write_err(_("patch applied partially\n"))
3293 ui.write_err(_("(fix the .rej files and run "
3310 ui.write_err(_("(fix the .rej files and run "
3294 "`hg commit --amend`)\n"))
3311 "`hg commit --amend`)\n"))
3295 ret = 1
3312 ret = 1
3296 break
3313 break
3297
3314
3298 if not haspatch:
3315 if not haspatch:
3299 raise error.Abort(_('%s: no diffs found') % patchurl)
3316 raise error.Abort(_('%s: no diffs found') % patchurl)
3300
3317
3301 if msgs:
3318 if msgs:
3302 repo.savecommitmessage('\n* * *\n'.join(msgs))
3319 repo.savecommitmessage('\n* * *\n'.join(msgs))
3303 return ret
3320 return ret
3304
3321
3305 @command('incoming|in',
3322 @command('incoming|in',
3306 [('f', 'force', None,
3323 [('f', 'force', None,
3307 _('run even if remote repository is unrelated')),
3324 _('run even if remote repository is unrelated')),
3308 ('n', 'newest-first', None, _('show newest record first')),
3325 ('n', 'newest-first', None, _('show newest record first')),
3309 ('', 'bundle', '',
3326 ('', 'bundle', '',
3310 _('file to store the bundles into'), _('FILE')),
3327 _('file to store the bundles into'), _('FILE')),
3311 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3328 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3312 ('B', 'bookmarks', False, _("compare bookmarks")),
3329 ('B', 'bookmarks', False, _("compare bookmarks")),
3313 ('b', 'branch', [],
3330 ('b', 'branch', [],
3314 _('a specific branch you would like to pull'), _('BRANCH')),
3331 _('a specific branch you would like to pull'), _('BRANCH')),
3315 ] + logopts + remoteopts + subrepoopts,
3332 ] + logopts + remoteopts + subrepoopts,
3316 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3333 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3317 def incoming(ui, repo, source="default", **opts):
3334 def incoming(ui, repo, source="default", **opts):
3318 """show new changesets found in source
3335 """show new changesets found in source
3319
3336
3320 Show new changesets found in the specified path/URL or the default
3337 Show new changesets found in the specified path/URL or the default
3321 pull location. These are the changesets that would have been pulled
3338 pull location. These are the changesets that would have been pulled
3322 by :hg:`pull` at the time you issued this command.
3339 by :hg:`pull` at the time you issued this command.
3323
3340
3324 See pull for valid source format details.
3341 See pull for valid source format details.
3325
3342
3326 .. container:: verbose
3343 .. container:: verbose
3327
3344
3328 With -B/--bookmarks, the result of bookmark comparison between
3345 With -B/--bookmarks, the result of bookmark comparison between
3329 local and remote repositories is displayed. With -v/--verbose,
3346 local and remote repositories is displayed. With -v/--verbose,
3330 status is also displayed for each bookmark like below::
3347 status is also displayed for each bookmark like below::
3331
3348
3332 BM1 01234567890a added
3349 BM1 01234567890a added
3333 BM2 1234567890ab advanced
3350 BM2 1234567890ab advanced
3334 BM3 234567890abc diverged
3351 BM3 234567890abc diverged
3335 BM4 34567890abcd changed
3352 BM4 34567890abcd changed
3336
3353
3337 The action taken locally when pulling depends on the
3354 The action taken locally when pulling depends on the
3338 status of each bookmark:
3355 status of each bookmark:
3339
3356
3340 :``added``: pull will create it
3357 :``added``: pull will create it
3341 :``advanced``: pull will update it
3358 :``advanced``: pull will update it
3342 :``diverged``: pull will create a divergent bookmark
3359 :``diverged``: pull will create a divergent bookmark
3343 :``changed``: result depends on remote changesets
3360 :``changed``: result depends on remote changesets
3344
3361
3345 From the point of view of pulling behavior, bookmark
3362 From the point of view of pulling behavior, bookmark
3346 existing only in the remote repository are treated as ``added``,
3363 existing only in the remote repository are treated as ``added``,
3347 even if it is in fact locally deleted.
3364 even if it is in fact locally deleted.
3348
3365
3349 .. container:: verbose
3366 .. container:: verbose
3350
3367
3351 For remote repository, using --bundle avoids downloading the
3368 For remote repository, using --bundle avoids downloading the
3352 changesets twice if the incoming is followed by a pull.
3369 changesets twice if the incoming is followed by a pull.
3353
3370
3354 Examples:
3371 Examples:
3355
3372
3356 - show incoming changes with patches and full description::
3373 - show incoming changes with patches and full description::
3357
3374
3358 hg incoming -vp
3375 hg incoming -vp
3359
3376
3360 - show incoming changes excluding merges, store a bundle::
3377 - show incoming changes excluding merges, store a bundle::
3361
3378
3362 hg in -vpM --bundle incoming.hg
3379 hg in -vpM --bundle incoming.hg
3363 hg pull incoming.hg
3380 hg pull incoming.hg
3364
3381
3365 - briefly list changes inside a bundle::
3382 - briefly list changes inside a bundle::
3366
3383
3367 hg in changes.hg -T "{desc|firstline}\\n"
3384 hg in changes.hg -T "{desc|firstline}\\n"
3368
3385
3369 Returns 0 if there are incoming changes, 1 otherwise.
3386 Returns 0 if there are incoming changes, 1 otherwise.
3370 """
3387 """
3371 opts = pycompat.byteskwargs(opts)
3388 opts = pycompat.byteskwargs(opts)
3372 if opts.get('graph'):
3389 if opts.get('graph'):
3373 logcmdutil.checkunsupportedgraphflags([], opts)
3390 logcmdutil.checkunsupportedgraphflags([], opts)
3374 def display(other, chlist, displayer):
3391 def display(other, chlist, displayer):
3375 revdag = logcmdutil.graphrevs(other, chlist, opts)
3392 revdag = logcmdutil.graphrevs(other, chlist, opts)
3376 logcmdutil.displaygraph(ui, repo, revdag, displayer,
3393 logcmdutil.displaygraph(ui, repo, revdag, displayer,
3377 graphmod.asciiedges)
3394 graphmod.asciiedges)
3378
3395
3379 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3396 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3380 return 0
3397 return 0
3381
3398
3382 if opts.get('bundle') and opts.get('subrepos'):
3399 if opts.get('bundle') and opts.get('subrepos'):
3383 raise error.Abort(_('cannot combine --bundle and --subrepos'))
3400 raise error.Abort(_('cannot combine --bundle and --subrepos'))
3384
3401
3385 if opts.get('bookmarks'):
3402 if opts.get('bookmarks'):
3386 source, branches = hg.parseurl(ui.expandpath(source),
3403 source, branches = hg.parseurl(ui.expandpath(source),
3387 opts.get('branch'))
3404 opts.get('branch'))
3388 other = hg.peer(repo, opts, source)
3405 other = hg.peer(repo, opts, source)
3389 if 'bookmarks' not in other.listkeys('namespaces'):
3406 if 'bookmarks' not in other.listkeys('namespaces'):
3390 ui.warn(_("remote doesn't support bookmarks\n"))
3407 ui.warn(_("remote doesn't support bookmarks\n"))
3391 return 0
3408 return 0
3392 ui.pager('incoming')
3409 ui.pager('incoming')
3393 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3410 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3394 return bookmarks.incoming(ui, repo, other)
3411 return bookmarks.incoming(ui, repo, other)
3395
3412
3396 repo._subtoppath = ui.expandpath(source)
3413 repo._subtoppath = ui.expandpath(source)
3397 try:
3414 try:
3398 return hg.incoming(ui, repo, source, opts)
3415 return hg.incoming(ui, repo, source, opts)
3399 finally:
3416 finally:
3400 del repo._subtoppath
3417 del repo._subtoppath
3401
3418
3402
3419
3403 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
3420 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
3404 norepo=True)
3421 norepo=True)
3405 def init(ui, dest=".", **opts):
3422 def init(ui, dest=".", **opts):
3406 """create a new repository in the given directory
3423 """create a new repository in the given directory
3407
3424
3408 Initialize a new repository in the given directory. If the given
3425 Initialize a new repository in the given directory. If the given
3409 directory does not exist, it will be created.
3426 directory does not exist, it will be created.
3410
3427
3411 If no directory is given, the current directory is used.
3428 If no directory is given, the current directory is used.
3412
3429
3413 It is possible to specify an ``ssh://`` URL as the destination.
3430 It is possible to specify an ``ssh://`` URL as the destination.
3414 See :hg:`help urls` for more information.
3431 See :hg:`help urls` for more information.
3415
3432
3416 Returns 0 on success.
3433 Returns 0 on success.
3417 """
3434 """
3418 opts = pycompat.byteskwargs(opts)
3435 opts = pycompat.byteskwargs(opts)
3419 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3436 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3420
3437
3421 @command('locate',
3438 @command('locate',
3422 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3439 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3423 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3440 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3424 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3441 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3425 ] + walkopts,
3442 ] + walkopts,
3426 _('[OPTION]... [PATTERN]...'))
3443 _('[OPTION]... [PATTERN]...'))
3427 def locate(ui, repo, *pats, **opts):
3444 def locate(ui, repo, *pats, **opts):
3428 """locate files matching specific patterns (DEPRECATED)
3445 """locate files matching specific patterns (DEPRECATED)
3429
3446
3430 Print files under Mercurial control in the working directory whose
3447 Print files under Mercurial control in the working directory whose
3431 names match the given patterns.
3448 names match the given patterns.
3432
3449
3433 By default, this command searches all directories in the working
3450 By default, this command searches all directories in the working
3434 directory. To search just the current directory and its
3451 directory. To search just the current directory and its
3435 subdirectories, use "--include .".
3452 subdirectories, use "--include .".
3436
3453
3437 If no patterns are given to match, this command prints the names
3454 If no patterns are given to match, this command prints the names
3438 of all files under Mercurial control in the working directory.
3455 of all files under Mercurial control in the working directory.
3439
3456
3440 If you want to feed the output of this command into the "xargs"
3457 If you want to feed the output of this command into the "xargs"
3441 command, use the -0 option to both this command and "xargs". This
3458 command, use the -0 option to both this command and "xargs". This
3442 will avoid the problem of "xargs" treating single filenames that
3459 will avoid the problem of "xargs" treating single filenames that
3443 contain whitespace as multiple filenames.
3460 contain whitespace as multiple filenames.
3444
3461
3445 See :hg:`help files` for a more versatile command.
3462 See :hg:`help files` for a more versatile command.
3446
3463
3447 Returns 0 if a match is found, 1 otherwise.
3464 Returns 0 if a match is found, 1 otherwise.
3448 """
3465 """
3449 opts = pycompat.byteskwargs(opts)
3466 opts = pycompat.byteskwargs(opts)
3450 if opts.get('print0'):
3467 if opts.get('print0'):
3451 end = '\0'
3468 end = '\0'
3452 else:
3469 else:
3453 end = '\n'
3470 end = '\n'
3454 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3471 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3455
3472
3456 ret = 1
3473 ret = 1
3457 m = scmutil.match(ctx, pats, opts, default='relglob',
3474 m = scmutil.match(ctx, pats, opts, default='relglob',
3458 badfn=lambda x, y: False)
3475 badfn=lambda x, y: False)
3459
3476
3460 ui.pager('locate')
3477 ui.pager('locate')
3461 if ctx.rev() is None:
3478 if ctx.rev() is None:
3462 # When run on the working copy, "locate" includes removed files, so
3479 # When run on the working copy, "locate" includes removed files, so
3463 # we get the list of files from the dirstate.
3480 # we get the list of files from the dirstate.
3464 filesgen = sorted(repo.dirstate.matches(m))
3481 filesgen = sorted(repo.dirstate.matches(m))
3465 else:
3482 else:
3466 filesgen = ctx.matches(m)
3483 filesgen = ctx.matches(m)
3467 for abs in filesgen:
3484 for abs in filesgen:
3468 if opts.get('fullpath'):
3485 if opts.get('fullpath'):
3469 ui.write(repo.wjoin(abs), end)
3486 ui.write(repo.wjoin(abs), end)
3470 else:
3487 else:
3471 ui.write(((pats and m.rel(abs)) or abs), end)
3488 ui.write(((pats and m.rel(abs)) or abs), end)
3472 ret = 0
3489 ret = 0
3473
3490
3474 return ret
3491 return ret
3475
3492
3476 @command('^log|history',
3493 @command('^log|history',
3477 [('f', 'follow', None,
3494 [('f', 'follow', None,
3478 _('follow changeset history, or file history across copies and renames')),
3495 _('follow changeset history, or file history across copies and renames')),
3479 ('', 'follow-first', None,
3496 ('', 'follow-first', None,
3480 _('only follow the first parent of merge changesets (DEPRECATED)')),
3497 _('only follow the first parent of merge changesets (DEPRECATED)')),
3481 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3498 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3482 ('C', 'copies', None, _('show copied files')),
3499 ('C', 'copies', None, _('show copied files')),
3483 ('k', 'keyword', [],
3500 ('k', 'keyword', [],
3484 _('do case-insensitive search for a given text'), _('TEXT')),
3501 _('do case-insensitive search for a given text'), _('TEXT')),
3485 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
3502 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
3486 ('L', 'line-range', [],
3503 ('L', 'line-range', [],
3487 _('follow line range of specified file (EXPERIMENTAL)'),
3504 _('follow line range of specified file (EXPERIMENTAL)'),
3488 _('FILE,RANGE')),
3505 _('FILE,RANGE')),
3489 ('', 'removed', None, _('include revisions where files were removed')),
3506 ('', 'removed', None, _('include revisions where files were removed')),
3490 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3507 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3491 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3508 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3492 ('', 'only-branch', [],
3509 ('', 'only-branch', [],
3493 _('show only changesets within the given named branch (DEPRECATED)'),
3510 _('show only changesets within the given named branch (DEPRECATED)'),
3494 _('BRANCH')),
3511 _('BRANCH')),
3495 ('b', 'branch', [],
3512 ('b', 'branch', [],
3496 _('show changesets within the given named branch'), _('BRANCH')),
3513 _('show changesets within the given named branch'), _('BRANCH')),
3497 ('P', 'prune', [],
3514 ('P', 'prune', [],
3498 _('do not display revision or any of its ancestors'), _('REV')),
3515 _('do not display revision or any of its ancestors'), _('REV')),
3499 ] + logopts + walkopts,
3516 ] + logopts + walkopts,
3500 _('[OPTION]... [FILE]'),
3517 _('[OPTION]... [FILE]'),
3501 inferrepo=True,
3518 inferrepo=True,
3502 intents={INTENT_READONLY})
3519 intents={INTENT_READONLY})
3503 def log(ui, repo, *pats, **opts):
3520 def log(ui, repo, *pats, **opts):
3504 """show revision history of entire repository or files
3521 """show revision history of entire repository or files
3505
3522
3506 Print the revision history of the specified files or the entire
3523 Print the revision history of the specified files or the entire
3507 project.
3524 project.
3508
3525
3509 If no revision range is specified, the default is ``tip:0`` unless
3526 If no revision range is specified, the default is ``tip:0`` unless
3510 --follow is set, in which case the working directory parent is
3527 --follow is set, in which case the working directory parent is
3511 used as the starting revision.
3528 used as the starting revision.
3512
3529
3513 File history is shown without following rename or copy history of
3530 File history is shown without following rename or copy history of
3514 files. Use -f/--follow with a filename to follow history across
3531 files. Use -f/--follow with a filename to follow history across
3515 renames and copies. --follow without a filename will only show
3532 renames and copies. --follow without a filename will only show
3516 ancestors of the starting revision.
3533 ancestors of the starting revision.
3517
3534
3518 By default this command prints revision number and changeset id,
3535 By default this command prints revision number and changeset id,
3519 tags, non-trivial parents, user, date and time, and a summary for
3536 tags, non-trivial parents, user, date and time, and a summary for
3520 each commit. When the -v/--verbose switch is used, the list of
3537 each commit. When the -v/--verbose switch is used, the list of
3521 changed files and full commit message are shown.
3538 changed files and full commit message are shown.
3522
3539
3523 With --graph the revisions are shown as an ASCII art DAG with the most
3540 With --graph the revisions are shown as an ASCII art DAG with the most
3524 recent changeset at the top.
3541 recent changeset at the top.
3525 'o' is a changeset, '@' is a working directory parent, '_' closes a branch,
3542 'o' is a changeset, '@' is a working directory parent, '_' closes a branch,
3526 'x' is obsolete, '*' is unstable, and '+' represents a fork where the
3543 'x' is obsolete, '*' is unstable, and '+' represents a fork where the
3527 changeset from the lines below is a parent of the 'o' merge on the same
3544 changeset from the lines below is a parent of the 'o' merge on the same
3528 line.
3545 line.
3529 Paths in the DAG are represented with '|', '/' and so forth. ':' in place
3546 Paths in the DAG are represented with '|', '/' and so forth. ':' in place
3530 of a '|' indicates one or more revisions in a path are omitted.
3547 of a '|' indicates one or more revisions in a path are omitted.
3531
3548
3532 .. container:: verbose
3549 .. container:: verbose
3533
3550
3534 Use -L/--line-range FILE,M:N options to follow the history of lines
3551 Use -L/--line-range FILE,M:N options to follow the history of lines
3535 from M to N in FILE. With -p/--patch only diff hunks affecting
3552 from M to N in FILE. With -p/--patch only diff hunks affecting
3536 specified line range will be shown. This option requires --follow;
3553 specified line range will be shown. This option requires --follow;
3537 it can be specified multiple times. Currently, this option is not
3554 it can be specified multiple times. Currently, this option is not
3538 compatible with --graph. This option is experimental.
3555 compatible with --graph. This option is experimental.
3539
3556
3540 .. note::
3557 .. note::
3541
3558
3542 :hg:`log --patch` may generate unexpected diff output for merge
3559 :hg:`log --patch` may generate unexpected diff output for merge
3543 changesets, as it will only compare the merge changeset against
3560 changesets, as it will only compare the merge changeset against
3544 its first parent. Also, only files different from BOTH parents
3561 its first parent. Also, only files different from BOTH parents
3545 will appear in files:.
3562 will appear in files:.
3546
3563
3547 .. note::
3564 .. note::
3548
3565
3549 For performance reasons, :hg:`log FILE` may omit duplicate changes
3566 For performance reasons, :hg:`log FILE` may omit duplicate changes
3550 made on branches and will not show removals or mode changes. To
3567 made on branches and will not show removals or mode changes. To
3551 see all such changes, use the --removed switch.
3568 see all such changes, use the --removed switch.
3552
3569
3553 .. container:: verbose
3570 .. container:: verbose
3554
3571
3555 .. note::
3572 .. note::
3556
3573
3557 The history resulting from -L/--line-range options depends on diff
3574 The history resulting from -L/--line-range options depends on diff
3558 options; for instance if white-spaces are ignored, respective changes
3575 options; for instance if white-spaces are ignored, respective changes
3559 with only white-spaces in specified line range will not be listed.
3576 with only white-spaces in specified line range will not be listed.
3560
3577
3561 .. container:: verbose
3578 .. container:: verbose
3562
3579
3563 Some examples:
3580 Some examples:
3564
3581
3565 - changesets with full descriptions and file lists::
3582 - changesets with full descriptions and file lists::
3566
3583
3567 hg log -v
3584 hg log -v
3568
3585
3569 - changesets ancestral to the working directory::
3586 - changesets ancestral to the working directory::
3570
3587
3571 hg log -f
3588 hg log -f
3572
3589
3573 - last 10 commits on the current branch::
3590 - last 10 commits on the current branch::
3574
3591
3575 hg log -l 10 -b .
3592 hg log -l 10 -b .
3576
3593
3577 - changesets showing all modifications of a file, including removals::
3594 - changesets showing all modifications of a file, including removals::
3578
3595
3579 hg log --removed file.c
3596 hg log --removed file.c
3580
3597
3581 - all changesets that touch a directory, with diffs, excluding merges::
3598 - all changesets that touch a directory, with diffs, excluding merges::
3582
3599
3583 hg log -Mp lib/
3600 hg log -Mp lib/
3584
3601
3585 - all revision numbers that match a keyword::
3602 - all revision numbers that match a keyword::
3586
3603
3587 hg log -k bug --template "{rev}\\n"
3604 hg log -k bug --template "{rev}\\n"
3588
3605
3589 - the full hash identifier of the working directory parent::
3606 - the full hash identifier of the working directory parent::
3590
3607
3591 hg log -r . --template "{node}\\n"
3608 hg log -r . --template "{node}\\n"
3592
3609
3593 - list available log templates::
3610 - list available log templates::
3594
3611
3595 hg log -T list
3612 hg log -T list
3596
3613
3597 - check if a given changeset is included in a tagged release::
3614 - check if a given changeset is included in a tagged release::
3598
3615
3599 hg log -r "a21ccf and ancestor(1.9)"
3616 hg log -r "a21ccf and ancestor(1.9)"
3600
3617
3601 - find all changesets by some user in a date range::
3618 - find all changesets by some user in a date range::
3602
3619
3603 hg log -k alice -d "may 2008 to jul 2008"
3620 hg log -k alice -d "may 2008 to jul 2008"
3604
3621
3605 - summary of all changesets after the last tag::
3622 - summary of all changesets after the last tag::
3606
3623
3607 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3624 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3608
3625
3609 - changesets touching lines 13 to 23 for file.c::
3626 - changesets touching lines 13 to 23 for file.c::
3610
3627
3611 hg log -L file.c,13:23
3628 hg log -L file.c,13:23
3612
3629
3613 - changesets touching lines 13 to 23 for file.c and lines 2 to 6 of
3630 - changesets touching lines 13 to 23 for file.c and lines 2 to 6 of
3614 main.c with patch::
3631 main.c with patch::
3615
3632
3616 hg log -L file.c,13:23 -L main.c,2:6 -p
3633 hg log -L file.c,13:23 -L main.c,2:6 -p
3617
3634
3618 See :hg:`help dates` for a list of formats valid for -d/--date.
3635 See :hg:`help dates` for a list of formats valid for -d/--date.
3619
3636
3620 See :hg:`help revisions` for more about specifying and ordering
3637 See :hg:`help revisions` for more about specifying and ordering
3621 revisions.
3638 revisions.
3622
3639
3623 See :hg:`help templates` for more about pre-packaged styles and
3640 See :hg:`help templates` for more about pre-packaged styles and
3624 specifying custom templates. The default template used by the log
3641 specifying custom templates. The default template used by the log
3625 command can be customized via the ``ui.logtemplate`` configuration
3642 command can be customized via the ``ui.logtemplate`` configuration
3626 setting.
3643 setting.
3627
3644
3628 Returns 0 on success.
3645 Returns 0 on success.
3629
3646
3630 """
3647 """
3631 opts = pycompat.byteskwargs(opts)
3648 opts = pycompat.byteskwargs(opts)
3632 linerange = opts.get('line_range')
3649 linerange = opts.get('line_range')
3633
3650
3634 if linerange and not opts.get('follow'):
3651 if linerange and not opts.get('follow'):
3635 raise error.Abort(_('--line-range requires --follow'))
3652 raise error.Abort(_('--line-range requires --follow'))
3636
3653
3637 if linerange and pats:
3654 if linerange and pats:
3638 # TODO: take pats as patterns with no line-range filter
3655 # TODO: take pats as patterns with no line-range filter
3639 raise error.Abort(
3656 raise error.Abort(
3640 _('FILE arguments are not compatible with --line-range option')
3657 _('FILE arguments are not compatible with --line-range option')
3641 )
3658 )
3642
3659
3643 repo = scmutil.unhidehashlikerevs(repo, opts.get('rev'), 'nowarn')
3660 repo = scmutil.unhidehashlikerevs(repo, opts.get('rev'), 'nowarn')
3644 revs, differ = logcmdutil.getrevs(repo, pats, opts)
3661 revs, differ = logcmdutil.getrevs(repo, pats, opts)
3645 if linerange:
3662 if linerange:
3646 # TODO: should follow file history from logcmdutil._initialrevs(),
3663 # TODO: should follow file history from logcmdutil._initialrevs(),
3647 # then filter the result by logcmdutil._makerevset() and --limit
3664 # then filter the result by logcmdutil._makerevset() and --limit
3648 revs, differ = logcmdutil.getlinerangerevs(repo, revs, opts)
3665 revs, differ = logcmdutil.getlinerangerevs(repo, revs, opts)
3649
3666
3650 getrenamed = None
3667 getrenamed = None
3651 if opts.get('copies'):
3668 if opts.get('copies'):
3652 endrev = None
3669 endrev = None
3653 if revs:
3670 if revs:
3654 endrev = revs.max() + 1
3671 endrev = revs.max() + 1
3655 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3672 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3656
3673
3657 ui.pager('log')
3674 ui.pager('log')
3658 displayer = logcmdutil.changesetdisplayer(ui, repo, opts, differ,
3675 displayer = logcmdutil.changesetdisplayer(ui, repo, opts, differ,
3659 buffered=True)
3676 buffered=True)
3660 if opts.get('graph'):
3677 if opts.get('graph'):
3661 displayfn = logcmdutil.displaygraphrevs
3678 displayfn = logcmdutil.displaygraphrevs
3662 else:
3679 else:
3663 displayfn = logcmdutil.displayrevs
3680 displayfn = logcmdutil.displayrevs
3664 displayfn(ui, repo, revs, displayer, getrenamed)
3681 displayfn(ui, repo, revs, displayer, getrenamed)
3665
3682
3666 @command('manifest',
3683 @command('manifest',
3667 [('r', 'rev', '', _('revision to display'), _('REV')),
3684 [('r', 'rev', '', _('revision to display'), _('REV')),
3668 ('', 'all', False, _("list files from all revisions"))]
3685 ('', 'all', False, _("list files from all revisions"))]
3669 + formatteropts,
3686 + formatteropts,
3670 _('[-r REV]'),
3687 _('[-r REV]'),
3671 intents={INTENT_READONLY})
3688 intents={INTENT_READONLY})
3672 def manifest(ui, repo, node=None, rev=None, **opts):
3689 def manifest(ui, repo, node=None, rev=None, **opts):
3673 """output the current or given revision of the project manifest
3690 """output the current or given revision of the project manifest
3674
3691
3675 Print a list of version controlled files for the given revision.
3692 Print a list of version controlled files for the given revision.
3676 If no revision is given, the first parent of the working directory
3693 If no revision is given, the first parent of the working directory
3677 is used, or the null revision if no revision is checked out.
3694 is used, or the null revision if no revision is checked out.
3678
3695
3679 With -v, print file permissions, symlink and executable bits.
3696 With -v, print file permissions, symlink and executable bits.
3680 With --debug, print file revision hashes.
3697 With --debug, print file revision hashes.
3681
3698
3682 If option --all is specified, the list of all files from all revisions
3699 If option --all is specified, the list of all files from all revisions
3683 is printed. This includes deleted and renamed files.
3700 is printed. This includes deleted and renamed files.
3684
3701
3685 Returns 0 on success.
3702 Returns 0 on success.
3686 """
3703 """
3687 opts = pycompat.byteskwargs(opts)
3704 opts = pycompat.byteskwargs(opts)
3688 fm = ui.formatter('manifest', opts)
3705 fm = ui.formatter('manifest', opts)
3689
3706
3690 if opts.get('all'):
3707 if opts.get('all'):
3691 if rev or node:
3708 if rev or node:
3692 raise error.Abort(_("can't specify a revision with --all"))
3709 raise error.Abort(_("can't specify a revision with --all"))
3693
3710
3694 res = set()
3711 res = set()
3695 for rev in repo:
3712 for rev in repo:
3696 ctx = repo[rev]
3713 ctx = repo[rev]
3697 res |= set(ctx.files())
3714 res |= set(ctx.files())
3698
3715
3699 ui.pager('manifest')
3716 ui.pager('manifest')
3700 for f in sorted(res):
3717 for f in sorted(res):
3701 fm.startitem()
3718 fm.startitem()
3702 fm.write("path", '%s\n', f)
3719 fm.write("path", '%s\n', f)
3703 fm.end()
3720 fm.end()
3704 return
3721 return
3705
3722
3706 if rev and node:
3723 if rev and node:
3707 raise error.Abort(_("please specify just one revision"))
3724 raise error.Abort(_("please specify just one revision"))
3708
3725
3709 if not node:
3726 if not node:
3710 node = rev
3727 node = rev
3711
3728
3712 char = {'l': '@', 'x': '*', '': '', 't': 'd'}
3729 char = {'l': '@', 'x': '*', '': '', 't': 'd'}
3713 mode = {'l': '644', 'x': '755', '': '644', 't': '755'}
3730 mode = {'l': '644', 'x': '755', '': '644', 't': '755'}
3714 if node:
3731 if node:
3715 repo = scmutil.unhidehashlikerevs(repo, [node], 'nowarn')
3732 repo = scmutil.unhidehashlikerevs(repo, [node], 'nowarn')
3716 ctx = scmutil.revsingle(repo, node)
3733 ctx = scmutil.revsingle(repo, node)
3717 mf = ctx.manifest()
3734 mf = ctx.manifest()
3718 ui.pager('manifest')
3735 ui.pager('manifest')
3719 for f in ctx:
3736 for f in ctx:
3720 fm.startitem()
3737 fm.startitem()
3721 fm.context(ctx=ctx)
3738 fm.context(ctx=ctx)
3722 fl = ctx[f].flags()
3739 fl = ctx[f].flags()
3723 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
3740 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
3724 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
3741 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
3725 fm.write('path', '%s\n', f)
3742 fm.write('path', '%s\n', f)
3726 fm.end()
3743 fm.end()
3727
3744
3728 @command('^merge',
3745 @command('^merge',
3729 [('f', 'force', None,
3746 [('f', 'force', None,
3730 _('force a merge including outstanding changes (DEPRECATED)')),
3747 _('force a merge including outstanding changes (DEPRECATED)')),
3731 ('r', 'rev', '', _('revision to merge'), _('REV')),
3748 ('r', 'rev', '', _('revision to merge'), _('REV')),
3732 ('P', 'preview', None,
3749 ('P', 'preview', None,
3733 _('review revisions to merge (no merge is performed)')),
3750 _('review revisions to merge (no merge is performed)')),
3734 ('', 'abort', None, _('abort the ongoing merge')),
3751 ('', 'abort', None, _('abort the ongoing merge')),
3735 ] + mergetoolopts,
3752 ] + mergetoolopts,
3736 _('[-P] [[-r] REV]'))
3753 _('[-P] [[-r] REV]'))
3737 def merge(ui, repo, node=None, **opts):
3754 def merge(ui, repo, node=None, **opts):
3738 """merge another revision into working directory
3755 """merge another revision into working directory
3739
3756
3740 The current working directory is updated with all changes made in
3757 The current working directory is updated with all changes made in
3741 the requested revision since the last common predecessor revision.
3758 the requested revision since the last common predecessor revision.
3742
3759
3743 Files that changed between either parent are marked as changed for
3760 Files that changed between either parent are marked as changed for
3744 the next commit and a commit must be performed before any further
3761 the next commit and a commit must be performed before any further
3745 updates to the repository are allowed. The next commit will have
3762 updates to the repository are allowed. The next commit will have
3746 two parents.
3763 two parents.
3747
3764
3748 ``--tool`` can be used to specify the merge tool used for file
3765 ``--tool`` can be used to specify the merge tool used for file
3749 merges. It overrides the HGMERGE environment variable and your
3766 merges. It overrides the HGMERGE environment variable and your
3750 configuration files. See :hg:`help merge-tools` for options.
3767 configuration files. See :hg:`help merge-tools` for options.
3751
3768
3752 If no revision is specified, the working directory's parent is a
3769 If no revision is specified, the working directory's parent is a
3753 head revision, and the current branch contains exactly one other
3770 head revision, and the current branch contains exactly one other
3754 head, the other head is merged with by default. Otherwise, an
3771 head, the other head is merged with by default. Otherwise, an
3755 explicit revision with which to merge with must be provided.
3772 explicit revision with which to merge with must be provided.
3756
3773
3757 See :hg:`help resolve` for information on handling file conflicts.
3774 See :hg:`help resolve` for information on handling file conflicts.
3758
3775
3759 To undo an uncommitted merge, use :hg:`merge --abort` which
3776 To undo an uncommitted merge, use :hg:`merge --abort` which
3760 will check out a clean copy of the original merge parent, losing
3777 will check out a clean copy of the original merge parent, losing
3761 all changes.
3778 all changes.
3762
3779
3763 Returns 0 on success, 1 if there are unresolved files.
3780 Returns 0 on success, 1 if there are unresolved files.
3764 """
3781 """
3765
3782
3766 opts = pycompat.byteskwargs(opts)
3783 opts = pycompat.byteskwargs(opts)
3767 abort = opts.get('abort')
3784 abort = opts.get('abort')
3768 if abort and repo.dirstate.p2() == nullid:
3785 if abort and repo.dirstate.p2() == nullid:
3769 cmdutil.wrongtooltocontinue(repo, _('merge'))
3786 cmdutil.wrongtooltocontinue(repo, _('merge'))
3770 if abort:
3787 if abort:
3771 if node:
3788 if node:
3772 raise error.Abort(_("cannot specify a node with --abort"))
3789 raise error.Abort(_("cannot specify a node with --abort"))
3773 if opts.get('rev'):
3790 if opts.get('rev'):
3774 raise error.Abort(_("cannot specify both --rev and --abort"))
3791 raise error.Abort(_("cannot specify both --rev and --abort"))
3775 if opts.get('preview'):
3792 if opts.get('preview'):
3776 raise error.Abort(_("cannot specify --preview with --abort"))
3793 raise error.Abort(_("cannot specify --preview with --abort"))
3777 if opts.get('rev') and node:
3794 if opts.get('rev') and node:
3778 raise error.Abort(_("please specify just one revision"))
3795 raise error.Abort(_("please specify just one revision"))
3779 if not node:
3796 if not node:
3780 node = opts.get('rev')
3797 node = opts.get('rev')
3781
3798
3782 if node:
3799 if node:
3783 node = scmutil.revsingle(repo, node).node()
3800 node = scmutil.revsingle(repo, node).node()
3784
3801
3785 if not node and not abort:
3802 if not node and not abort:
3786 node = repo[destutil.destmerge(repo)].node()
3803 node = repo[destutil.destmerge(repo)].node()
3787
3804
3788 if opts.get('preview'):
3805 if opts.get('preview'):
3789 # find nodes that are ancestors of p2 but not of p1
3806 # find nodes that are ancestors of p2 but not of p1
3790 p1 = repo.lookup('.')
3807 p1 = repo.lookup('.')
3791 p2 = node
3808 p2 = node
3792 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
3809 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
3793
3810
3794 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
3811 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
3795 for node in nodes:
3812 for node in nodes:
3796 displayer.show(repo[node])
3813 displayer.show(repo[node])
3797 displayer.close()
3814 displayer.close()
3798 return 0
3815 return 0
3799
3816
3800 # ui.forcemerge is an internal variable, do not document
3817 # ui.forcemerge is an internal variable, do not document
3801 overrides = {('ui', 'forcemerge'): opts.get('tool', '')}
3818 overrides = {('ui', 'forcemerge'): opts.get('tool', '')}
3802 with ui.configoverride(overrides, 'merge'):
3819 with ui.configoverride(overrides, 'merge'):
3803 force = opts.get('force')
3820 force = opts.get('force')
3804 labels = ['working copy', 'merge rev']
3821 labels = ['working copy', 'merge rev']
3805 return hg.merge(repo, node, force=force, mergeforce=force,
3822 return hg.merge(repo, node, force=force, mergeforce=force,
3806 labels=labels, abort=abort)
3823 labels=labels, abort=abort)
3807
3824
3808 @command('outgoing|out',
3825 @command('outgoing|out',
3809 [('f', 'force', None, _('run even when the destination is unrelated')),
3826 [('f', 'force', None, _('run even when the destination is unrelated')),
3810 ('r', 'rev', [],
3827 ('r', 'rev', [],
3811 _('a changeset intended to be included in the destination'), _('REV')),
3828 _('a changeset intended to be included in the destination'), _('REV')),
3812 ('n', 'newest-first', None, _('show newest record first')),
3829 ('n', 'newest-first', None, _('show newest record first')),
3813 ('B', 'bookmarks', False, _('compare bookmarks')),
3830 ('B', 'bookmarks', False, _('compare bookmarks')),
3814 ('b', 'branch', [], _('a specific branch you would like to push'),
3831 ('b', 'branch', [], _('a specific branch you would like to push'),
3815 _('BRANCH')),
3832 _('BRANCH')),
3816 ] + logopts + remoteopts + subrepoopts,
3833 ] + logopts + remoteopts + subrepoopts,
3817 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
3834 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
3818 def outgoing(ui, repo, dest=None, **opts):
3835 def outgoing(ui, repo, dest=None, **opts):
3819 """show changesets not found in the destination
3836 """show changesets not found in the destination
3820
3837
3821 Show changesets not found in the specified destination repository
3838 Show changesets not found in the specified destination repository
3822 or the default push location. These are the changesets that would
3839 or the default push location. These are the changesets that would
3823 be pushed if a push was requested.
3840 be pushed if a push was requested.
3824
3841
3825 See pull for details of valid destination formats.
3842 See pull for details of valid destination formats.
3826
3843
3827 .. container:: verbose
3844 .. container:: verbose
3828
3845
3829 With -B/--bookmarks, the result of bookmark comparison between
3846 With -B/--bookmarks, the result of bookmark comparison between
3830 local and remote repositories is displayed. With -v/--verbose,
3847 local and remote repositories is displayed. With -v/--verbose,
3831 status is also displayed for each bookmark like below::
3848 status is also displayed for each bookmark like below::
3832
3849
3833 BM1 01234567890a added
3850 BM1 01234567890a added
3834 BM2 deleted
3851 BM2 deleted
3835 BM3 234567890abc advanced
3852 BM3 234567890abc advanced
3836 BM4 34567890abcd diverged
3853 BM4 34567890abcd diverged
3837 BM5 4567890abcde changed
3854 BM5 4567890abcde changed
3838
3855
3839 The action taken when pushing depends on the
3856 The action taken when pushing depends on the
3840 status of each bookmark:
3857 status of each bookmark:
3841
3858
3842 :``added``: push with ``-B`` will create it
3859 :``added``: push with ``-B`` will create it
3843 :``deleted``: push with ``-B`` will delete it
3860 :``deleted``: push with ``-B`` will delete it
3844 :``advanced``: push will update it
3861 :``advanced``: push will update it
3845 :``diverged``: push with ``-B`` will update it
3862 :``diverged``: push with ``-B`` will update it
3846 :``changed``: push with ``-B`` will update it
3863 :``changed``: push with ``-B`` will update it
3847
3864
3848 From the point of view of pushing behavior, bookmarks
3865 From the point of view of pushing behavior, bookmarks
3849 existing only in the remote repository are treated as
3866 existing only in the remote repository are treated as
3850 ``deleted``, even if it is in fact added remotely.
3867 ``deleted``, even if it is in fact added remotely.
3851
3868
3852 Returns 0 if there are outgoing changes, 1 otherwise.
3869 Returns 0 if there are outgoing changes, 1 otherwise.
3853 """
3870 """
3854 # hg._outgoing() needs to re-resolve the path in order to handle #branch
3871 # hg._outgoing() needs to re-resolve the path in order to handle #branch
3855 # style URLs, so don't overwrite dest.
3872 # style URLs, so don't overwrite dest.
3856 path = ui.paths.getpath(dest, default=('default-push', 'default'))
3873 path = ui.paths.getpath(dest, default=('default-push', 'default'))
3857 if not path:
3874 if not path:
3858 raise error.Abort(_('default repository not configured!'),
3875 raise error.Abort(_('default repository not configured!'),
3859 hint=_("see 'hg help config.paths'"))
3876 hint=_("see 'hg help config.paths'"))
3860
3877
3861 opts = pycompat.byteskwargs(opts)
3878 opts = pycompat.byteskwargs(opts)
3862 if opts.get('graph'):
3879 if opts.get('graph'):
3863 logcmdutil.checkunsupportedgraphflags([], opts)
3880 logcmdutil.checkunsupportedgraphflags([], opts)
3864 o, other = hg._outgoing(ui, repo, dest, opts)
3881 o, other = hg._outgoing(ui, repo, dest, opts)
3865 if not o:
3882 if not o:
3866 cmdutil.outgoinghooks(ui, repo, other, opts, o)
3883 cmdutil.outgoinghooks(ui, repo, other, opts, o)
3867 return
3884 return
3868
3885
3869 revdag = logcmdutil.graphrevs(repo, o, opts)
3886 revdag = logcmdutil.graphrevs(repo, o, opts)
3870 ui.pager('outgoing')
3887 ui.pager('outgoing')
3871 displayer = logcmdutil.changesetdisplayer(ui, repo, opts, buffered=True)
3888 displayer = logcmdutil.changesetdisplayer(ui, repo, opts, buffered=True)
3872 logcmdutil.displaygraph(ui, repo, revdag, displayer,
3889 logcmdutil.displaygraph(ui, repo, revdag, displayer,
3873 graphmod.asciiedges)
3890 graphmod.asciiedges)
3874 cmdutil.outgoinghooks(ui, repo, other, opts, o)
3891 cmdutil.outgoinghooks(ui, repo, other, opts, o)
3875 return 0
3892 return 0
3876
3893
3877 if opts.get('bookmarks'):
3894 if opts.get('bookmarks'):
3878 dest = path.pushloc or path.loc
3895 dest = path.pushloc or path.loc
3879 other = hg.peer(repo, opts, dest)
3896 other = hg.peer(repo, opts, dest)
3880 if 'bookmarks' not in other.listkeys('namespaces'):
3897 if 'bookmarks' not in other.listkeys('namespaces'):
3881 ui.warn(_("remote doesn't support bookmarks\n"))
3898 ui.warn(_("remote doesn't support bookmarks\n"))
3882 return 0
3899 return 0
3883 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
3900 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
3884 ui.pager('outgoing')
3901 ui.pager('outgoing')
3885 return bookmarks.outgoing(ui, repo, other)
3902 return bookmarks.outgoing(ui, repo, other)
3886
3903
3887 repo._subtoppath = path.pushloc or path.loc
3904 repo._subtoppath = path.pushloc or path.loc
3888 try:
3905 try:
3889 return hg.outgoing(ui, repo, dest, opts)
3906 return hg.outgoing(ui, repo, dest, opts)
3890 finally:
3907 finally:
3891 del repo._subtoppath
3908 del repo._subtoppath
3892
3909
3893 @command('parents',
3910 @command('parents',
3894 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
3911 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
3895 ] + templateopts,
3912 ] + templateopts,
3896 _('[-r REV] [FILE]'),
3913 _('[-r REV] [FILE]'),
3897 inferrepo=True)
3914 inferrepo=True)
3898 def parents(ui, repo, file_=None, **opts):
3915 def parents(ui, repo, file_=None, **opts):
3899 """show the parents of the working directory or revision (DEPRECATED)
3916 """show the parents of the working directory or revision (DEPRECATED)
3900
3917
3901 Print the working directory's parent revisions. If a revision is
3918 Print the working directory's parent revisions. If a revision is
3902 given via -r/--rev, the parent of that revision will be printed.
3919 given via -r/--rev, the parent of that revision will be printed.
3903 If a file argument is given, the revision in which the file was
3920 If a file argument is given, the revision in which the file was
3904 last changed (before the working directory revision or the
3921 last changed (before the working directory revision or the
3905 argument to --rev if given) is printed.
3922 argument to --rev if given) is printed.
3906
3923
3907 This command is equivalent to::
3924 This command is equivalent to::
3908
3925
3909 hg log -r "p1()+p2()" or
3926 hg log -r "p1()+p2()" or
3910 hg log -r "p1(REV)+p2(REV)" or
3927 hg log -r "p1(REV)+p2(REV)" or
3911 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
3928 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
3912 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
3929 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
3913
3930
3914 See :hg:`summary` and :hg:`help revsets` for related information.
3931 See :hg:`summary` and :hg:`help revsets` for related information.
3915
3932
3916 Returns 0 on success.
3933 Returns 0 on success.
3917 """
3934 """
3918
3935
3919 opts = pycompat.byteskwargs(opts)
3936 opts = pycompat.byteskwargs(opts)
3920 rev = opts.get('rev')
3937 rev = opts.get('rev')
3921 if rev:
3938 if rev:
3922 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
3939 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
3923 ctx = scmutil.revsingle(repo, rev, None)
3940 ctx = scmutil.revsingle(repo, rev, None)
3924
3941
3925 if file_:
3942 if file_:
3926 m = scmutil.match(ctx, (file_,), opts)
3943 m = scmutil.match(ctx, (file_,), opts)
3927 if m.anypats() or len(m.files()) != 1:
3944 if m.anypats() or len(m.files()) != 1:
3928 raise error.Abort(_('can only specify an explicit filename'))
3945 raise error.Abort(_('can only specify an explicit filename'))
3929 file_ = m.files()[0]
3946 file_ = m.files()[0]
3930 filenodes = []
3947 filenodes = []
3931 for cp in ctx.parents():
3948 for cp in ctx.parents():
3932 if not cp:
3949 if not cp:
3933 continue
3950 continue
3934 try:
3951 try:
3935 filenodes.append(cp.filenode(file_))
3952 filenodes.append(cp.filenode(file_))
3936 except error.LookupError:
3953 except error.LookupError:
3937 pass
3954 pass
3938 if not filenodes:
3955 if not filenodes:
3939 raise error.Abort(_("'%s' not found in manifest!") % file_)
3956 raise error.Abort(_("'%s' not found in manifest!") % file_)
3940 p = []
3957 p = []
3941 for fn in filenodes:
3958 for fn in filenodes:
3942 fctx = repo.filectx(file_, fileid=fn)
3959 fctx = repo.filectx(file_, fileid=fn)
3943 p.append(fctx.node())
3960 p.append(fctx.node())
3944 else:
3961 else:
3945 p = [cp.node() for cp in ctx.parents()]
3962 p = [cp.node() for cp in ctx.parents()]
3946
3963
3947 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
3964 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
3948 for n in p:
3965 for n in p:
3949 if n != nullid:
3966 if n != nullid:
3950 displayer.show(repo[n])
3967 displayer.show(repo[n])
3951 displayer.close()
3968 displayer.close()
3952
3969
3953 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True,
3970 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True,
3954 intents={INTENT_READONLY})
3971 intents={INTENT_READONLY})
3955 def paths(ui, repo, search=None, **opts):
3972 def paths(ui, repo, search=None, **opts):
3956 """show aliases for remote repositories
3973 """show aliases for remote repositories
3957
3974
3958 Show definition of symbolic path name NAME. If no name is given,
3975 Show definition of symbolic path name NAME. If no name is given,
3959 show definition of all available names.
3976 show definition of all available names.
3960
3977
3961 Option -q/--quiet suppresses all output when searching for NAME
3978 Option -q/--quiet suppresses all output when searching for NAME
3962 and shows only the path names when listing all definitions.
3979 and shows only the path names when listing all definitions.
3963
3980
3964 Path names are defined in the [paths] section of your
3981 Path names are defined in the [paths] section of your
3965 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
3982 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
3966 repository, ``.hg/hgrc`` is used, too.
3983 repository, ``.hg/hgrc`` is used, too.
3967
3984
3968 The path names ``default`` and ``default-push`` have a special
3985 The path names ``default`` and ``default-push`` have a special
3969 meaning. When performing a push or pull operation, they are used
3986 meaning. When performing a push or pull operation, they are used
3970 as fallbacks if no location is specified on the command-line.
3987 as fallbacks if no location is specified on the command-line.
3971 When ``default-push`` is set, it will be used for push and
3988 When ``default-push`` is set, it will be used for push and
3972 ``default`` will be used for pull; otherwise ``default`` is used
3989 ``default`` will be used for pull; otherwise ``default`` is used
3973 as the fallback for both. When cloning a repository, the clone
3990 as the fallback for both. When cloning a repository, the clone
3974 source is written as ``default`` in ``.hg/hgrc``.
3991 source is written as ``default`` in ``.hg/hgrc``.
3975
3992
3976 .. note::
3993 .. note::
3977
3994
3978 ``default`` and ``default-push`` apply to all inbound (e.g.
3995 ``default`` and ``default-push`` apply to all inbound (e.g.
3979 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
3996 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
3980 and :hg:`bundle`) operations.
3997 and :hg:`bundle`) operations.
3981
3998
3982 See :hg:`help urls` for more information.
3999 See :hg:`help urls` for more information.
3983
4000
3984 Returns 0 on success.
4001 Returns 0 on success.
3985 """
4002 """
3986
4003
3987 opts = pycompat.byteskwargs(opts)
4004 opts = pycompat.byteskwargs(opts)
3988 ui.pager('paths')
4005 ui.pager('paths')
3989 if search:
4006 if search:
3990 pathitems = [(name, path) for name, path in ui.paths.iteritems()
4007 pathitems = [(name, path) for name, path in ui.paths.iteritems()
3991 if name == search]
4008 if name == search]
3992 else:
4009 else:
3993 pathitems = sorted(ui.paths.iteritems())
4010 pathitems = sorted(ui.paths.iteritems())
3994
4011
3995 fm = ui.formatter('paths', opts)
4012 fm = ui.formatter('paths', opts)
3996 if fm.isplain():
4013 if fm.isplain():
3997 hidepassword = util.hidepassword
4014 hidepassword = util.hidepassword
3998 else:
4015 else:
3999 hidepassword = bytes
4016 hidepassword = bytes
4000 if ui.quiet:
4017 if ui.quiet:
4001 namefmt = '%s\n'
4018 namefmt = '%s\n'
4002 else:
4019 else:
4003 namefmt = '%s = '
4020 namefmt = '%s = '
4004 showsubopts = not search and not ui.quiet
4021 showsubopts = not search and not ui.quiet
4005
4022
4006 for name, path in pathitems:
4023 for name, path in pathitems:
4007 fm.startitem()
4024 fm.startitem()
4008 fm.condwrite(not search, 'name', namefmt, name)
4025 fm.condwrite(not search, 'name', namefmt, name)
4009 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
4026 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
4010 for subopt, value in sorted(path.suboptions.items()):
4027 for subopt, value in sorted(path.suboptions.items()):
4011 assert subopt not in ('name', 'url')
4028 assert subopt not in ('name', 'url')
4012 if showsubopts:
4029 if showsubopts:
4013 fm.plain('%s:%s = ' % (name, subopt))
4030 fm.plain('%s:%s = ' % (name, subopt))
4014 fm.condwrite(showsubopts, subopt, '%s\n', value)
4031 fm.condwrite(showsubopts, subopt, '%s\n', value)
4015
4032
4016 fm.end()
4033 fm.end()
4017
4034
4018 if search and not pathitems:
4035 if search and not pathitems:
4019 if not ui.quiet:
4036 if not ui.quiet:
4020 ui.warn(_("not found!\n"))
4037 ui.warn(_("not found!\n"))
4021 return 1
4038 return 1
4022 else:
4039 else:
4023 return 0
4040 return 0
4024
4041
4025 @command('phase',
4042 @command('phase',
4026 [('p', 'public', False, _('set changeset phase to public')),
4043 [('p', 'public', False, _('set changeset phase to public')),
4027 ('d', 'draft', False, _('set changeset phase to draft')),
4044 ('d', 'draft', False, _('set changeset phase to draft')),
4028 ('s', 'secret', False, _('set changeset phase to secret')),
4045 ('s', 'secret', False, _('set changeset phase to secret')),
4029 ('f', 'force', False, _('allow to move boundary backward')),
4046 ('f', 'force', False, _('allow to move boundary backward')),
4030 ('r', 'rev', [], _('target revision'), _('REV')),
4047 ('r', 'rev', [], _('target revision'), _('REV')),
4031 ],
4048 ],
4032 _('[-p|-d|-s] [-f] [-r] [REV...]'))
4049 _('[-p|-d|-s] [-f] [-r] [REV...]'))
4033 def phase(ui, repo, *revs, **opts):
4050 def phase(ui, repo, *revs, **opts):
4034 """set or show the current phase name
4051 """set or show the current phase name
4035
4052
4036 With no argument, show the phase name of the current revision(s).
4053 With no argument, show the phase name of the current revision(s).
4037
4054
4038 With one of -p/--public, -d/--draft or -s/--secret, change the
4055 With one of -p/--public, -d/--draft or -s/--secret, change the
4039 phase value of the specified revisions.
4056 phase value of the specified revisions.
4040
4057
4041 Unless -f/--force is specified, :hg:`phase` won't move changesets from a
4058 Unless -f/--force is specified, :hg:`phase` won't move changesets from a
4042 lower phase to a higher phase. Phases are ordered as follows::
4059 lower phase to a higher phase. Phases are ordered as follows::
4043
4060
4044 public < draft < secret
4061 public < draft < secret
4045
4062
4046 Returns 0 on success, 1 if some phases could not be changed.
4063 Returns 0 on success, 1 if some phases could not be changed.
4047
4064
4048 (For more information about the phases concept, see :hg:`help phases`.)
4065 (For more information about the phases concept, see :hg:`help phases`.)
4049 """
4066 """
4050 opts = pycompat.byteskwargs(opts)
4067 opts = pycompat.byteskwargs(opts)
4051 # search for a unique phase argument
4068 # search for a unique phase argument
4052 targetphase = None
4069 targetphase = None
4053 for idx, name in enumerate(phases.phasenames):
4070 for idx, name in enumerate(phases.phasenames):
4054 if opts.get(name, False):
4071 if opts.get(name, False):
4055 if targetphase is not None:
4072 if targetphase is not None:
4056 raise error.Abort(_('only one phase can be specified'))
4073 raise error.Abort(_('only one phase can be specified'))
4057 targetphase = idx
4074 targetphase = idx
4058
4075
4059 # look for specified revision
4076 # look for specified revision
4060 revs = list(revs)
4077 revs = list(revs)
4061 revs.extend(opts['rev'])
4078 revs.extend(opts['rev'])
4062 if not revs:
4079 if not revs:
4063 # display both parents as the second parent phase can influence
4080 # display both parents as the second parent phase can influence
4064 # the phase of a merge commit
4081 # the phase of a merge commit
4065 revs = [c.rev() for c in repo[None].parents()]
4082 revs = [c.rev() for c in repo[None].parents()]
4066
4083
4067 revs = scmutil.revrange(repo, revs)
4084 revs = scmutil.revrange(repo, revs)
4068
4085
4069 ret = 0
4086 ret = 0
4070 if targetphase is None:
4087 if targetphase is None:
4071 # display
4088 # display
4072 for r in revs:
4089 for r in revs:
4073 ctx = repo[r]
4090 ctx = repo[r]
4074 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4091 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4075 else:
4092 else:
4076 with repo.lock(), repo.transaction("phase") as tr:
4093 with repo.lock(), repo.transaction("phase") as tr:
4077 # set phase
4094 # set phase
4078 if not revs:
4095 if not revs:
4079 raise error.Abort(_('empty revision set'))
4096 raise error.Abort(_('empty revision set'))
4080 nodes = [repo[r].node() for r in revs]
4097 nodes = [repo[r].node() for r in revs]
4081 # moving revision from public to draft may hide them
4098 # moving revision from public to draft may hide them
4082 # We have to check result on an unfiltered repository
4099 # We have to check result on an unfiltered repository
4083 unfi = repo.unfiltered()
4100 unfi = repo.unfiltered()
4084 getphase = unfi._phasecache.phase
4101 getphase = unfi._phasecache.phase
4085 olddata = [getphase(unfi, r) for r in unfi]
4102 olddata = [getphase(unfi, r) for r in unfi]
4086 phases.advanceboundary(repo, tr, targetphase, nodes)
4103 phases.advanceboundary(repo, tr, targetphase, nodes)
4087 if opts['force']:
4104 if opts['force']:
4088 phases.retractboundary(repo, tr, targetphase, nodes)
4105 phases.retractboundary(repo, tr, targetphase, nodes)
4089 getphase = unfi._phasecache.phase
4106 getphase = unfi._phasecache.phase
4090 newdata = [getphase(unfi, r) for r in unfi]
4107 newdata = [getphase(unfi, r) for r in unfi]
4091 changes = sum(newdata[r] != olddata[r] for r in unfi)
4108 changes = sum(newdata[r] != olddata[r] for r in unfi)
4092 cl = unfi.changelog
4109 cl = unfi.changelog
4093 rejected = [n for n in nodes
4110 rejected = [n for n in nodes
4094 if newdata[cl.rev(n)] < targetphase]
4111 if newdata[cl.rev(n)] < targetphase]
4095 if rejected:
4112 if rejected:
4096 ui.warn(_('cannot move %i changesets to a higher '
4113 ui.warn(_('cannot move %i changesets to a higher '
4097 'phase, use --force\n') % len(rejected))
4114 'phase, use --force\n') % len(rejected))
4098 ret = 1
4115 ret = 1
4099 if changes:
4116 if changes:
4100 msg = _('phase changed for %i changesets\n') % changes
4117 msg = _('phase changed for %i changesets\n') % changes
4101 if ret:
4118 if ret:
4102 ui.status(msg)
4119 ui.status(msg)
4103 else:
4120 else:
4104 ui.note(msg)
4121 ui.note(msg)
4105 else:
4122 else:
4106 ui.warn(_('no phases changed\n'))
4123 ui.warn(_('no phases changed\n'))
4107 return ret
4124 return ret
4108
4125
4109 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
4126 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
4110 """Run after a changegroup has been added via pull/unbundle
4127 """Run after a changegroup has been added via pull/unbundle
4111
4128
4112 This takes arguments below:
4129 This takes arguments below:
4113
4130
4114 :modheads: change of heads by pull/unbundle
4131 :modheads: change of heads by pull/unbundle
4115 :optupdate: updating working directory is needed or not
4132 :optupdate: updating working directory is needed or not
4116 :checkout: update destination revision (or None to default destination)
4133 :checkout: update destination revision (or None to default destination)
4117 :brev: a name, which might be a bookmark to be activated after updating
4134 :brev: a name, which might be a bookmark to be activated after updating
4118 """
4135 """
4119 if modheads == 0:
4136 if modheads == 0:
4120 return
4137 return
4121 if optupdate:
4138 if optupdate:
4122 try:
4139 try:
4123 return hg.updatetotally(ui, repo, checkout, brev)
4140 return hg.updatetotally(ui, repo, checkout, brev)
4124 except error.UpdateAbort as inst:
4141 except error.UpdateAbort as inst:
4125 msg = _("not updating: %s") % stringutil.forcebytestr(inst)
4142 msg = _("not updating: %s") % stringutil.forcebytestr(inst)
4126 hint = inst.hint
4143 hint = inst.hint
4127 raise error.UpdateAbort(msg, hint=hint)
4144 raise error.UpdateAbort(msg, hint=hint)
4128 if modheads > 1:
4145 if modheads > 1:
4129 currentbranchheads = len(repo.branchheads())
4146 currentbranchheads = len(repo.branchheads())
4130 if currentbranchheads == modheads:
4147 if currentbranchheads == modheads:
4131 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4148 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4132 elif currentbranchheads > 1:
4149 elif currentbranchheads > 1:
4133 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4150 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4134 "merge)\n"))
4151 "merge)\n"))
4135 else:
4152 else:
4136 ui.status(_("(run 'hg heads' to see heads)\n"))
4153 ui.status(_("(run 'hg heads' to see heads)\n"))
4137 elif not ui.configbool('commands', 'update.requiredest'):
4154 elif not ui.configbool('commands', 'update.requiredest'):
4138 ui.status(_("(run 'hg update' to get a working copy)\n"))
4155 ui.status(_("(run 'hg update' to get a working copy)\n"))
4139
4156
4140 @command('^pull',
4157 @command('^pull',
4141 [('u', 'update', None,
4158 [('u', 'update', None,
4142 _('update to new branch head if new descendants were pulled')),
4159 _('update to new branch head if new descendants were pulled')),
4143 ('f', 'force', None, _('run even when remote repository is unrelated')),
4160 ('f', 'force', None, _('run even when remote repository is unrelated')),
4144 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4161 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4145 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4162 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4146 ('b', 'branch', [], _('a specific branch you would like to pull'),
4163 ('b', 'branch', [], _('a specific branch you would like to pull'),
4147 _('BRANCH')),
4164 _('BRANCH')),
4148 ] + remoteopts,
4165 ] + remoteopts,
4149 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4166 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4150 def pull(ui, repo, source="default", **opts):
4167 def pull(ui, repo, source="default", **opts):
4151 """pull changes from the specified source
4168 """pull changes from the specified source
4152
4169
4153 Pull changes from a remote repository to a local one.
4170 Pull changes from a remote repository to a local one.
4154
4171
4155 This finds all changes from the repository at the specified path
4172 This finds all changes from the repository at the specified path
4156 or URL and adds them to a local repository (the current one unless
4173 or URL and adds them to a local repository (the current one unless
4157 -R is specified). By default, this does not update the copy of the
4174 -R is specified). By default, this does not update the copy of the
4158 project in the working directory.
4175 project in the working directory.
4159
4176
4160 When cloning from servers that support it, Mercurial may fetch
4177 When cloning from servers that support it, Mercurial may fetch
4161 pre-generated data. When this is done, hooks operating on incoming
4178 pre-generated data. When this is done, hooks operating on incoming
4162 changesets and changegroups may fire more than once, once for each
4179 changesets and changegroups may fire more than once, once for each
4163 pre-generated bundle and as well as for any additional remaining
4180 pre-generated bundle and as well as for any additional remaining
4164 data. See :hg:`help -e clonebundles` for more.
4181 data. See :hg:`help -e clonebundles` for more.
4165
4182
4166 Use :hg:`incoming` if you want to see what would have been added
4183 Use :hg:`incoming` if you want to see what would have been added
4167 by a pull at the time you issued this command. If you then decide
4184 by a pull at the time you issued this command. If you then decide
4168 to add those changes to the repository, you should use :hg:`pull
4185 to add those changes to the repository, you should use :hg:`pull
4169 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4186 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4170
4187
4171 If SOURCE is omitted, the 'default' path will be used.
4188 If SOURCE is omitted, the 'default' path will be used.
4172 See :hg:`help urls` for more information.
4189 See :hg:`help urls` for more information.
4173
4190
4174 Specifying bookmark as ``.`` is equivalent to specifying the active
4191 Specifying bookmark as ``.`` is equivalent to specifying the active
4175 bookmark's name.
4192 bookmark's name.
4176
4193
4177 Returns 0 on success, 1 if an update had unresolved files.
4194 Returns 0 on success, 1 if an update had unresolved files.
4178 """
4195 """
4179
4196
4180 opts = pycompat.byteskwargs(opts)
4197 opts = pycompat.byteskwargs(opts)
4181 if ui.configbool('commands', 'update.requiredest') and opts.get('update'):
4198 if ui.configbool('commands', 'update.requiredest') and opts.get('update'):
4182 msg = _('update destination required by configuration')
4199 msg = _('update destination required by configuration')
4183 hint = _('use hg pull followed by hg update DEST')
4200 hint = _('use hg pull followed by hg update DEST')
4184 raise error.Abort(msg, hint=hint)
4201 raise error.Abort(msg, hint=hint)
4185
4202
4186 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4203 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4187 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4204 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4188 other = hg.peer(repo, opts, source)
4205 other = hg.peer(repo, opts, source)
4189 try:
4206 try:
4190 revs, checkout = hg.addbranchrevs(repo, other, branches,
4207 revs, checkout = hg.addbranchrevs(repo, other, branches,
4191 opts.get('rev'))
4208 opts.get('rev'))
4192
4209
4193
4210
4194 pullopargs = {}
4211 pullopargs = {}
4195 if opts.get('bookmark'):
4212 if opts.get('bookmark'):
4196 if not revs:
4213 if not revs:
4197 revs = []
4214 revs = []
4198 # The list of bookmark used here is not the one used to actually
4215 # The list of bookmark used here is not the one used to actually
4199 # update the bookmark name. This can result in the revision pulled
4216 # update the bookmark name. This can result in the revision pulled
4200 # not ending up with the name of the bookmark because of a race
4217 # not ending up with the name of the bookmark because of a race
4201 # condition on the server. (See issue 4689 for details)
4218 # condition on the server. (See issue 4689 for details)
4202 remotebookmarks = other.listkeys('bookmarks')
4219 remotebookmarks = other.listkeys('bookmarks')
4203 remotebookmarks = bookmarks.unhexlifybookmarks(remotebookmarks)
4220 remotebookmarks = bookmarks.unhexlifybookmarks(remotebookmarks)
4204 pullopargs['remotebookmarks'] = remotebookmarks
4221 pullopargs['remotebookmarks'] = remotebookmarks
4205 for b in opts['bookmark']:
4222 for b in opts['bookmark']:
4206 b = repo._bookmarks.expandname(b)
4223 b = repo._bookmarks.expandname(b)
4207 if b not in remotebookmarks:
4224 if b not in remotebookmarks:
4208 raise error.Abort(_('remote bookmark %s not found!') % b)
4225 raise error.Abort(_('remote bookmark %s not found!') % b)
4209 revs.append(hex(remotebookmarks[b]))
4226 revs.append(hex(remotebookmarks[b]))
4210
4227
4211 if revs:
4228 if revs:
4212 try:
4229 try:
4213 # When 'rev' is a bookmark name, we cannot guarantee that it
4230 # When 'rev' is a bookmark name, we cannot guarantee that it
4214 # will be updated with that name because of a race condition
4231 # will be updated with that name because of a race condition
4215 # server side. (See issue 4689 for details)
4232 # server side. (See issue 4689 for details)
4216 oldrevs = revs
4233 oldrevs = revs
4217 revs = [] # actually, nodes
4234 revs = [] # actually, nodes
4218 for r in oldrevs:
4235 for r in oldrevs:
4219 with other.commandexecutor() as e:
4236 with other.commandexecutor() as e:
4220 node = e.callcommand('lookup', {'key': r}).result()
4237 node = e.callcommand('lookup', {'key': r}).result()
4221
4238
4222 revs.append(node)
4239 revs.append(node)
4223 if r == checkout:
4240 if r == checkout:
4224 checkout = node
4241 checkout = node
4225 except error.CapabilityError:
4242 except error.CapabilityError:
4226 err = _("other repository doesn't support revision lookup, "
4243 err = _("other repository doesn't support revision lookup, "
4227 "so a rev cannot be specified.")
4244 "so a rev cannot be specified.")
4228 raise error.Abort(err)
4245 raise error.Abort(err)
4229
4246
4230 wlock = util.nullcontextmanager()
4247 wlock = util.nullcontextmanager()
4231 if opts.get('update'):
4248 if opts.get('update'):
4232 wlock = repo.wlock()
4249 wlock = repo.wlock()
4233 with wlock:
4250 with wlock:
4234 pullopargs.update(opts.get('opargs', {}))
4251 pullopargs.update(opts.get('opargs', {}))
4235 modheads = exchange.pull(repo, other, heads=revs,
4252 modheads = exchange.pull(repo, other, heads=revs,
4236 force=opts.get('force'),
4253 force=opts.get('force'),
4237 bookmarks=opts.get('bookmark', ()),
4254 bookmarks=opts.get('bookmark', ()),
4238 opargs=pullopargs).cgresult
4255 opargs=pullopargs).cgresult
4239
4256
4240 # brev is a name, which might be a bookmark to be activated at
4257 # brev is a name, which might be a bookmark to be activated at
4241 # the end of the update. In other words, it is an explicit
4258 # the end of the update. In other words, it is an explicit
4242 # destination of the update
4259 # destination of the update
4243 brev = None
4260 brev = None
4244
4261
4245 if checkout:
4262 if checkout:
4246 checkout = repo.changelog.rev(checkout)
4263 checkout = repo.changelog.rev(checkout)
4247
4264
4248 # order below depends on implementation of
4265 # order below depends on implementation of
4249 # hg.addbranchrevs(). opts['bookmark'] is ignored,
4266 # hg.addbranchrevs(). opts['bookmark'] is ignored,
4250 # because 'checkout' is determined without it.
4267 # because 'checkout' is determined without it.
4251 if opts.get('rev'):
4268 if opts.get('rev'):
4252 brev = opts['rev'][0]
4269 brev = opts['rev'][0]
4253 elif opts.get('branch'):
4270 elif opts.get('branch'):
4254 brev = opts['branch'][0]
4271 brev = opts['branch'][0]
4255 else:
4272 else:
4256 brev = branches[0]
4273 brev = branches[0]
4257 repo._subtoppath = source
4274 repo._subtoppath = source
4258 try:
4275 try:
4259 ret = postincoming(ui, repo, modheads, opts.get('update'),
4276 ret = postincoming(ui, repo, modheads, opts.get('update'),
4260 checkout, brev)
4277 checkout, brev)
4261
4278
4262 finally:
4279 finally:
4263 del repo._subtoppath
4280 del repo._subtoppath
4264
4281
4265 finally:
4282 finally:
4266 other.close()
4283 other.close()
4267 return ret
4284 return ret
4268
4285
4269 @command('^push',
4286 @command('^push',
4270 [('f', 'force', None, _('force push')),
4287 [('f', 'force', None, _('force push')),
4271 ('r', 'rev', [],
4288 ('r', 'rev', [],
4272 _('a changeset intended to be included in the destination'),
4289 _('a changeset intended to be included in the destination'),
4273 _('REV')),
4290 _('REV')),
4274 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4291 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4275 ('b', 'branch', [],
4292 ('b', 'branch', [],
4276 _('a specific branch you would like to push'), _('BRANCH')),
4293 _('a specific branch you would like to push'), _('BRANCH')),
4277 ('', 'new-branch', False, _('allow pushing a new branch')),
4294 ('', 'new-branch', False, _('allow pushing a new branch')),
4278 ('', 'pushvars', [], _('variables that can be sent to server (ADVANCED)')),
4295 ('', 'pushvars', [], _('variables that can be sent to server (ADVANCED)')),
4279 ] + remoteopts,
4296 ] + remoteopts,
4280 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4297 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4281 def push(ui, repo, dest=None, **opts):
4298 def push(ui, repo, dest=None, **opts):
4282 """push changes to the specified destination
4299 """push changes to the specified destination
4283
4300
4284 Push changesets from the local repository to the specified
4301 Push changesets from the local repository to the specified
4285 destination.
4302 destination.
4286
4303
4287 This operation is symmetrical to pull: it is identical to a pull
4304 This operation is symmetrical to pull: it is identical to a pull
4288 in the destination repository from the current one.
4305 in the destination repository from the current one.
4289
4306
4290 By default, push will not allow creation of new heads at the
4307 By default, push will not allow creation of new heads at the
4291 destination, since multiple heads would make it unclear which head
4308 destination, since multiple heads would make it unclear which head
4292 to use. In this situation, it is recommended to pull and merge
4309 to use. In this situation, it is recommended to pull and merge
4293 before pushing.
4310 before pushing.
4294
4311
4295 Use --new-branch if you want to allow push to create a new named
4312 Use --new-branch if you want to allow push to create a new named
4296 branch that is not present at the destination. This allows you to
4313 branch that is not present at the destination. This allows you to
4297 only create a new branch without forcing other changes.
4314 only create a new branch without forcing other changes.
4298
4315
4299 .. note::
4316 .. note::
4300
4317
4301 Extra care should be taken with the -f/--force option,
4318 Extra care should be taken with the -f/--force option,
4302 which will push all new heads on all branches, an action which will
4319 which will push all new heads on all branches, an action which will
4303 almost always cause confusion for collaborators.
4320 almost always cause confusion for collaborators.
4304
4321
4305 If -r/--rev is used, the specified revision and all its ancestors
4322 If -r/--rev is used, the specified revision and all its ancestors
4306 will be pushed to the remote repository.
4323 will be pushed to the remote repository.
4307
4324
4308 If -B/--bookmark is used, the specified bookmarked revision, its
4325 If -B/--bookmark is used, the specified bookmarked revision, its
4309 ancestors, and the bookmark will be pushed to the remote
4326 ancestors, and the bookmark will be pushed to the remote
4310 repository. Specifying ``.`` is equivalent to specifying the active
4327 repository. Specifying ``.`` is equivalent to specifying the active
4311 bookmark's name.
4328 bookmark's name.
4312
4329
4313 Please see :hg:`help urls` for important details about ``ssh://``
4330 Please see :hg:`help urls` for important details about ``ssh://``
4314 URLs. If DESTINATION is omitted, a default path will be used.
4331 URLs. If DESTINATION is omitted, a default path will be used.
4315
4332
4316 .. container:: verbose
4333 .. container:: verbose
4317
4334
4318 The --pushvars option sends strings to the server that become
4335 The --pushvars option sends strings to the server that become
4319 environment variables prepended with ``HG_USERVAR_``. For example,
4336 environment variables prepended with ``HG_USERVAR_``. For example,
4320 ``--pushvars ENABLE_FEATURE=true``, provides the server side hooks with
4337 ``--pushvars ENABLE_FEATURE=true``, provides the server side hooks with
4321 ``HG_USERVAR_ENABLE_FEATURE=true`` as part of their environment.
4338 ``HG_USERVAR_ENABLE_FEATURE=true`` as part of their environment.
4322
4339
4323 pushvars can provide for user-overridable hooks as well as set debug
4340 pushvars can provide for user-overridable hooks as well as set debug
4324 levels. One example is having a hook that blocks commits containing
4341 levels. One example is having a hook that blocks commits containing
4325 conflict markers, but enables the user to override the hook if the file
4342 conflict markers, but enables the user to override the hook if the file
4326 is using conflict markers for testing purposes or the file format has
4343 is using conflict markers for testing purposes or the file format has
4327 strings that look like conflict markers.
4344 strings that look like conflict markers.
4328
4345
4329 By default, servers will ignore `--pushvars`. To enable it add the
4346 By default, servers will ignore `--pushvars`. To enable it add the
4330 following to your configuration file::
4347 following to your configuration file::
4331
4348
4332 [push]
4349 [push]
4333 pushvars.server = true
4350 pushvars.server = true
4334
4351
4335 Returns 0 if push was successful, 1 if nothing to push.
4352 Returns 0 if push was successful, 1 if nothing to push.
4336 """
4353 """
4337
4354
4338 opts = pycompat.byteskwargs(opts)
4355 opts = pycompat.byteskwargs(opts)
4339 if opts.get('bookmark'):
4356 if opts.get('bookmark'):
4340 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
4357 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
4341 for b in opts['bookmark']:
4358 for b in opts['bookmark']:
4342 # translate -B options to -r so changesets get pushed
4359 # translate -B options to -r so changesets get pushed
4343 b = repo._bookmarks.expandname(b)
4360 b = repo._bookmarks.expandname(b)
4344 if b in repo._bookmarks:
4361 if b in repo._bookmarks:
4345 opts.setdefault('rev', []).append(b)
4362 opts.setdefault('rev', []).append(b)
4346 else:
4363 else:
4347 # if we try to push a deleted bookmark, translate it to null
4364 # if we try to push a deleted bookmark, translate it to null
4348 # this lets simultaneous -r, -b options continue working
4365 # this lets simultaneous -r, -b options continue working
4349 opts.setdefault('rev', []).append("null")
4366 opts.setdefault('rev', []).append("null")
4350
4367
4351 path = ui.paths.getpath(dest, default=('default-push', 'default'))
4368 path = ui.paths.getpath(dest, default=('default-push', 'default'))
4352 if not path:
4369 if not path:
4353 raise error.Abort(_('default repository not configured!'),
4370 raise error.Abort(_('default repository not configured!'),
4354 hint=_("see 'hg help config.paths'"))
4371 hint=_("see 'hg help config.paths'"))
4355 dest = path.pushloc or path.loc
4372 dest = path.pushloc or path.loc
4356 branches = (path.branch, opts.get('branch') or [])
4373 branches = (path.branch, opts.get('branch') or [])
4357 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4374 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4358 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4375 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4359 other = hg.peer(repo, opts, dest)
4376 other = hg.peer(repo, opts, dest)
4360
4377
4361 if revs:
4378 if revs:
4362 revs = [repo[r].node() for r in scmutil.revrange(repo, revs)]
4379 revs = [repo[r].node() for r in scmutil.revrange(repo, revs)]
4363 if not revs:
4380 if not revs:
4364 raise error.Abort(_("specified revisions evaluate to an empty set"),
4381 raise error.Abort(_("specified revisions evaluate to an empty set"),
4365 hint=_("use different revision arguments"))
4382 hint=_("use different revision arguments"))
4366 elif path.pushrev:
4383 elif path.pushrev:
4367 # It doesn't make any sense to specify ancestor revisions. So limit
4384 # It doesn't make any sense to specify ancestor revisions. So limit
4368 # to DAG heads to make discovery simpler.
4385 # to DAG heads to make discovery simpler.
4369 expr = revsetlang.formatspec('heads(%r)', path.pushrev)
4386 expr = revsetlang.formatspec('heads(%r)', path.pushrev)
4370 revs = scmutil.revrange(repo, [expr])
4387 revs = scmutil.revrange(repo, [expr])
4371 revs = [repo[rev].node() for rev in revs]
4388 revs = [repo[rev].node() for rev in revs]
4372 if not revs:
4389 if not revs:
4373 raise error.Abort(_('default push revset for path evaluates to an '
4390 raise error.Abort(_('default push revset for path evaluates to an '
4374 'empty set'))
4391 'empty set'))
4375
4392
4376 repo._subtoppath = dest
4393 repo._subtoppath = dest
4377 try:
4394 try:
4378 # push subrepos depth-first for coherent ordering
4395 # push subrepos depth-first for coherent ordering
4379 c = repo['.']
4396 c = repo['.']
4380 subs = c.substate # only repos that are committed
4397 subs = c.substate # only repos that are committed
4381 for s in sorted(subs):
4398 for s in sorted(subs):
4382 result = c.sub(s).push(opts)
4399 result = c.sub(s).push(opts)
4383 if result == 0:
4400 if result == 0:
4384 return not result
4401 return not result
4385 finally:
4402 finally:
4386 del repo._subtoppath
4403 del repo._subtoppath
4387
4404
4388 opargs = dict(opts.get('opargs', {})) # copy opargs since we may mutate it
4405 opargs = dict(opts.get('opargs', {})) # copy opargs since we may mutate it
4389 opargs.setdefault('pushvars', []).extend(opts.get('pushvars', []))
4406 opargs.setdefault('pushvars', []).extend(opts.get('pushvars', []))
4390
4407
4391 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
4408 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
4392 newbranch=opts.get('new_branch'),
4409 newbranch=opts.get('new_branch'),
4393 bookmarks=opts.get('bookmark', ()),
4410 bookmarks=opts.get('bookmark', ()),
4394 opargs=opargs)
4411 opargs=opargs)
4395
4412
4396 result = not pushop.cgresult
4413 result = not pushop.cgresult
4397
4414
4398 if pushop.bkresult is not None:
4415 if pushop.bkresult is not None:
4399 if pushop.bkresult == 2:
4416 if pushop.bkresult == 2:
4400 result = 2
4417 result = 2
4401 elif not result and pushop.bkresult:
4418 elif not result and pushop.bkresult:
4402 result = 2
4419 result = 2
4403
4420
4404 return result
4421 return result
4405
4422
4406 @command('recover', [])
4423 @command('recover', [])
4407 def recover(ui, repo):
4424 def recover(ui, repo):
4408 """roll back an interrupted transaction
4425 """roll back an interrupted transaction
4409
4426
4410 Recover from an interrupted commit or pull.
4427 Recover from an interrupted commit or pull.
4411
4428
4412 This command tries to fix the repository status after an
4429 This command tries to fix the repository status after an
4413 interrupted operation. It should only be necessary when Mercurial
4430 interrupted operation. It should only be necessary when Mercurial
4414 suggests it.
4431 suggests it.
4415
4432
4416 Returns 0 if successful, 1 if nothing to recover or verify fails.
4433 Returns 0 if successful, 1 if nothing to recover or verify fails.
4417 """
4434 """
4418 if repo.recover():
4435 if repo.recover():
4419 return hg.verify(repo)
4436 return hg.verify(repo)
4420 return 1
4437 return 1
4421
4438
4422 @command('^remove|rm',
4439 @command('^remove|rm',
4423 [('A', 'after', None, _('record delete for missing files')),
4440 [('A', 'after', None, _('record delete for missing files')),
4424 ('f', 'force', None,
4441 ('f', 'force', None,
4425 _('forget added files, delete modified files')),
4442 _('forget added files, delete modified files')),
4426 ] + subrepoopts + walkopts + dryrunopts,
4443 ] + subrepoopts + walkopts + dryrunopts,
4427 _('[OPTION]... FILE...'),
4444 _('[OPTION]... FILE...'),
4428 inferrepo=True)
4445 inferrepo=True)
4429 def remove(ui, repo, *pats, **opts):
4446 def remove(ui, repo, *pats, **opts):
4430 """remove the specified files on the next commit
4447 """remove the specified files on the next commit
4431
4448
4432 Schedule the indicated files for removal from the current branch.
4449 Schedule the indicated files for removal from the current branch.
4433
4450
4434 This command schedules the files to be removed at the next commit.
4451 This command schedules the files to be removed at the next commit.
4435 To undo a remove before that, see :hg:`revert`. To undo added
4452 To undo a remove before that, see :hg:`revert`. To undo added
4436 files, see :hg:`forget`.
4453 files, see :hg:`forget`.
4437
4454
4438 .. container:: verbose
4455 .. container:: verbose
4439
4456
4440 -A/--after can be used to remove only files that have already
4457 -A/--after can be used to remove only files that have already
4441 been deleted, -f/--force can be used to force deletion, and -Af
4458 been deleted, -f/--force can be used to force deletion, and -Af
4442 can be used to remove files from the next revision without
4459 can be used to remove files from the next revision without
4443 deleting them from the working directory.
4460 deleting them from the working directory.
4444
4461
4445 The following table details the behavior of remove for different
4462 The following table details the behavior of remove for different
4446 file states (columns) and option combinations (rows). The file
4463 file states (columns) and option combinations (rows). The file
4447 states are Added [A], Clean [C], Modified [M] and Missing [!]
4464 states are Added [A], Clean [C], Modified [M] and Missing [!]
4448 (as reported by :hg:`status`). The actions are Warn, Remove
4465 (as reported by :hg:`status`). The actions are Warn, Remove
4449 (from branch) and Delete (from disk):
4466 (from branch) and Delete (from disk):
4450
4467
4451 ========= == == == ==
4468 ========= == == == ==
4452 opt/state A C M !
4469 opt/state A C M !
4453 ========= == == == ==
4470 ========= == == == ==
4454 none W RD W R
4471 none W RD W R
4455 -f R RD RD R
4472 -f R RD RD R
4456 -A W W W R
4473 -A W W W R
4457 -Af R R R R
4474 -Af R R R R
4458 ========= == == == ==
4475 ========= == == == ==
4459
4476
4460 .. note::
4477 .. note::
4461
4478
4462 :hg:`remove` never deletes files in Added [A] state from the
4479 :hg:`remove` never deletes files in Added [A] state from the
4463 working directory, not even if ``--force`` is specified.
4480 working directory, not even if ``--force`` is specified.
4464
4481
4465 Returns 0 on success, 1 if any warnings encountered.
4482 Returns 0 on success, 1 if any warnings encountered.
4466 """
4483 """
4467
4484
4468 opts = pycompat.byteskwargs(opts)
4485 opts = pycompat.byteskwargs(opts)
4469 after, force = opts.get('after'), opts.get('force')
4486 after, force = opts.get('after'), opts.get('force')
4470 dryrun = opts.get('dry_run')
4487 dryrun = opts.get('dry_run')
4471 if not pats and not after:
4488 if not pats and not after:
4472 raise error.Abort(_('no files specified'))
4489 raise error.Abort(_('no files specified'))
4473
4490
4474 m = scmutil.match(repo[None], pats, opts)
4491 m = scmutil.match(repo[None], pats, opts)
4475 subrepos = opts.get('subrepos')
4492 subrepos = opts.get('subrepos')
4476 return cmdutil.remove(ui, repo, m, "", after, force, subrepos,
4493 return cmdutil.remove(ui, repo, m, "", after, force, subrepos,
4477 dryrun=dryrun)
4494 dryrun=dryrun)
4478
4495
4479 @command('rename|move|mv',
4496 @command('rename|move|mv',
4480 [('A', 'after', None, _('record a rename that has already occurred')),
4497 [('A', 'after', None, _('record a rename that has already occurred')),
4481 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4498 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4482 ] + walkopts + dryrunopts,
4499 ] + walkopts + dryrunopts,
4483 _('[OPTION]... SOURCE... DEST'))
4500 _('[OPTION]... SOURCE... DEST'))
4484 def rename(ui, repo, *pats, **opts):
4501 def rename(ui, repo, *pats, **opts):
4485 """rename files; equivalent of copy + remove
4502 """rename files; equivalent of copy + remove
4486
4503
4487 Mark dest as copies of sources; mark sources for deletion. If dest
4504 Mark dest as copies of sources; mark sources for deletion. If dest
4488 is a directory, copies are put in that directory. If dest is a
4505 is a directory, copies are put in that directory. If dest is a
4489 file, there can only be one source.
4506 file, there can only be one source.
4490
4507
4491 By default, this command copies the contents of files as they
4508 By default, this command copies the contents of files as they
4492 exist in the working directory. If invoked with -A/--after, the
4509 exist in the working directory. If invoked with -A/--after, the
4493 operation is recorded, but no copying is performed.
4510 operation is recorded, but no copying is performed.
4494
4511
4495 This command takes effect at the next commit. To undo a rename
4512 This command takes effect at the next commit. To undo a rename
4496 before that, see :hg:`revert`.
4513 before that, see :hg:`revert`.
4497
4514
4498 Returns 0 on success, 1 if errors are encountered.
4515 Returns 0 on success, 1 if errors are encountered.
4499 """
4516 """
4500 opts = pycompat.byteskwargs(opts)
4517 opts = pycompat.byteskwargs(opts)
4501 with repo.wlock(False):
4518 with repo.wlock(False):
4502 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4519 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4503
4520
4504 @command('resolve',
4521 @command('resolve',
4505 [('a', 'all', None, _('select all unresolved files')),
4522 [('a', 'all', None, _('select all unresolved files')),
4506 ('l', 'list', None, _('list state of files needing merge')),
4523 ('l', 'list', None, _('list state of files needing merge')),
4507 ('m', 'mark', None, _('mark files as resolved')),
4524 ('m', 'mark', None, _('mark files as resolved')),
4508 ('u', 'unmark', None, _('mark files as unresolved')),
4525 ('u', 'unmark', None, _('mark files as unresolved')),
4509 ('n', 'no-status', None, _('hide status prefix')),
4526 ('n', 'no-status', None, _('hide status prefix')),
4510 ('', 're-merge', None, _('re-merge files'))]
4527 ('', 're-merge', None, _('re-merge files'))]
4511 + mergetoolopts + walkopts + formatteropts,
4528 + mergetoolopts + walkopts + formatteropts,
4512 _('[OPTION]... [FILE]...'),
4529 _('[OPTION]... [FILE]...'),
4513 inferrepo=True)
4530 inferrepo=True)
4514 def resolve(ui, repo, *pats, **opts):
4531 def resolve(ui, repo, *pats, **opts):
4515 """redo merges or set/view the merge status of files
4532 """redo merges or set/view the merge status of files
4516
4533
4517 Merges with unresolved conflicts are often the result of
4534 Merges with unresolved conflicts are often the result of
4518 non-interactive merging using the ``internal:merge`` configuration
4535 non-interactive merging using the ``internal:merge`` configuration
4519 setting, or a command-line merge tool like ``diff3``. The resolve
4536 setting, or a command-line merge tool like ``diff3``. The resolve
4520 command is used to manage the files involved in a merge, after
4537 command is used to manage the files involved in a merge, after
4521 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4538 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4522 working directory must have two parents). See :hg:`help
4539 working directory must have two parents). See :hg:`help
4523 merge-tools` for information on configuring merge tools.
4540 merge-tools` for information on configuring merge tools.
4524
4541
4525 The resolve command can be used in the following ways:
4542 The resolve command can be used in the following ways:
4526
4543
4527 - :hg:`resolve [--re-merge] [--tool TOOL] FILE...`: attempt to re-merge
4544 - :hg:`resolve [--re-merge] [--tool TOOL] FILE...`: attempt to re-merge
4528 the specified files, discarding any previous merge attempts. Re-merging
4545 the specified files, discarding any previous merge attempts. Re-merging
4529 is not performed for files already marked as resolved. Use ``--all/-a``
4546 is not performed for files already marked as resolved. Use ``--all/-a``
4530 to select all unresolved files. ``--tool`` can be used to specify
4547 to select all unresolved files. ``--tool`` can be used to specify
4531 the merge tool used for the given files. It overrides the HGMERGE
4548 the merge tool used for the given files. It overrides the HGMERGE
4532 environment variable and your configuration files. Previous file
4549 environment variable and your configuration files. Previous file
4533 contents are saved with a ``.orig`` suffix.
4550 contents are saved with a ``.orig`` suffix.
4534
4551
4535 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4552 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4536 (e.g. after having manually fixed-up the files). The default is
4553 (e.g. after having manually fixed-up the files). The default is
4537 to mark all unresolved files.
4554 to mark all unresolved files.
4538
4555
4539 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4556 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4540 default is to mark all resolved files.
4557 default is to mark all resolved files.
4541
4558
4542 - :hg:`resolve -l`: list files which had or still have conflicts.
4559 - :hg:`resolve -l`: list files which had or still have conflicts.
4543 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4560 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4544 You can use ``set:unresolved()`` or ``set:resolved()`` to filter
4561 You can use ``set:unresolved()`` or ``set:resolved()`` to filter
4545 the list. See :hg:`help filesets` for details.
4562 the list. See :hg:`help filesets` for details.
4546
4563
4547 .. note::
4564 .. note::
4548
4565
4549 Mercurial will not let you commit files with unresolved merge
4566 Mercurial will not let you commit files with unresolved merge
4550 conflicts. You must use :hg:`resolve -m ...` before you can
4567 conflicts. You must use :hg:`resolve -m ...` before you can
4551 commit after a conflicting merge.
4568 commit after a conflicting merge.
4552
4569
4553 Returns 0 on success, 1 if any files fail a resolve attempt.
4570 Returns 0 on success, 1 if any files fail a resolve attempt.
4554 """
4571 """
4555
4572
4556 opts = pycompat.byteskwargs(opts)
4573 opts = pycompat.byteskwargs(opts)
4557 confirm = ui.configbool('commands', 'resolve.confirm')
4574 confirm = ui.configbool('commands', 'resolve.confirm')
4558 flaglist = 'all mark unmark list no_status re_merge'.split()
4575 flaglist = 'all mark unmark list no_status re_merge'.split()
4559 all, mark, unmark, show, nostatus, remerge = \
4576 all, mark, unmark, show, nostatus, remerge = \
4560 [opts.get(o) for o in flaglist]
4577 [opts.get(o) for o in flaglist]
4561
4578
4562 actioncount = len(list(filter(None, [show, mark, unmark, remerge])))
4579 actioncount = len(list(filter(None, [show, mark, unmark, remerge])))
4563 if actioncount > 1:
4580 if actioncount > 1:
4564 raise error.Abort(_("too many actions specified"))
4581 raise error.Abort(_("too many actions specified"))
4565 elif (actioncount == 0
4582 elif (actioncount == 0
4566 and ui.configbool('commands', 'resolve.explicit-re-merge')):
4583 and ui.configbool('commands', 'resolve.explicit-re-merge')):
4567 hint = _('use --mark, --unmark, --list or --re-merge')
4584 hint = _('use --mark, --unmark, --list or --re-merge')
4568 raise error.Abort(_('no action specified'), hint=hint)
4585 raise error.Abort(_('no action specified'), hint=hint)
4569 if pats and all:
4586 if pats and all:
4570 raise error.Abort(_("can't specify --all and patterns"))
4587 raise error.Abort(_("can't specify --all and patterns"))
4571 if not (all or pats or show or mark or unmark):
4588 if not (all or pats or show or mark or unmark):
4572 raise error.Abort(_('no files or directories specified'),
4589 raise error.Abort(_('no files or directories specified'),
4573 hint=('use --all to re-merge all unresolved files'))
4590 hint=('use --all to re-merge all unresolved files'))
4574
4591
4575 if confirm:
4592 if confirm:
4576 if all:
4593 if all:
4577 if ui.promptchoice(_(b're-merge all unresolved files (yn)?'
4594 if ui.promptchoice(_(b're-merge all unresolved files (yn)?'
4578 b'$$ &Yes $$ &No')):
4595 b'$$ &Yes $$ &No')):
4579 raise error.Abort(_('user quit'))
4596 raise error.Abort(_('user quit'))
4580 if mark and not pats:
4597 if mark and not pats:
4581 if ui.promptchoice(_(b'mark all unresolved files as resolved (yn)?'
4598 if ui.promptchoice(_(b'mark all unresolved files as resolved (yn)?'
4582 b'$$ &Yes $$ &No')):
4599 b'$$ &Yes $$ &No')):
4583 raise error.Abort(_('user quit'))
4600 raise error.Abort(_('user quit'))
4584 if unmark and not pats:
4601 if unmark and not pats:
4585 if ui.promptchoice(_(b'mark all resolved files as unresolved (yn)?'
4602 if ui.promptchoice(_(b'mark all resolved files as unresolved (yn)?'
4586 b'$$ &Yes $$ &No')):
4603 b'$$ &Yes $$ &No')):
4587 raise error.Abort(_('user quit'))
4604 raise error.Abort(_('user quit'))
4588
4605
4589 if show:
4606 if show:
4590 ui.pager('resolve')
4607 ui.pager('resolve')
4591 fm = ui.formatter('resolve', opts)
4608 fm = ui.formatter('resolve', opts)
4592 ms = mergemod.mergestate.read(repo)
4609 ms = mergemod.mergestate.read(repo)
4593 wctx = repo[None]
4610 wctx = repo[None]
4594 m = scmutil.match(wctx, pats, opts)
4611 m = scmutil.match(wctx, pats, opts)
4595
4612
4596 # Labels and keys based on merge state. Unresolved path conflicts show
4613 # Labels and keys based on merge state. Unresolved path conflicts show
4597 # as 'P'. Resolved path conflicts show as 'R', the same as normal
4614 # as 'P'. Resolved path conflicts show as 'R', the same as normal
4598 # resolved conflicts.
4615 # resolved conflicts.
4599 mergestateinfo = {
4616 mergestateinfo = {
4600 mergemod.MERGE_RECORD_UNRESOLVED: ('resolve.unresolved', 'U'),
4617 mergemod.MERGE_RECORD_UNRESOLVED: ('resolve.unresolved', 'U'),
4601 mergemod.MERGE_RECORD_RESOLVED: ('resolve.resolved', 'R'),
4618 mergemod.MERGE_RECORD_RESOLVED: ('resolve.resolved', 'R'),
4602 mergemod.MERGE_RECORD_UNRESOLVED_PATH: ('resolve.unresolved', 'P'),
4619 mergemod.MERGE_RECORD_UNRESOLVED_PATH: ('resolve.unresolved', 'P'),
4603 mergemod.MERGE_RECORD_RESOLVED_PATH: ('resolve.resolved', 'R'),
4620 mergemod.MERGE_RECORD_RESOLVED_PATH: ('resolve.resolved', 'R'),
4604 mergemod.MERGE_RECORD_DRIVER_RESOLVED: ('resolve.driverresolved',
4621 mergemod.MERGE_RECORD_DRIVER_RESOLVED: ('resolve.driverresolved',
4605 'D'),
4622 'D'),
4606 }
4623 }
4607
4624
4608 for f in ms:
4625 for f in ms:
4609 if not m(f):
4626 if not m(f):
4610 continue
4627 continue
4611
4628
4612 label, key = mergestateinfo[ms[f]]
4629 label, key = mergestateinfo[ms[f]]
4613 fm.startitem()
4630 fm.startitem()
4614 fm.context(ctx=wctx)
4631 fm.context(ctx=wctx)
4615 fm.condwrite(not nostatus, 'status', '%s ', key, label=label)
4632 fm.condwrite(not nostatus, 'status', '%s ', key, label=label)
4616 fm.write('path', '%s\n', f, label=label)
4633 fm.write('path', '%s\n', f, label=label)
4617 fm.end()
4634 fm.end()
4618 return 0
4635 return 0
4619
4636
4620 with repo.wlock():
4637 with repo.wlock():
4621 ms = mergemod.mergestate.read(repo)
4638 ms = mergemod.mergestate.read(repo)
4622
4639
4623 if not (ms.active() or repo.dirstate.p2() != nullid):
4640 if not (ms.active() or repo.dirstate.p2() != nullid):
4624 raise error.Abort(
4641 raise error.Abort(
4625 _('resolve command not applicable when not merging'))
4642 _('resolve command not applicable when not merging'))
4626
4643
4627 wctx = repo[None]
4644 wctx = repo[None]
4628
4645
4629 if (ms.mergedriver
4646 if (ms.mergedriver
4630 and ms.mdstate() == mergemod.MERGE_DRIVER_STATE_UNMARKED):
4647 and ms.mdstate() == mergemod.MERGE_DRIVER_STATE_UNMARKED):
4631 proceed = mergemod.driverpreprocess(repo, ms, wctx)
4648 proceed = mergemod.driverpreprocess(repo, ms, wctx)
4632 ms.commit()
4649 ms.commit()
4633 # allow mark and unmark to go through
4650 # allow mark and unmark to go through
4634 if not mark and not unmark and not proceed:
4651 if not mark and not unmark and not proceed:
4635 return 1
4652 return 1
4636
4653
4637 m = scmutil.match(wctx, pats, opts)
4654 m = scmutil.match(wctx, pats, opts)
4638 ret = 0
4655 ret = 0
4639 didwork = False
4656 didwork = False
4640 runconclude = False
4657 runconclude = False
4641
4658
4642 tocomplete = []
4659 tocomplete = []
4643 hasconflictmarkers = []
4660 hasconflictmarkers = []
4644 if mark:
4661 if mark:
4645 markcheck = ui.config('commands', 'resolve.mark-check')
4662 markcheck = ui.config('commands', 'resolve.mark-check')
4646 if markcheck not in ['warn', 'abort']:
4663 if markcheck not in ['warn', 'abort']:
4647 # Treat all invalid / unrecognized values as 'none'.
4664 # Treat all invalid / unrecognized values as 'none'.
4648 markcheck = False
4665 markcheck = False
4649 for f in ms:
4666 for f in ms:
4650 if not m(f):
4667 if not m(f):
4651 continue
4668 continue
4652
4669
4653 didwork = True
4670 didwork = True
4654
4671
4655 # don't let driver-resolved files be marked, and run the conclude
4672 # don't let driver-resolved files be marked, and run the conclude
4656 # step if asked to resolve
4673 # step if asked to resolve
4657 if ms[f] == mergemod.MERGE_RECORD_DRIVER_RESOLVED:
4674 if ms[f] == mergemod.MERGE_RECORD_DRIVER_RESOLVED:
4658 exact = m.exact(f)
4675 exact = m.exact(f)
4659 if mark:
4676 if mark:
4660 if exact:
4677 if exact:
4661 ui.warn(_('not marking %s as it is driver-resolved\n')
4678 ui.warn(_('not marking %s as it is driver-resolved\n')
4662 % f)
4679 % f)
4663 elif unmark:
4680 elif unmark:
4664 if exact:
4681 if exact:
4665 ui.warn(_('not unmarking %s as it is driver-resolved\n')
4682 ui.warn(_('not unmarking %s as it is driver-resolved\n')
4666 % f)
4683 % f)
4667 else:
4684 else:
4668 runconclude = True
4685 runconclude = True
4669 continue
4686 continue
4670
4687
4671 # path conflicts must be resolved manually
4688 # path conflicts must be resolved manually
4672 if ms[f] in (mergemod.MERGE_RECORD_UNRESOLVED_PATH,
4689 if ms[f] in (mergemod.MERGE_RECORD_UNRESOLVED_PATH,
4673 mergemod.MERGE_RECORD_RESOLVED_PATH):
4690 mergemod.MERGE_RECORD_RESOLVED_PATH):
4674 if mark:
4691 if mark:
4675 ms.mark(f, mergemod.MERGE_RECORD_RESOLVED_PATH)
4692 ms.mark(f, mergemod.MERGE_RECORD_RESOLVED_PATH)
4676 elif unmark:
4693 elif unmark:
4677 ms.mark(f, mergemod.MERGE_RECORD_UNRESOLVED_PATH)
4694 ms.mark(f, mergemod.MERGE_RECORD_UNRESOLVED_PATH)
4678 elif ms[f] == mergemod.MERGE_RECORD_UNRESOLVED_PATH:
4695 elif ms[f] == mergemod.MERGE_RECORD_UNRESOLVED_PATH:
4679 ui.warn(_('%s: path conflict must be resolved manually\n')
4696 ui.warn(_('%s: path conflict must be resolved manually\n')
4680 % f)
4697 % f)
4681 continue
4698 continue
4682
4699
4683 if mark:
4700 if mark:
4684 if markcheck:
4701 if markcheck:
4685 with repo.wvfs(f) as fobj:
4702 with repo.wvfs(f) as fobj:
4686 fdata = fobj.read()
4703 fdata = fobj.read()
4687 if filemerge.hasconflictmarkers(fdata) and \
4704 if filemerge.hasconflictmarkers(fdata) and \
4688 ms[f] != mergemod.MERGE_RECORD_RESOLVED:
4705 ms[f] != mergemod.MERGE_RECORD_RESOLVED:
4689 hasconflictmarkers.append(f)
4706 hasconflictmarkers.append(f)
4690 ms.mark(f, mergemod.MERGE_RECORD_RESOLVED)
4707 ms.mark(f, mergemod.MERGE_RECORD_RESOLVED)
4691 elif unmark:
4708 elif unmark:
4692 ms.mark(f, mergemod.MERGE_RECORD_UNRESOLVED)
4709 ms.mark(f, mergemod.MERGE_RECORD_UNRESOLVED)
4693 else:
4710 else:
4694 # backup pre-resolve (merge uses .orig for its own purposes)
4711 # backup pre-resolve (merge uses .orig for its own purposes)
4695 a = repo.wjoin(f)
4712 a = repo.wjoin(f)
4696 try:
4713 try:
4697 util.copyfile(a, a + ".resolve")
4714 util.copyfile(a, a + ".resolve")
4698 except (IOError, OSError) as inst:
4715 except (IOError, OSError) as inst:
4699 if inst.errno != errno.ENOENT:
4716 if inst.errno != errno.ENOENT:
4700 raise
4717 raise
4701
4718
4702 try:
4719 try:
4703 # preresolve file
4720 # preresolve file
4704 overrides = {('ui', 'forcemerge'): opts.get('tool', '')}
4721 overrides = {('ui', 'forcemerge'): opts.get('tool', '')}
4705 with ui.configoverride(overrides, 'resolve'):
4722 with ui.configoverride(overrides, 'resolve'):
4706 complete, r = ms.preresolve(f, wctx)
4723 complete, r = ms.preresolve(f, wctx)
4707 if not complete:
4724 if not complete:
4708 tocomplete.append(f)
4725 tocomplete.append(f)
4709 elif r:
4726 elif r:
4710 ret = 1
4727 ret = 1
4711 finally:
4728 finally:
4712 ms.commit()
4729 ms.commit()
4713
4730
4714 # replace filemerge's .orig file with our resolve file, but only
4731 # replace filemerge's .orig file with our resolve file, but only
4715 # for merges that are complete
4732 # for merges that are complete
4716 if complete:
4733 if complete:
4717 try:
4734 try:
4718 util.rename(a + ".resolve",
4735 util.rename(a + ".resolve",
4719 scmutil.origpath(ui, repo, a))
4736 scmutil.origpath(ui, repo, a))
4720 except OSError as inst:
4737 except OSError as inst:
4721 if inst.errno != errno.ENOENT:
4738 if inst.errno != errno.ENOENT:
4722 raise
4739 raise
4723
4740
4724 if hasconflictmarkers:
4741 if hasconflictmarkers:
4725 ui.warn(_('warning: the following files still have conflict '
4742 ui.warn(_('warning: the following files still have conflict '
4726 'markers:\n ') + '\n '.join(hasconflictmarkers) + '\n')
4743 'markers:\n ') + '\n '.join(hasconflictmarkers) + '\n')
4727 if markcheck == 'abort' and not all:
4744 if markcheck == 'abort' and not all:
4728 raise error.Abort(_('conflict markers detected'),
4745 raise error.Abort(_('conflict markers detected'),
4729 hint=_('use --all to mark anyway'))
4746 hint=_('use --all to mark anyway'))
4730
4747
4731 for f in tocomplete:
4748 for f in tocomplete:
4732 try:
4749 try:
4733 # resolve file
4750 # resolve file
4734 overrides = {('ui', 'forcemerge'): opts.get('tool', '')}
4751 overrides = {('ui', 'forcemerge'): opts.get('tool', '')}
4735 with ui.configoverride(overrides, 'resolve'):
4752 with ui.configoverride(overrides, 'resolve'):
4736 r = ms.resolve(f, wctx)
4753 r = ms.resolve(f, wctx)
4737 if r:
4754 if r:
4738 ret = 1
4755 ret = 1
4739 finally:
4756 finally:
4740 ms.commit()
4757 ms.commit()
4741
4758
4742 # replace filemerge's .orig file with our resolve file
4759 # replace filemerge's .orig file with our resolve file
4743 a = repo.wjoin(f)
4760 a = repo.wjoin(f)
4744 try:
4761 try:
4745 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
4762 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
4746 except OSError as inst:
4763 except OSError as inst:
4747 if inst.errno != errno.ENOENT:
4764 if inst.errno != errno.ENOENT:
4748 raise
4765 raise
4749
4766
4750 ms.commit()
4767 ms.commit()
4751 ms.recordactions()
4768 ms.recordactions()
4752
4769
4753 if not didwork and pats:
4770 if not didwork and pats:
4754 hint = None
4771 hint = None
4755 if not any([p for p in pats if p.find(':') >= 0]):
4772 if not any([p for p in pats if p.find(':') >= 0]):
4756 pats = ['path:%s' % p for p in pats]
4773 pats = ['path:%s' % p for p in pats]
4757 m = scmutil.match(wctx, pats, opts)
4774 m = scmutil.match(wctx, pats, opts)
4758 for f in ms:
4775 for f in ms:
4759 if not m(f):
4776 if not m(f):
4760 continue
4777 continue
4761 def flag(o):
4778 def flag(o):
4762 if o == 're_merge':
4779 if o == 're_merge':
4763 return '--re-merge '
4780 return '--re-merge '
4764 return '-%s ' % o[0:1]
4781 return '-%s ' % o[0:1]
4765 flags = ''.join([flag(o) for o in flaglist if opts.get(o)])
4782 flags = ''.join([flag(o) for o in flaglist if opts.get(o)])
4766 hint = _("(try: hg resolve %s%s)\n") % (
4783 hint = _("(try: hg resolve %s%s)\n") % (
4767 flags,
4784 flags,
4768 ' '.join(pats))
4785 ' '.join(pats))
4769 break
4786 break
4770 ui.warn(_("arguments do not match paths that need resolving\n"))
4787 ui.warn(_("arguments do not match paths that need resolving\n"))
4771 if hint:
4788 if hint:
4772 ui.warn(hint)
4789 ui.warn(hint)
4773 elif ms.mergedriver and ms.mdstate() != 's':
4790 elif ms.mergedriver and ms.mdstate() != 's':
4774 # run conclude step when either a driver-resolved file is requested
4791 # run conclude step when either a driver-resolved file is requested
4775 # or there are no driver-resolved files
4792 # or there are no driver-resolved files
4776 # we can't use 'ret' to determine whether any files are unresolved
4793 # we can't use 'ret' to determine whether any files are unresolved
4777 # because we might not have tried to resolve some
4794 # because we might not have tried to resolve some
4778 if ((runconclude or not list(ms.driverresolved()))
4795 if ((runconclude or not list(ms.driverresolved()))
4779 and not list(ms.unresolved())):
4796 and not list(ms.unresolved())):
4780 proceed = mergemod.driverconclude(repo, ms, wctx)
4797 proceed = mergemod.driverconclude(repo, ms, wctx)
4781 ms.commit()
4798 ms.commit()
4782 if not proceed:
4799 if not proceed:
4783 return 1
4800 return 1
4784
4801
4785 # Nudge users into finishing an unfinished operation
4802 # Nudge users into finishing an unfinished operation
4786 unresolvedf = list(ms.unresolved())
4803 unresolvedf = list(ms.unresolved())
4787 driverresolvedf = list(ms.driverresolved())
4804 driverresolvedf = list(ms.driverresolved())
4788 if not unresolvedf and not driverresolvedf:
4805 if not unresolvedf and not driverresolvedf:
4789 ui.status(_('(no more unresolved files)\n'))
4806 ui.status(_('(no more unresolved files)\n'))
4790 cmdutil.checkafterresolved(repo)
4807 cmdutil.checkafterresolved(repo)
4791 elif not unresolvedf:
4808 elif not unresolvedf:
4792 ui.status(_('(no more unresolved files -- '
4809 ui.status(_('(no more unresolved files -- '
4793 'run "hg resolve --all" to conclude)\n'))
4810 'run "hg resolve --all" to conclude)\n'))
4794
4811
4795 return ret
4812 return ret
4796
4813
4797 @command('revert',
4814 @command('revert',
4798 [('a', 'all', None, _('revert all changes when no arguments given')),
4815 [('a', 'all', None, _('revert all changes when no arguments given')),
4799 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4816 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4800 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4817 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4801 ('C', 'no-backup', None, _('do not save backup copies of files')),
4818 ('C', 'no-backup', None, _('do not save backup copies of files')),
4802 ('i', 'interactive', None, _('interactively select the changes')),
4819 ('i', 'interactive', None, _('interactively select the changes')),
4803 ] + walkopts + dryrunopts,
4820 ] + walkopts + dryrunopts,
4804 _('[OPTION]... [-r REV] [NAME]...'))
4821 _('[OPTION]... [-r REV] [NAME]...'))
4805 def revert(ui, repo, *pats, **opts):
4822 def revert(ui, repo, *pats, **opts):
4806 """restore files to their checkout state
4823 """restore files to their checkout state
4807
4824
4808 .. note::
4825 .. note::
4809
4826
4810 To check out earlier revisions, you should use :hg:`update REV`.
4827 To check out earlier revisions, you should use :hg:`update REV`.
4811 To cancel an uncommitted merge (and lose your changes),
4828 To cancel an uncommitted merge (and lose your changes),
4812 use :hg:`merge --abort`.
4829 use :hg:`merge --abort`.
4813
4830
4814 With no revision specified, revert the specified files or directories
4831 With no revision specified, revert the specified files or directories
4815 to the contents they had in the parent of the working directory.
4832 to the contents they had in the parent of the working directory.
4816 This restores the contents of files to an unmodified
4833 This restores the contents of files to an unmodified
4817 state and unschedules adds, removes, copies, and renames. If the
4834 state and unschedules adds, removes, copies, and renames. If the
4818 working directory has two parents, you must explicitly specify a
4835 working directory has two parents, you must explicitly specify a
4819 revision.
4836 revision.
4820
4837
4821 Using the -r/--rev or -d/--date options, revert the given files or
4838 Using the -r/--rev or -d/--date options, revert the given files or
4822 directories to their states as of a specific revision. Because
4839 directories to their states as of a specific revision. Because
4823 revert does not change the working directory parents, this will
4840 revert does not change the working directory parents, this will
4824 cause these files to appear modified. This can be helpful to "back
4841 cause these files to appear modified. This can be helpful to "back
4825 out" some or all of an earlier change. See :hg:`backout` for a
4842 out" some or all of an earlier change. See :hg:`backout` for a
4826 related method.
4843 related method.
4827
4844
4828 Modified files are saved with a .orig suffix before reverting.
4845 Modified files are saved with a .orig suffix before reverting.
4829 To disable these backups, use --no-backup. It is possible to store
4846 To disable these backups, use --no-backup. It is possible to store
4830 the backup files in a custom directory relative to the root of the
4847 the backup files in a custom directory relative to the root of the
4831 repository by setting the ``ui.origbackuppath`` configuration
4848 repository by setting the ``ui.origbackuppath`` configuration
4832 option.
4849 option.
4833
4850
4834 See :hg:`help dates` for a list of formats valid for -d/--date.
4851 See :hg:`help dates` for a list of formats valid for -d/--date.
4835
4852
4836 See :hg:`help backout` for a way to reverse the effect of an
4853 See :hg:`help backout` for a way to reverse the effect of an
4837 earlier changeset.
4854 earlier changeset.
4838
4855
4839 Returns 0 on success.
4856 Returns 0 on success.
4840 """
4857 """
4841
4858
4842 opts = pycompat.byteskwargs(opts)
4859 opts = pycompat.byteskwargs(opts)
4843 if opts.get("date"):
4860 if opts.get("date"):
4844 if opts.get("rev"):
4861 if opts.get("rev"):
4845 raise error.Abort(_("you can't specify a revision and a date"))
4862 raise error.Abort(_("you can't specify a revision and a date"))
4846 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4863 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4847
4864
4848 parent, p2 = repo.dirstate.parents()
4865 parent, p2 = repo.dirstate.parents()
4849 if not opts.get('rev') and p2 != nullid:
4866 if not opts.get('rev') and p2 != nullid:
4850 # revert after merge is a trap for new users (issue2915)
4867 # revert after merge is a trap for new users (issue2915)
4851 raise error.Abort(_('uncommitted merge with no revision specified'),
4868 raise error.Abort(_('uncommitted merge with no revision specified'),
4852 hint=_("use 'hg update' or see 'hg help revert'"))
4869 hint=_("use 'hg update' or see 'hg help revert'"))
4853
4870
4854 rev = opts.get('rev')
4871 rev = opts.get('rev')
4855 if rev:
4872 if rev:
4856 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
4873 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
4857 ctx = scmutil.revsingle(repo, rev)
4874 ctx = scmutil.revsingle(repo, rev)
4858
4875
4859 if (not (pats or opts.get('include') or opts.get('exclude') or
4876 if (not (pats or opts.get('include') or opts.get('exclude') or
4860 opts.get('all') or opts.get('interactive'))):
4877 opts.get('all') or opts.get('interactive'))):
4861 msg = _("no files or directories specified")
4878 msg = _("no files or directories specified")
4862 if p2 != nullid:
4879 if p2 != nullid:
4863 hint = _("uncommitted merge, use --all to discard all changes,"
4880 hint = _("uncommitted merge, use --all to discard all changes,"
4864 " or 'hg update -C .' to abort the merge")
4881 " or 'hg update -C .' to abort the merge")
4865 raise error.Abort(msg, hint=hint)
4882 raise error.Abort(msg, hint=hint)
4866 dirty = any(repo.status())
4883 dirty = any(repo.status())
4867 node = ctx.node()
4884 node = ctx.node()
4868 if node != parent:
4885 if node != parent:
4869 if dirty:
4886 if dirty:
4870 hint = _("uncommitted changes, use --all to discard all"
4887 hint = _("uncommitted changes, use --all to discard all"
4871 " changes, or 'hg update %s' to update") % ctx.rev()
4888 " changes, or 'hg update %s' to update") % ctx.rev()
4872 else:
4889 else:
4873 hint = _("use --all to revert all files,"
4890 hint = _("use --all to revert all files,"
4874 " or 'hg update %s' to update") % ctx.rev()
4891 " or 'hg update %s' to update") % ctx.rev()
4875 elif dirty:
4892 elif dirty:
4876 hint = _("uncommitted changes, use --all to discard all changes")
4893 hint = _("uncommitted changes, use --all to discard all changes")
4877 else:
4894 else:
4878 hint = _("use --all to revert all files")
4895 hint = _("use --all to revert all files")
4879 raise error.Abort(msg, hint=hint)
4896 raise error.Abort(msg, hint=hint)
4880
4897
4881 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats,
4898 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats,
4882 **pycompat.strkwargs(opts))
4899 **pycompat.strkwargs(opts))
4883
4900
4884 @command('rollback', dryrunopts +
4901 @command('rollback', dryrunopts +
4885 [('f', 'force', False, _('ignore safety measures'))])
4902 [('f', 'force', False, _('ignore safety measures'))])
4886 def rollback(ui, repo, **opts):
4903 def rollback(ui, repo, **opts):
4887 """roll back the last transaction (DANGEROUS) (DEPRECATED)
4904 """roll back the last transaction (DANGEROUS) (DEPRECATED)
4888
4905
4889 Please use :hg:`commit --amend` instead of rollback to correct
4906 Please use :hg:`commit --amend` instead of rollback to correct
4890 mistakes in the last commit.
4907 mistakes in the last commit.
4891
4908
4892 This command should be used with care. There is only one level of
4909 This command should be used with care. There is only one level of
4893 rollback, and there is no way to undo a rollback. It will also
4910 rollback, and there is no way to undo a rollback. It will also
4894 restore the dirstate at the time of the last transaction, losing
4911 restore the dirstate at the time of the last transaction, losing
4895 any dirstate changes since that time. This command does not alter
4912 any dirstate changes since that time. This command does not alter
4896 the working directory.
4913 the working directory.
4897
4914
4898 Transactions are used to encapsulate the effects of all commands
4915 Transactions are used to encapsulate the effects of all commands
4899 that create new changesets or propagate existing changesets into a
4916 that create new changesets or propagate existing changesets into a
4900 repository.
4917 repository.
4901
4918
4902 .. container:: verbose
4919 .. container:: verbose
4903
4920
4904 For example, the following commands are transactional, and their
4921 For example, the following commands are transactional, and their
4905 effects can be rolled back:
4922 effects can be rolled back:
4906
4923
4907 - commit
4924 - commit
4908 - import
4925 - import
4909 - pull
4926 - pull
4910 - push (with this repository as the destination)
4927 - push (with this repository as the destination)
4911 - unbundle
4928 - unbundle
4912
4929
4913 To avoid permanent data loss, rollback will refuse to rollback a
4930 To avoid permanent data loss, rollback will refuse to rollback a
4914 commit transaction if it isn't checked out. Use --force to
4931 commit transaction if it isn't checked out. Use --force to
4915 override this protection.
4932 override this protection.
4916
4933
4917 The rollback command can be entirely disabled by setting the
4934 The rollback command can be entirely disabled by setting the
4918 ``ui.rollback`` configuration setting to false. If you're here
4935 ``ui.rollback`` configuration setting to false. If you're here
4919 because you want to use rollback and it's disabled, you can
4936 because you want to use rollback and it's disabled, you can
4920 re-enable the command by setting ``ui.rollback`` to true.
4937 re-enable the command by setting ``ui.rollback`` to true.
4921
4938
4922 This command is not intended for use on public repositories. Once
4939 This command is not intended for use on public repositories. Once
4923 changes are visible for pull by other users, rolling a transaction
4940 changes are visible for pull by other users, rolling a transaction
4924 back locally is ineffective (someone else may already have pulled
4941 back locally is ineffective (someone else may already have pulled
4925 the changes). Furthermore, a race is possible with readers of the
4942 the changes). Furthermore, a race is possible with readers of the
4926 repository; for example an in-progress pull from the repository
4943 repository; for example an in-progress pull from the repository
4927 may fail if a rollback is performed.
4944 may fail if a rollback is performed.
4928
4945
4929 Returns 0 on success, 1 if no rollback data is available.
4946 Returns 0 on success, 1 if no rollback data is available.
4930 """
4947 """
4931 if not ui.configbool('ui', 'rollback'):
4948 if not ui.configbool('ui', 'rollback'):
4932 raise error.Abort(_('rollback is disabled because it is unsafe'),
4949 raise error.Abort(_('rollback is disabled because it is unsafe'),
4933 hint=('see `hg help -v rollback` for information'))
4950 hint=('see `hg help -v rollback` for information'))
4934 return repo.rollback(dryrun=opts.get(r'dry_run'),
4951 return repo.rollback(dryrun=opts.get(r'dry_run'),
4935 force=opts.get(r'force'))
4952 force=opts.get(r'force'))
4936
4953
4937 @command('root', [], intents={INTENT_READONLY})
4954 @command('root', [], intents={INTENT_READONLY})
4938 def root(ui, repo):
4955 def root(ui, repo):
4939 """print the root (top) of the current working directory
4956 """print the root (top) of the current working directory
4940
4957
4941 Print the root directory of the current repository.
4958 Print the root directory of the current repository.
4942
4959
4943 Returns 0 on success.
4960 Returns 0 on success.
4944 """
4961 """
4945 ui.write(repo.root + "\n")
4962 ui.write(repo.root + "\n")
4946
4963
4947 @command('^serve',
4964 @command('^serve',
4948 [('A', 'accesslog', '', _('name of access log file to write to'),
4965 [('A', 'accesslog', '', _('name of access log file to write to'),
4949 _('FILE')),
4966 _('FILE')),
4950 ('d', 'daemon', None, _('run server in background')),
4967 ('d', 'daemon', None, _('run server in background')),
4951 ('', 'daemon-postexec', [], _('used internally by daemon mode')),
4968 ('', 'daemon-postexec', [], _('used internally by daemon mode')),
4952 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4969 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4953 # use string type, then we can check if something was passed
4970 # use string type, then we can check if something was passed
4954 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4971 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4955 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4972 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4956 _('ADDR')),
4973 _('ADDR')),
4957 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4974 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4958 _('PREFIX')),
4975 _('PREFIX')),
4959 ('n', 'name', '',
4976 ('n', 'name', '',
4960 _('name to show in web pages (default: working directory)'), _('NAME')),
4977 _('name to show in web pages (default: working directory)'), _('NAME')),
4961 ('', 'web-conf', '',
4978 ('', 'web-conf', '',
4962 _("name of the hgweb config file (see 'hg help hgweb')"), _('FILE')),
4979 _("name of the hgweb config file (see 'hg help hgweb')"), _('FILE')),
4963 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4980 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4964 _('FILE')),
4981 _('FILE')),
4965 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4982 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4966 ('', 'stdio', None, _('for remote clients (ADVANCED)')),
4983 ('', 'stdio', None, _('for remote clients (ADVANCED)')),
4967 ('', 'cmdserver', '', _('for remote clients (ADVANCED)'), _('MODE')),
4984 ('', 'cmdserver', '', _('for remote clients (ADVANCED)'), _('MODE')),
4968 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4985 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4969 ('', 'style', '', _('template style to use'), _('STYLE')),
4986 ('', 'style', '', _('template style to use'), _('STYLE')),
4970 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4987 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4971 ('', 'certificate', '', _('SSL certificate file'), _('FILE')),
4988 ('', 'certificate', '', _('SSL certificate file'), _('FILE')),
4972 ('', 'print-url', None, _('start and print only the URL'))]
4989 ('', 'print-url', None, _('start and print only the URL'))]
4973 + subrepoopts,
4990 + subrepoopts,
4974 _('[OPTION]...'),
4991 _('[OPTION]...'),
4975 optionalrepo=True)
4992 optionalrepo=True)
4976 def serve(ui, repo, **opts):
4993 def serve(ui, repo, **opts):
4977 """start stand-alone webserver
4994 """start stand-alone webserver
4978
4995
4979 Start a local HTTP repository browser and pull server. You can use
4996 Start a local HTTP repository browser and pull server. You can use
4980 this for ad-hoc sharing and browsing of repositories. It is
4997 this for ad-hoc sharing and browsing of repositories. It is
4981 recommended to use a real web server to serve a repository for
4998 recommended to use a real web server to serve a repository for
4982 longer periods of time.
4999 longer periods of time.
4983
5000
4984 Please note that the server does not implement access control.
5001 Please note that the server does not implement access control.
4985 This means that, by default, anybody can read from the server and
5002 This means that, by default, anybody can read from the server and
4986 nobody can write to it by default. Set the ``web.allow-push``
5003 nobody can write to it by default. Set the ``web.allow-push``
4987 option to ``*`` to allow everybody to push to the server. You
5004 option to ``*`` to allow everybody to push to the server. You
4988 should use a real web server if you need to authenticate users.
5005 should use a real web server if you need to authenticate users.
4989
5006
4990 By default, the server logs accesses to stdout and errors to
5007 By default, the server logs accesses to stdout and errors to
4991 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5008 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
4992 files.
5009 files.
4993
5010
4994 To have the server choose a free port number to listen on, specify
5011 To have the server choose a free port number to listen on, specify
4995 a port number of 0; in this case, the server will print the port
5012 a port number of 0; in this case, the server will print the port
4996 number it uses.
5013 number it uses.
4997
5014
4998 Returns 0 on success.
5015 Returns 0 on success.
4999 """
5016 """
5000
5017
5001 opts = pycompat.byteskwargs(opts)
5018 opts = pycompat.byteskwargs(opts)
5002 if opts["stdio"] and opts["cmdserver"]:
5019 if opts["stdio"] and opts["cmdserver"]:
5003 raise error.Abort(_("cannot use --stdio with --cmdserver"))
5020 raise error.Abort(_("cannot use --stdio with --cmdserver"))
5004 if opts["print_url"] and ui.verbose:
5021 if opts["print_url"] and ui.verbose:
5005 raise error.Abort(_("cannot use --print-url with --verbose"))
5022 raise error.Abort(_("cannot use --print-url with --verbose"))
5006
5023
5007 if opts["stdio"]:
5024 if opts["stdio"]:
5008 if repo is None:
5025 if repo is None:
5009 raise error.RepoError(_("there is no Mercurial repository here"
5026 raise error.RepoError(_("there is no Mercurial repository here"
5010 " (.hg not found)"))
5027 " (.hg not found)"))
5011 s = wireprotoserver.sshserver(ui, repo)
5028 s = wireprotoserver.sshserver(ui, repo)
5012 s.serve_forever()
5029 s.serve_forever()
5013
5030
5014 service = server.createservice(ui, repo, opts)
5031 service = server.createservice(ui, repo, opts)
5015 return server.runservice(opts, initfn=service.init, runfn=service.run)
5032 return server.runservice(opts, initfn=service.init, runfn=service.run)
5016
5033
5017 _NOTTERSE = 'nothing'
5034 _NOTTERSE = 'nothing'
5018
5035
5019 @command('^status|st',
5036 @command('^status|st',
5020 [('A', 'all', None, _('show status of all files')),
5037 [('A', 'all', None, _('show status of all files')),
5021 ('m', 'modified', None, _('show only modified files')),
5038 ('m', 'modified', None, _('show only modified files')),
5022 ('a', 'added', None, _('show only added files')),
5039 ('a', 'added', None, _('show only added files')),
5023 ('r', 'removed', None, _('show only removed files')),
5040 ('r', 'removed', None, _('show only removed files')),
5024 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5041 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5025 ('c', 'clean', None, _('show only files without changes')),
5042 ('c', 'clean', None, _('show only files without changes')),
5026 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5043 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5027 ('i', 'ignored', None, _('show only ignored files')),
5044 ('i', 'ignored', None, _('show only ignored files')),
5028 ('n', 'no-status', None, _('hide status prefix')),
5045 ('n', 'no-status', None, _('hide status prefix')),
5029 ('t', 'terse', _NOTTERSE, _('show the terse output (EXPERIMENTAL)')),
5046 ('t', 'terse', _NOTTERSE, _('show the terse output (EXPERIMENTAL)')),
5030 ('C', 'copies', None, _('show source of copied files')),
5047 ('C', 'copies', None, _('show source of copied files')),
5031 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5048 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5032 ('', 'rev', [], _('show difference from revision'), _('REV')),
5049 ('', 'rev', [], _('show difference from revision'), _('REV')),
5033 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5050 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5034 ] + walkopts + subrepoopts + formatteropts,
5051 ] + walkopts + subrepoopts + formatteropts,
5035 _('[OPTION]... [FILE]...'),
5052 _('[OPTION]... [FILE]...'),
5036 inferrepo=True,
5053 inferrepo=True,
5037 intents={INTENT_READONLY})
5054 intents={INTENT_READONLY})
5038 def status(ui, repo, *pats, **opts):
5055 def status(ui, repo, *pats, **opts):
5039 """show changed files in the working directory
5056 """show changed files in the working directory
5040
5057
5041 Show status of files in the repository. If names are given, only
5058 Show status of files in the repository. If names are given, only
5042 files that match are shown. Files that are clean or ignored or
5059 files that match are shown. Files that are clean or ignored or
5043 the source of a copy/move operation, are not listed unless
5060 the source of a copy/move operation, are not listed unless
5044 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5061 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5045 Unless options described with "show only ..." are given, the
5062 Unless options described with "show only ..." are given, the
5046 options -mardu are used.
5063 options -mardu are used.
5047
5064
5048 Option -q/--quiet hides untracked (unknown and ignored) files
5065 Option -q/--quiet hides untracked (unknown and ignored) files
5049 unless explicitly requested with -u/--unknown or -i/--ignored.
5066 unless explicitly requested with -u/--unknown or -i/--ignored.
5050
5067
5051 .. note::
5068 .. note::
5052
5069
5053 :hg:`status` may appear to disagree with diff if permissions have
5070 :hg:`status` may appear to disagree with diff if permissions have
5054 changed or a merge has occurred. The standard diff format does
5071 changed or a merge has occurred. The standard diff format does
5055 not report permission changes and diff only reports changes
5072 not report permission changes and diff only reports changes
5056 relative to one merge parent.
5073 relative to one merge parent.
5057
5074
5058 If one revision is given, it is used as the base revision.
5075 If one revision is given, it is used as the base revision.
5059 If two revisions are given, the differences between them are
5076 If two revisions are given, the differences between them are
5060 shown. The --change option can also be used as a shortcut to list
5077 shown. The --change option can also be used as a shortcut to list
5061 the changed files of a revision from its first parent.
5078 the changed files of a revision from its first parent.
5062
5079
5063 The codes used to show the status of files are::
5080 The codes used to show the status of files are::
5064
5081
5065 M = modified
5082 M = modified
5066 A = added
5083 A = added
5067 R = removed
5084 R = removed
5068 C = clean
5085 C = clean
5069 ! = missing (deleted by non-hg command, but still tracked)
5086 ! = missing (deleted by non-hg command, but still tracked)
5070 ? = not tracked
5087 ? = not tracked
5071 I = ignored
5088 I = ignored
5072 = origin of the previous file (with --copies)
5089 = origin of the previous file (with --copies)
5073
5090
5074 .. container:: verbose
5091 .. container:: verbose
5075
5092
5076 The -t/--terse option abbreviates the output by showing only the directory
5093 The -t/--terse option abbreviates the output by showing only the directory
5077 name if all the files in it share the same status. The option takes an
5094 name if all the files in it share the same status. The option takes an
5078 argument indicating the statuses to abbreviate: 'm' for 'modified', 'a'
5095 argument indicating the statuses to abbreviate: 'm' for 'modified', 'a'
5079 for 'added', 'r' for 'removed', 'd' for 'deleted', 'u' for 'unknown', 'i'
5096 for 'added', 'r' for 'removed', 'd' for 'deleted', 'u' for 'unknown', 'i'
5080 for 'ignored' and 'c' for clean.
5097 for 'ignored' and 'c' for clean.
5081
5098
5082 It abbreviates only those statuses which are passed. Note that clean and
5099 It abbreviates only those statuses which are passed. Note that clean and
5083 ignored files are not displayed with '--terse ic' unless the -c/--clean
5100 ignored files are not displayed with '--terse ic' unless the -c/--clean
5084 and -i/--ignored options are also used.
5101 and -i/--ignored options are also used.
5085
5102
5086 The -v/--verbose option shows information when the repository is in an
5103 The -v/--verbose option shows information when the repository is in an
5087 unfinished merge, shelve, rebase state etc. You can have this behavior
5104 unfinished merge, shelve, rebase state etc. You can have this behavior
5088 turned on by default by enabling the ``commands.status.verbose`` option.
5105 turned on by default by enabling the ``commands.status.verbose`` option.
5089
5106
5090 You can skip displaying some of these states by setting
5107 You can skip displaying some of these states by setting
5091 ``commands.status.skipstates`` to one or more of: 'bisect', 'graft',
5108 ``commands.status.skipstates`` to one or more of: 'bisect', 'graft',
5092 'histedit', 'merge', 'rebase', or 'unshelve'.
5109 'histedit', 'merge', 'rebase', or 'unshelve'.
5093
5110
5094 Examples:
5111 Examples:
5095
5112
5096 - show changes in the working directory relative to a
5113 - show changes in the working directory relative to a
5097 changeset::
5114 changeset::
5098
5115
5099 hg status --rev 9353
5116 hg status --rev 9353
5100
5117
5101 - show changes in the working directory relative to the
5118 - show changes in the working directory relative to the
5102 current directory (see :hg:`help patterns` for more information)::
5119 current directory (see :hg:`help patterns` for more information)::
5103
5120
5104 hg status re:
5121 hg status re:
5105
5122
5106 - show all changes including copies in an existing changeset::
5123 - show all changes including copies in an existing changeset::
5107
5124
5108 hg status --copies --change 9353
5125 hg status --copies --change 9353
5109
5126
5110 - get a NUL separated list of added files, suitable for xargs::
5127 - get a NUL separated list of added files, suitable for xargs::
5111
5128
5112 hg status -an0
5129 hg status -an0
5113
5130
5114 - show more information about the repository status, abbreviating
5131 - show more information about the repository status, abbreviating
5115 added, removed, modified, deleted, and untracked paths::
5132 added, removed, modified, deleted, and untracked paths::
5116
5133
5117 hg status -v -t mardu
5134 hg status -v -t mardu
5118
5135
5119 Returns 0 on success.
5136 Returns 0 on success.
5120
5137
5121 """
5138 """
5122
5139
5123 opts = pycompat.byteskwargs(opts)
5140 opts = pycompat.byteskwargs(opts)
5124 revs = opts.get('rev')
5141 revs = opts.get('rev')
5125 change = opts.get('change')
5142 change = opts.get('change')
5126 terse = opts.get('terse')
5143 terse = opts.get('terse')
5127 if terse is _NOTTERSE:
5144 if terse is _NOTTERSE:
5128 if revs:
5145 if revs:
5129 terse = ''
5146 terse = ''
5130 else:
5147 else:
5131 terse = ui.config('commands', 'status.terse')
5148 terse = ui.config('commands', 'status.terse')
5132
5149
5133 if revs and change:
5150 if revs and change:
5134 msg = _('cannot specify --rev and --change at the same time')
5151 msg = _('cannot specify --rev and --change at the same time')
5135 raise error.Abort(msg)
5152 raise error.Abort(msg)
5136 elif revs and terse:
5153 elif revs and terse:
5137 msg = _('cannot use --terse with --rev')
5154 msg = _('cannot use --terse with --rev')
5138 raise error.Abort(msg)
5155 raise error.Abort(msg)
5139 elif change:
5156 elif change:
5140 repo = scmutil.unhidehashlikerevs(repo, [change], 'nowarn')
5157 repo = scmutil.unhidehashlikerevs(repo, [change], 'nowarn')
5141 ctx2 = scmutil.revsingle(repo, change, None)
5158 ctx2 = scmutil.revsingle(repo, change, None)
5142 ctx1 = ctx2.p1()
5159 ctx1 = ctx2.p1()
5143 else:
5160 else:
5144 repo = scmutil.unhidehashlikerevs(repo, revs, 'nowarn')
5161 repo = scmutil.unhidehashlikerevs(repo, revs, 'nowarn')
5145 ctx1, ctx2 = scmutil.revpair(repo, revs)
5162 ctx1, ctx2 = scmutil.revpair(repo, revs)
5146
5163
5147 if pats or ui.configbool('commands', 'status.relative'):
5164 if pats or ui.configbool('commands', 'status.relative'):
5148 cwd = repo.getcwd()
5165 cwd = repo.getcwd()
5149 else:
5166 else:
5150 cwd = ''
5167 cwd = ''
5151
5168
5152 if opts.get('print0'):
5169 if opts.get('print0'):
5153 end = '\0'
5170 end = '\0'
5154 else:
5171 else:
5155 end = '\n'
5172 end = '\n'
5156 copy = {}
5173 copy = {}
5157 states = 'modified added removed deleted unknown ignored clean'.split()
5174 states = 'modified added removed deleted unknown ignored clean'.split()
5158 show = [k for k in states if opts.get(k)]
5175 show = [k for k in states if opts.get(k)]
5159 if opts.get('all'):
5176 if opts.get('all'):
5160 show += ui.quiet and (states[:4] + ['clean']) or states
5177 show += ui.quiet and (states[:4] + ['clean']) or states
5161
5178
5162 if not show:
5179 if not show:
5163 if ui.quiet:
5180 if ui.quiet:
5164 show = states[:4]
5181 show = states[:4]
5165 else:
5182 else:
5166 show = states[:5]
5183 show = states[:5]
5167
5184
5168 m = scmutil.match(ctx2, pats, opts)
5185 m = scmutil.match(ctx2, pats, opts)
5169 if terse:
5186 if terse:
5170 # we need to compute clean and unknown to terse
5187 # we need to compute clean and unknown to terse
5171 stat = repo.status(ctx1.node(), ctx2.node(), m,
5188 stat = repo.status(ctx1.node(), ctx2.node(), m,
5172 'ignored' in show or 'i' in terse,
5189 'ignored' in show or 'i' in terse,
5173 clean=True, unknown=True,
5190 clean=True, unknown=True,
5174 listsubrepos=opts.get('subrepos'))
5191 listsubrepos=opts.get('subrepos'))
5175
5192
5176 stat = cmdutil.tersedir(stat, terse)
5193 stat = cmdutil.tersedir(stat, terse)
5177 else:
5194 else:
5178 stat = repo.status(ctx1.node(), ctx2.node(), m,
5195 stat = repo.status(ctx1.node(), ctx2.node(), m,
5179 'ignored' in show, 'clean' in show,
5196 'ignored' in show, 'clean' in show,
5180 'unknown' in show, opts.get('subrepos'))
5197 'unknown' in show, opts.get('subrepos'))
5181
5198
5182 changestates = zip(states, pycompat.iterbytestr('MAR!?IC'), stat)
5199 changestates = zip(states, pycompat.iterbytestr('MAR!?IC'), stat)
5183
5200
5184 if (opts.get('all') or opts.get('copies')
5201 if (opts.get('all') or opts.get('copies')
5185 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
5202 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
5186 copy = copies.pathcopies(ctx1, ctx2, m)
5203 copy = copies.pathcopies(ctx1, ctx2, m)
5187
5204
5188 ui.pager('status')
5205 ui.pager('status')
5189 fm = ui.formatter('status', opts)
5206 fm = ui.formatter('status', opts)
5190 fmt = '%s' + end
5207 fmt = '%s' + end
5191 showchar = not opts.get('no_status')
5208 showchar = not opts.get('no_status')
5192
5209
5193 for state, char, files in changestates:
5210 for state, char, files in changestates:
5194 if state in show:
5211 if state in show:
5195 label = 'status.' + state
5212 label = 'status.' + state
5196 for f in files:
5213 for f in files:
5197 fm.startitem()
5214 fm.startitem()
5198 fm.context(ctx=ctx2)
5215 fm.context(ctx=ctx2)
5199 fm.data(path=f)
5216 fm.data(path=f)
5200 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5217 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5201 fm.plain(fmt % repo.pathto(f, cwd), label=label)
5218 fm.plain(fmt % repo.pathto(f, cwd), label=label)
5202 if f in copy:
5219 if f in copy:
5203 fm.data(source=copy[f])
5220 fm.data(source=copy[f])
5204 fm.plain((' %s' + end) % repo.pathto(copy[f], cwd),
5221 fm.plain((' %s' + end) % repo.pathto(copy[f], cwd),
5205 label='status.copied')
5222 label='status.copied')
5206
5223
5207 if ((ui.verbose or ui.configbool('commands', 'status.verbose'))
5224 if ((ui.verbose or ui.configbool('commands', 'status.verbose'))
5208 and not ui.plain()):
5225 and not ui.plain()):
5209 cmdutil.morestatus(repo, fm)
5226 cmdutil.morestatus(repo, fm)
5210 fm.end()
5227 fm.end()
5211
5228
5212 @command('^summary|sum',
5229 @command('^summary|sum',
5213 [('', 'remote', None, _('check for push and pull'))],
5230 [('', 'remote', None, _('check for push and pull'))],
5214 '[--remote]',
5231 '[--remote]',
5215 intents={INTENT_READONLY})
5232 intents={INTENT_READONLY})
5216 def summary(ui, repo, **opts):
5233 def summary(ui, repo, **opts):
5217 """summarize working directory state
5234 """summarize working directory state
5218
5235
5219 This generates a brief summary of the working directory state,
5236 This generates a brief summary of the working directory state,
5220 including parents, branch, commit status, phase and available updates.
5237 including parents, branch, commit status, phase and available updates.
5221
5238
5222 With the --remote option, this will check the default paths for
5239 With the --remote option, this will check the default paths for
5223 incoming and outgoing changes. This can be time-consuming.
5240 incoming and outgoing changes. This can be time-consuming.
5224
5241
5225 Returns 0 on success.
5242 Returns 0 on success.
5226 """
5243 """
5227
5244
5228 opts = pycompat.byteskwargs(opts)
5245 opts = pycompat.byteskwargs(opts)
5229 ui.pager('summary')
5246 ui.pager('summary')
5230 ctx = repo[None]
5247 ctx = repo[None]
5231 parents = ctx.parents()
5248 parents = ctx.parents()
5232 pnode = parents[0].node()
5249 pnode = parents[0].node()
5233 marks = []
5250 marks = []
5234
5251
5235 ms = None
5252 ms = None
5236 try:
5253 try:
5237 ms = mergemod.mergestate.read(repo)
5254 ms = mergemod.mergestate.read(repo)
5238 except error.UnsupportedMergeRecords as e:
5255 except error.UnsupportedMergeRecords as e:
5239 s = ' '.join(e.recordtypes)
5256 s = ' '.join(e.recordtypes)
5240 ui.warn(
5257 ui.warn(
5241 _('warning: merge state has unsupported record types: %s\n') % s)
5258 _('warning: merge state has unsupported record types: %s\n') % s)
5242 unresolved = []
5259 unresolved = []
5243 else:
5260 else:
5244 unresolved = list(ms.unresolved())
5261 unresolved = list(ms.unresolved())
5245
5262
5246 for p in parents:
5263 for p in parents:
5247 # label with log.changeset (instead of log.parent) since this
5264 # label with log.changeset (instead of log.parent) since this
5248 # shows a working directory parent *changeset*:
5265 # shows a working directory parent *changeset*:
5249 # i18n: column positioning for "hg summary"
5266 # i18n: column positioning for "hg summary"
5250 ui.write(_('parent: %d:%s ') % (p.rev(), p),
5267 ui.write(_('parent: %d:%s ') % (p.rev(), p),
5251 label=logcmdutil.changesetlabels(p))
5268 label=logcmdutil.changesetlabels(p))
5252 ui.write(' '.join(p.tags()), label='log.tag')
5269 ui.write(' '.join(p.tags()), label='log.tag')
5253 if p.bookmarks():
5270 if p.bookmarks():
5254 marks.extend(p.bookmarks())
5271 marks.extend(p.bookmarks())
5255 if p.rev() == -1:
5272 if p.rev() == -1:
5256 if not len(repo):
5273 if not len(repo):
5257 ui.write(_(' (empty repository)'))
5274 ui.write(_(' (empty repository)'))
5258 else:
5275 else:
5259 ui.write(_(' (no revision checked out)'))
5276 ui.write(_(' (no revision checked out)'))
5260 if p.obsolete():
5277 if p.obsolete():
5261 ui.write(_(' (obsolete)'))
5278 ui.write(_(' (obsolete)'))
5262 if p.isunstable():
5279 if p.isunstable():
5263 instabilities = (ui.label(instability, 'trouble.%s' % instability)
5280 instabilities = (ui.label(instability, 'trouble.%s' % instability)
5264 for instability in p.instabilities())
5281 for instability in p.instabilities())
5265 ui.write(' ('
5282 ui.write(' ('
5266 + ', '.join(instabilities)
5283 + ', '.join(instabilities)
5267 + ')')
5284 + ')')
5268 ui.write('\n')
5285 ui.write('\n')
5269 if p.description():
5286 if p.description():
5270 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5287 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5271 label='log.summary')
5288 label='log.summary')
5272
5289
5273 branch = ctx.branch()
5290 branch = ctx.branch()
5274 bheads = repo.branchheads(branch)
5291 bheads = repo.branchheads(branch)
5275 # i18n: column positioning for "hg summary"
5292 # i18n: column positioning for "hg summary"
5276 m = _('branch: %s\n') % branch
5293 m = _('branch: %s\n') % branch
5277 if branch != 'default':
5294 if branch != 'default':
5278 ui.write(m, label='log.branch')
5295 ui.write(m, label='log.branch')
5279 else:
5296 else:
5280 ui.status(m, label='log.branch')
5297 ui.status(m, label='log.branch')
5281
5298
5282 if marks:
5299 if marks:
5283 active = repo._activebookmark
5300 active = repo._activebookmark
5284 # i18n: column positioning for "hg summary"
5301 # i18n: column positioning for "hg summary"
5285 ui.write(_('bookmarks:'), label='log.bookmark')
5302 ui.write(_('bookmarks:'), label='log.bookmark')
5286 if active is not None:
5303 if active is not None:
5287 if active in marks:
5304 if active in marks:
5288 ui.write(' *' + active, label=bookmarks.activebookmarklabel)
5305 ui.write(' *' + active, label=bookmarks.activebookmarklabel)
5289 marks.remove(active)
5306 marks.remove(active)
5290 else:
5307 else:
5291 ui.write(' [%s]' % active, label=bookmarks.activebookmarklabel)
5308 ui.write(' [%s]' % active, label=bookmarks.activebookmarklabel)
5292 for m in marks:
5309 for m in marks:
5293 ui.write(' ' + m, label='log.bookmark')
5310 ui.write(' ' + m, label='log.bookmark')
5294 ui.write('\n', label='log.bookmark')
5311 ui.write('\n', label='log.bookmark')
5295
5312
5296 status = repo.status(unknown=True)
5313 status = repo.status(unknown=True)
5297
5314
5298 c = repo.dirstate.copies()
5315 c = repo.dirstate.copies()
5299 copied, renamed = [], []
5316 copied, renamed = [], []
5300 for d, s in c.iteritems():
5317 for d, s in c.iteritems():
5301 if s in status.removed:
5318 if s in status.removed:
5302 status.removed.remove(s)
5319 status.removed.remove(s)
5303 renamed.append(d)
5320 renamed.append(d)
5304 else:
5321 else:
5305 copied.append(d)
5322 copied.append(d)
5306 if d in status.added:
5323 if d in status.added:
5307 status.added.remove(d)
5324 status.added.remove(d)
5308
5325
5309 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5326 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5310
5327
5311 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
5328 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
5312 (ui.label(_('%d added'), 'status.added'), status.added),
5329 (ui.label(_('%d added'), 'status.added'), status.added),
5313 (ui.label(_('%d removed'), 'status.removed'), status.removed),
5330 (ui.label(_('%d removed'), 'status.removed'), status.removed),
5314 (ui.label(_('%d renamed'), 'status.copied'), renamed),
5331 (ui.label(_('%d renamed'), 'status.copied'), renamed),
5315 (ui.label(_('%d copied'), 'status.copied'), copied),
5332 (ui.label(_('%d copied'), 'status.copied'), copied),
5316 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
5333 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
5317 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
5334 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
5318 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
5335 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
5319 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
5336 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
5320 t = []
5337 t = []
5321 for l, s in labels:
5338 for l, s in labels:
5322 if s:
5339 if s:
5323 t.append(l % len(s))
5340 t.append(l % len(s))
5324
5341
5325 t = ', '.join(t)
5342 t = ', '.join(t)
5326 cleanworkdir = False
5343 cleanworkdir = False
5327
5344
5328 if repo.vfs.exists('graftstate'):
5345 if repo.vfs.exists('graftstate'):
5329 t += _(' (graft in progress)')
5346 t += _(' (graft in progress)')
5330 if repo.vfs.exists('updatestate'):
5347 if repo.vfs.exists('updatestate'):
5331 t += _(' (interrupted update)')
5348 t += _(' (interrupted update)')
5332 elif len(parents) > 1:
5349 elif len(parents) > 1:
5333 t += _(' (merge)')
5350 t += _(' (merge)')
5334 elif branch != parents[0].branch():
5351 elif branch != parents[0].branch():
5335 t += _(' (new branch)')
5352 t += _(' (new branch)')
5336 elif (parents[0].closesbranch() and
5353 elif (parents[0].closesbranch() and
5337 pnode in repo.branchheads(branch, closed=True)):
5354 pnode in repo.branchheads(branch, closed=True)):
5338 t += _(' (head closed)')
5355 t += _(' (head closed)')
5339 elif not (status.modified or status.added or status.removed or renamed or
5356 elif not (status.modified or status.added or status.removed or renamed or
5340 copied or subs):
5357 copied or subs):
5341 t += _(' (clean)')
5358 t += _(' (clean)')
5342 cleanworkdir = True
5359 cleanworkdir = True
5343 elif pnode not in bheads:
5360 elif pnode not in bheads:
5344 t += _(' (new branch head)')
5361 t += _(' (new branch head)')
5345
5362
5346 if parents:
5363 if parents:
5347 pendingphase = max(p.phase() for p in parents)
5364 pendingphase = max(p.phase() for p in parents)
5348 else:
5365 else:
5349 pendingphase = phases.public
5366 pendingphase = phases.public
5350
5367
5351 if pendingphase > phases.newcommitphase(ui):
5368 if pendingphase > phases.newcommitphase(ui):
5352 t += ' (%s)' % phases.phasenames[pendingphase]
5369 t += ' (%s)' % phases.phasenames[pendingphase]
5353
5370
5354 if cleanworkdir:
5371 if cleanworkdir:
5355 # i18n: column positioning for "hg summary"
5372 # i18n: column positioning for "hg summary"
5356 ui.status(_('commit: %s\n') % t.strip())
5373 ui.status(_('commit: %s\n') % t.strip())
5357 else:
5374 else:
5358 # i18n: column positioning for "hg summary"
5375 # i18n: column positioning for "hg summary"
5359 ui.write(_('commit: %s\n') % t.strip())
5376 ui.write(_('commit: %s\n') % t.strip())
5360
5377
5361 # all ancestors of branch heads - all ancestors of parent = new csets
5378 # all ancestors of branch heads - all ancestors of parent = new csets
5362 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
5379 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
5363 bheads))
5380 bheads))
5364
5381
5365 if new == 0:
5382 if new == 0:
5366 # i18n: column positioning for "hg summary"
5383 # i18n: column positioning for "hg summary"
5367 ui.status(_('update: (current)\n'))
5384 ui.status(_('update: (current)\n'))
5368 elif pnode not in bheads:
5385 elif pnode not in bheads:
5369 # i18n: column positioning for "hg summary"
5386 # i18n: column positioning for "hg summary"
5370 ui.write(_('update: %d new changesets (update)\n') % new)
5387 ui.write(_('update: %d new changesets (update)\n') % new)
5371 else:
5388 else:
5372 # i18n: column positioning for "hg summary"
5389 # i18n: column positioning for "hg summary"
5373 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5390 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5374 (new, len(bheads)))
5391 (new, len(bheads)))
5375
5392
5376 t = []
5393 t = []
5377 draft = len(repo.revs('draft()'))
5394 draft = len(repo.revs('draft()'))
5378 if draft:
5395 if draft:
5379 t.append(_('%d draft') % draft)
5396 t.append(_('%d draft') % draft)
5380 secret = len(repo.revs('secret()'))
5397 secret = len(repo.revs('secret()'))
5381 if secret:
5398 if secret:
5382 t.append(_('%d secret') % secret)
5399 t.append(_('%d secret') % secret)
5383
5400
5384 if draft or secret:
5401 if draft or secret:
5385 ui.status(_('phases: %s\n') % ', '.join(t))
5402 ui.status(_('phases: %s\n') % ', '.join(t))
5386
5403
5387 if obsolete.isenabled(repo, obsolete.createmarkersopt):
5404 if obsolete.isenabled(repo, obsolete.createmarkersopt):
5388 for trouble in ("orphan", "contentdivergent", "phasedivergent"):
5405 for trouble in ("orphan", "contentdivergent", "phasedivergent"):
5389 numtrouble = len(repo.revs(trouble + "()"))
5406 numtrouble = len(repo.revs(trouble + "()"))
5390 # We write all the possibilities to ease translation
5407 # We write all the possibilities to ease translation
5391 troublemsg = {
5408 troublemsg = {
5392 "orphan": _("orphan: %d changesets"),
5409 "orphan": _("orphan: %d changesets"),
5393 "contentdivergent": _("content-divergent: %d changesets"),
5410 "contentdivergent": _("content-divergent: %d changesets"),
5394 "phasedivergent": _("phase-divergent: %d changesets"),
5411 "phasedivergent": _("phase-divergent: %d changesets"),
5395 }
5412 }
5396 if numtrouble > 0:
5413 if numtrouble > 0:
5397 ui.status(troublemsg[trouble] % numtrouble + "\n")
5414 ui.status(troublemsg[trouble] % numtrouble + "\n")
5398
5415
5399 cmdutil.summaryhooks(ui, repo)
5416 cmdutil.summaryhooks(ui, repo)
5400
5417
5401 if opts.get('remote'):
5418 if opts.get('remote'):
5402 needsincoming, needsoutgoing = True, True
5419 needsincoming, needsoutgoing = True, True
5403 else:
5420 else:
5404 needsincoming, needsoutgoing = False, False
5421 needsincoming, needsoutgoing = False, False
5405 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5422 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5406 if i:
5423 if i:
5407 needsincoming = True
5424 needsincoming = True
5408 if o:
5425 if o:
5409 needsoutgoing = True
5426 needsoutgoing = True
5410 if not needsincoming and not needsoutgoing:
5427 if not needsincoming and not needsoutgoing:
5411 return
5428 return
5412
5429
5413 def getincoming():
5430 def getincoming():
5414 source, branches = hg.parseurl(ui.expandpath('default'))
5431 source, branches = hg.parseurl(ui.expandpath('default'))
5415 sbranch = branches[0]
5432 sbranch = branches[0]
5416 try:
5433 try:
5417 other = hg.peer(repo, {}, source)
5434 other = hg.peer(repo, {}, source)
5418 except error.RepoError:
5435 except error.RepoError:
5419 if opts.get('remote'):
5436 if opts.get('remote'):
5420 raise
5437 raise
5421 return source, sbranch, None, None, None
5438 return source, sbranch, None, None, None
5422 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5439 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5423 if revs:
5440 if revs:
5424 revs = [other.lookup(rev) for rev in revs]
5441 revs = [other.lookup(rev) for rev in revs]
5425 ui.debug('comparing with %s\n' % util.hidepassword(source))
5442 ui.debug('comparing with %s\n' % util.hidepassword(source))
5426 repo.ui.pushbuffer()
5443 repo.ui.pushbuffer()
5427 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5444 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5428 repo.ui.popbuffer()
5445 repo.ui.popbuffer()
5429 return source, sbranch, other, commoninc, commoninc[1]
5446 return source, sbranch, other, commoninc, commoninc[1]
5430
5447
5431 if needsincoming:
5448 if needsincoming:
5432 source, sbranch, sother, commoninc, incoming = getincoming()
5449 source, sbranch, sother, commoninc, incoming = getincoming()
5433 else:
5450 else:
5434 source = sbranch = sother = commoninc = incoming = None
5451 source = sbranch = sother = commoninc = incoming = None
5435
5452
5436 def getoutgoing():
5453 def getoutgoing():
5437 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5454 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5438 dbranch = branches[0]
5455 dbranch = branches[0]
5439 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5456 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5440 if source != dest:
5457 if source != dest:
5441 try:
5458 try:
5442 dother = hg.peer(repo, {}, dest)
5459 dother = hg.peer(repo, {}, dest)
5443 except error.RepoError:
5460 except error.RepoError:
5444 if opts.get('remote'):
5461 if opts.get('remote'):
5445 raise
5462 raise
5446 return dest, dbranch, None, None
5463 return dest, dbranch, None, None
5447 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5464 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5448 elif sother is None:
5465 elif sother is None:
5449 # there is no explicit destination peer, but source one is invalid
5466 # there is no explicit destination peer, but source one is invalid
5450 return dest, dbranch, None, None
5467 return dest, dbranch, None, None
5451 else:
5468 else:
5452 dother = sother
5469 dother = sother
5453 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5470 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5454 common = None
5471 common = None
5455 else:
5472 else:
5456 common = commoninc
5473 common = commoninc
5457 if revs:
5474 if revs:
5458 revs = [repo.lookup(rev) for rev in revs]
5475 revs = [repo.lookup(rev) for rev in revs]
5459 repo.ui.pushbuffer()
5476 repo.ui.pushbuffer()
5460 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5477 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5461 commoninc=common)
5478 commoninc=common)
5462 repo.ui.popbuffer()
5479 repo.ui.popbuffer()
5463 return dest, dbranch, dother, outgoing
5480 return dest, dbranch, dother, outgoing
5464
5481
5465 if needsoutgoing:
5482 if needsoutgoing:
5466 dest, dbranch, dother, outgoing = getoutgoing()
5483 dest, dbranch, dother, outgoing = getoutgoing()
5467 else:
5484 else:
5468 dest = dbranch = dother = outgoing = None
5485 dest = dbranch = dother = outgoing = None
5469
5486
5470 if opts.get('remote'):
5487 if opts.get('remote'):
5471 t = []
5488 t = []
5472 if incoming:
5489 if incoming:
5473 t.append(_('1 or more incoming'))
5490 t.append(_('1 or more incoming'))
5474 o = outgoing.missing
5491 o = outgoing.missing
5475 if o:
5492 if o:
5476 t.append(_('%d outgoing') % len(o))
5493 t.append(_('%d outgoing') % len(o))
5477 other = dother or sother
5494 other = dother or sother
5478 if 'bookmarks' in other.listkeys('namespaces'):
5495 if 'bookmarks' in other.listkeys('namespaces'):
5479 counts = bookmarks.summary(repo, other)
5496 counts = bookmarks.summary(repo, other)
5480 if counts[0] > 0:
5497 if counts[0] > 0:
5481 t.append(_('%d incoming bookmarks') % counts[0])
5498 t.append(_('%d incoming bookmarks') % counts[0])
5482 if counts[1] > 0:
5499 if counts[1] > 0:
5483 t.append(_('%d outgoing bookmarks') % counts[1])
5500 t.append(_('%d outgoing bookmarks') % counts[1])
5484
5501
5485 if t:
5502 if t:
5486 # i18n: column positioning for "hg summary"
5503 # i18n: column positioning for "hg summary"
5487 ui.write(_('remote: %s\n') % (', '.join(t)))
5504 ui.write(_('remote: %s\n') % (', '.join(t)))
5488 else:
5505 else:
5489 # i18n: column positioning for "hg summary"
5506 # i18n: column positioning for "hg summary"
5490 ui.status(_('remote: (synced)\n'))
5507 ui.status(_('remote: (synced)\n'))
5491
5508
5492 cmdutil.summaryremotehooks(ui, repo, opts,
5509 cmdutil.summaryremotehooks(ui, repo, opts,
5493 ((source, sbranch, sother, commoninc),
5510 ((source, sbranch, sother, commoninc),
5494 (dest, dbranch, dother, outgoing)))
5511 (dest, dbranch, dother, outgoing)))
5495
5512
5496 @command('tag',
5513 @command('tag',
5497 [('f', 'force', None, _('force tag')),
5514 [('f', 'force', None, _('force tag')),
5498 ('l', 'local', None, _('make the tag local')),
5515 ('l', 'local', None, _('make the tag local')),
5499 ('r', 'rev', '', _('revision to tag'), _('REV')),
5516 ('r', 'rev', '', _('revision to tag'), _('REV')),
5500 ('', 'remove', None, _('remove a tag')),
5517 ('', 'remove', None, _('remove a tag')),
5501 # -l/--local is already there, commitopts cannot be used
5518 # -l/--local is already there, commitopts cannot be used
5502 ('e', 'edit', None, _('invoke editor on commit messages')),
5519 ('e', 'edit', None, _('invoke editor on commit messages')),
5503 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5520 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5504 ] + commitopts2,
5521 ] + commitopts2,
5505 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5522 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5506 def tag(ui, repo, name1, *names, **opts):
5523 def tag(ui, repo, name1, *names, **opts):
5507 """add one or more tags for the current or given revision
5524 """add one or more tags for the current or given revision
5508
5525
5509 Name a particular revision using <name>.
5526 Name a particular revision using <name>.
5510
5527
5511 Tags are used to name particular revisions of the repository and are
5528 Tags are used to name particular revisions of the repository and are
5512 very useful to compare different revisions, to go back to significant
5529 very useful to compare different revisions, to go back to significant
5513 earlier versions or to mark branch points as releases, etc. Changing
5530 earlier versions or to mark branch points as releases, etc. Changing
5514 an existing tag is normally disallowed; use -f/--force to override.
5531 an existing tag is normally disallowed; use -f/--force to override.
5515
5532
5516 If no revision is given, the parent of the working directory is
5533 If no revision is given, the parent of the working directory is
5517 used.
5534 used.
5518
5535
5519 To facilitate version control, distribution, and merging of tags,
5536 To facilitate version control, distribution, and merging of tags,
5520 they are stored as a file named ".hgtags" which is managed similarly
5537 they are stored as a file named ".hgtags" which is managed similarly
5521 to other project files and can be hand-edited if necessary. This
5538 to other project files and can be hand-edited if necessary. This
5522 also means that tagging creates a new commit. The file
5539 also means that tagging creates a new commit. The file
5523 ".hg/localtags" is used for local tags (not shared among
5540 ".hg/localtags" is used for local tags (not shared among
5524 repositories).
5541 repositories).
5525
5542
5526 Tag commits are usually made at the head of a branch. If the parent
5543 Tag commits are usually made at the head of a branch. If the parent
5527 of the working directory is not a branch head, :hg:`tag` aborts; use
5544 of the working directory is not a branch head, :hg:`tag` aborts; use
5528 -f/--force to force the tag commit to be based on a non-head
5545 -f/--force to force the tag commit to be based on a non-head
5529 changeset.
5546 changeset.
5530
5547
5531 See :hg:`help dates` for a list of formats valid for -d/--date.
5548 See :hg:`help dates` for a list of formats valid for -d/--date.
5532
5549
5533 Since tag names have priority over branch names during revision
5550 Since tag names have priority over branch names during revision
5534 lookup, using an existing branch name as a tag name is discouraged.
5551 lookup, using an existing branch name as a tag name is discouraged.
5535
5552
5536 Returns 0 on success.
5553 Returns 0 on success.
5537 """
5554 """
5538 opts = pycompat.byteskwargs(opts)
5555 opts = pycompat.byteskwargs(opts)
5539 with repo.wlock(), repo.lock():
5556 with repo.wlock(), repo.lock():
5540 rev_ = "."
5557 rev_ = "."
5541 names = [t.strip() for t in (name1,) + names]
5558 names = [t.strip() for t in (name1,) + names]
5542 if len(names) != len(set(names)):
5559 if len(names) != len(set(names)):
5543 raise error.Abort(_('tag names must be unique'))
5560 raise error.Abort(_('tag names must be unique'))
5544 for n in names:
5561 for n in names:
5545 scmutil.checknewlabel(repo, n, 'tag')
5562 scmutil.checknewlabel(repo, n, 'tag')
5546 if not n:
5563 if not n:
5547 raise error.Abort(_('tag names cannot consist entirely of '
5564 raise error.Abort(_('tag names cannot consist entirely of '
5548 'whitespace'))
5565 'whitespace'))
5549 if opts.get('rev') and opts.get('remove'):
5566 if opts.get('rev') and opts.get('remove'):
5550 raise error.Abort(_("--rev and --remove are incompatible"))
5567 raise error.Abort(_("--rev and --remove are incompatible"))
5551 if opts.get('rev'):
5568 if opts.get('rev'):
5552 rev_ = opts['rev']
5569 rev_ = opts['rev']
5553 message = opts.get('message')
5570 message = opts.get('message')
5554 if opts.get('remove'):
5571 if opts.get('remove'):
5555 if opts.get('local'):
5572 if opts.get('local'):
5556 expectedtype = 'local'
5573 expectedtype = 'local'
5557 else:
5574 else:
5558 expectedtype = 'global'
5575 expectedtype = 'global'
5559
5576
5560 for n in names:
5577 for n in names:
5561 if not repo.tagtype(n):
5578 if not repo.tagtype(n):
5562 raise error.Abort(_("tag '%s' does not exist") % n)
5579 raise error.Abort(_("tag '%s' does not exist") % n)
5563 if repo.tagtype(n) != expectedtype:
5580 if repo.tagtype(n) != expectedtype:
5564 if expectedtype == 'global':
5581 if expectedtype == 'global':
5565 raise error.Abort(_("tag '%s' is not a global tag") % n)
5582 raise error.Abort(_("tag '%s' is not a global tag") % n)
5566 else:
5583 else:
5567 raise error.Abort(_("tag '%s' is not a local tag") % n)
5584 raise error.Abort(_("tag '%s' is not a local tag") % n)
5568 rev_ = 'null'
5585 rev_ = 'null'
5569 if not message:
5586 if not message:
5570 # we don't translate commit messages
5587 # we don't translate commit messages
5571 message = 'Removed tag %s' % ', '.join(names)
5588 message = 'Removed tag %s' % ', '.join(names)
5572 elif not opts.get('force'):
5589 elif not opts.get('force'):
5573 for n in names:
5590 for n in names:
5574 if n in repo.tags():
5591 if n in repo.tags():
5575 raise error.Abort(_("tag '%s' already exists "
5592 raise error.Abort(_("tag '%s' already exists "
5576 "(use -f to force)") % n)
5593 "(use -f to force)") % n)
5577 if not opts.get('local'):
5594 if not opts.get('local'):
5578 p1, p2 = repo.dirstate.parents()
5595 p1, p2 = repo.dirstate.parents()
5579 if p2 != nullid:
5596 if p2 != nullid:
5580 raise error.Abort(_('uncommitted merge'))
5597 raise error.Abort(_('uncommitted merge'))
5581 bheads = repo.branchheads()
5598 bheads = repo.branchheads()
5582 if not opts.get('force') and bheads and p1 not in bheads:
5599 if not opts.get('force') and bheads and p1 not in bheads:
5583 raise error.Abort(_('working directory is not at a branch head '
5600 raise error.Abort(_('working directory is not at a branch head '
5584 '(use -f to force)'))
5601 '(use -f to force)'))
5585 node = scmutil.revsingle(repo, rev_).node()
5602 node = scmutil.revsingle(repo, rev_).node()
5586
5603
5587 if not message:
5604 if not message:
5588 # we don't translate commit messages
5605 # we don't translate commit messages
5589 message = ('Added tag %s for changeset %s' %
5606 message = ('Added tag %s for changeset %s' %
5590 (', '.join(names), short(node)))
5607 (', '.join(names), short(node)))
5591
5608
5592 date = opts.get('date')
5609 date = opts.get('date')
5593 if date:
5610 if date:
5594 date = dateutil.parsedate(date)
5611 date = dateutil.parsedate(date)
5595
5612
5596 if opts.get('remove'):
5613 if opts.get('remove'):
5597 editform = 'tag.remove'
5614 editform = 'tag.remove'
5598 else:
5615 else:
5599 editform = 'tag.add'
5616 editform = 'tag.add'
5600 editor = cmdutil.getcommiteditor(editform=editform,
5617 editor = cmdutil.getcommiteditor(editform=editform,
5601 **pycompat.strkwargs(opts))
5618 **pycompat.strkwargs(opts))
5602
5619
5603 # don't allow tagging the null rev
5620 # don't allow tagging the null rev
5604 if (not opts.get('remove') and
5621 if (not opts.get('remove') and
5605 scmutil.revsingle(repo, rev_).rev() == nullrev):
5622 scmutil.revsingle(repo, rev_).rev() == nullrev):
5606 raise error.Abort(_("cannot tag null revision"))
5623 raise error.Abort(_("cannot tag null revision"))
5607
5624
5608 tagsmod.tag(repo, names, node, message, opts.get('local'),
5625 tagsmod.tag(repo, names, node, message, opts.get('local'),
5609 opts.get('user'), date, editor=editor)
5626 opts.get('user'), date, editor=editor)
5610
5627
5611 @command('tags', formatteropts, '', intents={INTENT_READONLY})
5628 @command('tags', formatteropts, '', intents={INTENT_READONLY})
5612 def tags(ui, repo, **opts):
5629 def tags(ui, repo, **opts):
5613 """list repository tags
5630 """list repository tags
5614
5631
5615 This lists both regular and local tags. When the -v/--verbose
5632 This lists both regular and local tags. When the -v/--verbose
5616 switch is used, a third column "local" is printed for local tags.
5633 switch is used, a third column "local" is printed for local tags.
5617 When the -q/--quiet switch is used, only the tag name is printed.
5634 When the -q/--quiet switch is used, only the tag name is printed.
5618
5635
5619 Returns 0 on success.
5636 Returns 0 on success.
5620 """
5637 """
5621
5638
5622 opts = pycompat.byteskwargs(opts)
5639 opts = pycompat.byteskwargs(opts)
5623 ui.pager('tags')
5640 ui.pager('tags')
5624 fm = ui.formatter('tags', opts)
5641 fm = ui.formatter('tags', opts)
5625 contexthint = fm.contexthint('tag rev node type')
5642 contexthint = fm.contexthint('tag rev node type')
5626 hexfunc = fm.hexfunc
5643 hexfunc = fm.hexfunc
5627 tagtype = ""
5644 tagtype = ""
5628
5645
5629 for t, n in reversed(repo.tagslist()):
5646 for t, n in reversed(repo.tagslist()):
5630 hn = hexfunc(n)
5647 hn = hexfunc(n)
5631 label = 'tags.normal'
5648 label = 'tags.normal'
5632 tagtype = ''
5649 tagtype = ''
5633 if repo.tagtype(t) == 'local':
5650 if repo.tagtype(t) == 'local':
5634 label = 'tags.local'
5651 label = 'tags.local'
5635 tagtype = 'local'
5652 tagtype = 'local'
5636
5653
5637 fm.startitem()
5654 fm.startitem()
5638 if 'ctx' in contexthint:
5655 if 'ctx' in contexthint:
5639 fm.context(ctx=repo[n])
5656 fm.context(ctx=repo[n])
5640 fm.write('tag', '%s', t, label=label)
5657 fm.write('tag', '%s', t, label=label)
5641 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5658 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5642 fm.condwrite(not ui.quiet, 'rev node', fmt,
5659 fm.condwrite(not ui.quiet, 'rev node', fmt,
5643 repo.changelog.rev(n), hn, label=label)
5660 repo.changelog.rev(n), hn, label=label)
5644 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5661 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5645 tagtype, label=label)
5662 tagtype, label=label)
5646 fm.plain('\n')
5663 fm.plain('\n')
5647 fm.end()
5664 fm.end()
5648
5665
5649 @command('tip',
5666 @command('tip',
5650 [('p', 'patch', None, _('show patch')),
5667 [('p', 'patch', None, _('show patch')),
5651 ('g', 'git', None, _('use git extended diff format')),
5668 ('g', 'git', None, _('use git extended diff format')),
5652 ] + templateopts,
5669 ] + templateopts,
5653 _('[-p] [-g]'))
5670 _('[-p] [-g]'))
5654 def tip(ui, repo, **opts):
5671 def tip(ui, repo, **opts):
5655 """show the tip revision (DEPRECATED)
5672 """show the tip revision (DEPRECATED)
5656
5673
5657 The tip revision (usually just called the tip) is the changeset
5674 The tip revision (usually just called the tip) is the changeset
5658 most recently added to the repository (and therefore the most
5675 most recently added to the repository (and therefore the most
5659 recently changed head).
5676 recently changed head).
5660
5677
5661 If you have just made a commit, that commit will be the tip. If
5678 If you have just made a commit, that commit will be the tip. If
5662 you have just pulled changes from another repository, the tip of
5679 you have just pulled changes from another repository, the tip of
5663 that repository becomes the current tip. The "tip" tag is special
5680 that repository becomes the current tip. The "tip" tag is special
5664 and cannot be renamed or assigned to a different changeset.
5681 and cannot be renamed or assigned to a different changeset.
5665
5682
5666 This command is deprecated, please use :hg:`heads` instead.
5683 This command is deprecated, please use :hg:`heads` instead.
5667
5684
5668 Returns 0 on success.
5685 Returns 0 on success.
5669 """
5686 """
5670 opts = pycompat.byteskwargs(opts)
5687 opts = pycompat.byteskwargs(opts)
5671 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
5688 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
5672 displayer.show(repo['tip'])
5689 displayer.show(repo['tip'])
5673 displayer.close()
5690 displayer.close()
5674
5691
5675 @command('unbundle',
5692 @command('unbundle',
5676 [('u', 'update', None,
5693 [('u', 'update', None,
5677 _('update to new branch head if changesets were unbundled'))],
5694 _('update to new branch head if changesets were unbundled'))],
5678 _('[-u] FILE...'))
5695 _('[-u] FILE...'))
5679 def unbundle(ui, repo, fname1, *fnames, **opts):
5696 def unbundle(ui, repo, fname1, *fnames, **opts):
5680 """apply one or more bundle files
5697 """apply one or more bundle files
5681
5698
5682 Apply one or more bundle files generated by :hg:`bundle`.
5699 Apply one or more bundle files generated by :hg:`bundle`.
5683
5700
5684 Returns 0 on success, 1 if an update has unresolved files.
5701 Returns 0 on success, 1 if an update has unresolved files.
5685 """
5702 """
5686 fnames = (fname1,) + fnames
5703 fnames = (fname1,) + fnames
5687
5704
5688 with repo.lock():
5705 with repo.lock():
5689 for fname in fnames:
5706 for fname in fnames:
5690 f = hg.openpath(ui, fname)
5707 f = hg.openpath(ui, fname)
5691 gen = exchange.readbundle(ui, f, fname)
5708 gen = exchange.readbundle(ui, f, fname)
5692 if isinstance(gen, streamclone.streamcloneapplier):
5709 if isinstance(gen, streamclone.streamcloneapplier):
5693 raise error.Abort(
5710 raise error.Abort(
5694 _('packed bundles cannot be applied with '
5711 _('packed bundles cannot be applied with '
5695 '"hg unbundle"'),
5712 '"hg unbundle"'),
5696 hint=_('use "hg debugapplystreamclonebundle"'))
5713 hint=_('use "hg debugapplystreamclonebundle"'))
5697 url = 'bundle:' + fname
5714 url = 'bundle:' + fname
5698 try:
5715 try:
5699 txnname = 'unbundle'
5716 txnname = 'unbundle'
5700 if not isinstance(gen, bundle2.unbundle20):
5717 if not isinstance(gen, bundle2.unbundle20):
5701 txnname = 'unbundle\n%s' % util.hidepassword(url)
5718 txnname = 'unbundle\n%s' % util.hidepassword(url)
5702 with repo.transaction(txnname) as tr:
5719 with repo.transaction(txnname) as tr:
5703 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
5720 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
5704 url=url)
5721 url=url)
5705 except error.BundleUnknownFeatureError as exc:
5722 except error.BundleUnknownFeatureError as exc:
5706 raise error.Abort(
5723 raise error.Abort(
5707 _('%s: unknown bundle feature, %s') % (fname, exc),
5724 _('%s: unknown bundle feature, %s') % (fname, exc),
5708 hint=_("see https://mercurial-scm.org/"
5725 hint=_("see https://mercurial-scm.org/"
5709 "wiki/BundleFeature for more "
5726 "wiki/BundleFeature for more "
5710 "information"))
5727 "information"))
5711 modheads = bundle2.combinechangegroupresults(op)
5728 modheads = bundle2.combinechangegroupresults(op)
5712
5729
5713 return postincoming(ui, repo, modheads, opts.get(r'update'), None, None)
5730 return postincoming(ui, repo, modheads, opts.get(r'update'), None, None)
5714
5731
5715 @command('^update|up|checkout|co',
5732 @command('^update|up|checkout|co',
5716 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5733 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5717 ('c', 'check', None, _('require clean working directory')),
5734 ('c', 'check', None, _('require clean working directory')),
5718 ('m', 'merge', None, _('merge uncommitted changes')),
5735 ('m', 'merge', None, _('merge uncommitted changes')),
5719 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5736 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5720 ('r', 'rev', '', _('revision'), _('REV'))
5737 ('r', 'rev', '', _('revision'), _('REV'))
5721 ] + mergetoolopts,
5738 ] + mergetoolopts,
5722 _('[-C|-c|-m] [-d DATE] [[-r] REV]'))
5739 _('[-C|-c|-m] [-d DATE] [[-r] REV]'))
5723 def update(ui, repo, node=None, **opts):
5740 def update(ui, repo, node=None, **opts):
5724 """update working directory (or switch revisions)
5741 """update working directory (or switch revisions)
5725
5742
5726 Update the repository's working directory to the specified
5743 Update the repository's working directory to the specified
5727 changeset. If no changeset is specified, update to the tip of the
5744 changeset. If no changeset is specified, update to the tip of the
5728 current named branch and move the active bookmark (see :hg:`help
5745 current named branch and move the active bookmark (see :hg:`help
5729 bookmarks`).
5746 bookmarks`).
5730
5747
5731 Update sets the working directory's parent revision to the specified
5748 Update sets the working directory's parent revision to the specified
5732 changeset (see :hg:`help parents`).
5749 changeset (see :hg:`help parents`).
5733
5750
5734 If the changeset is not a descendant or ancestor of the working
5751 If the changeset is not a descendant or ancestor of the working
5735 directory's parent and there are uncommitted changes, the update is
5752 directory's parent and there are uncommitted changes, the update is
5736 aborted. With the -c/--check option, the working directory is checked
5753 aborted. With the -c/--check option, the working directory is checked
5737 for uncommitted changes; if none are found, the working directory is
5754 for uncommitted changes; if none are found, the working directory is
5738 updated to the specified changeset.
5755 updated to the specified changeset.
5739
5756
5740 .. container:: verbose
5757 .. container:: verbose
5741
5758
5742 The -C/--clean, -c/--check, and -m/--merge options control what
5759 The -C/--clean, -c/--check, and -m/--merge options control what
5743 happens if the working directory contains uncommitted changes.
5760 happens if the working directory contains uncommitted changes.
5744 At most of one of them can be specified.
5761 At most of one of them can be specified.
5745
5762
5746 1. If no option is specified, and if
5763 1. If no option is specified, and if
5747 the requested changeset is an ancestor or descendant of
5764 the requested changeset is an ancestor or descendant of
5748 the working directory's parent, the uncommitted changes
5765 the working directory's parent, the uncommitted changes
5749 are merged into the requested changeset and the merged
5766 are merged into the requested changeset and the merged
5750 result is left uncommitted. If the requested changeset is
5767 result is left uncommitted. If the requested changeset is
5751 not an ancestor or descendant (that is, it is on another
5768 not an ancestor or descendant (that is, it is on another
5752 branch), the update is aborted and the uncommitted changes
5769 branch), the update is aborted and the uncommitted changes
5753 are preserved.
5770 are preserved.
5754
5771
5755 2. With the -m/--merge option, the update is allowed even if the
5772 2. With the -m/--merge option, the update is allowed even if the
5756 requested changeset is not an ancestor or descendant of
5773 requested changeset is not an ancestor or descendant of
5757 the working directory's parent.
5774 the working directory's parent.
5758
5775
5759 3. With the -c/--check option, the update is aborted and the
5776 3. With the -c/--check option, the update is aborted and the
5760 uncommitted changes are preserved.
5777 uncommitted changes are preserved.
5761
5778
5762 4. With the -C/--clean option, uncommitted changes are discarded and
5779 4. With the -C/--clean option, uncommitted changes are discarded and
5763 the working directory is updated to the requested changeset.
5780 the working directory is updated to the requested changeset.
5764
5781
5765 To cancel an uncommitted merge (and lose your changes), use
5782 To cancel an uncommitted merge (and lose your changes), use
5766 :hg:`merge --abort`.
5783 :hg:`merge --abort`.
5767
5784
5768 Use null as the changeset to remove the working directory (like
5785 Use null as the changeset to remove the working directory (like
5769 :hg:`clone -U`).
5786 :hg:`clone -U`).
5770
5787
5771 If you want to revert just one file to an older revision, use
5788 If you want to revert just one file to an older revision, use
5772 :hg:`revert [-r REV] NAME`.
5789 :hg:`revert [-r REV] NAME`.
5773
5790
5774 See :hg:`help dates` for a list of formats valid for -d/--date.
5791 See :hg:`help dates` for a list of formats valid for -d/--date.
5775
5792
5776 Returns 0 on success, 1 if there are unresolved files.
5793 Returns 0 on success, 1 if there are unresolved files.
5777 """
5794 """
5778 rev = opts.get(r'rev')
5795 rev = opts.get(r'rev')
5779 date = opts.get(r'date')
5796 date = opts.get(r'date')
5780 clean = opts.get(r'clean')
5797 clean = opts.get(r'clean')
5781 check = opts.get(r'check')
5798 check = opts.get(r'check')
5782 merge = opts.get(r'merge')
5799 merge = opts.get(r'merge')
5783 if rev and node:
5800 if rev and node:
5784 raise error.Abort(_("please specify just one revision"))
5801 raise error.Abort(_("please specify just one revision"))
5785
5802
5786 if ui.configbool('commands', 'update.requiredest'):
5803 if ui.configbool('commands', 'update.requiredest'):
5787 if not node and not rev and not date:
5804 if not node and not rev and not date:
5788 raise error.Abort(_('you must specify a destination'),
5805 raise error.Abort(_('you must specify a destination'),
5789 hint=_('for example: hg update ".::"'))
5806 hint=_('for example: hg update ".::"'))
5790
5807
5791 if rev is None or rev == '':
5808 if rev is None or rev == '':
5792 rev = node
5809 rev = node
5793
5810
5794 if date and rev is not None:
5811 if date and rev is not None:
5795 raise error.Abort(_("you can't specify a revision and a date"))
5812 raise error.Abort(_("you can't specify a revision and a date"))
5796
5813
5797 if len([x for x in (clean, check, merge) if x]) > 1:
5814 if len([x for x in (clean, check, merge) if x]) > 1:
5798 raise error.Abort(_("can only specify one of -C/--clean, -c/--check, "
5815 raise error.Abort(_("can only specify one of -C/--clean, -c/--check, "
5799 "or -m/--merge"))
5816 "or -m/--merge"))
5800
5817
5801 updatecheck = None
5818 updatecheck = None
5802 if check:
5819 if check:
5803 updatecheck = 'abort'
5820 updatecheck = 'abort'
5804 elif merge:
5821 elif merge:
5805 updatecheck = 'none'
5822 updatecheck = 'none'
5806
5823
5807 with repo.wlock():
5824 with repo.wlock():
5808 cmdutil.clearunfinished(repo)
5825 cmdutil.clearunfinished(repo)
5809
5826
5810 if date:
5827 if date:
5811 rev = cmdutil.finddate(ui, repo, date)
5828 rev = cmdutil.finddate(ui, repo, date)
5812
5829
5813 # if we defined a bookmark, we have to remember the original name
5830 # if we defined a bookmark, we have to remember the original name
5814 brev = rev
5831 brev = rev
5815 if rev:
5832 if rev:
5816 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
5833 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
5817 ctx = scmutil.revsingle(repo, rev, rev)
5834 ctx = scmutil.revsingle(repo, rev, rev)
5818 rev = ctx.rev()
5835 rev = ctx.rev()
5819 hidden = ctx.hidden()
5836 hidden = ctx.hidden()
5820 overrides = {('ui', 'forcemerge'): opts.get(r'tool', '')}
5837 overrides = {('ui', 'forcemerge'): opts.get(r'tool', '')}
5821 with ui.configoverride(overrides, 'update'):
5838 with ui.configoverride(overrides, 'update'):
5822 ret = hg.updatetotally(ui, repo, rev, brev, clean=clean,
5839 ret = hg.updatetotally(ui, repo, rev, brev, clean=clean,
5823 updatecheck=updatecheck)
5840 updatecheck=updatecheck)
5824 if hidden:
5841 if hidden:
5825 ctxstr = ctx.hex()[:12]
5842 ctxstr = ctx.hex()[:12]
5826 ui.warn(_("updated to hidden changeset %s\n") % ctxstr)
5843 ui.warn(_("updated to hidden changeset %s\n") % ctxstr)
5827
5844
5828 if ctx.obsolete():
5845 if ctx.obsolete():
5829 obsfatemsg = obsutil._getfilteredreason(repo, ctxstr, ctx)
5846 obsfatemsg = obsutil._getfilteredreason(repo, ctxstr, ctx)
5830 ui.warn("(%s)\n" % obsfatemsg)
5847 ui.warn("(%s)\n" % obsfatemsg)
5831 return ret
5848 return ret
5832
5849
5833 @command('verify', [])
5850 @command('verify', [])
5834 def verify(ui, repo):
5851 def verify(ui, repo):
5835 """verify the integrity of the repository
5852 """verify the integrity of the repository
5836
5853
5837 Verify the integrity of the current repository.
5854 Verify the integrity of the current repository.
5838
5855
5839 This will perform an extensive check of the repository's
5856 This will perform an extensive check of the repository's
5840 integrity, validating the hashes and checksums of each entry in
5857 integrity, validating the hashes and checksums of each entry in
5841 the changelog, manifest, and tracked files, as well as the
5858 the changelog, manifest, and tracked files, as well as the
5842 integrity of their crosslinks and indices.
5859 integrity of their crosslinks and indices.
5843
5860
5844 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
5861 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
5845 for more information about recovery from corruption of the
5862 for more information about recovery from corruption of the
5846 repository.
5863 repository.
5847
5864
5848 Returns 0 on success, 1 if errors are encountered.
5865 Returns 0 on success, 1 if errors are encountered.
5849 """
5866 """
5850 return hg.verify(repo)
5867 return hg.verify(repo)
5851
5868
5852 @command('version', [] + formatteropts, norepo=True,
5869 @command('version', [] + formatteropts, norepo=True,
5853 intents={INTENT_READONLY})
5870 intents={INTENT_READONLY})
5854 def version_(ui, **opts):
5871 def version_(ui, **opts):
5855 """output version and copyright information"""
5872 """output version and copyright information"""
5856 opts = pycompat.byteskwargs(opts)
5873 opts = pycompat.byteskwargs(opts)
5857 if ui.verbose:
5874 if ui.verbose:
5858 ui.pager('version')
5875 ui.pager('version')
5859 fm = ui.formatter("version", opts)
5876 fm = ui.formatter("version", opts)
5860 fm.startitem()
5877 fm.startitem()
5861 fm.write("ver", _("Mercurial Distributed SCM (version %s)\n"),
5878 fm.write("ver", _("Mercurial Distributed SCM (version %s)\n"),
5862 util.version())
5879 util.version())
5863 license = _(
5880 license = _(
5864 "(see https://mercurial-scm.org for more information)\n"
5881 "(see https://mercurial-scm.org for more information)\n"
5865 "\nCopyright (C) 2005-2018 Matt Mackall and others\n"
5882 "\nCopyright (C) 2005-2018 Matt Mackall and others\n"
5866 "This is free software; see the source for copying conditions. "
5883 "This is free software; see the source for copying conditions. "
5867 "There is NO\nwarranty; "
5884 "There is NO\nwarranty; "
5868 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5885 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5869 )
5886 )
5870 if not ui.quiet:
5887 if not ui.quiet:
5871 fm.plain(license)
5888 fm.plain(license)
5872
5889
5873 if ui.verbose:
5890 if ui.verbose:
5874 fm.plain(_("\nEnabled extensions:\n\n"))
5891 fm.plain(_("\nEnabled extensions:\n\n"))
5875 # format names and versions into columns
5892 # format names and versions into columns
5876 names = []
5893 names = []
5877 vers = []
5894 vers = []
5878 isinternals = []
5895 isinternals = []
5879 for name, module in extensions.extensions():
5896 for name, module in extensions.extensions():
5880 names.append(name)
5897 names.append(name)
5881 vers.append(extensions.moduleversion(module) or None)
5898 vers.append(extensions.moduleversion(module) or None)
5882 isinternals.append(extensions.ismoduleinternal(module))
5899 isinternals.append(extensions.ismoduleinternal(module))
5883 fn = fm.nested("extensions", tmpl='{name}\n')
5900 fn = fm.nested("extensions", tmpl='{name}\n')
5884 if names:
5901 if names:
5885 namefmt = " %%-%ds " % max(len(n) for n in names)
5902 namefmt = " %%-%ds " % max(len(n) for n in names)
5886 places = [_("external"), _("internal")]
5903 places = [_("external"), _("internal")]
5887 for n, v, p in zip(names, vers, isinternals):
5904 for n, v, p in zip(names, vers, isinternals):
5888 fn.startitem()
5905 fn.startitem()
5889 fn.condwrite(ui.verbose, "name", namefmt, n)
5906 fn.condwrite(ui.verbose, "name", namefmt, n)
5890 if ui.verbose:
5907 if ui.verbose:
5891 fn.plain("%s " % places[p])
5908 fn.plain("%s " % places[p])
5892 fn.data(bundled=p)
5909 fn.data(bundled=p)
5893 fn.condwrite(ui.verbose and v, "ver", "%s", v)
5910 fn.condwrite(ui.verbose and v, "ver", "%s", v)
5894 if ui.verbose:
5911 if ui.verbose:
5895 fn.plain("\n")
5912 fn.plain("\n")
5896 fn.end()
5913 fn.end()
5897 fm.end()
5914 fm.end()
5898
5915
5899 def loadcmdtable(ui, name, cmdtable):
5916 def loadcmdtable(ui, name, cmdtable):
5900 """Load command functions from specified cmdtable
5917 """Load command functions from specified cmdtable
5901 """
5918 """
5902 overrides = [cmd for cmd in cmdtable if cmd in table]
5919 overrides = [cmd for cmd in cmdtable if cmd in table]
5903 if overrides:
5920 if overrides:
5904 ui.warn(_("extension '%s' overrides commands: %s\n")
5921 ui.warn(_("extension '%s' overrides commands: %s\n")
5905 % (name, " ".join(overrides)))
5922 % (name, " ".join(overrides)))
5906 table.update(cmdtable)
5923 table.update(cmdtable)
@@ -1,283 +1,280 b''
1 $ . "$TESTDIR/narrow-library.sh"
1 $ . "$TESTDIR/narrow-library.sh"
2
2
3 $ hg init master
3 $ hg init master
4 $ cd master
4 $ cd master
5 $ cat >> .hg/hgrc <<EOF
5 $ cat >> .hg/hgrc <<EOF
6 > [narrow]
6 > [narrow]
7 > serveellipses=True
7 > serveellipses=True
8 > EOF
8 > EOF
9 $ mkdir dir
9 $ mkdir dir
10 $ mkdir dir/src
10 $ mkdir dir/src
11 $ cd dir/src
11 $ cd dir/src
12 $ for x in `$TESTDIR/seq.py 20`; do echo $x > "f$x"; hg add "f$x"; hg commit -m "Commit src $x"; done
12 $ for x in `$TESTDIR/seq.py 20`; do echo $x > "f$x"; hg add "f$x"; hg commit -m "Commit src $x"; done
13 $ cd ..
13 $ cd ..
14 $ mkdir tests
14 $ mkdir tests
15 $ cd tests
15 $ cd tests
16 $ for x in `$TESTDIR/seq.py 20`; do echo $x > "t$x"; hg add "t$x"; hg commit -m "Commit test $x"; done
16 $ for x in `$TESTDIR/seq.py 20`; do echo $x > "t$x"; hg add "t$x"; hg commit -m "Commit test $x"; done
17 $ cd ../../..
17 $ cd ../../..
18
18
19 Only path: and rootfilesin: pattern prefixes are allowed
19 Only path: and rootfilesin: pattern prefixes are allowed
20
20
21 $ hg clone --narrow ssh://user@dummy/master badnarrow --noupdate --include 'glob:**'
21 $ hg clone --narrow ssh://user@dummy/master badnarrow --noupdate --include 'glob:**'
22 requesting all changes
23 abort: invalid prefix on narrow pattern: glob:**
22 abort: invalid prefix on narrow pattern: glob:**
24 (narrow patterns must begin with one of the following: path:, rootfilesin:)
23 (narrow patterns must begin with one of the following: path:, rootfilesin:)
25 [255]
24 [255]
26
25
27 $ hg clone --narrow ssh://user@dummy/master badnarrow --noupdate --exclude 'set:ignored'
26 $ hg clone --narrow ssh://user@dummy/master badnarrow --noupdate --exclude 'set:ignored'
28 requesting all changes
29 abort: invalid prefix on narrow pattern: set:ignored
27 abort: invalid prefix on narrow pattern: set:ignored
30 (narrow patterns must begin with one of the following: path:, rootfilesin:)
28 (narrow patterns must begin with one of the following: path:, rootfilesin:)
31 [255]
29 [255]
32
30
33 narrow clone a file, f10
31 narrow clone a file, f10
34
32
35 $ hg clone --narrow ssh://user@dummy/master narrow --noupdate --include "dir/src/f10"
33 $ hg clone --narrow ssh://user@dummy/master narrow --noupdate --include "dir/src/f10"
36 requesting all changes
34 requesting all changes
37 adding changesets
35 adding changesets
38 adding manifests
36 adding manifests
39 adding file changes
37 adding file changes
40 added 3 changesets with 1 changes to 1 files
38 added 3 changesets with 1 changes to 1 files
41 new changesets *:* (glob)
39 new changesets *:* (glob)
42 $ cd narrow
40 $ cd narrow
43 $ cat .hg/requires | grep -v generaldelta
41 $ cat .hg/requires | grep -v generaldelta
44 dotencode
42 dotencode
45 fncache
43 fncache
46 narrowhg-experimental
44 narrowhg-experimental
47 revlogv1
45 revlogv1
48 store
46 store
49 testonly-simplestore (reposimplestore !)
47 testonly-simplestore (reposimplestore !)
50
48
51 $ hg tracked
49 $ hg tracked
52 I path:dir/src/f10
50 I path:dir/src/f10
53 $ hg tracked
51 $ hg tracked
54 I path:dir/src/f10
52 I path:dir/src/f10
55 $ hg update
53 $ hg update
56 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
54 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
57 $ find * | sort
55 $ find * | sort
58 dir
56 dir
59 dir/src
57 dir/src
60 dir/src/f10
58 dir/src/f10
61 $ cat dir/src/f10
59 $ cat dir/src/f10
62 10
60 10
63
61
64 $ cd ..
62 $ cd ..
65
63
66 narrow clone with a newline should fail
64 narrow clone with a newline should fail
67
65
68 $ hg clone --narrow ssh://user@dummy/master narrow_fail --noupdate --include 'dir/src/f10
66 $ hg clone --narrow ssh://user@dummy/master narrow_fail --noupdate --include 'dir/src/f10
69 > '
67 > '
70 requesting all changes
71 abort: newlines are not allowed in narrowspec paths
68 abort: newlines are not allowed in narrowspec paths
72 [255]
69 [255]
73
70
74 narrow clone a directory, tests/, except tests/t19
71 narrow clone a directory, tests/, except tests/t19
75
72
76 $ hg clone --narrow ssh://user@dummy/master narrowdir --noupdate --include "dir/tests/" --exclude "dir/tests/t19"
73 $ hg clone --narrow ssh://user@dummy/master narrowdir --noupdate --include "dir/tests/" --exclude "dir/tests/t19"
77 requesting all changes
74 requesting all changes
78 adding changesets
75 adding changesets
79 adding manifests
76 adding manifests
80 adding file changes
77 adding file changes
81 added 21 changesets with 19 changes to 19 files
78 added 21 changesets with 19 changes to 19 files
82 new changesets *:* (glob)
79 new changesets *:* (glob)
83 $ cd narrowdir
80 $ cd narrowdir
84 $ hg tracked
81 $ hg tracked
85 I path:dir/tests
82 I path:dir/tests
86 X path:dir/tests/t19
83 X path:dir/tests/t19
87 $ hg tracked
84 $ hg tracked
88 I path:dir/tests
85 I path:dir/tests
89 X path:dir/tests/t19
86 X path:dir/tests/t19
90 $ hg update
87 $ hg update
91 19 files updated, 0 files merged, 0 files removed, 0 files unresolved
88 19 files updated, 0 files merged, 0 files removed, 0 files unresolved
92 $ find * | sort
89 $ find * | sort
93 dir
90 dir
94 dir/tests
91 dir/tests
95 dir/tests/t1
92 dir/tests/t1
96 dir/tests/t10
93 dir/tests/t10
97 dir/tests/t11
94 dir/tests/t11
98 dir/tests/t12
95 dir/tests/t12
99 dir/tests/t13
96 dir/tests/t13
100 dir/tests/t14
97 dir/tests/t14
101 dir/tests/t15
98 dir/tests/t15
102 dir/tests/t16
99 dir/tests/t16
103 dir/tests/t17
100 dir/tests/t17
104 dir/tests/t18
101 dir/tests/t18
105 dir/tests/t2
102 dir/tests/t2
106 dir/tests/t20
103 dir/tests/t20
107 dir/tests/t3
104 dir/tests/t3
108 dir/tests/t4
105 dir/tests/t4
109 dir/tests/t5
106 dir/tests/t5
110 dir/tests/t6
107 dir/tests/t6
111 dir/tests/t7
108 dir/tests/t7
112 dir/tests/t8
109 dir/tests/t8
113 dir/tests/t9
110 dir/tests/t9
114
111
115 $ cd ..
112 $ cd ..
116
113
117 narrow clone everything but a directory (tests/)
114 narrow clone everything but a directory (tests/)
118
115
119 $ hg clone --narrow ssh://user@dummy/master narrowroot --noupdate --exclude "dir/tests"
116 $ hg clone --narrow ssh://user@dummy/master narrowroot --noupdate --exclude "dir/tests"
120 requesting all changes
117 requesting all changes
121 adding changesets
118 adding changesets
122 adding manifests
119 adding manifests
123 adding file changes
120 adding file changes
124 added 21 changesets with 20 changes to 20 files
121 added 21 changesets with 20 changes to 20 files
125 new changesets *:* (glob)
122 new changesets *:* (glob)
126 $ cd narrowroot
123 $ cd narrowroot
127 $ hg tracked
124 $ hg tracked
128 I path:.
125 I path:.
129 X path:dir/tests
126 X path:dir/tests
130 $ hg tracked
127 $ hg tracked
131 I path:.
128 I path:.
132 X path:dir/tests
129 X path:dir/tests
133 $ hg update
130 $ hg update
134 20 files updated, 0 files merged, 0 files removed, 0 files unresolved
131 20 files updated, 0 files merged, 0 files removed, 0 files unresolved
135 $ find * | sort
132 $ find * | sort
136 dir
133 dir
137 dir/src
134 dir/src
138 dir/src/f1
135 dir/src/f1
139 dir/src/f10
136 dir/src/f10
140 dir/src/f11
137 dir/src/f11
141 dir/src/f12
138 dir/src/f12
142 dir/src/f13
139 dir/src/f13
143 dir/src/f14
140 dir/src/f14
144 dir/src/f15
141 dir/src/f15
145 dir/src/f16
142 dir/src/f16
146 dir/src/f17
143 dir/src/f17
147 dir/src/f18
144 dir/src/f18
148 dir/src/f19
145 dir/src/f19
149 dir/src/f2
146 dir/src/f2
150 dir/src/f20
147 dir/src/f20
151 dir/src/f3
148 dir/src/f3
152 dir/src/f4
149 dir/src/f4
153 dir/src/f5
150 dir/src/f5
154 dir/src/f6
151 dir/src/f6
155 dir/src/f7
152 dir/src/f7
156 dir/src/f8
153 dir/src/f8
157 dir/src/f9
154 dir/src/f9
158
155
159 $ cd ..
156 $ cd ..
160
157
161 narrow clone no paths at all
158 narrow clone no paths at all
162
159
163 $ hg clone --narrow ssh://user@dummy/master narrowempty --noupdate
160 $ hg clone --narrow ssh://user@dummy/master narrowempty --noupdate
164 requesting all changes
161 requesting all changes
165 adding changesets
162 adding changesets
166 adding manifests
163 adding manifests
167 adding file changes
164 adding file changes
168 added 1 changesets with 0 changes to 0 files
165 added 1 changesets with 0 changes to 0 files
169 new changesets * (glob)
166 new changesets * (glob)
170 $ cd narrowempty
167 $ cd narrowempty
171 $ hg tracked
168 $ hg tracked
172 $ hg update
169 $ hg update
173 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
170 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
174 $ ls
171 $ ls
175
172
176 $ cd ..
173 $ cd ..
177
174
178 simple clone
175 simple clone
179 $ hg clone ssh://user@dummy/master simpleclone
176 $ hg clone ssh://user@dummy/master simpleclone
180 requesting all changes
177 requesting all changes
181 adding changesets
178 adding changesets
182 adding manifests
179 adding manifests
183 adding file changes
180 adding file changes
184 added 40 changesets with 40 changes to 40 files
181 added 40 changesets with 40 changes to 40 files
185 new changesets * (glob)
182 new changesets * (glob)
186 updating to branch default
183 updating to branch default
187 40 files updated, 0 files merged, 0 files removed, 0 files unresolved
184 40 files updated, 0 files merged, 0 files removed, 0 files unresolved
188 $ cd simpleclone
185 $ cd simpleclone
189 $ find * | sort
186 $ find * | sort
190 dir
187 dir
191 dir/src
188 dir/src
192 dir/src/f1
189 dir/src/f1
193 dir/src/f10
190 dir/src/f10
194 dir/src/f11
191 dir/src/f11
195 dir/src/f12
192 dir/src/f12
196 dir/src/f13
193 dir/src/f13
197 dir/src/f14
194 dir/src/f14
198 dir/src/f15
195 dir/src/f15
199 dir/src/f16
196 dir/src/f16
200 dir/src/f17
197 dir/src/f17
201 dir/src/f18
198 dir/src/f18
202 dir/src/f19
199 dir/src/f19
203 dir/src/f2
200 dir/src/f2
204 dir/src/f20
201 dir/src/f20
205 dir/src/f3
202 dir/src/f3
206 dir/src/f4
203 dir/src/f4
207 dir/src/f5
204 dir/src/f5
208 dir/src/f6
205 dir/src/f6
209 dir/src/f7
206 dir/src/f7
210 dir/src/f8
207 dir/src/f8
211 dir/src/f9
208 dir/src/f9
212 dir/tests
209 dir/tests
213 dir/tests/t1
210 dir/tests/t1
214 dir/tests/t10
211 dir/tests/t10
215 dir/tests/t11
212 dir/tests/t11
216 dir/tests/t12
213 dir/tests/t12
217 dir/tests/t13
214 dir/tests/t13
218 dir/tests/t14
215 dir/tests/t14
219 dir/tests/t15
216 dir/tests/t15
220 dir/tests/t16
217 dir/tests/t16
221 dir/tests/t17
218 dir/tests/t17
222 dir/tests/t18
219 dir/tests/t18
223 dir/tests/t19
220 dir/tests/t19
224 dir/tests/t2
221 dir/tests/t2
225 dir/tests/t20
222 dir/tests/t20
226 dir/tests/t3
223 dir/tests/t3
227 dir/tests/t4
224 dir/tests/t4
228 dir/tests/t5
225 dir/tests/t5
229 dir/tests/t6
226 dir/tests/t6
230 dir/tests/t7
227 dir/tests/t7
231 dir/tests/t8
228 dir/tests/t8
232 dir/tests/t9
229 dir/tests/t9
233
230
234 $ cd ..
231 $ cd ..
235
232
236 Testing the --narrowspec flag to clone
233 Testing the --narrowspec flag to clone
237
234
238 $ cat >> narrowspecs <<EOF
235 $ cat >> narrowspecs <<EOF
239 > %include foo
236 > %include foo
240 > [include]
237 > [include]
241 > path:dir/tests/
238 > path:dir/tests/
242 > path:dir/src/f12
239 > path:dir/src/f12
243 > EOF
240 > EOF
244
241
245 $ hg clone ssh://user@dummy/master specfile --narrowspec narrowspecs
242 $ hg clone ssh://user@dummy/master specfile --narrowspec narrowspecs
246 reading narrowspec from '$TESTTMP/narrowspecs'
243 reading narrowspec from '$TESTTMP/narrowspecs'
247 abort: cannot specify other files using '%include' in narrowspec
244 abort: cannot specify other files using '%include' in narrowspec
248 [255]
245 [255]
249
246
250 $ cat > narrowspecs <<EOF
247 $ cat > narrowspecs <<EOF
251 > [include]
248 > [include]
252 > path:dir/tests/
249 > path:dir/tests/
253 > path:dir/src/f12
250 > path:dir/src/f12
254 > EOF
251 > EOF
255
252
256 $ hg clone ssh://user@dummy/master specfile --narrowspec narrowspecs
253 $ hg clone ssh://user@dummy/master specfile --narrowspec narrowspecs
257 reading narrowspec from '$TESTTMP/narrowspecs'
254 reading narrowspec from '$TESTTMP/narrowspecs'
258 requesting all changes
255 requesting all changes
259 adding changesets
256 adding changesets
260 adding manifests
257 adding manifests
261 adding file changes
258 adding file changes
262 added 23 changesets with 21 changes to 21 files
259 added 23 changesets with 21 changes to 21 files
263 new changesets c13e3773edb4:26ce255d5b5d
260 new changesets c13e3773edb4:26ce255d5b5d
264 updating to branch default
261 updating to branch default
265 21 files updated, 0 files merged, 0 files removed, 0 files unresolved
262 21 files updated, 0 files merged, 0 files removed, 0 files unresolved
266 $ cd specfile
263 $ cd specfile
267 $ hg tracked
264 $ hg tracked
268 I path:dir/src/f12
265 I path:dir/src/f12
269 I path:dir/tests
266 I path:dir/tests
270 $ cd ..
267 $ cd ..
271
268
272 Narrow spec with invalid patterns is rejected
269 Narrow spec with invalid patterns is rejected
273
270
274 $ cat > narrowspecs <<EOF
271 $ cat > narrowspecs <<EOF
275 > [include]
272 > [include]
276 > glob:**
273 > glob:**
277 > EOF
274 > EOF
278
275
279 $ hg clone ssh://user@dummy/master badspecfile --narrowspec narrowspecs
276 $ hg clone ssh://user@dummy/master badspecfile --narrowspec narrowspecs
280 reading narrowspec from '$TESTTMP/narrowspecs'
277 reading narrowspec from '$TESTTMP/narrowspecs'
281 abort: invalid prefix on narrow pattern: glob:**
278 abort: invalid prefix on narrow pattern: glob:**
282 (narrow patterns must begin with one of the following: path:, rootfilesin:)
279 (narrow patterns must begin with one of the following: path:, rootfilesin:)
283 [255]
280 [255]
@@ -1,402 +1,399 b''
1 #testcases flat tree
1 #testcases flat tree
2
2
3 $ . "$TESTDIR/narrow-library.sh"
3 $ . "$TESTDIR/narrow-library.sh"
4
4
5 #if tree
5 #if tree
6 $ cat << EOF >> $HGRCPATH
6 $ cat << EOF >> $HGRCPATH
7 > [experimental]
7 > [experimental]
8 > treemanifest = 1
8 > treemanifest = 1
9 > EOF
9 > EOF
10 #endif
10 #endif
11
11
12 $ hg init master
12 $ hg init master
13 $ cd master
13 $ cd master
14 $ cat >> .hg/hgrc <<EOF
14 $ cat >> .hg/hgrc <<EOF
15 > [narrow]
15 > [narrow]
16 > serveellipses=True
16 > serveellipses=True
17 > EOF
17 > EOF
18 $ for x in `$TESTDIR/seq.py 0 10`
18 $ for x in `$TESTDIR/seq.py 0 10`
19 > do
19 > do
20 > mkdir d$x
20 > mkdir d$x
21 > echo $x > d$x/f
21 > echo $x > d$x/f
22 > hg add d$x/f
22 > hg add d$x/f
23 > hg commit -m "add d$x/f"
23 > hg commit -m "add d$x/f"
24 > done
24 > done
25 $ hg log -T "{rev}: {desc}\n"
25 $ hg log -T "{rev}: {desc}\n"
26 10: add d10/f
26 10: add d10/f
27 9: add d9/f
27 9: add d9/f
28 8: add d8/f
28 8: add d8/f
29 7: add d7/f
29 7: add d7/f
30 6: add d6/f
30 6: add d6/f
31 5: add d5/f
31 5: add d5/f
32 4: add d4/f
32 4: add d4/f
33 3: add d3/f
33 3: add d3/f
34 2: add d2/f
34 2: add d2/f
35 1: add d1/f
35 1: add d1/f
36 0: add d0/f
36 0: add d0/f
37 $ cd ..
37 $ cd ..
38
38
39 Error if '.' or '..' are in the directory to track.
39 Error if '.' or '..' are in the directory to track.
40 $ hg clone --narrow ssh://user@dummy/master foo --include ./asdf
40 $ hg clone --narrow ssh://user@dummy/master foo --include ./asdf
41 requesting all changes
42 abort: "." and ".." are not allowed in narrowspec paths
41 abort: "." and ".." are not allowed in narrowspec paths
43 [255]
42 [255]
44 $ hg clone --narrow ssh://user@dummy/master foo --include asdf/..
43 $ hg clone --narrow ssh://user@dummy/master foo --include asdf/..
45 requesting all changes
46 abort: "." and ".." are not allowed in narrowspec paths
44 abort: "." and ".." are not allowed in narrowspec paths
47 [255]
45 [255]
48 $ hg clone --narrow ssh://user@dummy/master foo --include a/./c
46 $ hg clone --narrow ssh://user@dummy/master foo --include a/./c
49 requesting all changes
50 abort: "." and ".." are not allowed in narrowspec paths
47 abort: "." and ".." are not allowed in narrowspec paths
51 [255]
48 [255]
52
49
53 Names with '.' in them are OK.
50 Names with '.' in them are OK.
54 $ hg clone --narrow ssh://user@dummy/master should-work --include a/.b/c
51 $ hg clone --narrow ssh://user@dummy/master should-work --include a/.b/c
55 requesting all changes
52 requesting all changes
56 adding changesets
53 adding changesets
57 adding manifests
54 adding manifests
58 adding file changes
55 adding file changes
59 added 1 changesets with 0 changes to 0 files
56 added 1 changesets with 0 changes to 0 files
60 new changesets * (glob)
57 new changesets * (glob)
61 updating to branch default
58 updating to branch default
62 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
59 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
63
60
64 Test repo with local changes
61 Test repo with local changes
65 $ hg clone --narrow ssh://user@dummy/master narrow-local-changes --include d0 --include d3 --include d6
62 $ hg clone --narrow ssh://user@dummy/master narrow-local-changes --include d0 --include d3 --include d6
66 requesting all changes
63 requesting all changes
67 adding changesets
64 adding changesets
68 adding manifests
65 adding manifests
69 adding file changes
66 adding file changes
70 added 6 changesets with 3 changes to 3 files
67 added 6 changesets with 3 changes to 3 files
71 new changesets *:* (glob)
68 new changesets *:* (glob)
72 updating to branch default
69 updating to branch default
73 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
70 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
74 $ cd narrow-local-changes
71 $ cd narrow-local-changes
75 $ cat >> $HGRCPATH << EOF
72 $ cat >> $HGRCPATH << EOF
76 > [experimental]
73 > [experimental]
77 > evolution=createmarkers
74 > evolution=createmarkers
78 > EOF
75 > EOF
79 $ echo local change >> d0/f
76 $ echo local change >> d0/f
80 $ hg ci -m 'local change to d0'
77 $ hg ci -m 'local change to d0'
81 $ hg co '.^'
78 $ hg co '.^'
82 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
79 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
83 $ echo local change >> d3/f
80 $ echo local change >> d3/f
84 $ hg ci -m 'local hidden change to d3'
81 $ hg ci -m 'local hidden change to d3'
85 created new head
82 created new head
86 $ hg ci --amend -m 'local change to d3'
83 $ hg ci --amend -m 'local change to d3'
87 $ hg tracked --removeinclude d0
84 $ hg tracked --removeinclude d0
88 comparing with ssh://user@dummy/master
85 comparing with ssh://user@dummy/master
89 searching for changes
86 searching for changes
90 looking for local changes to affected paths
87 looking for local changes to affected paths
91 The following changeset(s) or their ancestors have local changes not on the remote:
88 The following changeset(s) or their ancestors have local changes not on the remote:
92 * (glob)
89 * (glob)
93 abort: local changes found
90 abort: local changes found
94 (use --force-delete-local-changes to ignore)
91 (use --force-delete-local-changes to ignore)
95 [255]
92 [255]
96 Check that nothing was removed by the failed attempts
93 Check that nothing was removed by the failed attempts
97 $ hg tracked
94 $ hg tracked
98 I path:d0
95 I path:d0
99 I path:d3
96 I path:d3
100 I path:d6
97 I path:d6
101 $ hg files
98 $ hg files
102 d0/f
99 d0/f
103 d3/f
100 d3/f
104 d6/f
101 d6/f
105 $ find *
102 $ find *
106 d0
103 d0
107 d0/f
104 d0/f
108 d3
105 d3
109 d3/f
106 d3/f
110 d6
107 d6
111 d6/f
108 d6/f
112 $ hg verify -q
109 $ hg verify -q
113 Force deletion of local changes
110 Force deletion of local changes
114 $ hg log -T "{rev}: {desc} {outsidenarrow}\n"
111 $ hg log -T "{rev}: {desc} {outsidenarrow}\n"
115 8: local change to d3
112 8: local change to d3
116 6: local change to d0
113 6: local change to d0
117 5: add d10/f outsidenarrow
114 5: add d10/f outsidenarrow
118 4: add d6/f
115 4: add d6/f
119 3: add d5/f outsidenarrow
116 3: add d5/f outsidenarrow
120 2: add d3/f
117 2: add d3/f
121 1: add d2/f outsidenarrow
118 1: add d2/f outsidenarrow
122 0: add d0/f
119 0: add d0/f
123 $ hg tracked --removeinclude d0 --force-delete-local-changes
120 $ hg tracked --removeinclude d0 --force-delete-local-changes
124 comparing with ssh://user@dummy/master
121 comparing with ssh://user@dummy/master
125 searching for changes
122 searching for changes
126 looking for local changes to affected paths
123 looking for local changes to affected paths
127 The following changeset(s) or their ancestors have local changes not on the remote:
124 The following changeset(s) or their ancestors have local changes not on the remote:
128 * (glob)
125 * (glob)
129 saved backup bundle to $TESTTMP/narrow-local-changes/.hg/strip-backup/*-narrow.hg (glob)
126 saved backup bundle to $TESTTMP/narrow-local-changes/.hg/strip-backup/*-narrow.hg (glob)
130 deleting data/d0/f.i (reporevlogstore !)
127 deleting data/d0/f.i (reporevlogstore !)
131 deleting meta/d0/00manifest.i (tree !)
128 deleting meta/d0/00manifest.i (tree !)
132 deleting data/d0/f/362fef284ce2ca02aecc8de6d5e8a1c3af0556fe (reposimplestore !)
129 deleting data/d0/f/362fef284ce2ca02aecc8de6d5e8a1c3af0556fe (reposimplestore !)
133 deleting data/d0/f/4374b5650fc5ae54ac857c0f0381971fdde376f7 (reposimplestore !)
130 deleting data/d0/f/4374b5650fc5ae54ac857c0f0381971fdde376f7 (reposimplestore !)
134 deleting data/d0/f/index (reposimplestore !)
131 deleting data/d0/f/index (reposimplestore !)
135
132
136 $ hg log -T "{rev}: {desc} {outsidenarrow}\n"
133 $ hg log -T "{rev}: {desc} {outsidenarrow}\n"
137 7: local change to d3
134 7: local change to d3
138 5: add d10/f outsidenarrow
135 5: add d10/f outsidenarrow
139 4: add d6/f
136 4: add d6/f
140 3: add d5/f outsidenarrow
137 3: add d5/f outsidenarrow
141 2: add d3/f
138 2: add d3/f
142 1: add d2/f outsidenarrow
139 1: add d2/f outsidenarrow
143 0: add d0/f outsidenarrow
140 0: add d0/f outsidenarrow
144 Can restore stripped local changes after widening
141 Can restore stripped local changes after widening
145 $ hg tracked --addinclude d0 -q
142 $ hg tracked --addinclude d0 -q
146 $ hg unbundle .hg/strip-backup/*-narrow.hg -q
143 $ hg unbundle .hg/strip-backup/*-narrow.hg -q
147 $ hg --hidden co -r 'desc("local change to d0")' -q
144 $ hg --hidden co -r 'desc("local change to d0")' -q
148 $ cat d0/f
145 $ cat d0/f
149 0
146 0
150 local change
147 local change
151 Pruned commits affecting removed paths should not prevent narrowing
148 Pruned commits affecting removed paths should not prevent narrowing
152 $ hg co '.^'
149 $ hg co '.^'
153 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
150 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
154 $ hg debugobsolete `hg log -T '{node}' -r 'desc("local change to d0")'`
151 $ hg debugobsolete `hg log -T '{node}' -r 'desc("local change to d0")'`
155 obsoleted 1 changesets
152 obsoleted 1 changesets
156 $ hg tracked --removeinclude d0
153 $ hg tracked --removeinclude d0
157 comparing with ssh://user@dummy/master
154 comparing with ssh://user@dummy/master
158 searching for changes
155 searching for changes
159 looking for local changes to affected paths
156 looking for local changes to affected paths
160 saved backup bundle to $TESTTMP/narrow-local-changes/.hg/strip-backup/*-narrow.hg (glob)
157 saved backup bundle to $TESTTMP/narrow-local-changes/.hg/strip-backup/*-narrow.hg (glob)
161 deleting data/d0/f.i (reporevlogstore !)
158 deleting data/d0/f.i (reporevlogstore !)
162 deleting meta/d0/00manifest.i (tree !)
159 deleting meta/d0/00manifest.i (tree !)
163 deleting data/d0/f/362fef284ce2ca02aecc8de6d5e8a1c3af0556fe (reposimplestore !)
160 deleting data/d0/f/362fef284ce2ca02aecc8de6d5e8a1c3af0556fe (reposimplestore !)
164 deleting data/d0/f/4374b5650fc5ae54ac857c0f0381971fdde376f7 (reposimplestore !)
161 deleting data/d0/f/4374b5650fc5ae54ac857c0f0381971fdde376f7 (reposimplestore !)
165 deleting data/d0/f/index (reposimplestore !)
162 deleting data/d0/f/index (reposimplestore !)
166
163
167 Updates off of stripped commit if necessary
164 Updates off of stripped commit if necessary
168 $ hg co -r 'desc("local change to d3")' -q
165 $ hg co -r 'desc("local change to d3")' -q
169 $ echo local change >> d6/f
166 $ echo local change >> d6/f
170 $ hg ci -m 'local change to d6'
167 $ hg ci -m 'local change to d6'
171 $ hg tracked --removeinclude d3 --force-delete-local-changes
168 $ hg tracked --removeinclude d3 --force-delete-local-changes
172 comparing with ssh://user@dummy/master
169 comparing with ssh://user@dummy/master
173 searching for changes
170 searching for changes
174 looking for local changes to affected paths
171 looking for local changes to affected paths
175 The following changeset(s) or their ancestors have local changes not on the remote:
172 The following changeset(s) or their ancestors have local changes not on the remote:
176 * (glob)
173 * (glob)
177 * (glob)
174 * (glob)
178 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
175 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
179 saved backup bundle to $TESTTMP/narrow-local-changes/.hg/strip-backup/*-narrow.hg (glob)
176 saved backup bundle to $TESTTMP/narrow-local-changes/.hg/strip-backup/*-narrow.hg (glob)
180 deleting data/d3/f.i (reporevlogstore !)
177 deleting data/d3/f.i (reporevlogstore !)
181 deleting meta/d3/00manifest.i (tree !)
178 deleting meta/d3/00manifest.i (tree !)
182 deleting data/d3/f/2661d26c649684b482d10f91960cc3db683c38b4 (reposimplestore !)
179 deleting data/d3/f/2661d26c649684b482d10f91960cc3db683c38b4 (reposimplestore !)
183 deleting data/d3/f/99fa7136105a15e2045ce3d9152e4837c5349e4d (reposimplestore !)
180 deleting data/d3/f/99fa7136105a15e2045ce3d9152e4837c5349e4d (reposimplestore !)
184 deleting data/d3/f/index (reposimplestore !)
181 deleting data/d3/f/index (reposimplestore !)
185 $ hg log -T '{desc}\n' -r .
182 $ hg log -T '{desc}\n' -r .
186 add d10/f
183 add d10/f
187 Updates to nullid if necessary
184 Updates to nullid if necessary
188 $ hg tracked --addinclude d3 -q
185 $ hg tracked --addinclude d3 -q
189 $ hg co null -q
186 $ hg co null -q
190 $ mkdir d3
187 $ mkdir d3
191 $ echo local change > d3/f
188 $ echo local change > d3/f
192 $ hg add d3/f
189 $ hg add d3/f
193 $ hg ci -m 'local change to d3'
190 $ hg ci -m 'local change to d3'
194 created new head
191 created new head
195 $ hg tracked --removeinclude d3 --force-delete-local-changes
192 $ hg tracked --removeinclude d3 --force-delete-local-changes
196 comparing with ssh://user@dummy/master
193 comparing with ssh://user@dummy/master
197 searching for changes
194 searching for changes
198 looking for local changes to affected paths
195 looking for local changes to affected paths
199 The following changeset(s) or their ancestors have local changes not on the remote:
196 The following changeset(s) or their ancestors have local changes not on the remote:
200 * (glob)
197 * (glob)
201 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
198 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
202 saved backup bundle to $TESTTMP/narrow-local-changes/.hg/strip-backup/*-narrow.hg (glob)
199 saved backup bundle to $TESTTMP/narrow-local-changes/.hg/strip-backup/*-narrow.hg (glob)
203 deleting data/d3/f.i (reporevlogstore !)
200 deleting data/d3/f.i (reporevlogstore !)
204 deleting meta/d3/00manifest.i (tree !)
201 deleting meta/d3/00manifest.i (tree !)
205 deleting data/d3/f/2661d26c649684b482d10f91960cc3db683c38b4 (reposimplestore !)
202 deleting data/d3/f/2661d26c649684b482d10f91960cc3db683c38b4 (reposimplestore !)
206 deleting data/d3/f/5ce0767945cbdbca3b924bb9fbf5143f72ab40ac (reposimplestore !)
203 deleting data/d3/f/5ce0767945cbdbca3b924bb9fbf5143f72ab40ac (reposimplestore !)
207 deleting data/d3/f/index (reposimplestore !)
204 deleting data/d3/f/index (reposimplestore !)
208 $ hg id
205 $ hg id
209 000000000000
206 000000000000
210 $ cd ..
207 $ cd ..
211
208
212 Can remove last include, making repo empty
209 Can remove last include, making repo empty
213 $ hg clone --narrow ssh://user@dummy/master narrow-empty --include d0 -r 5
210 $ hg clone --narrow ssh://user@dummy/master narrow-empty --include d0 -r 5
214 adding changesets
211 adding changesets
215 adding manifests
212 adding manifests
216 adding file changes
213 adding file changes
217 added 2 changesets with 1 changes to 1 files
214 added 2 changesets with 1 changes to 1 files
218 new changesets *:* (glob)
215 new changesets *:* (glob)
219 updating to branch default
216 updating to branch default
220 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
217 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
221 $ cd narrow-empty
218 $ cd narrow-empty
222 $ hg tracked --removeinclude d0
219 $ hg tracked --removeinclude d0
223 comparing with ssh://user@dummy/master
220 comparing with ssh://user@dummy/master
224 searching for changes
221 searching for changes
225 looking for local changes to affected paths
222 looking for local changes to affected paths
226 deleting data/d0/f.i (reporevlogstore !)
223 deleting data/d0/f.i (reporevlogstore !)
227 deleting meta/d0/00manifest.i (tree !)
224 deleting meta/d0/00manifest.i (tree !)
228 deleting data/d0/f/362fef284ce2ca02aecc8de6d5e8a1c3af0556fe (reposimplestore !)
225 deleting data/d0/f/362fef284ce2ca02aecc8de6d5e8a1c3af0556fe (reposimplestore !)
229 deleting data/d0/f/index (reposimplestore !)
226 deleting data/d0/f/index (reposimplestore !)
230 $ hg tracked
227 $ hg tracked
231 $ hg files
228 $ hg files
232 [1]
229 [1]
233 $ test -d d0
230 $ test -d d0
234 [1]
231 [1]
235 Do some work in the empty clone
232 Do some work in the empty clone
236 $ hg diff --change .
233 $ hg diff --change .
237 $ hg branch foo
234 $ hg branch foo
238 marked working directory as branch foo
235 marked working directory as branch foo
239 (branches are permanent and global, did you want a bookmark?)
236 (branches are permanent and global, did you want a bookmark?)
240 $ hg ci -m empty
237 $ hg ci -m empty
241 $ hg pull -q
238 $ hg pull -q
242 Can widen the empty clone
239 Can widen the empty clone
243 $ hg tracked --addinclude d0
240 $ hg tracked --addinclude d0
244 comparing with ssh://user@dummy/master
241 comparing with ssh://user@dummy/master
245 searching for changes
242 searching for changes
246 no changes found
243 no changes found
247 saved backup bundle to $TESTTMP/narrow-empty/.hg/strip-backup/*-widen.hg (glob)
244 saved backup bundle to $TESTTMP/narrow-empty/.hg/strip-backup/*-widen.hg (glob)
248 adding changesets
245 adding changesets
249 adding manifests
246 adding manifests
250 adding file changes
247 adding file changes
251 added 3 changesets with 1 changes to 1 files
248 added 3 changesets with 1 changes to 1 files
252 new changesets *:* (glob)
249 new changesets *:* (glob)
253 $ hg tracked
250 $ hg tracked
254 I path:d0
251 I path:d0
255 $ hg files
252 $ hg files
256 d0/f
253 d0/f
257 $ find *
254 $ find *
258 d0
255 d0
259 d0/f
256 d0/f
260 $ cd ..
257 $ cd ..
261
258
262 TODO(martinvonz): test including e.g. d3/g and then removing it once
259 TODO(martinvonz): test including e.g. d3/g and then removing it once
263 https://bitbucket.org/Google/narrowhg/issues/6 is fixed
260 https://bitbucket.org/Google/narrowhg/issues/6 is fixed
264
261
265 $ hg clone --narrow ssh://user@dummy/master narrow --include d0 --include d3 --include d6 --include d9
262 $ hg clone --narrow ssh://user@dummy/master narrow --include d0 --include d3 --include d6 --include d9
266 requesting all changes
263 requesting all changes
267 adding changesets
264 adding changesets
268 adding manifests
265 adding manifests
269 adding file changes
266 adding file changes
270 added 8 changesets with 4 changes to 4 files
267 added 8 changesets with 4 changes to 4 files
271 new changesets *:* (glob)
268 new changesets *:* (glob)
272 updating to branch default
269 updating to branch default
273 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
270 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
274 $ cd narrow
271 $ cd narrow
275 $ hg tracked
272 $ hg tracked
276 I path:d0
273 I path:d0
277 I path:d3
274 I path:d3
278 I path:d6
275 I path:d6
279 I path:d9
276 I path:d9
280 $ hg tracked --removeinclude d6
277 $ hg tracked --removeinclude d6
281 comparing with ssh://user@dummy/master
278 comparing with ssh://user@dummy/master
282 searching for changes
279 searching for changes
283 looking for local changes to affected paths
280 looking for local changes to affected paths
284 deleting data/d6/f.i (reporevlogstore !)
281 deleting data/d6/f.i (reporevlogstore !)
285 deleting meta/d6/00manifest.i (tree !)
282 deleting meta/d6/00manifest.i (tree !)
286 deleting data/d6/f/7339d30678f451ac8c3f38753beeb4cf2e1655c7 (reposimplestore !)
283 deleting data/d6/f/7339d30678f451ac8c3f38753beeb4cf2e1655c7 (reposimplestore !)
287 deleting data/d6/f/index (reposimplestore !)
284 deleting data/d6/f/index (reposimplestore !)
288 $ hg tracked
285 $ hg tracked
289 I path:d0
286 I path:d0
290 I path:d3
287 I path:d3
291 I path:d9
288 I path:d9
292 #if repofncache
289 #if repofncache
293 $ hg debugrebuildfncache
290 $ hg debugrebuildfncache
294 fncache already up to date
291 fncache already up to date
295 #endif
292 #endif
296 $ find *
293 $ find *
297 d0
294 d0
298 d0/f
295 d0/f
299 d3
296 d3
300 d3/f
297 d3/f
301 d9
298 d9
302 d9/f
299 d9/f
303 $ hg verify -q
300 $ hg verify -q
304 $ hg tracked --addexclude d3/f
301 $ hg tracked --addexclude d3/f
305 comparing with ssh://user@dummy/master
302 comparing with ssh://user@dummy/master
306 searching for changes
303 searching for changes
307 looking for local changes to affected paths
304 looking for local changes to affected paths
308 deleting data/d3/f.i (reporevlogstore !)
305 deleting data/d3/f.i (reporevlogstore !)
309 deleting data/d3/f/2661d26c649684b482d10f91960cc3db683c38b4 (reposimplestore !)
306 deleting data/d3/f/2661d26c649684b482d10f91960cc3db683c38b4 (reposimplestore !)
310 deleting data/d3/f/index (reposimplestore !)
307 deleting data/d3/f/index (reposimplestore !)
311 $ hg tracked
308 $ hg tracked
312 I path:d0
309 I path:d0
313 I path:d3
310 I path:d3
314 I path:d9
311 I path:d9
315 X path:d3/f
312 X path:d3/f
316 #if repofncache
313 #if repofncache
317 $ hg debugrebuildfncache
314 $ hg debugrebuildfncache
318 fncache already up to date
315 fncache already up to date
319 #endif
316 #endif
320 $ find *
317 $ find *
321 d0
318 d0
322 d0/f
319 d0/f
323 d9
320 d9
324 d9/f
321 d9/f
325 $ hg verify -q
322 $ hg verify -q
326 $ hg tracked --addexclude d0
323 $ hg tracked --addexclude d0
327 comparing with ssh://user@dummy/master
324 comparing with ssh://user@dummy/master
328 searching for changes
325 searching for changes
329 looking for local changes to affected paths
326 looking for local changes to affected paths
330 deleting data/d0/f.i (reporevlogstore !)
327 deleting data/d0/f.i (reporevlogstore !)
331 deleting meta/d0/00manifest.i (tree !)
328 deleting meta/d0/00manifest.i (tree !)
332 deleting data/d0/f/362fef284ce2ca02aecc8de6d5e8a1c3af0556fe (reposimplestore !)
329 deleting data/d0/f/362fef284ce2ca02aecc8de6d5e8a1c3af0556fe (reposimplestore !)
333 deleting data/d0/f/index (reposimplestore !)
330 deleting data/d0/f/index (reposimplestore !)
334 $ hg tracked
331 $ hg tracked
335 I path:d3
332 I path:d3
336 I path:d9
333 I path:d9
337 X path:d0
334 X path:d0
338 X path:d3/f
335 X path:d3/f
339 #if repofncache
336 #if repofncache
340 $ hg debugrebuildfncache
337 $ hg debugrebuildfncache
341 fncache already up to date
338 fncache already up to date
342 #endif
339 #endif
343 $ find *
340 $ find *
344 d9
341 d9
345 d9/f
342 d9/f
346
343
347 Make a 15 of changes to d9 to test the path without --verbose
344 Make a 15 of changes to d9 to test the path without --verbose
348 (Note: using regexes instead of "* (glob)" because if the test fails, it
345 (Note: using regexes instead of "* (glob)" because if the test fails, it
349 produces more sensible diffs)
346 produces more sensible diffs)
350 $ hg tracked
347 $ hg tracked
351 I path:d3
348 I path:d3
352 I path:d9
349 I path:d9
353 X path:d0
350 X path:d0
354 X path:d3/f
351 X path:d3/f
355 $ for x in `$TESTDIR/seq.py 1 15`
352 $ for x in `$TESTDIR/seq.py 1 15`
356 > do
353 > do
357 > echo local change >> d9/f
354 > echo local change >> d9/f
358 > hg commit -m "change $x to d9/f"
355 > hg commit -m "change $x to d9/f"
359 > done
356 > done
360 $ hg tracked --removeinclude d9
357 $ hg tracked --removeinclude d9
361 comparing with ssh://user@dummy/master
358 comparing with ssh://user@dummy/master
362 searching for changes
359 searching for changes
363 looking for local changes to affected paths
360 looking for local changes to affected paths
364 The following changeset(s) or their ancestors have local changes not on the remote:
361 The following changeset(s) or their ancestors have local changes not on the remote:
365 ^[0-9a-f]{12}$ (re)
362 ^[0-9a-f]{12}$ (re)
366 ^[0-9a-f]{12}$ (re)
363 ^[0-9a-f]{12}$ (re)
367 ^[0-9a-f]{12}$ (re)
364 ^[0-9a-f]{12}$ (re)
368 ^[0-9a-f]{12}$ (re)
365 ^[0-9a-f]{12}$ (re)
369 ^[0-9a-f]{12}$ (re)
366 ^[0-9a-f]{12}$ (re)
370 ^[0-9a-f]{12}$ (re)
367 ^[0-9a-f]{12}$ (re)
371 ^[0-9a-f]{12}$ (re)
368 ^[0-9a-f]{12}$ (re)
372 ^[0-9a-f]{12}$ (re)
369 ^[0-9a-f]{12}$ (re)
373 ^[0-9a-f]{12}$ (re)
370 ^[0-9a-f]{12}$ (re)
374 ^[0-9a-f]{12}$ (re)
371 ^[0-9a-f]{12}$ (re)
375 ...and 5 more, use --verbose to list all
372 ...and 5 more, use --verbose to list all
376 abort: local changes found
373 abort: local changes found
377 (use --force-delete-local-changes to ignore)
374 (use --force-delete-local-changes to ignore)
378 [255]
375 [255]
379 Now test it *with* verbose.
376 Now test it *with* verbose.
380 $ hg tracked --removeinclude d9 --verbose
377 $ hg tracked --removeinclude d9 --verbose
381 comparing with ssh://user@dummy/master
378 comparing with ssh://user@dummy/master
382 searching for changes
379 searching for changes
383 looking for local changes to affected paths
380 looking for local changes to affected paths
384 The following changeset(s) or their ancestors have local changes not on the remote:
381 The following changeset(s) or their ancestors have local changes not on the remote:
385 ^[0-9a-f]{12}$ (re)
382 ^[0-9a-f]{12}$ (re)
386 ^[0-9a-f]{12}$ (re)
383 ^[0-9a-f]{12}$ (re)
387 ^[0-9a-f]{12}$ (re)
384 ^[0-9a-f]{12}$ (re)
388 ^[0-9a-f]{12}$ (re)
385 ^[0-9a-f]{12}$ (re)
389 ^[0-9a-f]{12}$ (re)
386 ^[0-9a-f]{12}$ (re)
390 ^[0-9a-f]{12}$ (re)
387 ^[0-9a-f]{12}$ (re)
391 ^[0-9a-f]{12}$ (re)
388 ^[0-9a-f]{12}$ (re)
392 ^[0-9a-f]{12}$ (re)
389 ^[0-9a-f]{12}$ (re)
393 ^[0-9a-f]{12}$ (re)
390 ^[0-9a-f]{12}$ (re)
394 ^[0-9a-f]{12}$ (re)
391 ^[0-9a-f]{12}$ (re)
395 ^[0-9a-f]{12}$ (re)
392 ^[0-9a-f]{12}$ (re)
396 ^[0-9a-f]{12}$ (re)
393 ^[0-9a-f]{12}$ (re)
397 ^[0-9a-f]{12}$ (re)
394 ^[0-9a-f]{12}$ (re)
398 ^[0-9a-f]{12}$ (re)
395 ^[0-9a-f]{12}$ (re)
399 ^[0-9a-f]{12}$ (re)
396 ^[0-9a-f]{12}$ (re)
400 abort: local changes found
397 abort: local changes found
401 (use --force-delete-local-changes to ignore)
398 (use --force-delete-local-changes to ignore)
402 [255]
399 [255]
General Comments 0
You need to be logged in to leave comments. Login now