##// END OF EJS Templates
showconfig: allow multiple section.name selectors (issue5797)...
Yuya Nishihara -
r36435:199443c5 default
parent child Browse files
Show More
@@ -1,5615 +1,5607 b''
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import difflib
10 import difflib
11 import errno
11 import errno
12 import os
12 import os
13 import re
13 import re
14 import sys
14 import sys
15
15
16 from .i18n import _
16 from .i18n import _
17 from .node import (
17 from .node import (
18 hex,
18 hex,
19 nullid,
19 nullid,
20 nullrev,
20 nullrev,
21 short,
21 short,
22 )
22 )
23 from . import (
23 from . import (
24 archival,
24 archival,
25 bookmarks,
25 bookmarks,
26 bundle2,
26 bundle2,
27 changegroup,
27 changegroup,
28 cmdutil,
28 cmdutil,
29 copies,
29 copies,
30 debugcommands as debugcommandsmod,
30 debugcommands as debugcommandsmod,
31 destutil,
31 destutil,
32 dirstateguard,
32 dirstateguard,
33 discovery,
33 discovery,
34 encoding,
34 encoding,
35 error,
35 error,
36 exchange,
36 exchange,
37 extensions,
37 extensions,
38 formatter,
38 formatter,
39 graphmod,
39 graphmod,
40 hbisect,
40 hbisect,
41 help,
41 help,
42 hg,
42 hg,
43 lock as lockmod,
43 lock as lockmod,
44 logcmdutil,
44 logcmdutil,
45 merge as mergemod,
45 merge as mergemod,
46 obsolete,
46 obsolete,
47 obsutil,
47 obsutil,
48 patch,
48 patch,
49 phases,
49 phases,
50 pycompat,
50 pycompat,
51 rcutil,
51 rcutil,
52 registrar,
52 registrar,
53 revsetlang,
53 revsetlang,
54 rewriteutil,
54 rewriteutil,
55 scmutil,
55 scmutil,
56 server,
56 server,
57 streamclone,
57 streamclone,
58 tags as tagsmod,
58 tags as tagsmod,
59 templatekw,
59 templatekw,
60 ui as uimod,
60 ui as uimod,
61 util,
61 util,
62 wireprotoserver,
62 wireprotoserver,
63 )
63 )
64
64
65 release = lockmod.release
65 release = lockmod.release
66
66
67 table = {}
67 table = {}
68 table.update(debugcommandsmod.command._table)
68 table.update(debugcommandsmod.command._table)
69
69
70 command = registrar.command(table)
70 command = registrar.command(table)
71 readonly = registrar.command.readonly
71 readonly = registrar.command.readonly
72
72
73 # common command options
73 # common command options
74
74
75 globalopts = [
75 globalopts = [
76 ('R', 'repository', '',
76 ('R', 'repository', '',
77 _('repository root directory or name of overlay bundle file'),
77 _('repository root directory or name of overlay bundle file'),
78 _('REPO')),
78 _('REPO')),
79 ('', 'cwd', '',
79 ('', 'cwd', '',
80 _('change working directory'), _('DIR')),
80 _('change working directory'), _('DIR')),
81 ('y', 'noninteractive', None,
81 ('y', 'noninteractive', None,
82 _('do not prompt, automatically pick the first choice for all prompts')),
82 _('do not prompt, automatically pick the first choice for all prompts')),
83 ('q', 'quiet', None, _('suppress output')),
83 ('q', 'quiet', None, _('suppress output')),
84 ('v', 'verbose', None, _('enable additional output')),
84 ('v', 'verbose', None, _('enable additional output')),
85 ('', 'color', '',
85 ('', 'color', '',
86 # i18n: 'always', 'auto', 'never', and 'debug' are keywords
86 # i18n: 'always', 'auto', 'never', and 'debug' are keywords
87 # and should not be translated
87 # and should not be translated
88 _("when to colorize (boolean, always, auto, never, or debug)"),
88 _("when to colorize (boolean, always, auto, never, or debug)"),
89 _('TYPE')),
89 _('TYPE')),
90 ('', 'config', [],
90 ('', 'config', [],
91 _('set/override config option (use \'section.name=value\')'),
91 _('set/override config option (use \'section.name=value\')'),
92 _('CONFIG')),
92 _('CONFIG')),
93 ('', 'debug', None, _('enable debugging output')),
93 ('', 'debug', None, _('enable debugging output')),
94 ('', 'debugger', None, _('start debugger')),
94 ('', 'debugger', None, _('start debugger')),
95 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
95 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
96 _('ENCODE')),
96 _('ENCODE')),
97 ('', 'encodingmode', encoding.encodingmode,
97 ('', 'encodingmode', encoding.encodingmode,
98 _('set the charset encoding mode'), _('MODE')),
98 _('set the charset encoding mode'), _('MODE')),
99 ('', 'traceback', None, _('always print a traceback on exception')),
99 ('', 'traceback', None, _('always print a traceback on exception')),
100 ('', 'time', None, _('time how long the command takes')),
100 ('', 'time', None, _('time how long the command takes')),
101 ('', 'profile', None, _('print command execution profile')),
101 ('', 'profile', None, _('print command execution profile')),
102 ('', 'version', None, _('output version information and exit')),
102 ('', 'version', None, _('output version information and exit')),
103 ('h', 'help', None, _('display help and exit')),
103 ('h', 'help', None, _('display help and exit')),
104 ('', 'hidden', False, _('consider hidden changesets')),
104 ('', 'hidden', False, _('consider hidden changesets')),
105 ('', 'pager', 'auto',
105 ('', 'pager', 'auto',
106 _("when to paginate (boolean, always, auto, or never)"), _('TYPE')),
106 _("when to paginate (boolean, always, auto, or never)"), _('TYPE')),
107 ]
107 ]
108
108
109 dryrunopts = cmdutil.dryrunopts
109 dryrunopts = cmdutil.dryrunopts
110 remoteopts = cmdutil.remoteopts
110 remoteopts = cmdutil.remoteopts
111 walkopts = cmdutil.walkopts
111 walkopts = cmdutil.walkopts
112 commitopts = cmdutil.commitopts
112 commitopts = cmdutil.commitopts
113 commitopts2 = cmdutil.commitopts2
113 commitopts2 = cmdutil.commitopts2
114 formatteropts = cmdutil.formatteropts
114 formatteropts = cmdutil.formatteropts
115 templateopts = cmdutil.templateopts
115 templateopts = cmdutil.templateopts
116 logopts = cmdutil.logopts
116 logopts = cmdutil.logopts
117 diffopts = cmdutil.diffopts
117 diffopts = cmdutil.diffopts
118 diffwsopts = cmdutil.diffwsopts
118 diffwsopts = cmdutil.diffwsopts
119 diffopts2 = cmdutil.diffopts2
119 diffopts2 = cmdutil.diffopts2
120 mergetoolopts = cmdutil.mergetoolopts
120 mergetoolopts = cmdutil.mergetoolopts
121 similarityopts = cmdutil.similarityopts
121 similarityopts = cmdutil.similarityopts
122 subrepoopts = cmdutil.subrepoopts
122 subrepoopts = cmdutil.subrepoopts
123 debugrevlogopts = cmdutil.debugrevlogopts
123 debugrevlogopts = cmdutil.debugrevlogopts
124
124
125 # Commands start here, listed alphabetically
125 # Commands start here, listed alphabetically
126
126
127 @command('^add',
127 @command('^add',
128 walkopts + subrepoopts + dryrunopts,
128 walkopts + subrepoopts + dryrunopts,
129 _('[OPTION]... [FILE]...'),
129 _('[OPTION]... [FILE]...'),
130 inferrepo=True)
130 inferrepo=True)
131 def add(ui, repo, *pats, **opts):
131 def add(ui, repo, *pats, **opts):
132 """add the specified files on the next commit
132 """add the specified files on the next commit
133
133
134 Schedule files to be version controlled and added to the
134 Schedule files to be version controlled and added to the
135 repository.
135 repository.
136
136
137 The files will be added to the repository at the next commit. To
137 The files will be added to the repository at the next commit. To
138 undo an add before that, see :hg:`forget`.
138 undo an add before that, see :hg:`forget`.
139
139
140 If no names are given, add all files to the repository (except
140 If no names are given, add all files to the repository (except
141 files matching ``.hgignore``).
141 files matching ``.hgignore``).
142
142
143 .. container:: verbose
143 .. container:: verbose
144
144
145 Examples:
145 Examples:
146
146
147 - New (unknown) files are added
147 - New (unknown) files are added
148 automatically by :hg:`add`::
148 automatically by :hg:`add`::
149
149
150 $ ls
150 $ ls
151 foo.c
151 foo.c
152 $ hg status
152 $ hg status
153 ? foo.c
153 ? foo.c
154 $ hg add
154 $ hg add
155 adding foo.c
155 adding foo.c
156 $ hg status
156 $ hg status
157 A foo.c
157 A foo.c
158
158
159 - Specific files to be added can be specified::
159 - Specific files to be added can be specified::
160
160
161 $ ls
161 $ ls
162 bar.c foo.c
162 bar.c foo.c
163 $ hg status
163 $ hg status
164 ? bar.c
164 ? bar.c
165 ? foo.c
165 ? foo.c
166 $ hg add bar.c
166 $ hg add bar.c
167 $ hg status
167 $ hg status
168 A bar.c
168 A bar.c
169 ? foo.c
169 ? foo.c
170
170
171 Returns 0 if all files are successfully added.
171 Returns 0 if all files are successfully added.
172 """
172 """
173
173
174 m = scmutil.match(repo[None], pats, pycompat.byteskwargs(opts))
174 m = scmutil.match(repo[None], pats, pycompat.byteskwargs(opts))
175 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
175 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
176 return rejected and 1 or 0
176 return rejected and 1 or 0
177
177
178 @command('addremove',
178 @command('addremove',
179 similarityopts + subrepoopts + walkopts + dryrunopts,
179 similarityopts + subrepoopts + walkopts + dryrunopts,
180 _('[OPTION]... [FILE]...'),
180 _('[OPTION]... [FILE]...'),
181 inferrepo=True)
181 inferrepo=True)
182 def addremove(ui, repo, *pats, **opts):
182 def addremove(ui, repo, *pats, **opts):
183 """add all new files, delete all missing files
183 """add all new files, delete all missing files
184
184
185 Add all new files and remove all missing files from the
185 Add all new files and remove all missing files from the
186 repository.
186 repository.
187
187
188 Unless names are given, new files are ignored if they match any of
188 Unless names are given, new files are ignored if they match any of
189 the patterns in ``.hgignore``. As with add, these changes take
189 the patterns in ``.hgignore``. As with add, these changes take
190 effect at the next commit.
190 effect at the next commit.
191
191
192 Use the -s/--similarity option to detect renamed files. This
192 Use the -s/--similarity option to detect renamed files. This
193 option takes a percentage between 0 (disabled) and 100 (files must
193 option takes a percentage between 0 (disabled) and 100 (files must
194 be identical) as its parameter. With a parameter greater than 0,
194 be identical) as its parameter. With a parameter greater than 0,
195 this compares every removed file with every added file and records
195 this compares every removed file with every added file and records
196 those similar enough as renames. Detecting renamed files this way
196 those similar enough as renames. Detecting renamed files this way
197 can be expensive. After using this option, :hg:`status -C` can be
197 can be expensive. After using this option, :hg:`status -C` can be
198 used to check which files were identified as moved or renamed. If
198 used to check which files were identified as moved or renamed. If
199 not specified, -s/--similarity defaults to 100 and only renames of
199 not specified, -s/--similarity defaults to 100 and only renames of
200 identical files are detected.
200 identical files are detected.
201
201
202 .. container:: verbose
202 .. container:: verbose
203
203
204 Examples:
204 Examples:
205
205
206 - A number of files (bar.c and foo.c) are new,
206 - A number of files (bar.c and foo.c) are new,
207 while foobar.c has been removed (without using :hg:`remove`)
207 while foobar.c has been removed (without using :hg:`remove`)
208 from the repository::
208 from the repository::
209
209
210 $ ls
210 $ ls
211 bar.c foo.c
211 bar.c foo.c
212 $ hg status
212 $ hg status
213 ! foobar.c
213 ! foobar.c
214 ? bar.c
214 ? bar.c
215 ? foo.c
215 ? foo.c
216 $ hg addremove
216 $ hg addremove
217 adding bar.c
217 adding bar.c
218 adding foo.c
218 adding foo.c
219 removing foobar.c
219 removing foobar.c
220 $ hg status
220 $ hg status
221 A bar.c
221 A bar.c
222 A foo.c
222 A foo.c
223 R foobar.c
223 R foobar.c
224
224
225 - A file foobar.c was moved to foo.c without using :hg:`rename`.
225 - A file foobar.c was moved to foo.c without using :hg:`rename`.
226 Afterwards, it was edited slightly::
226 Afterwards, it was edited slightly::
227
227
228 $ ls
228 $ ls
229 foo.c
229 foo.c
230 $ hg status
230 $ hg status
231 ! foobar.c
231 ! foobar.c
232 ? foo.c
232 ? foo.c
233 $ hg addremove --similarity 90
233 $ hg addremove --similarity 90
234 removing foobar.c
234 removing foobar.c
235 adding foo.c
235 adding foo.c
236 recording removal of foobar.c as rename to foo.c (94% similar)
236 recording removal of foobar.c as rename to foo.c (94% similar)
237 $ hg status -C
237 $ hg status -C
238 A foo.c
238 A foo.c
239 foobar.c
239 foobar.c
240 R foobar.c
240 R foobar.c
241
241
242 Returns 0 if all files are successfully added.
242 Returns 0 if all files are successfully added.
243 """
243 """
244 opts = pycompat.byteskwargs(opts)
244 opts = pycompat.byteskwargs(opts)
245 try:
245 try:
246 sim = float(opts.get('similarity') or 100)
246 sim = float(opts.get('similarity') or 100)
247 except ValueError:
247 except ValueError:
248 raise error.Abort(_('similarity must be a number'))
248 raise error.Abort(_('similarity must be a number'))
249 if sim < 0 or sim > 100:
249 if sim < 0 or sim > 100:
250 raise error.Abort(_('similarity must be between 0 and 100'))
250 raise error.Abort(_('similarity must be between 0 and 100'))
251 matcher = scmutil.match(repo[None], pats, opts)
251 matcher = scmutil.match(repo[None], pats, opts)
252 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
252 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
253
253
254 @command('^annotate|blame',
254 @command('^annotate|blame',
255 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
255 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
256 ('', 'follow', None,
256 ('', 'follow', None,
257 _('follow copies/renames and list the filename (DEPRECATED)')),
257 _('follow copies/renames and list the filename (DEPRECATED)')),
258 ('', 'no-follow', None, _("don't follow copies and renames")),
258 ('', 'no-follow', None, _("don't follow copies and renames")),
259 ('a', 'text', None, _('treat all files as text')),
259 ('a', 'text', None, _('treat all files as text')),
260 ('u', 'user', None, _('list the author (long with -v)')),
260 ('u', 'user', None, _('list the author (long with -v)')),
261 ('f', 'file', None, _('list the filename')),
261 ('f', 'file', None, _('list the filename')),
262 ('d', 'date', None, _('list the date (short with -q)')),
262 ('d', 'date', None, _('list the date (short with -q)')),
263 ('n', 'number', None, _('list the revision number (default)')),
263 ('n', 'number', None, _('list the revision number (default)')),
264 ('c', 'changeset', None, _('list the changeset')),
264 ('c', 'changeset', None, _('list the changeset')),
265 ('l', 'line-number', None, _('show line number at the first appearance')),
265 ('l', 'line-number', None, _('show line number at the first appearance')),
266 ('', 'skip', [], _('revision to not display (EXPERIMENTAL)'), _('REV')),
266 ('', 'skip', [], _('revision to not display (EXPERIMENTAL)'), _('REV')),
267 ] + diffwsopts + walkopts + formatteropts,
267 ] + diffwsopts + walkopts + formatteropts,
268 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
268 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
269 inferrepo=True)
269 inferrepo=True)
270 def annotate(ui, repo, *pats, **opts):
270 def annotate(ui, repo, *pats, **opts):
271 """show changeset information by line for each file
271 """show changeset information by line for each file
272
272
273 List changes in files, showing the revision id responsible for
273 List changes in files, showing the revision id responsible for
274 each line.
274 each line.
275
275
276 This command is useful for discovering when a change was made and
276 This command is useful for discovering when a change was made and
277 by whom.
277 by whom.
278
278
279 If you include --file, --user, or --date, the revision number is
279 If you include --file, --user, or --date, the revision number is
280 suppressed unless you also include --number.
280 suppressed unless you also include --number.
281
281
282 Without the -a/--text option, annotate will avoid processing files
282 Without the -a/--text option, annotate will avoid processing files
283 it detects as binary. With -a, annotate will annotate the file
283 it detects as binary. With -a, annotate will annotate the file
284 anyway, although the results will probably be neither useful
284 anyway, although the results will probably be neither useful
285 nor desirable.
285 nor desirable.
286
286
287 Returns 0 on success.
287 Returns 0 on success.
288 """
288 """
289 opts = pycompat.byteskwargs(opts)
289 opts = pycompat.byteskwargs(opts)
290 if not pats:
290 if not pats:
291 raise error.Abort(_('at least one filename or pattern is required'))
291 raise error.Abort(_('at least one filename or pattern is required'))
292
292
293 if opts.get('follow'):
293 if opts.get('follow'):
294 # --follow is deprecated and now just an alias for -f/--file
294 # --follow is deprecated and now just an alias for -f/--file
295 # to mimic the behavior of Mercurial before version 1.5
295 # to mimic the behavior of Mercurial before version 1.5
296 opts['file'] = True
296 opts['file'] = True
297
297
298 rev = opts.get('rev')
298 rev = opts.get('rev')
299 if rev:
299 if rev:
300 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
300 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
301 ctx = scmutil.revsingle(repo, rev)
301 ctx = scmutil.revsingle(repo, rev)
302
302
303 rootfm = ui.formatter('annotate', opts)
303 rootfm = ui.formatter('annotate', opts)
304 if ui.quiet:
304 if ui.quiet:
305 datefunc = util.shortdate
305 datefunc = util.shortdate
306 else:
306 else:
307 datefunc = util.datestr
307 datefunc = util.datestr
308 if ctx.rev() is None:
308 if ctx.rev() is None:
309 def hexfn(node):
309 def hexfn(node):
310 if node is None:
310 if node is None:
311 return None
311 return None
312 else:
312 else:
313 return rootfm.hexfunc(node)
313 return rootfm.hexfunc(node)
314 if opts.get('changeset'):
314 if opts.get('changeset'):
315 # omit "+" suffix which is appended to node hex
315 # omit "+" suffix which is appended to node hex
316 def formatrev(rev):
316 def formatrev(rev):
317 if rev is None:
317 if rev is None:
318 return '%d' % ctx.p1().rev()
318 return '%d' % ctx.p1().rev()
319 else:
319 else:
320 return '%d' % rev
320 return '%d' % rev
321 else:
321 else:
322 def formatrev(rev):
322 def formatrev(rev):
323 if rev is None:
323 if rev is None:
324 return '%d+' % ctx.p1().rev()
324 return '%d+' % ctx.p1().rev()
325 else:
325 else:
326 return '%d ' % rev
326 return '%d ' % rev
327 def formathex(hex):
327 def formathex(hex):
328 if hex is None:
328 if hex is None:
329 return '%s+' % rootfm.hexfunc(ctx.p1().node())
329 return '%s+' % rootfm.hexfunc(ctx.p1().node())
330 else:
330 else:
331 return '%s ' % hex
331 return '%s ' % hex
332 else:
332 else:
333 hexfn = rootfm.hexfunc
333 hexfn = rootfm.hexfunc
334 formatrev = formathex = pycompat.bytestr
334 formatrev = formathex = pycompat.bytestr
335
335
336 opmap = [('user', ' ', lambda x: x.fctx.user(), ui.shortuser),
336 opmap = [('user', ' ', lambda x: x.fctx.user(), ui.shortuser),
337 ('number', ' ', lambda x: x.fctx.rev(), formatrev),
337 ('number', ' ', lambda x: x.fctx.rev(), formatrev),
338 ('changeset', ' ', lambda x: hexfn(x.fctx.node()), formathex),
338 ('changeset', ' ', lambda x: hexfn(x.fctx.node()), formathex),
339 ('date', ' ', lambda x: x.fctx.date(), util.cachefunc(datefunc)),
339 ('date', ' ', lambda x: x.fctx.date(), util.cachefunc(datefunc)),
340 ('file', ' ', lambda x: x.fctx.path(), pycompat.bytestr),
340 ('file', ' ', lambda x: x.fctx.path(), pycompat.bytestr),
341 ('line_number', ':', lambda x: x.lineno, pycompat.bytestr),
341 ('line_number', ':', lambda x: x.lineno, pycompat.bytestr),
342 ]
342 ]
343 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
343 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
344
344
345 if (not opts.get('user') and not opts.get('changeset')
345 if (not opts.get('user') and not opts.get('changeset')
346 and not opts.get('date') and not opts.get('file')):
346 and not opts.get('date') and not opts.get('file')):
347 opts['number'] = True
347 opts['number'] = True
348
348
349 linenumber = opts.get('line_number') is not None
349 linenumber = opts.get('line_number') is not None
350 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
350 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'))
351 raise error.Abort(_('at least one of -n/-c is required for -l'))
352
352
353 ui.pager('annotate')
353 ui.pager('annotate')
354
354
355 if rootfm.isplain():
355 if rootfm.isplain():
356 def makefunc(get, fmt):
356 def makefunc(get, fmt):
357 return lambda x: fmt(get(x))
357 return lambda x: fmt(get(x))
358 else:
358 else:
359 def makefunc(get, fmt):
359 def makefunc(get, fmt):
360 return get
360 return get
361 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
361 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
362 if opts.get(op)]
362 if opts.get(op)]
363 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
363 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
364 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
364 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
365 if opts.get(op))
365 if opts.get(op))
366
366
367 def bad(x, y):
367 def bad(x, y):
368 raise error.Abort("%s: %s" % (x, y))
368 raise error.Abort("%s: %s" % (x, y))
369
369
370 m = scmutil.match(ctx, pats, opts, badfn=bad)
370 m = scmutil.match(ctx, pats, opts, badfn=bad)
371
371
372 follow = not opts.get('no_follow')
372 follow = not opts.get('no_follow')
373 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
373 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
374 whitespace=True)
374 whitespace=True)
375 skiprevs = opts.get('skip')
375 skiprevs = opts.get('skip')
376 if skiprevs:
376 if skiprevs:
377 skiprevs = scmutil.revrange(repo, skiprevs)
377 skiprevs = scmutil.revrange(repo, skiprevs)
378
378
379 for abs in ctx.walk(m):
379 for abs in ctx.walk(m):
380 fctx = ctx[abs]
380 fctx = ctx[abs]
381 rootfm.startitem()
381 rootfm.startitem()
382 rootfm.data(abspath=abs, path=m.rel(abs))
382 rootfm.data(abspath=abs, path=m.rel(abs))
383 if not opts.get('text') and fctx.isbinary():
383 if not opts.get('text') and fctx.isbinary():
384 rootfm.plain(_("%s: binary file\n")
384 rootfm.plain(_("%s: binary file\n")
385 % ((pats and m.rel(abs)) or abs))
385 % ((pats and m.rel(abs)) or abs))
386 continue
386 continue
387
387
388 fm = rootfm.nested('lines')
388 fm = rootfm.nested('lines')
389 lines = fctx.annotate(follow=follow, linenumber=linenumber,
389 lines = fctx.annotate(follow=follow, linenumber=linenumber,
390 skiprevs=skiprevs, diffopts=diffopts)
390 skiprevs=skiprevs, diffopts=diffopts)
391 if not lines:
391 if not lines:
392 fm.end()
392 fm.end()
393 continue
393 continue
394 formats = []
394 formats = []
395 pieces = []
395 pieces = []
396
396
397 for f, sep in funcmap:
397 for f, sep in funcmap:
398 l = [f(n) for n, dummy in lines]
398 l = [f(n) for n, dummy in lines]
399 if fm.isplain():
399 if fm.isplain():
400 sizes = [encoding.colwidth(x) for x in l]
400 sizes = [encoding.colwidth(x) for x in l]
401 ml = max(sizes)
401 ml = max(sizes)
402 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
402 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
403 else:
403 else:
404 formats.append(['%s' for x in l])
404 formats.append(['%s' for x in l])
405 pieces.append(l)
405 pieces.append(l)
406
406
407 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
407 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
408 fm.startitem()
408 fm.startitem()
409 fm.write(fields, "".join(f), *p)
409 fm.write(fields, "".join(f), *p)
410 if l[0].skip:
410 if l[0].skip:
411 fmt = "* %s"
411 fmt = "* %s"
412 else:
412 else:
413 fmt = ": %s"
413 fmt = ": %s"
414 fm.write('line', fmt, l[1])
414 fm.write('line', fmt, l[1])
415
415
416 if not lines[-1][1].endswith('\n'):
416 if not lines[-1][1].endswith('\n'):
417 fm.plain('\n')
417 fm.plain('\n')
418 fm.end()
418 fm.end()
419
419
420 rootfm.end()
420 rootfm.end()
421
421
422 @command('archive',
422 @command('archive',
423 [('', 'no-decode', None, _('do not pass files through decoders')),
423 [('', 'no-decode', None, _('do not pass files through decoders')),
424 ('p', 'prefix', '', _('directory prefix for files in archive'),
424 ('p', 'prefix', '', _('directory prefix for files in archive'),
425 _('PREFIX')),
425 _('PREFIX')),
426 ('r', 'rev', '', _('revision to distribute'), _('REV')),
426 ('r', 'rev', '', _('revision to distribute'), _('REV')),
427 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
427 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
428 ] + subrepoopts + walkopts,
428 ] + subrepoopts + walkopts,
429 _('[OPTION]... DEST'))
429 _('[OPTION]... DEST'))
430 def archive(ui, repo, dest, **opts):
430 def archive(ui, repo, dest, **opts):
431 '''create an unversioned archive of a repository revision
431 '''create an unversioned archive of a repository revision
432
432
433 By default, the revision used is the parent of the working
433 By default, the revision used is the parent of the working
434 directory; use -r/--rev to specify a different revision.
434 directory; use -r/--rev to specify a different revision.
435
435
436 The archive type is automatically detected based on file
436 The archive type is automatically detected based on file
437 extension (to override, use -t/--type).
437 extension (to override, use -t/--type).
438
438
439 .. container:: verbose
439 .. container:: verbose
440
440
441 Examples:
441 Examples:
442
442
443 - create a zip file containing the 1.0 release::
443 - create a zip file containing the 1.0 release::
444
444
445 hg archive -r 1.0 project-1.0.zip
445 hg archive -r 1.0 project-1.0.zip
446
446
447 - create a tarball excluding .hg files::
447 - create a tarball excluding .hg files::
448
448
449 hg archive project.tar.gz -X ".hg*"
449 hg archive project.tar.gz -X ".hg*"
450
450
451 Valid types are:
451 Valid types are:
452
452
453 :``files``: a directory full of files (default)
453 :``files``: a directory full of files (default)
454 :``tar``: tar archive, uncompressed
454 :``tar``: tar archive, uncompressed
455 :``tbz2``: tar archive, compressed using bzip2
455 :``tbz2``: tar archive, compressed using bzip2
456 :``tgz``: tar archive, compressed using gzip
456 :``tgz``: tar archive, compressed using gzip
457 :``uzip``: zip archive, uncompressed
457 :``uzip``: zip archive, uncompressed
458 :``zip``: zip archive, compressed using deflate
458 :``zip``: zip archive, compressed using deflate
459
459
460 The exact name of the destination archive or directory is given
460 The exact name of the destination archive or directory is given
461 using a format string; see :hg:`help export` for details.
461 using a format string; see :hg:`help export` for details.
462
462
463 Each member added to an archive file has a directory prefix
463 Each member added to an archive file has a directory prefix
464 prepended. Use -p/--prefix to specify a format string for the
464 prepended. Use -p/--prefix to specify a format string for the
465 prefix. The default is the basename of the archive, with suffixes
465 prefix. The default is the basename of the archive, with suffixes
466 removed.
466 removed.
467
467
468 Returns 0 on success.
468 Returns 0 on success.
469 '''
469 '''
470
470
471 opts = pycompat.byteskwargs(opts)
471 opts = pycompat.byteskwargs(opts)
472 rev = opts.get('rev')
472 rev = opts.get('rev')
473 if rev:
473 if rev:
474 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
474 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
475 ctx = scmutil.revsingle(repo, rev)
475 ctx = scmutil.revsingle(repo, rev)
476 if not ctx:
476 if not ctx:
477 raise error.Abort(_('no working directory: please specify a revision'))
477 raise error.Abort(_('no working directory: please specify a revision'))
478 node = ctx.node()
478 node = ctx.node()
479 dest = cmdutil.makefilename(ctx, dest)
479 dest = cmdutil.makefilename(ctx, dest)
480 if os.path.realpath(dest) == repo.root:
480 if os.path.realpath(dest) == repo.root:
481 raise error.Abort(_('repository root cannot be destination'))
481 raise error.Abort(_('repository root cannot be destination'))
482
482
483 kind = opts.get('type') or archival.guesskind(dest) or 'files'
483 kind = opts.get('type') or archival.guesskind(dest) or 'files'
484 prefix = opts.get('prefix')
484 prefix = opts.get('prefix')
485
485
486 if dest == '-':
486 if dest == '-':
487 if kind == 'files':
487 if kind == 'files':
488 raise error.Abort(_('cannot archive plain files to stdout'))
488 raise error.Abort(_('cannot archive plain files to stdout'))
489 dest = cmdutil.makefileobj(ctx, dest)
489 dest = cmdutil.makefileobj(ctx, dest)
490 if not prefix:
490 if not prefix:
491 prefix = os.path.basename(repo.root) + '-%h'
491 prefix = os.path.basename(repo.root) + '-%h'
492
492
493 prefix = cmdutil.makefilename(ctx, prefix)
493 prefix = cmdutil.makefilename(ctx, prefix)
494 match = scmutil.match(ctx, [], opts)
494 match = scmutil.match(ctx, [], opts)
495 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
495 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
496 match, prefix, subrepos=opts.get('subrepos'))
496 match, prefix, subrepos=opts.get('subrepos'))
497
497
498 @command('backout',
498 @command('backout',
499 [('', 'merge', None, _('merge with old dirstate parent after backout')),
499 [('', 'merge', None, _('merge with old dirstate parent after backout')),
500 ('', 'commit', None,
500 ('', 'commit', None,
501 _('commit if no conflicts were encountered (DEPRECATED)')),
501 _('commit if no conflicts were encountered (DEPRECATED)')),
502 ('', 'no-commit', None, _('do not commit')),
502 ('', 'no-commit', None, _('do not commit')),
503 ('', 'parent', '',
503 ('', 'parent', '',
504 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
504 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
505 ('r', 'rev', '', _('revision to backout'), _('REV')),
505 ('r', 'rev', '', _('revision to backout'), _('REV')),
506 ('e', 'edit', False, _('invoke editor on commit messages')),
506 ('e', 'edit', False, _('invoke editor on commit messages')),
507 ] + mergetoolopts + walkopts + commitopts + commitopts2,
507 ] + mergetoolopts + walkopts + commitopts + commitopts2,
508 _('[OPTION]... [-r] REV'))
508 _('[OPTION]... [-r] REV'))
509 def backout(ui, repo, node=None, rev=None, **opts):
509 def backout(ui, repo, node=None, rev=None, **opts):
510 '''reverse effect of earlier changeset
510 '''reverse effect of earlier changeset
511
511
512 Prepare a new changeset with the effect of REV undone in the
512 Prepare a new changeset with the effect of REV undone in the
513 current working directory. If no conflicts were encountered,
513 current working directory. If no conflicts were encountered,
514 it will be committed immediately.
514 it will be committed immediately.
515
515
516 If REV is the parent of the working directory, then this new changeset
516 If REV is the parent of the working directory, then this new changeset
517 is committed automatically (unless --no-commit is specified).
517 is committed automatically (unless --no-commit is specified).
518
518
519 .. note::
519 .. note::
520
520
521 :hg:`backout` cannot be used to fix either an unwanted or
521 :hg:`backout` cannot be used to fix either an unwanted or
522 incorrect merge.
522 incorrect merge.
523
523
524 .. container:: verbose
524 .. container:: verbose
525
525
526 Examples:
526 Examples:
527
527
528 - Reverse the effect of the parent of the working directory.
528 - Reverse the effect of the parent of the working directory.
529 This backout will be committed immediately::
529 This backout will be committed immediately::
530
530
531 hg backout -r .
531 hg backout -r .
532
532
533 - Reverse the effect of previous bad revision 23::
533 - Reverse the effect of previous bad revision 23::
534
534
535 hg backout -r 23
535 hg backout -r 23
536
536
537 - Reverse the effect of previous bad revision 23 and
537 - Reverse the effect of previous bad revision 23 and
538 leave changes uncommitted::
538 leave changes uncommitted::
539
539
540 hg backout -r 23 --no-commit
540 hg backout -r 23 --no-commit
541 hg commit -m "Backout revision 23"
541 hg commit -m "Backout revision 23"
542
542
543 By default, the pending changeset will have one parent,
543 By default, the pending changeset will have one parent,
544 maintaining a linear history. With --merge, the pending
544 maintaining a linear history. With --merge, the pending
545 changeset will instead have two parents: the old parent of the
545 changeset will instead have two parents: the old parent of the
546 working directory and a new child of REV that simply undoes REV.
546 working directory and a new child of REV that simply undoes REV.
547
547
548 Before version 1.7, the behavior without --merge was equivalent
548 Before version 1.7, the behavior without --merge was equivalent
549 to specifying --merge followed by :hg:`update --clean .` to
549 to specifying --merge followed by :hg:`update --clean .` to
550 cancel the merge and leave the child of REV as a head to be
550 cancel the merge and leave the child of REV as a head to be
551 merged separately.
551 merged separately.
552
552
553 See :hg:`help dates` for a list of formats valid for -d/--date.
553 See :hg:`help dates` for a list of formats valid for -d/--date.
554
554
555 See :hg:`help revert` for a way to restore files to the state
555 See :hg:`help revert` for a way to restore files to the state
556 of another revision.
556 of another revision.
557
557
558 Returns 0 on success, 1 if nothing to backout or there are unresolved
558 Returns 0 on success, 1 if nothing to backout or there are unresolved
559 files.
559 files.
560 '''
560 '''
561 wlock = lock = None
561 wlock = lock = None
562 try:
562 try:
563 wlock = repo.wlock()
563 wlock = repo.wlock()
564 lock = repo.lock()
564 lock = repo.lock()
565 return _dobackout(ui, repo, node, rev, **opts)
565 return _dobackout(ui, repo, node, rev, **opts)
566 finally:
566 finally:
567 release(lock, wlock)
567 release(lock, wlock)
568
568
569 def _dobackout(ui, repo, node=None, rev=None, **opts):
569 def _dobackout(ui, repo, node=None, rev=None, **opts):
570 opts = pycompat.byteskwargs(opts)
570 opts = pycompat.byteskwargs(opts)
571 if opts.get('commit') and opts.get('no_commit'):
571 if opts.get('commit') and opts.get('no_commit'):
572 raise error.Abort(_("cannot use --commit with --no-commit"))
572 raise error.Abort(_("cannot use --commit with --no-commit"))
573 if opts.get('merge') and opts.get('no_commit'):
573 if opts.get('merge') and opts.get('no_commit'):
574 raise error.Abort(_("cannot use --merge with --no-commit"))
574 raise error.Abort(_("cannot use --merge with --no-commit"))
575
575
576 if rev and node:
576 if rev and node:
577 raise error.Abort(_("please specify just one revision"))
577 raise error.Abort(_("please specify just one revision"))
578
578
579 if not rev:
579 if not rev:
580 rev = node
580 rev = node
581
581
582 if not rev:
582 if not rev:
583 raise error.Abort(_("please specify a revision to backout"))
583 raise error.Abort(_("please specify a revision to backout"))
584
584
585 date = opts.get('date')
585 date = opts.get('date')
586 if date:
586 if date:
587 opts['date'] = util.parsedate(date)
587 opts['date'] = util.parsedate(date)
588
588
589 cmdutil.checkunfinished(repo)
589 cmdutil.checkunfinished(repo)
590 cmdutil.bailifchanged(repo)
590 cmdutil.bailifchanged(repo)
591 node = scmutil.revsingle(repo, rev).node()
591 node = scmutil.revsingle(repo, rev).node()
592
592
593 op1, op2 = repo.dirstate.parents()
593 op1, op2 = repo.dirstate.parents()
594 if not repo.changelog.isancestor(node, op1):
594 if not repo.changelog.isancestor(node, op1):
595 raise error.Abort(_('cannot backout change that is not an ancestor'))
595 raise error.Abort(_('cannot backout change that is not an ancestor'))
596
596
597 p1, p2 = repo.changelog.parents(node)
597 p1, p2 = repo.changelog.parents(node)
598 if p1 == nullid:
598 if p1 == nullid:
599 raise error.Abort(_('cannot backout a change with no parents'))
599 raise error.Abort(_('cannot backout a change with no parents'))
600 if p2 != nullid:
600 if p2 != nullid:
601 if not opts.get('parent'):
601 if not opts.get('parent'):
602 raise error.Abort(_('cannot backout a merge changeset'))
602 raise error.Abort(_('cannot backout a merge changeset'))
603 p = repo.lookup(opts['parent'])
603 p = repo.lookup(opts['parent'])
604 if p not in (p1, p2):
604 if p not in (p1, p2):
605 raise error.Abort(_('%s is not a parent of %s') %
605 raise error.Abort(_('%s is not a parent of %s') %
606 (short(p), short(node)))
606 (short(p), short(node)))
607 parent = p
607 parent = p
608 else:
608 else:
609 if opts.get('parent'):
609 if opts.get('parent'):
610 raise error.Abort(_('cannot use --parent on non-merge changeset'))
610 raise error.Abort(_('cannot use --parent on non-merge changeset'))
611 parent = p1
611 parent = p1
612
612
613 # the backout should appear on the same branch
613 # the backout should appear on the same branch
614 branch = repo.dirstate.branch()
614 branch = repo.dirstate.branch()
615 bheads = repo.branchheads(branch)
615 bheads = repo.branchheads(branch)
616 rctx = scmutil.revsingle(repo, hex(parent))
616 rctx = scmutil.revsingle(repo, hex(parent))
617 if not opts.get('merge') and op1 != node:
617 if not opts.get('merge') and op1 != node:
618 dsguard = dirstateguard.dirstateguard(repo, 'backout')
618 dsguard = dirstateguard.dirstateguard(repo, 'backout')
619 try:
619 try:
620 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
620 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
621 'backout')
621 'backout')
622 stats = mergemod.update(repo, parent, True, True, node, False)
622 stats = mergemod.update(repo, parent, True, True, node, False)
623 repo.setparents(op1, op2)
623 repo.setparents(op1, op2)
624 dsguard.close()
624 dsguard.close()
625 hg._showstats(repo, stats)
625 hg._showstats(repo, stats)
626 if stats[3]:
626 if stats[3]:
627 repo.ui.status(_("use 'hg resolve' to retry unresolved "
627 repo.ui.status(_("use 'hg resolve' to retry unresolved "
628 "file merges\n"))
628 "file merges\n"))
629 return 1
629 return 1
630 finally:
630 finally:
631 ui.setconfig('ui', 'forcemerge', '', '')
631 ui.setconfig('ui', 'forcemerge', '', '')
632 lockmod.release(dsguard)
632 lockmod.release(dsguard)
633 else:
633 else:
634 hg.clean(repo, node, show_stats=False)
634 hg.clean(repo, node, show_stats=False)
635 repo.dirstate.setbranch(branch)
635 repo.dirstate.setbranch(branch)
636 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
636 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
637
637
638 if opts.get('no_commit'):
638 if opts.get('no_commit'):
639 msg = _("changeset %s backed out, "
639 msg = _("changeset %s backed out, "
640 "don't forget to commit.\n")
640 "don't forget to commit.\n")
641 ui.status(msg % short(node))
641 ui.status(msg % short(node))
642 return 0
642 return 0
643
643
644 def commitfunc(ui, repo, message, match, opts):
644 def commitfunc(ui, repo, message, match, opts):
645 editform = 'backout'
645 editform = 'backout'
646 e = cmdutil.getcommiteditor(editform=editform,
646 e = cmdutil.getcommiteditor(editform=editform,
647 **pycompat.strkwargs(opts))
647 **pycompat.strkwargs(opts))
648 if not message:
648 if not message:
649 # we don't translate commit messages
649 # we don't translate commit messages
650 message = "Backed out changeset %s" % short(node)
650 message = "Backed out changeset %s" % short(node)
651 e = cmdutil.getcommiteditor(edit=True, editform=editform)
651 e = cmdutil.getcommiteditor(edit=True, editform=editform)
652 return repo.commit(message, opts.get('user'), opts.get('date'),
652 return repo.commit(message, opts.get('user'), opts.get('date'),
653 match, editor=e)
653 match, editor=e)
654 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
654 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
655 if not newnode:
655 if not newnode:
656 ui.status(_("nothing changed\n"))
656 ui.status(_("nothing changed\n"))
657 return 1
657 return 1
658 cmdutil.commitstatus(repo, newnode, branch, bheads)
658 cmdutil.commitstatus(repo, newnode, branch, bheads)
659
659
660 def nice(node):
660 def nice(node):
661 return '%d:%s' % (repo.changelog.rev(node), short(node))
661 return '%d:%s' % (repo.changelog.rev(node), short(node))
662 ui.status(_('changeset %s backs out changeset %s\n') %
662 ui.status(_('changeset %s backs out changeset %s\n') %
663 (nice(repo.changelog.tip()), nice(node)))
663 (nice(repo.changelog.tip()), nice(node)))
664 if opts.get('merge') and op1 != node:
664 if opts.get('merge') and op1 != node:
665 hg.clean(repo, op1, show_stats=False)
665 hg.clean(repo, op1, show_stats=False)
666 ui.status(_('merging with changeset %s\n')
666 ui.status(_('merging with changeset %s\n')
667 % nice(repo.changelog.tip()))
667 % nice(repo.changelog.tip()))
668 try:
668 try:
669 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
669 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
670 'backout')
670 'backout')
671 return hg.merge(repo, hex(repo.changelog.tip()))
671 return hg.merge(repo, hex(repo.changelog.tip()))
672 finally:
672 finally:
673 ui.setconfig('ui', 'forcemerge', '', '')
673 ui.setconfig('ui', 'forcemerge', '', '')
674 return 0
674 return 0
675
675
676 @command('bisect',
676 @command('bisect',
677 [('r', 'reset', False, _('reset bisect state')),
677 [('r', 'reset', False, _('reset bisect state')),
678 ('g', 'good', False, _('mark changeset good')),
678 ('g', 'good', False, _('mark changeset good')),
679 ('b', 'bad', False, _('mark changeset bad')),
679 ('b', 'bad', False, _('mark changeset bad')),
680 ('s', 'skip', False, _('skip testing changeset')),
680 ('s', 'skip', False, _('skip testing changeset')),
681 ('e', 'extend', False, _('extend the bisect range')),
681 ('e', 'extend', False, _('extend the bisect range')),
682 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
682 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
683 ('U', 'noupdate', False, _('do not update to target'))],
683 ('U', 'noupdate', False, _('do not update to target'))],
684 _("[-gbsr] [-U] [-c CMD] [REV]"))
684 _("[-gbsr] [-U] [-c CMD] [REV]"))
685 def bisect(ui, repo, rev=None, extra=None, command=None,
685 def bisect(ui, repo, rev=None, extra=None, command=None,
686 reset=None, good=None, bad=None, skip=None, extend=None,
686 reset=None, good=None, bad=None, skip=None, extend=None,
687 noupdate=None):
687 noupdate=None):
688 """subdivision search of changesets
688 """subdivision search of changesets
689
689
690 This command helps to find changesets which introduce problems. To
690 This command helps to find changesets which introduce problems. To
691 use, mark the earliest changeset you know exhibits the problem as
691 use, mark the earliest changeset you know exhibits the problem as
692 bad, then mark the latest changeset which is free from the problem
692 bad, then mark the latest changeset which is free from the problem
693 as good. Bisect will update your working directory to a revision
693 as good. Bisect will update your working directory to a revision
694 for testing (unless the -U/--noupdate option is specified). Once
694 for testing (unless the -U/--noupdate option is specified). Once
695 you have performed tests, mark the working directory as good or
695 you have performed tests, mark the working directory as good or
696 bad, and bisect will either update to another candidate changeset
696 bad, and bisect will either update to another candidate changeset
697 or announce that it has found the bad revision.
697 or announce that it has found the bad revision.
698
698
699 As a shortcut, you can also use the revision argument to mark a
699 As a shortcut, you can also use the revision argument to mark a
700 revision as good or bad without checking it out first.
700 revision as good or bad without checking it out first.
701
701
702 If you supply a command, it will be used for automatic bisection.
702 If you supply a command, it will be used for automatic bisection.
703 The environment variable HG_NODE will contain the ID of the
703 The environment variable HG_NODE will contain the ID of the
704 changeset being tested. The exit status of the command will be
704 changeset being tested. The exit status of the command will be
705 used to mark revisions as good or bad: status 0 means good, 125
705 used to mark revisions as good or bad: status 0 means good, 125
706 means to skip the revision, 127 (command not found) will abort the
706 means to skip the revision, 127 (command not found) will abort the
707 bisection, and any other non-zero exit status means the revision
707 bisection, and any other non-zero exit status means the revision
708 is bad.
708 is bad.
709
709
710 .. container:: verbose
710 .. container:: verbose
711
711
712 Some examples:
712 Some examples:
713
713
714 - start a bisection with known bad revision 34, and good revision 12::
714 - start a bisection with known bad revision 34, and good revision 12::
715
715
716 hg bisect --bad 34
716 hg bisect --bad 34
717 hg bisect --good 12
717 hg bisect --good 12
718
718
719 - advance the current bisection by marking current revision as good or
719 - advance the current bisection by marking current revision as good or
720 bad::
720 bad::
721
721
722 hg bisect --good
722 hg bisect --good
723 hg bisect --bad
723 hg bisect --bad
724
724
725 - mark the current revision, or a known revision, to be skipped (e.g. if
725 - mark the current revision, or a known revision, to be skipped (e.g. if
726 that revision is not usable because of another issue)::
726 that revision is not usable because of another issue)::
727
727
728 hg bisect --skip
728 hg bisect --skip
729 hg bisect --skip 23
729 hg bisect --skip 23
730
730
731 - skip all revisions that do not touch directories ``foo`` or ``bar``::
731 - skip all revisions that do not touch directories ``foo`` or ``bar``::
732
732
733 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
733 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
734
734
735 - forget the current bisection::
735 - forget the current bisection::
736
736
737 hg bisect --reset
737 hg bisect --reset
738
738
739 - use 'make && make tests' to automatically find the first broken
739 - use 'make && make tests' to automatically find the first broken
740 revision::
740 revision::
741
741
742 hg bisect --reset
742 hg bisect --reset
743 hg bisect --bad 34
743 hg bisect --bad 34
744 hg bisect --good 12
744 hg bisect --good 12
745 hg bisect --command "make && make tests"
745 hg bisect --command "make && make tests"
746
746
747 - see all changesets whose states are already known in the current
747 - see all changesets whose states are already known in the current
748 bisection::
748 bisection::
749
749
750 hg log -r "bisect(pruned)"
750 hg log -r "bisect(pruned)"
751
751
752 - see the changeset currently being bisected (especially useful
752 - see the changeset currently being bisected (especially useful
753 if running with -U/--noupdate)::
753 if running with -U/--noupdate)::
754
754
755 hg log -r "bisect(current)"
755 hg log -r "bisect(current)"
756
756
757 - see all changesets that took part in the current bisection::
757 - see all changesets that took part in the current bisection::
758
758
759 hg log -r "bisect(range)"
759 hg log -r "bisect(range)"
760
760
761 - you can even get a nice graph::
761 - you can even get a nice graph::
762
762
763 hg log --graph -r "bisect(range)"
763 hg log --graph -r "bisect(range)"
764
764
765 See :hg:`help revisions.bisect` for more about the `bisect()` predicate.
765 See :hg:`help revisions.bisect` for more about the `bisect()` predicate.
766
766
767 Returns 0 on success.
767 Returns 0 on success.
768 """
768 """
769 # backward compatibility
769 # backward compatibility
770 if rev in "good bad reset init".split():
770 if rev in "good bad reset init".split():
771 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
771 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
772 cmd, rev, extra = rev, extra, None
772 cmd, rev, extra = rev, extra, None
773 if cmd == "good":
773 if cmd == "good":
774 good = True
774 good = True
775 elif cmd == "bad":
775 elif cmd == "bad":
776 bad = True
776 bad = True
777 else:
777 else:
778 reset = True
778 reset = True
779 elif extra:
779 elif extra:
780 raise error.Abort(_('incompatible arguments'))
780 raise error.Abort(_('incompatible arguments'))
781
781
782 incompatibles = {
782 incompatibles = {
783 '--bad': bad,
783 '--bad': bad,
784 '--command': bool(command),
784 '--command': bool(command),
785 '--extend': extend,
785 '--extend': extend,
786 '--good': good,
786 '--good': good,
787 '--reset': reset,
787 '--reset': reset,
788 '--skip': skip,
788 '--skip': skip,
789 }
789 }
790
790
791 enabled = [x for x in incompatibles if incompatibles[x]]
791 enabled = [x for x in incompatibles if incompatibles[x]]
792
792
793 if len(enabled) > 1:
793 if len(enabled) > 1:
794 raise error.Abort(_('%s and %s are incompatible') %
794 raise error.Abort(_('%s and %s are incompatible') %
795 tuple(sorted(enabled)[0:2]))
795 tuple(sorted(enabled)[0:2]))
796
796
797 if reset:
797 if reset:
798 hbisect.resetstate(repo)
798 hbisect.resetstate(repo)
799 return
799 return
800
800
801 state = hbisect.load_state(repo)
801 state = hbisect.load_state(repo)
802
802
803 # update state
803 # update state
804 if good or bad or skip:
804 if good or bad or skip:
805 if rev:
805 if rev:
806 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
806 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
807 else:
807 else:
808 nodes = [repo.lookup('.')]
808 nodes = [repo.lookup('.')]
809 if good:
809 if good:
810 state['good'] += nodes
810 state['good'] += nodes
811 elif bad:
811 elif bad:
812 state['bad'] += nodes
812 state['bad'] += nodes
813 elif skip:
813 elif skip:
814 state['skip'] += nodes
814 state['skip'] += nodes
815 hbisect.save_state(repo, state)
815 hbisect.save_state(repo, state)
816 if not (state['good'] and state['bad']):
816 if not (state['good'] and state['bad']):
817 return
817 return
818
818
819 def mayupdate(repo, node, show_stats=True):
819 def mayupdate(repo, node, show_stats=True):
820 """common used update sequence"""
820 """common used update sequence"""
821 if noupdate:
821 if noupdate:
822 return
822 return
823 cmdutil.checkunfinished(repo)
823 cmdutil.checkunfinished(repo)
824 cmdutil.bailifchanged(repo)
824 cmdutil.bailifchanged(repo)
825 return hg.clean(repo, node, show_stats=show_stats)
825 return hg.clean(repo, node, show_stats=show_stats)
826
826
827 displayer = logcmdutil.changesetdisplayer(ui, repo, {})
827 displayer = logcmdutil.changesetdisplayer(ui, repo, {})
828
828
829 if command:
829 if command:
830 changesets = 1
830 changesets = 1
831 if noupdate:
831 if noupdate:
832 try:
832 try:
833 node = state['current'][0]
833 node = state['current'][0]
834 except LookupError:
834 except LookupError:
835 raise error.Abort(_('current bisect revision is unknown - '
835 raise error.Abort(_('current bisect revision is unknown - '
836 'start a new bisect to fix'))
836 'start a new bisect to fix'))
837 else:
837 else:
838 node, p2 = repo.dirstate.parents()
838 node, p2 = repo.dirstate.parents()
839 if p2 != nullid:
839 if p2 != nullid:
840 raise error.Abort(_('current bisect revision is a merge'))
840 raise error.Abort(_('current bisect revision is a merge'))
841 if rev:
841 if rev:
842 node = repo[scmutil.revsingle(repo, rev, node)].node()
842 node = repo[scmutil.revsingle(repo, rev, node)].node()
843 try:
843 try:
844 while changesets:
844 while changesets:
845 # update state
845 # update state
846 state['current'] = [node]
846 state['current'] = [node]
847 hbisect.save_state(repo, state)
847 hbisect.save_state(repo, state)
848 status = ui.system(command, environ={'HG_NODE': hex(node)},
848 status = ui.system(command, environ={'HG_NODE': hex(node)},
849 blockedtag='bisect_check')
849 blockedtag='bisect_check')
850 if status == 125:
850 if status == 125:
851 transition = "skip"
851 transition = "skip"
852 elif status == 0:
852 elif status == 0:
853 transition = "good"
853 transition = "good"
854 # status < 0 means process was killed
854 # status < 0 means process was killed
855 elif status == 127:
855 elif status == 127:
856 raise error.Abort(_("failed to execute %s") % command)
856 raise error.Abort(_("failed to execute %s") % command)
857 elif status < 0:
857 elif status < 0:
858 raise error.Abort(_("%s killed") % command)
858 raise error.Abort(_("%s killed") % command)
859 else:
859 else:
860 transition = "bad"
860 transition = "bad"
861 state[transition].append(node)
861 state[transition].append(node)
862 ctx = repo[node]
862 ctx = repo[node]
863 ui.status(_('changeset %d:%s: %s\n') % (ctx.rev(), ctx,
863 ui.status(_('changeset %d:%s: %s\n') % (ctx.rev(), ctx,
864 transition))
864 transition))
865 hbisect.checkstate(state)
865 hbisect.checkstate(state)
866 # bisect
866 # bisect
867 nodes, changesets, bgood = hbisect.bisect(repo, state)
867 nodes, changesets, bgood = hbisect.bisect(repo, state)
868 # update to next check
868 # update to next check
869 node = nodes[0]
869 node = nodes[0]
870 mayupdate(repo, node, show_stats=False)
870 mayupdate(repo, node, show_stats=False)
871 finally:
871 finally:
872 state['current'] = [node]
872 state['current'] = [node]
873 hbisect.save_state(repo, state)
873 hbisect.save_state(repo, state)
874 hbisect.printresult(ui, repo, state, displayer, nodes, bgood)
874 hbisect.printresult(ui, repo, state, displayer, nodes, bgood)
875 return
875 return
876
876
877 hbisect.checkstate(state)
877 hbisect.checkstate(state)
878
878
879 # actually bisect
879 # actually bisect
880 nodes, changesets, good = hbisect.bisect(repo, state)
880 nodes, changesets, good = hbisect.bisect(repo, state)
881 if extend:
881 if extend:
882 if not changesets:
882 if not changesets:
883 extendnode = hbisect.extendrange(repo, state, nodes, good)
883 extendnode = hbisect.extendrange(repo, state, nodes, good)
884 if extendnode is not None:
884 if extendnode is not None:
885 ui.write(_("Extending search to changeset %d:%s\n")
885 ui.write(_("Extending search to changeset %d:%s\n")
886 % (extendnode.rev(), extendnode))
886 % (extendnode.rev(), extendnode))
887 state['current'] = [extendnode.node()]
887 state['current'] = [extendnode.node()]
888 hbisect.save_state(repo, state)
888 hbisect.save_state(repo, state)
889 return mayupdate(repo, extendnode.node())
889 return mayupdate(repo, extendnode.node())
890 raise error.Abort(_("nothing to extend"))
890 raise error.Abort(_("nothing to extend"))
891
891
892 if changesets == 0:
892 if changesets == 0:
893 hbisect.printresult(ui, repo, state, displayer, nodes, good)
893 hbisect.printresult(ui, repo, state, displayer, nodes, good)
894 else:
894 else:
895 assert len(nodes) == 1 # only a single node can be tested next
895 assert len(nodes) == 1 # only a single node can be tested next
896 node = nodes[0]
896 node = nodes[0]
897 # compute the approximate number of remaining tests
897 # compute the approximate number of remaining tests
898 tests, size = 0, 2
898 tests, size = 0, 2
899 while size <= changesets:
899 while size <= changesets:
900 tests, size = tests + 1, size * 2
900 tests, size = tests + 1, size * 2
901 rev = repo.changelog.rev(node)
901 rev = repo.changelog.rev(node)
902 ui.write(_("Testing changeset %d:%s "
902 ui.write(_("Testing changeset %d:%s "
903 "(%d changesets remaining, ~%d tests)\n")
903 "(%d changesets remaining, ~%d tests)\n")
904 % (rev, short(node), changesets, tests))
904 % (rev, short(node), changesets, tests))
905 state['current'] = [node]
905 state['current'] = [node]
906 hbisect.save_state(repo, state)
906 hbisect.save_state(repo, state)
907 return mayupdate(repo, node)
907 return mayupdate(repo, node)
908
908
909 @command('bookmarks|bookmark',
909 @command('bookmarks|bookmark',
910 [('f', 'force', False, _('force')),
910 [('f', 'force', False, _('force')),
911 ('r', 'rev', '', _('revision for bookmark action'), _('REV')),
911 ('r', 'rev', '', _('revision for bookmark action'), _('REV')),
912 ('d', 'delete', False, _('delete a given bookmark')),
912 ('d', 'delete', False, _('delete a given bookmark')),
913 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
913 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
914 ('i', 'inactive', False, _('mark a bookmark inactive')),
914 ('i', 'inactive', False, _('mark a bookmark inactive')),
915 ] + formatteropts,
915 ] + formatteropts,
916 _('hg bookmarks [OPTIONS]... [NAME]...'))
916 _('hg bookmarks [OPTIONS]... [NAME]...'))
917 def bookmark(ui, repo, *names, **opts):
917 def bookmark(ui, repo, *names, **opts):
918 '''create a new bookmark or list existing bookmarks
918 '''create a new bookmark or list existing bookmarks
919
919
920 Bookmarks are labels on changesets to help track lines of development.
920 Bookmarks are labels on changesets to help track lines of development.
921 Bookmarks are unversioned and can be moved, renamed and deleted.
921 Bookmarks are unversioned and can be moved, renamed and deleted.
922 Deleting or moving a bookmark has no effect on the associated changesets.
922 Deleting or moving a bookmark has no effect on the associated changesets.
923
923
924 Creating or updating to a bookmark causes it to be marked as 'active'.
924 Creating or updating to a bookmark causes it to be marked as 'active'.
925 The active bookmark is indicated with a '*'.
925 The active bookmark is indicated with a '*'.
926 When a commit is made, the active bookmark will advance to the new commit.
926 When a commit is made, the active bookmark will advance to the new commit.
927 A plain :hg:`update` will also advance an active bookmark, if possible.
927 A plain :hg:`update` will also advance an active bookmark, if possible.
928 Updating away from a bookmark will cause it to be deactivated.
928 Updating away from a bookmark will cause it to be deactivated.
929
929
930 Bookmarks can be pushed and pulled between repositories (see
930 Bookmarks can be pushed and pulled between repositories (see
931 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
931 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
932 diverged, a new 'divergent bookmark' of the form 'name@path' will
932 diverged, a new 'divergent bookmark' of the form 'name@path' will
933 be created. Using :hg:`merge` will resolve the divergence.
933 be created. Using :hg:`merge` will resolve the divergence.
934
934
935 Specifying bookmark as '.' to -m or -d options is equivalent to specifying
935 Specifying bookmark as '.' to -m or -d options is equivalent to specifying
936 the active bookmark's name.
936 the active bookmark's name.
937
937
938 A bookmark named '@' has the special property that :hg:`clone` will
938 A bookmark named '@' has the special property that :hg:`clone` will
939 check it out by default if it exists.
939 check it out by default if it exists.
940
940
941 .. container:: verbose
941 .. container:: verbose
942
942
943 Examples:
943 Examples:
944
944
945 - create an active bookmark for a new line of development::
945 - create an active bookmark for a new line of development::
946
946
947 hg book new-feature
947 hg book new-feature
948
948
949 - create an inactive bookmark as a place marker::
949 - create an inactive bookmark as a place marker::
950
950
951 hg book -i reviewed
951 hg book -i reviewed
952
952
953 - create an inactive bookmark on another changeset::
953 - create an inactive bookmark on another changeset::
954
954
955 hg book -r .^ tested
955 hg book -r .^ tested
956
956
957 - rename bookmark turkey to dinner::
957 - rename bookmark turkey to dinner::
958
958
959 hg book -m turkey dinner
959 hg book -m turkey dinner
960
960
961 - move the '@' bookmark from another branch::
961 - move the '@' bookmark from another branch::
962
962
963 hg book -f @
963 hg book -f @
964 '''
964 '''
965 force = opts.get(r'force')
965 force = opts.get(r'force')
966 rev = opts.get(r'rev')
966 rev = opts.get(r'rev')
967 delete = opts.get(r'delete')
967 delete = opts.get(r'delete')
968 rename = opts.get(r'rename')
968 rename = opts.get(r'rename')
969 inactive = opts.get(r'inactive')
969 inactive = opts.get(r'inactive')
970
970
971 if delete and rename:
971 if delete and rename:
972 raise error.Abort(_("--delete and --rename are incompatible"))
972 raise error.Abort(_("--delete and --rename are incompatible"))
973 if delete and rev:
973 if delete and rev:
974 raise error.Abort(_("--rev is incompatible with --delete"))
974 raise error.Abort(_("--rev is incompatible with --delete"))
975 if rename and rev:
975 if rename and rev:
976 raise error.Abort(_("--rev is incompatible with --rename"))
976 raise error.Abort(_("--rev is incompatible with --rename"))
977 if not names and (delete or rev):
977 if not names and (delete or rev):
978 raise error.Abort(_("bookmark name required"))
978 raise error.Abort(_("bookmark name required"))
979
979
980 if delete or rename or names or inactive:
980 if delete or rename or names or inactive:
981 with repo.wlock(), repo.lock(), repo.transaction('bookmark') as tr:
981 with repo.wlock(), repo.lock(), repo.transaction('bookmark') as tr:
982 if delete:
982 if delete:
983 names = pycompat.maplist(repo._bookmarks.expandname, names)
983 names = pycompat.maplist(repo._bookmarks.expandname, names)
984 bookmarks.delete(repo, tr, names)
984 bookmarks.delete(repo, tr, names)
985 elif rename:
985 elif rename:
986 if not names:
986 if not names:
987 raise error.Abort(_("new bookmark name required"))
987 raise error.Abort(_("new bookmark name required"))
988 elif len(names) > 1:
988 elif len(names) > 1:
989 raise error.Abort(_("only one new bookmark name allowed"))
989 raise error.Abort(_("only one new bookmark name allowed"))
990 rename = repo._bookmarks.expandname(rename)
990 rename = repo._bookmarks.expandname(rename)
991 bookmarks.rename(repo, tr, rename, names[0], force, inactive)
991 bookmarks.rename(repo, tr, rename, names[0], force, inactive)
992 elif names:
992 elif names:
993 bookmarks.addbookmarks(repo, tr, names, rev, force, inactive)
993 bookmarks.addbookmarks(repo, tr, names, rev, force, inactive)
994 elif inactive:
994 elif inactive:
995 if len(repo._bookmarks) == 0:
995 if len(repo._bookmarks) == 0:
996 ui.status(_("no bookmarks set\n"))
996 ui.status(_("no bookmarks set\n"))
997 elif not repo._activebookmark:
997 elif not repo._activebookmark:
998 ui.status(_("no active bookmark\n"))
998 ui.status(_("no active bookmark\n"))
999 else:
999 else:
1000 bookmarks.deactivate(repo)
1000 bookmarks.deactivate(repo)
1001 else: # show bookmarks
1001 else: # show bookmarks
1002 bookmarks.printbookmarks(ui, repo, **opts)
1002 bookmarks.printbookmarks(ui, repo, **opts)
1003
1003
1004 @command('branch',
1004 @command('branch',
1005 [('f', 'force', None,
1005 [('f', 'force', None,
1006 _('set branch name even if it shadows an existing branch')),
1006 _('set branch name even if it shadows an existing branch')),
1007 ('C', 'clean', None, _('reset branch name to parent branch name')),
1007 ('C', 'clean', None, _('reset branch name to parent branch name')),
1008 ('r', 'rev', [], _('change branches of the given revs (EXPERIMENTAL)')),
1008 ('r', 'rev', [], _('change branches of the given revs (EXPERIMENTAL)')),
1009 ],
1009 ],
1010 _('[-fC] [NAME]'))
1010 _('[-fC] [NAME]'))
1011 def branch(ui, repo, label=None, **opts):
1011 def branch(ui, repo, label=None, **opts):
1012 """set or show the current branch name
1012 """set or show the current branch name
1013
1013
1014 .. note::
1014 .. note::
1015
1015
1016 Branch names are permanent and global. Use :hg:`bookmark` to create a
1016 Branch names are permanent and global. Use :hg:`bookmark` to create a
1017 light-weight bookmark instead. See :hg:`help glossary` for more
1017 light-weight bookmark instead. See :hg:`help glossary` for more
1018 information about named branches and bookmarks.
1018 information about named branches and bookmarks.
1019
1019
1020 With no argument, show the current branch name. With one argument,
1020 With no argument, show the current branch name. With one argument,
1021 set the working directory branch name (the branch will not exist
1021 set the working directory branch name (the branch will not exist
1022 in the repository until the next commit). Standard practice
1022 in the repository until the next commit). Standard practice
1023 recommends that primary development take place on the 'default'
1023 recommends that primary development take place on the 'default'
1024 branch.
1024 branch.
1025
1025
1026 Unless -f/--force is specified, branch will not let you set a
1026 Unless -f/--force is specified, branch will not let you set a
1027 branch name that already exists.
1027 branch name that already exists.
1028
1028
1029 Use -C/--clean to reset the working directory branch to that of
1029 Use -C/--clean to reset the working directory branch to that of
1030 the parent of the working directory, negating a previous branch
1030 the parent of the working directory, negating a previous branch
1031 change.
1031 change.
1032
1032
1033 Use the command :hg:`update` to switch to an existing branch. Use
1033 Use the command :hg:`update` to switch to an existing branch. Use
1034 :hg:`commit --close-branch` to mark this branch head as closed.
1034 :hg:`commit --close-branch` to mark this branch head as closed.
1035 When all heads of a branch are closed, the branch will be
1035 When all heads of a branch are closed, the branch will be
1036 considered closed.
1036 considered closed.
1037
1037
1038 Returns 0 on success.
1038 Returns 0 on success.
1039 """
1039 """
1040 opts = pycompat.byteskwargs(opts)
1040 opts = pycompat.byteskwargs(opts)
1041 revs = opts.get('rev')
1041 revs = opts.get('rev')
1042 if label:
1042 if label:
1043 label = label.strip()
1043 label = label.strip()
1044
1044
1045 if not opts.get('clean') and not label:
1045 if not opts.get('clean') and not label:
1046 if revs:
1046 if revs:
1047 raise error.Abort(_("no branch name specified for the revisions"))
1047 raise error.Abort(_("no branch name specified for the revisions"))
1048 ui.write("%s\n" % repo.dirstate.branch())
1048 ui.write("%s\n" % repo.dirstate.branch())
1049 return
1049 return
1050
1050
1051 with repo.wlock():
1051 with repo.wlock():
1052 if opts.get('clean'):
1052 if opts.get('clean'):
1053 label = repo[None].p1().branch()
1053 label = repo[None].p1().branch()
1054 repo.dirstate.setbranch(label)
1054 repo.dirstate.setbranch(label)
1055 ui.status(_('reset working directory to branch %s\n') % label)
1055 ui.status(_('reset working directory to branch %s\n') % label)
1056 elif label:
1056 elif label:
1057
1057
1058 scmutil.checknewlabel(repo, label, 'branch')
1058 scmutil.checknewlabel(repo, label, 'branch')
1059 if revs:
1059 if revs:
1060 return cmdutil.changebranch(ui, repo, revs, label)
1060 return cmdutil.changebranch(ui, repo, revs, label)
1061
1061
1062 if not opts.get('force') and label in repo.branchmap():
1062 if not opts.get('force') and label in repo.branchmap():
1063 if label not in [p.branch() for p in repo[None].parents()]:
1063 if label not in [p.branch() for p in repo[None].parents()]:
1064 raise error.Abort(_('a branch of the same name already'
1064 raise error.Abort(_('a branch of the same name already'
1065 ' exists'),
1065 ' exists'),
1066 # i18n: "it" refers to an existing branch
1066 # i18n: "it" refers to an existing branch
1067 hint=_("use 'hg update' to switch to it"))
1067 hint=_("use 'hg update' to switch to it"))
1068
1068
1069 repo.dirstate.setbranch(label)
1069 repo.dirstate.setbranch(label)
1070 ui.status(_('marked working directory as branch %s\n') % label)
1070 ui.status(_('marked working directory as branch %s\n') % label)
1071
1071
1072 # find any open named branches aside from default
1072 # find any open named branches aside from default
1073 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1073 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1074 if n != "default" and not c]
1074 if n != "default" and not c]
1075 if not others:
1075 if not others:
1076 ui.status(_('(branches are permanent and global, '
1076 ui.status(_('(branches are permanent and global, '
1077 'did you want a bookmark?)\n'))
1077 'did you want a bookmark?)\n'))
1078
1078
1079 @command('branches',
1079 @command('branches',
1080 [('a', 'active', False,
1080 [('a', 'active', False,
1081 _('show only branches that have unmerged heads (DEPRECATED)')),
1081 _('show only branches that have unmerged heads (DEPRECATED)')),
1082 ('c', 'closed', False, _('show normal and closed branches')),
1082 ('c', 'closed', False, _('show normal and closed branches')),
1083 ] + formatteropts,
1083 ] + formatteropts,
1084 _('[-c]'), cmdtype=readonly)
1084 _('[-c]'), cmdtype=readonly)
1085 def branches(ui, repo, active=False, closed=False, **opts):
1085 def branches(ui, repo, active=False, closed=False, **opts):
1086 """list repository named branches
1086 """list repository named branches
1087
1087
1088 List the repository's named branches, indicating which ones are
1088 List the repository's named branches, indicating which ones are
1089 inactive. If -c/--closed is specified, also list branches which have
1089 inactive. If -c/--closed is specified, also list branches which have
1090 been marked closed (see :hg:`commit --close-branch`).
1090 been marked closed (see :hg:`commit --close-branch`).
1091
1091
1092 Use the command :hg:`update` to switch to an existing branch.
1092 Use the command :hg:`update` to switch to an existing branch.
1093
1093
1094 Returns 0.
1094 Returns 0.
1095 """
1095 """
1096
1096
1097 opts = pycompat.byteskwargs(opts)
1097 opts = pycompat.byteskwargs(opts)
1098 ui.pager('branches')
1098 ui.pager('branches')
1099 fm = ui.formatter('branches', opts)
1099 fm = ui.formatter('branches', opts)
1100 hexfunc = fm.hexfunc
1100 hexfunc = fm.hexfunc
1101
1101
1102 allheads = set(repo.heads())
1102 allheads = set(repo.heads())
1103 branches = []
1103 branches = []
1104 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1104 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1105 isactive = False
1105 isactive = False
1106 if not isclosed:
1106 if not isclosed:
1107 openheads = set(repo.branchmap().iteropen(heads))
1107 openheads = set(repo.branchmap().iteropen(heads))
1108 isactive = bool(openheads & allheads)
1108 isactive = bool(openheads & allheads)
1109 branches.append((tag, repo[tip], isactive, not isclosed))
1109 branches.append((tag, repo[tip], isactive, not isclosed))
1110 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1110 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1111 reverse=True)
1111 reverse=True)
1112
1112
1113 for tag, ctx, isactive, isopen in branches:
1113 for tag, ctx, isactive, isopen in branches:
1114 if active and not isactive:
1114 if active and not isactive:
1115 continue
1115 continue
1116 if isactive:
1116 if isactive:
1117 label = 'branches.active'
1117 label = 'branches.active'
1118 notice = ''
1118 notice = ''
1119 elif not isopen:
1119 elif not isopen:
1120 if not closed:
1120 if not closed:
1121 continue
1121 continue
1122 label = 'branches.closed'
1122 label = 'branches.closed'
1123 notice = _(' (closed)')
1123 notice = _(' (closed)')
1124 else:
1124 else:
1125 label = 'branches.inactive'
1125 label = 'branches.inactive'
1126 notice = _(' (inactive)')
1126 notice = _(' (inactive)')
1127 current = (tag == repo.dirstate.branch())
1127 current = (tag == repo.dirstate.branch())
1128 if current:
1128 if current:
1129 label = 'branches.current'
1129 label = 'branches.current'
1130
1130
1131 fm.startitem()
1131 fm.startitem()
1132 fm.write('branch', '%s', tag, label=label)
1132 fm.write('branch', '%s', tag, label=label)
1133 rev = ctx.rev()
1133 rev = ctx.rev()
1134 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1134 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1135 fmt = ' ' * padsize + ' %d:%s'
1135 fmt = ' ' * padsize + ' %d:%s'
1136 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1136 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1137 label='log.changeset changeset.%s' % ctx.phasestr())
1137 label='log.changeset changeset.%s' % ctx.phasestr())
1138 fm.context(ctx=ctx)
1138 fm.context(ctx=ctx)
1139 fm.data(active=isactive, closed=not isopen, current=current)
1139 fm.data(active=isactive, closed=not isopen, current=current)
1140 if not ui.quiet:
1140 if not ui.quiet:
1141 fm.plain(notice)
1141 fm.plain(notice)
1142 fm.plain('\n')
1142 fm.plain('\n')
1143 fm.end()
1143 fm.end()
1144
1144
1145 @command('bundle',
1145 @command('bundle',
1146 [('f', 'force', None, _('run even when the destination is unrelated')),
1146 [('f', 'force', None, _('run even when the destination is unrelated')),
1147 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1147 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1148 _('REV')),
1148 _('REV')),
1149 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1149 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1150 _('BRANCH')),
1150 _('BRANCH')),
1151 ('', 'base', [],
1151 ('', 'base', [],
1152 _('a base changeset assumed to be available at the destination'),
1152 _('a base changeset assumed to be available at the destination'),
1153 _('REV')),
1153 _('REV')),
1154 ('a', 'all', None, _('bundle all changesets in the repository')),
1154 ('a', 'all', None, _('bundle all changesets in the repository')),
1155 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1155 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1156 ] + remoteopts,
1156 ] + remoteopts,
1157 _('[-f] [-t BUNDLESPEC] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1157 _('[-f] [-t BUNDLESPEC] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1158 def bundle(ui, repo, fname, dest=None, **opts):
1158 def bundle(ui, repo, fname, dest=None, **opts):
1159 """create a bundle file
1159 """create a bundle file
1160
1160
1161 Generate a bundle file containing data to be transferred to another
1161 Generate a bundle file containing data to be transferred to another
1162 repository.
1162 repository.
1163
1163
1164 To create a bundle containing all changesets, use -a/--all
1164 To create a bundle containing all changesets, use -a/--all
1165 (or --base null). Otherwise, hg assumes the destination will have
1165 (or --base null). Otherwise, hg assumes the destination will have
1166 all the nodes you specify with --base parameters. Otherwise, hg
1166 all the nodes you specify with --base parameters. Otherwise, hg
1167 will assume the repository has all the nodes in destination, or
1167 will assume the repository has all the nodes in destination, or
1168 default-push/default if no destination is specified, where destination
1168 default-push/default if no destination is specified, where destination
1169 is the repository you provide through DEST option.
1169 is the repository you provide through DEST option.
1170
1170
1171 You can change bundle format with the -t/--type option. See
1171 You can change bundle format with the -t/--type option. See
1172 :hg:`help bundlespec` for documentation on this format. By default,
1172 :hg:`help bundlespec` for documentation on this format. By default,
1173 the most appropriate format is used and compression defaults to
1173 the most appropriate format is used and compression defaults to
1174 bzip2.
1174 bzip2.
1175
1175
1176 The bundle file can then be transferred using conventional means
1176 The bundle file can then be transferred using conventional means
1177 and applied to another repository with the unbundle or pull
1177 and applied to another repository with the unbundle or pull
1178 command. This is useful when direct push and pull are not
1178 command. This is useful when direct push and pull are not
1179 available or when exporting an entire repository is undesirable.
1179 available or when exporting an entire repository is undesirable.
1180
1180
1181 Applying bundles preserves all changeset contents including
1181 Applying bundles preserves all changeset contents including
1182 permissions, copy/rename information, and revision history.
1182 permissions, copy/rename information, and revision history.
1183
1183
1184 Returns 0 on success, 1 if no changes found.
1184 Returns 0 on success, 1 if no changes found.
1185 """
1185 """
1186 opts = pycompat.byteskwargs(opts)
1186 opts = pycompat.byteskwargs(opts)
1187 revs = None
1187 revs = None
1188 if 'rev' in opts:
1188 if 'rev' in opts:
1189 revstrings = opts['rev']
1189 revstrings = opts['rev']
1190 revs = scmutil.revrange(repo, revstrings)
1190 revs = scmutil.revrange(repo, revstrings)
1191 if revstrings and not revs:
1191 if revstrings and not revs:
1192 raise error.Abort(_('no commits to bundle'))
1192 raise error.Abort(_('no commits to bundle'))
1193
1193
1194 bundletype = opts.get('type', 'bzip2').lower()
1194 bundletype = opts.get('type', 'bzip2').lower()
1195 try:
1195 try:
1196 bcompression, cgversion, params = exchange.parsebundlespec(
1196 bcompression, cgversion, params = exchange.parsebundlespec(
1197 repo, bundletype, strict=False)
1197 repo, bundletype, strict=False)
1198 except error.UnsupportedBundleSpecification as e:
1198 except error.UnsupportedBundleSpecification as e:
1199 raise error.Abort(str(e),
1199 raise error.Abort(str(e),
1200 hint=_("see 'hg help bundlespec' for supported "
1200 hint=_("see 'hg help bundlespec' for supported "
1201 "values for --type"))
1201 "values for --type"))
1202
1202
1203 # Packed bundles are a pseudo bundle format for now.
1203 # Packed bundles are a pseudo bundle format for now.
1204 if cgversion == 's1':
1204 if cgversion == 's1':
1205 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1205 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1206 hint=_("use 'hg debugcreatestreamclonebundle'"))
1206 hint=_("use 'hg debugcreatestreamclonebundle'"))
1207
1207
1208 if opts.get('all'):
1208 if opts.get('all'):
1209 if dest:
1209 if dest:
1210 raise error.Abort(_("--all is incompatible with specifying "
1210 raise error.Abort(_("--all is incompatible with specifying "
1211 "a destination"))
1211 "a destination"))
1212 if opts.get('base'):
1212 if opts.get('base'):
1213 ui.warn(_("ignoring --base because --all was specified\n"))
1213 ui.warn(_("ignoring --base because --all was specified\n"))
1214 base = ['null']
1214 base = ['null']
1215 else:
1215 else:
1216 base = scmutil.revrange(repo, opts.get('base'))
1216 base = scmutil.revrange(repo, opts.get('base'))
1217 if cgversion not in changegroup.supportedoutgoingversions(repo):
1217 if cgversion not in changegroup.supportedoutgoingversions(repo):
1218 raise error.Abort(_("repository does not support bundle version %s") %
1218 raise error.Abort(_("repository does not support bundle version %s") %
1219 cgversion)
1219 cgversion)
1220
1220
1221 if base:
1221 if base:
1222 if dest:
1222 if dest:
1223 raise error.Abort(_("--base is incompatible with specifying "
1223 raise error.Abort(_("--base is incompatible with specifying "
1224 "a destination"))
1224 "a destination"))
1225 common = [repo.lookup(rev) for rev in base]
1225 common = [repo.lookup(rev) for rev in base]
1226 heads = [repo.lookup(r) for r in revs] if revs else None
1226 heads = [repo.lookup(r) for r in revs] if revs else None
1227 outgoing = discovery.outgoing(repo, common, heads)
1227 outgoing = discovery.outgoing(repo, common, heads)
1228 else:
1228 else:
1229 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1229 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1230 dest, branches = hg.parseurl(dest, opts.get('branch'))
1230 dest, branches = hg.parseurl(dest, opts.get('branch'))
1231 other = hg.peer(repo, opts, dest)
1231 other = hg.peer(repo, opts, dest)
1232 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1232 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1233 heads = revs and map(repo.lookup, revs) or revs
1233 heads = revs and map(repo.lookup, revs) or revs
1234 outgoing = discovery.findcommonoutgoing(repo, other,
1234 outgoing = discovery.findcommonoutgoing(repo, other,
1235 onlyheads=heads,
1235 onlyheads=heads,
1236 force=opts.get('force'),
1236 force=opts.get('force'),
1237 portable=True)
1237 portable=True)
1238
1238
1239 if not outgoing.missing:
1239 if not outgoing.missing:
1240 scmutil.nochangesfound(ui, repo, not base and outgoing.excluded)
1240 scmutil.nochangesfound(ui, repo, not base and outgoing.excluded)
1241 return 1
1241 return 1
1242
1242
1243 if cgversion == '01': #bundle1
1243 if cgversion == '01': #bundle1
1244 if bcompression is None:
1244 if bcompression is None:
1245 bcompression = 'UN'
1245 bcompression = 'UN'
1246 bversion = 'HG10' + bcompression
1246 bversion = 'HG10' + bcompression
1247 bcompression = None
1247 bcompression = None
1248 elif cgversion in ('02', '03'):
1248 elif cgversion in ('02', '03'):
1249 bversion = 'HG20'
1249 bversion = 'HG20'
1250 else:
1250 else:
1251 raise error.ProgrammingError(
1251 raise error.ProgrammingError(
1252 'bundle: unexpected changegroup version %s' % cgversion)
1252 'bundle: unexpected changegroup version %s' % cgversion)
1253
1253
1254 # TODO compression options should be derived from bundlespec parsing.
1254 # TODO compression options should be derived from bundlespec parsing.
1255 # This is a temporary hack to allow adjusting bundle compression
1255 # This is a temporary hack to allow adjusting bundle compression
1256 # level without a) formalizing the bundlespec changes to declare it
1256 # level without a) formalizing the bundlespec changes to declare it
1257 # b) introducing a command flag.
1257 # b) introducing a command flag.
1258 compopts = {}
1258 compopts = {}
1259 complevel = ui.configint('experimental', 'bundlecomplevel')
1259 complevel = ui.configint('experimental', 'bundlecomplevel')
1260 if complevel is not None:
1260 if complevel is not None:
1261 compopts['level'] = complevel
1261 compopts['level'] = complevel
1262
1262
1263
1263
1264 contentopts = {'cg.version': cgversion}
1264 contentopts = {'cg.version': cgversion}
1265 if repo.ui.configbool('experimental', 'evolution.bundle-obsmarker'):
1265 if repo.ui.configbool('experimental', 'evolution.bundle-obsmarker'):
1266 contentopts['obsolescence'] = True
1266 contentopts['obsolescence'] = True
1267 if repo.ui.configbool('experimental', 'bundle-phases'):
1267 if repo.ui.configbool('experimental', 'bundle-phases'):
1268 contentopts['phases'] = True
1268 contentopts['phases'] = True
1269 bundle2.writenewbundle(ui, repo, 'bundle', fname, bversion, outgoing,
1269 bundle2.writenewbundle(ui, repo, 'bundle', fname, bversion, outgoing,
1270 contentopts, compression=bcompression,
1270 contentopts, compression=bcompression,
1271 compopts=compopts)
1271 compopts=compopts)
1272
1272
1273 @command('cat',
1273 @command('cat',
1274 [('o', 'output', '',
1274 [('o', 'output', '',
1275 _('print output to file with formatted name'), _('FORMAT')),
1275 _('print output to file with formatted name'), _('FORMAT')),
1276 ('r', 'rev', '', _('print the given revision'), _('REV')),
1276 ('r', 'rev', '', _('print the given revision'), _('REV')),
1277 ('', 'decode', None, _('apply any matching decode filter')),
1277 ('', 'decode', None, _('apply any matching decode filter')),
1278 ] + walkopts + formatteropts,
1278 ] + walkopts + formatteropts,
1279 _('[OPTION]... FILE...'),
1279 _('[OPTION]... FILE...'),
1280 inferrepo=True, cmdtype=readonly)
1280 inferrepo=True, cmdtype=readonly)
1281 def cat(ui, repo, file1, *pats, **opts):
1281 def cat(ui, repo, file1, *pats, **opts):
1282 """output the current or given revision of files
1282 """output the current or given revision of files
1283
1283
1284 Print the specified files as they were at the given revision. If
1284 Print the specified files as they were at the given revision. If
1285 no revision is given, the parent of the working directory is used.
1285 no revision is given, the parent of the working directory is used.
1286
1286
1287 Output may be to a file, in which case the name of the file is
1287 Output may be to a file, in which case the name of the file is
1288 given using a format string. The formatting rules as follows:
1288 given using a format string. The formatting rules as follows:
1289
1289
1290 :``%%``: literal "%" character
1290 :``%%``: literal "%" character
1291 :``%s``: basename of file being printed
1291 :``%s``: basename of file being printed
1292 :``%d``: dirname of file being printed, or '.' if in repository root
1292 :``%d``: dirname of file being printed, or '.' if in repository root
1293 :``%p``: root-relative path name of file being printed
1293 :``%p``: root-relative path name of file being printed
1294 :``%H``: changeset hash (40 hexadecimal digits)
1294 :``%H``: changeset hash (40 hexadecimal digits)
1295 :``%R``: changeset revision number
1295 :``%R``: changeset revision number
1296 :``%h``: short-form changeset hash (12 hexadecimal digits)
1296 :``%h``: short-form changeset hash (12 hexadecimal digits)
1297 :``%r``: zero-padded changeset revision number
1297 :``%r``: zero-padded changeset revision number
1298 :``%b``: basename of the exporting repository
1298 :``%b``: basename of the exporting repository
1299
1299
1300 Returns 0 on success.
1300 Returns 0 on success.
1301 """
1301 """
1302 opts = pycompat.byteskwargs(opts)
1302 opts = pycompat.byteskwargs(opts)
1303 rev = opts.get('rev')
1303 rev = opts.get('rev')
1304 if rev:
1304 if rev:
1305 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
1305 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
1306 ctx = scmutil.revsingle(repo, rev)
1306 ctx = scmutil.revsingle(repo, rev)
1307 m = scmutil.match(ctx, (file1,) + pats, opts)
1307 m = scmutil.match(ctx, (file1,) + pats, opts)
1308 fntemplate = opts.pop('output', '')
1308 fntemplate = opts.pop('output', '')
1309 if cmdutil.isstdiofilename(fntemplate):
1309 if cmdutil.isstdiofilename(fntemplate):
1310 fntemplate = ''
1310 fntemplate = ''
1311
1311
1312 if fntemplate:
1312 if fntemplate:
1313 fm = formatter.nullformatter(ui, 'cat')
1313 fm = formatter.nullformatter(ui, 'cat')
1314 else:
1314 else:
1315 ui.pager('cat')
1315 ui.pager('cat')
1316 fm = ui.formatter('cat', opts)
1316 fm = ui.formatter('cat', opts)
1317 with fm:
1317 with fm:
1318 return cmdutil.cat(ui, repo, ctx, m, fm, fntemplate, '',
1318 return cmdutil.cat(ui, repo, ctx, m, fm, fntemplate, '',
1319 **pycompat.strkwargs(opts))
1319 **pycompat.strkwargs(opts))
1320
1320
1321 @command('^clone',
1321 @command('^clone',
1322 [('U', 'noupdate', None, _('the clone will include an empty working '
1322 [('U', 'noupdate', None, _('the clone will include an empty working '
1323 'directory (only a repository)')),
1323 'directory (only a repository)')),
1324 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1324 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1325 _('REV')),
1325 _('REV')),
1326 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1326 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1327 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1327 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1328 ('', 'pull', None, _('use pull protocol to copy metadata')),
1328 ('', 'pull', None, _('use pull protocol to copy metadata')),
1329 ('', 'uncompressed', None,
1329 ('', 'uncompressed', None,
1330 _('an alias to --stream (DEPRECATED)')),
1330 _('an alias to --stream (DEPRECATED)')),
1331 ('', 'stream', None,
1331 ('', 'stream', None,
1332 _('clone with minimal data processing')),
1332 _('clone with minimal data processing')),
1333 ] + remoteopts,
1333 ] + remoteopts,
1334 _('[OPTION]... SOURCE [DEST]'),
1334 _('[OPTION]... SOURCE [DEST]'),
1335 norepo=True)
1335 norepo=True)
1336 def clone(ui, source, dest=None, **opts):
1336 def clone(ui, source, dest=None, **opts):
1337 """make a copy of an existing repository
1337 """make a copy of an existing repository
1338
1338
1339 Create a copy of an existing repository in a new directory.
1339 Create a copy of an existing repository in a new directory.
1340
1340
1341 If no destination directory name is specified, it defaults to the
1341 If no destination directory name is specified, it defaults to the
1342 basename of the source.
1342 basename of the source.
1343
1343
1344 The location of the source is added to the new repository's
1344 The location of the source is added to the new repository's
1345 ``.hg/hgrc`` file, as the default to be used for future pulls.
1345 ``.hg/hgrc`` file, as the default to be used for future pulls.
1346
1346
1347 Only local paths and ``ssh://`` URLs are supported as
1347 Only local paths and ``ssh://`` URLs are supported as
1348 destinations. For ``ssh://`` destinations, no working directory or
1348 destinations. For ``ssh://`` destinations, no working directory or
1349 ``.hg/hgrc`` will be created on the remote side.
1349 ``.hg/hgrc`` will be created on the remote side.
1350
1350
1351 If the source repository has a bookmark called '@' set, that
1351 If the source repository has a bookmark called '@' set, that
1352 revision will be checked out in the new repository by default.
1352 revision will be checked out in the new repository by default.
1353
1353
1354 To check out a particular version, use -u/--update, or
1354 To check out a particular version, use -u/--update, or
1355 -U/--noupdate to create a clone with no working directory.
1355 -U/--noupdate to create a clone with no working directory.
1356
1356
1357 To pull only a subset of changesets, specify one or more revisions
1357 To pull only a subset of changesets, specify one or more revisions
1358 identifiers with -r/--rev or branches with -b/--branch. The
1358 identifiers with -r/--rev or branches with -b/--branch. The
1359 resulting clone will contain only the specified changesets and
1359 resulting clone will contain only the specified changesets and
1360 their ancestors. These options (or 'clone src#rev dest') imply
1360 their ancestors. These options (or 'clone src#rev dest') imply
1361 --pull, even for local source repositories.
1361 --pull, even for local source repositories.
1362
1362
1363 In normal clone mode, the remote normalizes repository data into a common
1363 In normal clone mode, the remote normalizes repository data into a common
1364 exchange format and the receiving end translates this data into its local
1364 exchange format and the receiving end translates this data into its local
1365 storage format. --stream activates a different clone mode that essentially
1365 storage format. --stream activates a different clone mode that essentially
1366 copies repository files from the remote with minimal data processing. This
1366 copies repository files from the remote with minimal data processing. This
1367 significantly reduces the CPU cost of a clone both remotely and locally.
1367 significantly reduces the CPU cost of a clone both remotely and locally.
1368 However, it often increases the transferred data size by 30-40%. This can
1368 However, it often increases the transferred data size by 30-40%. This can
1369 result in substantially faster clones where I/O throughput is plentiful,
1369 result in substantially faster clones where I/O throughput is plentiful,
1370 especially for larger repositories. A side-effect of --stream clones is
1370 especially for larger repositories. A side-effect of --stream clones is
1371 that storage settings and requirements on the remote are applied locally:
1371 that storage settings and requirements on the remote are applied locally:
1372 a modern client may inherit legacy or inefficient storage used by the
1372 a modern client may inherit legacy or inefficient storage used by the
1373 remote or a legacy Mercurial client may not be able to clone from a
1373 remote or a legacy Mercurial client may not be able to clone from a
1374 modern Mercurial remote.
1374 modern Mercurial remote.
1375
1375
1376 .. note::
1376 .. note::
1377
1377
1378 Specifying a tag will include the tagged changeset but not the
1378 Specifying a tag will include the tagged changeset but not the
1379 changeset containing the tag.
1379 changeset containing the tag.
1380
1380
1381 .. container:: verbose
1381 .. container:: verbose
1382
1382
1383 For efficiency, hardlinks are used for cloning whenever the
1383 For efficiency, hardlinks are used for cloning whenever the
1384 source and destination are on the same filesystem (note this
1384 source and destination are on the same filesystem (note this
1385 applies only to the repository data, not to the working
1385 applies only to the repository data, not to the working
1386 directory). Some filesystems, such as AFS, implement hardlinking
1386 directory). Some filesystems, such as AFS, implement hardlinking
1387 incorrectly, but do not report errors. In these cases, use the
1387 incorrectly, but do not report errors. In these cases, use the
1388 --pull option to avoid hardlinking.
1388 --pull option to avoid hardlinking.
1389
1389
1390 Mercurial will update the working directory to the first applicable
1390 Mercurial will update the working directory to the first applicable
1391 revision from this list:
1391 revision from this list:
1392
1392
1393 a) null if -U or the source repository has no changesets
1393 a) null if -U or the source repository has no changesets
1394 b) if -u . and the source repository is local, the first parent of
1394 b) if -u . and the source repository is local, the first parent of
1395 the source repository's working directory
1395 the source repository's working directory
1396 c) the changeset specified with -u (if a branch name, this means the
1396 c) the changeset specified with -u (if a branch name, this means the
1397 latest head of that branch)
1397 latest head of that branch)
1398 d) the changeset specified with -r
1398 d) the changeset specified with -r
1399 e) the tipmost head specified with -b
1399 e) the tipmost head specified with -b
1400 f) the tipmost head specified with the url#branch source syntax
1400 f) the tipmost head specified with the url#branch source syntax
1401 g) the revision marked with the '@' bookmark, if present
1401 g) the revision marked with the '@' bookmark, if present
1402 h) the tipmost head of the default branch
1402 h) the tipmost head of the default branch
1403 i) tip
1403 i) tip
1404
1404
1405 When cloning from servers that support it, Mercurial may fetch
1405 When cloning from servers that support it, Mercurial may fetch
1406 pre-generated data from a server-advertised URL. When this is done,
1406 pre-generated data from a server-advertised URL. When this is done,
1407 hooks operating on incoming changesets and changegroups may fire twice,
1407 hooks operating on incoming changesets and changegroups may fire twice,
1408 once for the bundle fetched from the URL and another for any additional
1408 once for the bundle fetched from the URL and another for any additional
1409 data not fetched from this URL. In addition, if an error occurs, the
1409 data not fetched from this URL. In addition, if an error occurs, the
1410 repository may be rolled back to a partial clone. This behavior may
1410 repository may be rolled back to a partial clone. This behavior may
1411 change in future releases. See :hg:`help -e clonebundles` for more.
1411 change in future releases. See :hg:`help -e clonebundles` for more.
1412
1412
1413 Examples:
1413 Examples:
1414
1414
1415 - clone a remote repository to a new directory named hg/::
1415 - clone a remote repository to a new directory named hg/::
1416
1416
1417 hg clone https://www.mercurial-scm.org/repo/hg/
1417 hg clone https://www.mercurial-scm.org/repo/hg/
1418
1418
1419 - create a lightweight local clone::
1419 - create a lightweight local clone::
1420
1420
1421 hg clone project/ project-feature/
1421 hg clone project/ project-feature/
1422
1422
1423 - clone from an absolute path on an ssh server (note double-slash)::
1423 - clone from an absolute path on an ssh server (note double-slash)::
1424
1424
1425 hg clone ssh://user@server//home/projects/alpha/
1425 hg clone ssh://user@server//home/projects/alpha/
1426
1426
1427 - do a streaming clone while checking out a specified version::
1427 - do a streaming clone while checking out a specified version::
1428
1428
1429 hg clone --stream http://server/repo -u 1.5
1429 hg clone --stream http://server/repo -u 1.5
1430
1430
1431 - create a repository without changesets after a particular revision::
1431 - create a repository without changesets after a particular revision::
1432
1432
1433 hg clone -r 04e544 experimental/ good/
1433 hg clone -r 04e544 experimental/ good/
1434
1434
1435 - clone (and track) a particular named branch::
1435 - clone (and track) a particular named branch::
1436
1436
1437 hg clone https://www.mercurial-scm.org/repo/hg/#stable
1437 hg clone https://www.mercurial-scm.org/repo/hg/#stable
1438
1438
1439 See :hg:`help urls` for details on specifying URLs.
1439 See :hg:`help urls` for details on specifying URLs.
1440
1440
1441 Returns 0 on success.
1441 Returns 0 on success.
1442 """
1442 """
1443 opts = pycompat.byteskwargs(opts)
1443 opts = pycompat.byteskwargs(opts)
1444 if opts.get('noupdate') and opts.get('updaterev'):
1444 if opts.get('noupdate') and opts.get('updaterev'):
1445 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1445 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1446
1446
1447 r = hg.clone(ui, opts, source, dest,
1447 r = hg.clone(ui, opts, source, dest,
1448 pull=opts.get('pull'),
1448 pull=opts.get('pull'),
1449 stream=opts.get('stream') or opts.get('uncompressed'),
1449 stream=opts.get('stream') or opts.get('uncompressed'),
1450 rev=opts.get('rev'),
1450 rev=opts.get('rev'),
1451 update=opts.get('updaterev') or not opts.get('noupdate'),
1451 update=opts.get('updaterev') or not opts.get('noupdate'),
1452 branch=opts.get('branch'),
1452 branch=opts.get('branch'),
1453 shareopts=opts.get('shareopts'))
1453 shareopts=opts.get('shareopts'))
1454
1454
1455 return r is None
1455 return r is None
1456
1456
1457 @command('^commit|ci',
1457 @command('^commit|ci',
1458 [('A', 'addremove', None,
1458 [('A', 'addremove', None,
1459 _('mark new/missing files as added/removed before committing')),
1459 _('mark new/missing files as added/removed before committing')),
1460 ('', 'close-branch', None,
1460 ('', 'close-branch', None,
1461 _('mark a branch head as closed')),
1461 _('mark a branch head as closed')),
1462 ('', 'amend', None, _('amend the parent of the working directory')),
1462 ('', 'amend', None, _('amend the parent of the working directory')),
1463 ('s', 'secret', None, _('use the secret phase for committing')),
1463 ('s', 'secret', None, _('use the secret phase for committing')),
1464 ('e', 'edit', None, _('invoke editor on commit messages')),
1464 ('e', 'edit', None, _('invoke editor on commit messages')),
1465 ('i', 'interactive', None, _('use interactive mode')),
1465 ('i', 'interactive', None, _('use interactive mode')),
1466 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1466 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1467 _('[OPTION]... [FILE]...'),
1467 _('[OPTION]... [FILE]...'),
1468 inferrepo=True)
1468 inferrepo=True)
1469 def commit(ui, repo, *pats, **opts):
1469 def commit(ui, repo, *pats, **opts):
1470 """commit the specified files or all outstanding changes
1470 """commit the specified files or all outstanding changes
1471
1471
1472 Commit changes to the given files into the repository. Unlike a
1472 Commit changes to the given files into the repository. Unlike a
1473 centralized SCM, this operation is a local operation. See
1473 centralized SCM, this operation is a local operation. See
1474 :hg:`push` for a way to actively distribute your changes.
1474 :hg:`push` for a way to actively distribute your changes.
1475
1475
1476 If a list of files is omitted, all changes reported by :hg:`status`
1476 If a list of files is omitted, all changes reported by :hg:`status`
1477 will be committed.
1477 will be committed.
1478
1478
1479 If you are committing the result of a merge, do not provide any
1479 If you are committing the result of a merge, do not provide any
1480 filenames or -I/-X filters.
1480 filenames or -I/-X filters.
1481
1481
1482 If no commit message is specified, Mercurial starts your
1482 If no commit message is specified, Mercurial starts your
1483 configured editor where you can enter a message. In case your
1483 configured editor where you can enter a message. In case your
1484 commit fails, you will find a backup of your message in
1484 commit fails, you will find a backup of your message in
1485 ``.hg/last-message.txt``.
1485 ``.hg/last-message.txt``.
1486
1486
1487 The --close-branch flag can be used to mark the current branch
1487 The --close-branch flag can be used to mark the current branch
1488 head closed. When all heads of a branch are closed, the branch
1488 head closed. When all heads of a branch are closed, the branch
1489 will be considered closed and no longer listed.
1489 will be considered closed and no longer listed.
1490
1490
1491 The --amend flag can be used to amend the parent of the
1491 The --amend flag can be used to amend the parent of the
1492 working directory with a new commit that contains the changes
1492 working directory with a new commit that contains the changes
1493 in the parent in addition to those currently reported by :hg:`status`,
1493 in the parent in addition to those currently reported by :hg:`status`,
1494 if there are any. The old commit is stored in a backup bundle in
1494 if there are any. The old commit is stored in a backup bundle in
1495 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1495 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1496 on how to restore it).
1496 on how to restore it).
1497
1497
1498 Message, user and date are taken from the amended commit unless
1498 Message, user and date are taken from the amended commit unless
1499 specified. When a message isn't specified on the command line,
1499 specified. When a message isn't specified on the command line,
1500 the editor will open with the message of the amended commit.
1500 the editor will open with the message of the amended commit.
1501
1501
1502 It is not possible to amend public changesets (see :hg:`help phases`)
1502 It is not possible to amend public changesets (see :hg:`help phases`)
1503 or changesets that have children.
1503 or changesets that have children.
1504
1504
1505 See :hg:`help dates` for a list of formats valid for -d/--date.
1505 See :hg:`help dates` for a list of formats valid for -d/--date.
1506
1506
1507 Returns 0 on success, 1 if nothing changed.
1507 Returns 0 on success, 1 if nothing changed.
1508
1508
1509 .. container:: verbose
1509 .. container:: verbose
1510
1510
1511 Examples:
1511 Examples:
1512
1512
1513 - commit all files ending in .py::
1513 - commit all files ending in .py::
1514
1514
1515 hg commit --include "set:**.py"
1515 hg commit --include "set:**.py"
1516
1516
1517 - commit all non-binary files::
1517 - commit all non-binary files::
1518
1518
1519 hg commit --exclude "set:binary()"
1519 hg commit --exclude "set:binary()"
1520
1520
1521 - amend the current commit and set the date to now::
1521 - amend the current commit and set the date to now::
1522
1522
1523 hg commit --amend --date now
1523 hg commit --amend --date now
1524 """
1524 """
1525 wlock = lock = None
1525 wlock = lock = None
1526 try:
1526 try:
1527 wlock = repo.wlock()
1527 wlock = repo.wlock()
1528 lock = repo.lock()
1528 lock = repo.lock()
1529 return _docommit(ui, repo, *pats, **opts)
1529 return _docommit(ui, repo, *pats, **opts)
1530 finally:
1530 finally:
1531 release(lock, wlock)
1531 release(lock, wlock)
1532
1532
1533 def _docommit(ui, repo, *pats, **opts):
1533 def _docommit(ui, repo, *pats, **opts):
1534 if opts.get(r'interactive'):
1534 if opts.get(r'interactive'):
1535 opts.pop(r'interactive')
1535 opts.pop(r'interactive')
1536 ret = cmdutil.dorecord(ui, repo, commit, None, False,
1536 ret = cmdutil.dorecord(ui, repo, commit, None, False,
1537 cmdutil.recordfilter, *pats,
1537 cmdutil.recordfilter, *pats,
1538 **opts)
1538 **opts)
1539 # ret can be 0 (no changes to record) or the value returned by
1539 # ret can be 0 (no changes to record) or the value returned by
1540 # commit(), 1 if nothing changed or None on success.
1540 # commit(), 1 if nothing changed or None on success.
1541 return 1 if ret == 0 else ret
1541 return 1 if ret == 0 else ret
1542
1542
1543 opts = pycompat.byteskwargs(opts)
1543 opts = pycompat.byteskwargs(opts)
1544 if opts.get('subrepos'):
1544 if opts.get('subrepos'):
1545 if opts.get('amend'):
1545 if opts.get('amend'):
1546 raise error.Abort(_('cannot amend with --subrepos'))
1546 raise error.Abort(_('cannot amend with --subrepos'))
1547 # Let --subrepos on the command line override config setting.
1547 # Let --subrepos on the command line override config setting.
1548 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1548 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1549
1549
1550 cmdutil.checkunfinished(repo, commit=True)
1550 cmdutil.checkunfinished(repo, commit=True)
1551
1551
1552 branch = repo[None].branch()
1552 branch = repo[None].branch()
1553 bheads = repo.branchheads(branch)
1553 bheads = repo.branchheads(branch)
1554
1554
1555 extra = {}
1555 extra = {}
1556 if opts.get('close_branch'):
1556 if opts.get('close_branch'):
1557 extra['close'] = '1'
1557 extra['close'] = '1'
1558
1558
1559 if not bheads:
1559 if not bheads:
1560 raise error.Abort(_('can only close branch heads'))
1560 raise error.Abort(_('can only close branch heads'))
1561 elif opts.get('amend'):
1561 elif opts.get('amend'):
1562 if repo[None].parents()[0].p1().branch() != branch and \
1562 if repo[None].parents()[0].p1().branch() != branch and \
1563 repo[None].parents()[0].p2().branch() != branch:
1563 repo[None].parents()[0].p2().branch() != branch:
1564 raise error.Abort(_('can only close branch heads'))
1564 raise error.Abort(_('can only close branch heads'))
1565
1565
1566 if opts.get('amend'):
1566 if opts.get('amend'):
1567 if ui.configbool('ui', 'commitsubrepos'):
1567 if ui.configbool('ui', 'commitsubrepos'):
1568 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1568 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1569
1569
1570 old = repo['.']
1570 old = repo['.']
1571 rewriteutil.precheck(repo, [old.rev()], 'amend')
1571 rewriteutil.precheck(repo, [old.rev()], 'amend')
1572
1572
1573 # Currently histedit gets confused if an amend happens while histedit
1573 # Currently histedit gets confused if an amend happens while histedit
1574 # is in progress. Since we have a checkunfinished command, we are
1574 # is in progress. Since we have a checkunfinished command, we are
1575 # temporarily honoring it.
1575 # temporarily honoring it.
1576 #
1576 #
1577 # Note: eventually this guard will be removed. Please do not expect
1577 # Note: eventually this guard will be removed. Please do not expect
1578 # this behavior to remain.
1578 # this behavior to remain.
1579 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
1579 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
1580 cmdutil.checkunfinished(repo)
1580 cmdutil.checkunfinished(repo)
1581
1581
1582 node = cmdutil.amend(ui, repo, old, extra, pats, opts)
1582 node = cmdutil.amend(ui, repo, old, extra, pats, opts)
1583 if node == old.node():
1583 if node == old.node():
1584 ui.status(_("nothing changed\n"))
1584 ui.status(_("nothing changed\n"))
1585 return 1
1585 return 1
1586 else:
1586 else:
1587 def commitfunc(ui, repo, message, match, opts):
1587 def commitfunc(ui, repo, message, match, opts):
1588 overrides = {}
1588 overrides = {}
1589 if opts.get('secret'):
1589 if opts.get('secret'):
1590 overrides[('phases', 'new-commit')] = 'secret'
1590 overrides[('phases', 'new-commit')] = 'secret'
1591
1591
1592 baseui = repo.baseui
1592 baseui = repo.baseui
1593 with baseui.configoverride(overrides, 'commit'):
1593 with baseui.configoverride(overrides, 'commit'):
1594 with ui.configoverride(overrides, 'commit'):
1594 with ui.configoverride(overrides, 'commit'):
1595 editform = cmdutil.mergeeditform(repo[None],
1595 editform = cmdutil.mergeeditform(repo[None],
1596 'commit.normal')
1596 'commit.normal')
1597 editor = cmdutil.getcommiteditor(
1597 editor = cmdutil.getcommiteditor(
1598 editform=editform, **pycompat.strkwargs(opts))
1598 editform=editform, **pycompat.strkwargs(opts))
1599 return repo.commit(message,
1599 return repo.commit(message,
1600 opts.get('user'),
1600 opts.get('user'),
1601 opts.get('date'),
1601 opts.get('date'),
1602 match,
1602 match,
1603 editor=editor,
1603 editor=editor,
1604 extra=extra)
1604 extra=extra)
1605
1605
1606 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1606 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1607
1607
1608 if not node:
1608 if not node:
1609 stat = cmdutil.postcommitstatus(repo, pats, opts)
1609 stat = cmdutil.postcommitstatus(repo, pats, opts)
1610 if stat[3]:
1610 if stat[3]:
1611 ui.status(_("nothing changed (%d missing files, see "
1611 ui.status(_("nothing changed (%d missing files, see "
1612 "'hg status')\n") % len(stat[3]))
1612 "'hg status')\n") % len(stat[3]))
1613 else:
1613 else:
1614 ui.status(_("nothing changed\n"))
1614 ui.status(_("nothing changed\n"))
1615 return 1
1615 return 1
1616
1616
1617 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1617 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1618
1618
1619 @command('config|showconfig|debugconfig',
1619 @command('config|showconfig|debugconfig',
1620 [('u', 'untrusted', None, _('show untrusted configuration options')),
1620 [('u', 'untrusted', None, _('show untrusted configuration options')),
1621 ('e', 'edit', None, _('edit user config')),
1621 ('e', 'edit', None, _('edit user config')),
1622 ('l', 'local', None, _('edit repository config')),
1622 ('l', 'local', None, _('edit repository config')),
1623 ('g', 'global', None, _('edit global config'))] + formatteropts,
1623 ('g', 'global', None, _('edit global config'))] + formatteropts,
1624 _('[-u] [NAME]...'),
1624 _('[-u] [NAME]...'),
1625 optionalrepo=True, cmdtype=readonly)
1625 optionalrepo=True, cmdtype=readonly)
1626 def config(ui, repo, *values, **opts):
1626 def config(ui, repo, *values, **opts):
1627 """show combined config settings from all hgrc files
1627 """show combined config settings from all hgrc files
1628
1628
1629 With no arguments, print names and values of all config items.
1629 With no arguments, print names and values of all config items.
1630
1630
1631 With one argument of the form section.name, print just the value
1631 With one argument of the form section.name, print just the value
1632 of that config item.
1632 of that config item.
1633
1633
1634 With multiple arguments, print names and values of all config
1634 With multiple arguments, print names and values of all config
1635 items with matching section names.
1635 items with matching section names or section.names.
1636
1636
1637 With --edit, start an editor on the user-level config file. With
1637 With --edit, start an editor on the user-level config file. With
1638 --global, edit the system-wide config file. With --local, edit the
1638 --global, edit the system-wide config file. With --local, edit the
1639 repository-level config file.
1639 repository-level config file.
1640
1640
1641 With --debug, the source (filename and line number) is printed
1641 With --debug, the source (filename and line number) is printed
1642 for each config item.
1642 for each config item.
1643
1643
1644 See :hg:`help config` for more information about config files.
1644 See :hg:`help config` for more information about config files.
1645
1645
1646 Returns 0 on success, 1 if NAME does not exist.
1646 Returns 0 on success, 1 if NAME does not exist.
1647
1647
1648 """
1648 """
1649
1649
1650 opts = pycompat.byteskwargs(opts)
1650 opts = pycompat.byteskwargs(opts)
1651 if opts.get('edit') or opts.get('local') or opts.get('global'):
1651 if opts.get('edit') or opts.get('local') or opts.get('global'):
1652 if opts.get('local') and opts.get('global'):
1652 if opts.get('local') and opts.get('global'):
1653 raise error.Abort(_("can't use --local and --global together"))
1653 raise error.Abort(_("can't use --local and --global together"))
1654
1654
1655 if opts.get('local'):
1655 if opts.get('local'):
1656 if not repo:
1656 if not repo:
1657 raise error.Abort(_("can't use --local outside a repository"))
1657 raise error.Abort(_("can't use --local outside a repository"))
1658 paths = [repo.vfs.join('hgrc')]
1658 paths = [repo.vfs.join('hgrc')]
1659 elif opts.get('global'):
1659 elif opts.get('global'):
1660 paths = rcutil.systemrcpath()
1660 paths = rcutil.systemrcpath()
1661 else:
1661 else:
1662 paths = rcutil.userrcpath()
1662 paths = rcutil.userrcpath()
1663
1663
1664 for f in paths:
1664 for f in paths:
1665 if os.path.exists(f):
1665 if os.path.exists(f):
1666 break
1666 break
1667 else:
1667 else:
1668 if opts.get('global'):
1668 if opts.get('global'):
1669 samplehgrc = uimod.samplehgrcs['global']
1669 samplehgrc = uimod.samplehgrcs['global']
1670 elif opts.get('local'):
1670 elif opts.get('local'):
1671 samplehgrc = uimod.samplehgrcs['local']
1671 samplehgrc = uimod.samplehgrcs['local']
1672 else:
1672 else:
1673 samplehgrc = uimod.samplehgrcs['user']
1673 samplehgrc = uimod.samplehgrcs['user']
1674
1674
1675 f = paths[0]
1675 f = paths[0]
1676 fp = open(f, "wb")
1676 fp = open(f, "wb")
1677 fp.write(util.tonativeeol(samplehgrc))
1677 fp.write(util.tonativeeol(samplehgrc))
1678 fp.close()
1678 fp.close()
1679
1679
1680 editor = ui.geteditor()
1680 editor = ui.geteditor()
1681 ui.system("%s \"%s\"" % (editor, f),
1681 ui.system("%s \"%s\"" % (editor, f),
1682 onerr=error.Abort, errprefix=_("edit failed"),
1682 onerr=error.Abort, errprefix=_("edit failed"),
1683 blockedtag='config_edit')
1683 blockedtag='config_edit')
1684 return
1684 return
1685 ui.pager('config')
1685 ui.pager('config')
1686 fm = ui.formatter('config', opts)
1686 fm = ui.formatter('config', opts)
1687 for t, f in rcutil.rccomponents():
1687 for t, f in rcutil.rccomponents():
1688 if t == 'path':
1688 if t == 'path':
1689 ui.debug('read config from: %s\n' % f)
1689 ui.debug('read config from: %s\n' % f)
1690 elif t == 'items':
1690 elif t == 'items':
1691 for section, name, value, source in f:
1691 for section, name, value, source in f:
1692 ui.debug('set config by: %s\n' % source)
1692 ui.debug('set config by: %s\n' % source)
1693 else:
1693 else:
1694 raise error.ProgrammingError('unknown rctype: %s' % t)
1694 raise error.ProgrammingError('unknown rctype: %s' % t)
1695 untrusted = bool(opts.get('untrusted'))
1695 untrusted = bool(opts.get('untrusted'))
1696
1696
1697 selsections = selentries = []
1697 selsections = selentries = []
1698 if values:
1698 if values:
1699 selsections = [v for v in values if '.' not in v]
1699 selsections = [v for v in values if '.' not in v]
1700 selentries = [v for v in values if '.' in v]
1700 selentries = [v for v in values if '.' in v]
1701 if len(selentries) > 1 or selentries and selsections:
1701 uniquesel = (len(selentries) == 1 and not selsections)
1702 raise error.Abort(_('only one config item permitted'))
1703 selsections = set(selsections)
1702 selsections = set(selsections)
1704 selentries = set(selentries)
1703 selentries = set(selentries)
1705
1704
1706 matched = False
1705 matched = False
1707 for section, name, value in ui.walkconfig(untrusted=untrusted):
1706 for section, name, value in ui.walkconfig(untrusted=untrusted):
1708 source = ui.configsource(section, name, untrusted)
1707 source = ui.configsource(section, name, untrusted)
1709 value = pycompat.bytestr(value)
1708 value = pycompat.bytestr(value)
1710 if fm.isplain():
1709 if fm.isplain():
1711 source = source or 'none'
1710 source = source or 'none'
1712 value = value.replace('\n', '\\n')
1711 value = value.replace('\n', '\\n')
1713 entryname = section + '.' + name
1712 entryname = section + '.' + name
1714 if values:
1713 if values and not (section in selsections or entryname in selentries):
1715 if section in selsections:
1714 continue
1716 fm.startitem()
1715 fm.startitem()
1717 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1716 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1718 fm.write('name value', '%s=%s\n', entryname, value)
1717 if uniquesel:
1719 matched = True
1718 fm.data(name=entryname)
1720 elif entryname in selentries:
1719 fm.write('value', '%s\n', value)
1721 fm.startitem()
1722 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1723 fm.write('value', '%s\n', value)
1724 fm.data(name=entryname)
1725 matched = True
1726 else:
1720 else:
1727 fm.startitem()
1728 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1729 fm.write('name value', '%s=%s\n', entryname, value)
1721 fm.write('name value', '%s=%s\n', entryname, value)
1730 matched = True
1722 matched = True
1731 fm.end()
1723 fm.end()
1732 if matched:
1724 if matched:
1733 return 0
1725 return 0
1734 return 1
1726 return 1
1735
1727
1736 @command('copy|cp',
1728 @command('copy|cp',
1737 [('A', 'after', None, _('record a copy that has already occurred')),
1729 [('A', 'after', None, _('record a copy that has already occurred')),
1738 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1730 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1739 ] + walkopts + dryrunopts,
1731 ] + walkopts + dryrunopts,
1740 _('[OPTION]... [SOURCE]... DEST'))
1732 _('[OPTION]... [SOURCE]... DEST'))
1741 def copy(ui, repo, *pats, **opts):
1733 def copy(ui, repo, *pats, **opts):
1742 """mark files as copied for the next commit
1734 """mark files as copied for the next commit
1743
1735
1744 Mark dest as having copies of source files. If dest is a
1736 Mark dest as having copies of source files. If dest is a
1745 directory, copies are put in that directory. If dest is a file,
1737 directory, copies are put in that directory. If dest is a file,
1746 the source must be a single file.
1738 the source must be a single file.
1747
1739
1748 By default, this command copies the contents of files as they
1740 By default, this command copies the contents of files as they
1749 exist in the working directory. If invoked with -A/--after, the
1741 exist in the working directory. If invoked with -A/--after, the
1750 operation is recorded, but no copying is performed.
1742 operation is recorded, but no copying is performed.
1751
1743
1752 This command takes effect with the next commit. To undo a copy
1744 This command takes effect with the next commit. To undo a copy
1753 before that, see :hg:`revert`.
1745 before that, see :hg:`revert`.
1754
1746
1755 Returns 0 on success, 1 if errors are encountered.
1747 Returns 0 on success, 1 if errors are encountered.
1756 """
1748 """
1757 opts = pycompat.byteskwargs(opts)
1749 opts = pycompat.byteskwargs(opts)
1758 with repo.wlock(False):
1750 with repo.wlock(False):
1759 return cmdutil.copy(ui, repo, pats, opts)
1751 return cmdutil.copy(ui, repo, pats, opts)
1760
1752
1761 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1753 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1762 def debugcommands(ui, cmd='', *args):
1754 def debugcommands(ui, cmd='', *args):
1763 """list all available commands and options"""
1755 """list all available commands and options"""
1764 for cmd, vals in sorted(table.iteritems()):
1756 for cmd, vals in sorted(table.iteritems()):
1765 cmd = cmd.split('|')[0].strip('^')
1757 cmd = cmd.split('|')[0].strip('^')
1766 opts = ', '.join([i[1] for i in vals[1]])
1758 opts = ', '.join([i[1] for i in vals[1]])
1767 ui.write('%s: %s\n' % (cmd, opts))
1759 ui.write('%s: %s\n' % (cmd, opts))
1768
1760
1769 @command('debugcomplete',
1761 @command('debugcomplete',
1770 [('o', 'options', None, _('show the command options'))],
1762 [('o', 'options', None, _('show the command options'))],
1771 _('[-o] CMD'),
1763 _('[-o] CMD'),
1772 norepo=True)
1764 norepo=True)
1773 def debugcomplete(ui, cmd='', **opts):
1765 def debugcomplete(ui, cmd='', **opts):
1774 """returns the completion list associated with the given command"""
1766 """returns the completion list associated with the given command"""
1775
1767
1776 if opts.get(r'options'):
1768 if opts.get(r'options'):
1777 options = []
1769 options = []
1778 otables = [globalopts]
1770 otables = [globalopts]
1779 if cmd:
1771 if cmd:
1780 aliases, entry = cmdutil.findcmd(cmd, table, False)
1772 aliases, entry = cmdutil.findcmd(cmd, table, False)
1781 otables.append(entry[1])
1773 otables.append(entry[1])
1782 for t in otables:
1774 for t in otables:
1783 for o in t:
1775 for o in t:
1784 if "(DEPRECATED)" in o[3]:
1776 if "(DEPRECATED)" in o[3]:
1785 continue
1777 continue
1786 if o[0]:
1778 if o[0]:
1787 options.append('-%s' % o[0])
1779 options.append('-%s' % o[0])
1788 options.append('--%s' % o[1])
1780 options.append('--%s' % o[1])
1789 ui.write("%s\n" % "\n".join(options))
1781 ui.write("%s\n" % "\n".join(options))
1790 return
1782 return
1791
1783
1792 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
1784 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
1793 if ui.verbose:
1785 if ui.verbose:
1794 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1786 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1795 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1787 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1796
1788
1797 @command('^diff',
1789 @command('^diff',
1798 [('r', 'rev', [], _('revision'), _('REV')),
1790 [('r', 'rev', [], _('revision'), _('REV')),
1799 ('c', 'change', '', _('change made by revision'), _('REV'))
1791 ('c', 'change', '', _('change made by revision'), _('REV'))
1800 ] + diffopts + diffopts2 + walkopts + subrepoopts,
1792 ] + diffopts + diffopts2 + walkopts + subrepoopts,
1801 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
1793 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
1802 inferrepo=True, cmdtype=readonly)
1794 inferrepo=True, cmdtype=readonly)
1803 def diff(ui, repo, *pats, **opts):
1795 def diff(ui, repo, *pats, **opts):
1804 """diff repository (or selected files)
1796 """diff repository (or selected files)
1805
1797
1806 Show differences between revisions for the specified files.
1798 Show differences between revisions for the specified files.
1807
1799
1808 Differences between files are shown using the unified diff format.
1800 Differences between files are shown using the unified diff format.
1809
1801
1810 .. note::
1802 .. note::
1811
1803
1812 :hg:`diff` may generate unexpected results for merges, as it will
1804 :hg:`diff` may generate unexpected results for merges, as it will
1813 default to comparing against the working directory's first
1805 default to comparing against the working directory's first
1814 parent changeset if no revisions are specified.
1806 parent changeset if no revisions are specified.
1815
1807
1816 When two revision arguments are given, then changes are shown
1808 When two revision arguments are given, then changes are shown
1817 between those revisions. If only one revision is specified then
1809 between those revisions. If only one revision is specified then
1818 that revision is compared to the working directory, and, when no
1810 that revision is compared to the working directory, and, when no
1819 revisions are specified, the working directory files are compared
1811 revisions are specified, the working directory files are compared
1820 to its first parent.
1812 to its first parent.
1821
1813
1822 Alternatively you can specify -c/--change with a revision to see
1814 Alternatively you can specify -c/--change with a revision to see
1823 the changes in that changeset relative to its first parent.
1815 the changes in that changeset relative to its first parent.
1824
1816
1825 Without the -a/--text option, diff will avoid generating diffs of
1817 Without the -a/--text option, diff will avoid generating diffs of
1826 files it detects as binary. With -a, diff will generate a diff
1818 files it detects as binary. With -a, diff will generate a diff
1827 anyway, probably with undesirable results.
1819 anyway, probably with undesirable results.
1828
1820
1829 Use the -g/--git option to generate diffs in the git extended diff
1821 Use the -g/--git option to generate diffs in the git extended diff
1830 format. For more information, read :hg:`help diffs`.
1822 format. For more information, read :hg:`help diffs`.
1831
1823
1832 .. container:: verbose
1824 .. container:: verbose
1833
1825
1834 Examples:
1826 Examples:
1835
1827
1836 - compare a file in the current working directory to its parent::
1828 - compare a file in the current working directory to its parent::
1837
1829
1838 hg diff foo.c
1830 hg diff foo.c
1839
1831
1840 - compare two historical versions of a directory, with rename info::
1832 - compare two historical versions of a directory, with rename info::
1841
1833
1842 hg diff --git -r 1.0:1.2 lib/
1834 hg diff --git -r 1.0:1.2 lib/
1843
1835
1844 - get change stats relative to the last change on some date::
1836 - get change stats relative to the last change on some date::
1845
1837
1846 hg diff --stat -r "date('may 2')"
1838 hg diff --stat -r "date('may 2')"
1847
1839
1848 - diff all newly-added files that contain a keyword::
1840 - diff all newly-added files that contain a keyword::
1849
1841
1850 hg diff "set:added() and grep(GNU)"
1842 hg diff "set:added() and grep(GNU)"
1851
1843
1852 - compare a revision and its parents::
1844 - compare a revision and its parents::
1853
1845
1854 hg diff -c 9353 # compare against first parent
1846 hg diff -c 9353 # compare against first parent
1855 hg diff -r 9353^:9353 # same using revset syntax
1847 hg diff -r 9353^:9353 # same using revset syntax
1856 hg diff -r 9353^2:9353 # compare against the second parent
1848 hg diff -r 9353^2:9353 # compare against the second parent
1857
1849
1858 Returns 0 on success.
1850 Returns 0 on success.
1859 """
1851 """
1860
1852
1861 opts = pycompat.byteskwargs(opts)
1853 opts = pycompat.byteskwargs(opts)
1862 revs = opts.get('rev')
1854 revs = opts.get('rev')
1863 change = opts.get('change')
1855 change = opts.get('change')
1864 stat = opts.get('stat')
1856 stat = opts.get('stat')
1865 reverse = opts.get('reverse')
1857 reverse = opts.get('reverse')
1866
1858
1867 if revs and change:
1859 if revs and change:
1868 msg = _('cannot specify --rev and --change at the same time')
1860 msg = _('cannot specify --rev and --change at the same time')
1869 raise error.Abort(msg)
1861 raise error.Abort(msg)
1870 elif change:
1862 elif change:
1871 repo = scmutil.unhidehashlikerevs(repo, [change], 'nowarn')
1863 repo = scmutil.unhidehashlikerevs(repo, [change], 'nowarn')
1872 node2 = scmutil.revsingle(repo, change, None).node()
1864 node2 = scmutil.revsingle(repo, change, None).node()
1873 node1 = repo[node2].p1().node()
1865 node1 = repo[node2].p1().node()
1874 else:
1866 else:
1875 repo = scmutil.unhidehashlikerevs(repo, revs, 'nowarn')
1867 repo = scmutil.unhidehashlikerevs(repo, revs, 'nowarn')
1876 node1, node2 = scmutil.revpair(repo, revs)
1868 node1, node2 = scmutil.revpair(repo, revs)
1877
1869
1878 if reverse:
1870 if reverse:
1879 node1, node2 = node2, node1
1871 node1, node2 = node2, node1
1880
1872
1881 diffopts = patch.diffallopts(ui, opts)
1873 diffopts = patch.diffallopts(ui, opts)
1882 m = scmutil.match(repo[node2], pats, opts)
1874 m = scmutil.match(repo[node2], pats, opts)
1883 ui.pager('diff')
1875 ui.pager('diff')
1884 logcmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
1876 logcmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
1885 listsubrepos=opts.get('subrepos'),
1877 listsubrepos=opts.get('subrepos'),
1886 root=opts.get('root'))
1878 root=opts.get('root'))
1887
1879
1888 @command('^export',
1880 @command('^export',
1889 [('o', 'output', '',
1881 [('o', 'output', '',
1890 _('print output to file with formatted name'), _('FORMAT')),
1882 _('print output to file with formatted name'), _('FORMAT')),
1891 ('', 'switch-parent', None, _('diff against the second parent')),
1883 ('', 'switch-parent', None, _('diff against the second parent')),
1892 ('r', 'rev', [], _('revisions to export'), _('REV')),
1884 ('r', 'rev', [], _('revisions to export'), _('REV')),
1893 ] + diffopts,
1885 ] + diffopts,
1894 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'), cmdtype=readonly)
1886 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'), cmdtype=readonly)
1895 def export(ui, repo, *changesets, **opts):
1887 def export(ui, repo, *changesets, **opts):
1896 """dump the header and diffs for one or more changesets
1888 """dump the header and diffs for one or more changesets
1897
1889
1898 Print the changeset header and diffs for one or more revisions.
1890 Print the changeset header and diffs for one or more revisions.
1899 If no revision is given, the parent of the working directory is used.
1891 If no revision is given, the parent of the working directory is used.
1900
1892
1901 The information shown in the changeset header is: author, date,
1893 The information shown in the changeset header is: author, date,
1902 branch name (if non-default), changeset hash, parent(s) and commit
1894 branch name (if non-default), changeset hash, parent(s) and commit
1903 comment.
1895 comment.
1904
1896
1905 .. note::
1897 .. note::
1906
1898
1907 :hg:`export` may generate unexpected diff output for merge
1899 :hg:`export` may generate unexpected diff output for merge
1908 changesets, as it will compare the merge changeset against its
1900 changesets, as it will compare the merge changeset against its
1909 first parent only.
1901 first parent only.
1910
1902
1911 Output may be to a file, in which case the name of the file is
1903 Output may be to a file, in which case the name of the file is
1912 given using a format string. The formatting rules are as follows:
1904 given using a format string. The formatting rules are as follows:
1913
1905
1914 :``%%``: literal "%" character
1906 :``%%``: literal "%" character
1915 :``%H``: changeset hash (40 hexadecimal digits)
1907 :``%H``: changeset hash (40 hexadecimal digits)
1916 :``%N``: number of patches being generated
1908 :``%N``: number of patches being generated
1917 :``%R``: changeset revision number
1909 :``%R``: changeset revision number
1918 :``%b``: basename of the exporting repository
1910 :``%b``: basename of the exporting repository
1919 :``%h``: short-form changeset hash (12 hexadecimal digits)
1911 :``%h``: short-form changeset hash (12 hexadecimal digits)
1920 :``%m``: first line of the commit message (only alphanumeric characters)
1912 :``%m``: first line of the commit message (only alphanumeric characters)
1921 :``%n``: zero-padded sequence number, starting at 1
1913 :``%n``: zero-padded sequence number, starting at 1
1922 :``%r``: zero-padded changeset revision number
1914 :``%r``: zero-padded changeset revision number
1923
1915
1924 Without the -a/--text option, export will avoid generating diffs
1916 Without the -a/--text option, export will avoid generating diffs
1925 of files it detects as binary. With -a, export will generate a
1917 of files it detects as binary. With -a, export will generate a
1926 diff anyway, probably with undesirable results.
1918 diff anyway, probably with undesirable results.
1927
1919
1928 Use the -g/--git option to generate diffs in the git extended diff
1920 Use the -g/--git option to generate diffs in the git extended diff
1929 format. See :hg:`help diffs` for more information.
1921 format. See :hg:`help diffs` for more information.
1930
1922
1931 With the --switch-parent option, the diff will be against the
1923 With the --switch-parent option, the diff will be against the
1932 second parent. It can be useful to review a merge.
1924 second parent. It can be useful to review a merge.
1933
1925
1934 .. container:: verbose
1926 .. container:: verbose
1935
1927
1936 Examples:
1928 Examples:
1937
1929
1938 - use export and import to transplant a bugfix to the current
1930 - use export and import to transplant a bugfix to the current
1939 branch::
1931 branch::
1940
1932
1941 hg export -r 9353 | hg import -
1933 hg export -r 9353 | hg import -
1942
1934
1943 - export all the changesets between two revisions to a file with
1935 - export all the changesets between two revisions to a file with
1944 rename information::
1936 rename information::
1945
1937
1946 hg export --git -r 123:150 > changes.txt
1938 hg export --git -r 123:150 > changes.txt
1947
1939
1948 - split outgoing changes into a series of patches with
1940 - split outgoing changes into a series of patches with
1949 descriptive names::
1941 descriptive names::
1950
1942
1951 hg export -r "outgoing()" -o "%n-%m.patch"
1943 hg export -r "outgoing()" -o "%n-%m.patch"
1952
1944
1953 Returns 0 on success.
1945 Returns 0 on success.
1954 """
1946 """
1955 opts = pycompat.byteskwargs(opts)
1947 opts = pycompat.byteskwargs(opts)
1956 changesets += tuple(opts.get('rev', []))
1948 changesets += tuple(opts.get('rev', []))
1957 if not changesets:
1949 if not changesets:
1958 changesets = ['.']
1950 changesets = ['.']
1959 repo = scmutil.unhidehashlikerevs(repo, changesets, 'nowarn')
1951 repo = scmutil.unhidehashlikerevs(repo, changesets, 'nowarn')
1960 revs = scmutil.revrange(repo, changesets)
1952 revs = scmutil.revrange(repo, changesets)
1961 if not revs:
1953 if not revs:
1962 raise error.Abort(_("export requires at least one changeset"))
1954 raise error.Abort(_("export requires at least one changeset"))
1963 if len(revs) > 1:
1955 if len(revs) > 1:
1964 ui.note(_('exporting patches:\n'))
1956 ui.note(_('exporting patches:\n'))
1965 else:
1957 else:
1966 ui.note(_('exporting patch:\n'))
1958 ui.note(_('exporting patch:\n'))
1967 ui.pager('export')
1959 ui.pager('export')
1968 cmdutil.export(repo, revs, fntemplate=opts.get('output'),
1960 cmdutil.export(repo, revs, fntemplate=opts.get('output'),
1969 switch_parent=opts.get('switch_parent'),
1961 switch_parent=opts.get('switch_parent'),
1970 opts=patch.diffallopts(ui, opts))
1962 opts=patch.diffallopts(ui, opts))
1971
1963
1972 @command('files',
1964 @command('files',
1973 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
1965 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
1974 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
1966 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
1975 ] + walkopts + formatteropts + subrepoopts,
1967 ] + walkopts + formatteropts + subrepoopts,
1976 _('[OPTION]... [FILE]...'), cmdtype=readonly)
1968 _('[OPTION]... [FILE]...'), cmdtype=readonly)
1977 def files(ui, repo, *pats, **opts):
1969 def files(ui, repo, *pats, **opts):
1978 """list tracked files
1970 """list tracked files
1979
1971
1980 Print files under Mercurial control in the working directory or
1972 Print files under Mercurial control in the working directory or
1981 specified revision for given files (excluding removed files).
1973 specified revision for given files (excluding removed files).
1982 Files can be specified as filenames or filesets.
1974 Files can be specified as filenames or filesets.
1983
1975
1984 If no files are given to match, this command prints the names
1976 If no files are given to match, this command prints the names
1985 of all files under Mercurial control.
1977 of all files under Mercurial control.
1986
1978
1987 .. container:: verbose
1979 .. container:: verbose
1988
1980
1989 Examples:
1981 Examples:
1990
1982
1991 - list all files under the current directory::
1983 - list all files under the current directory::
1992
1984
1993 hg files .
1985 hg files .
1994
1986
1995 - shows sizes and flags for current revision::
1987 - shows sizes and flags for current revision::
1996
1988
1997 hg files -vr .
1989 hg files -vr .
1998
1990
1999 - list all files named README::
1991 - list all files named README::
2000
1992
2001 hg files -I "**/README"
1993 hg files -I "**/README"
2002
1994
2003 - list all binary files::
1995 - list all binary files::
2004
1996
2005 hg files "set:binary()"
1997 hg files "set:binary()"
2006
1998
2007 - find files containing a regular expression::
1999 - find files containing a regular expression::
2008
2000
2009 hg files "set:grep('bob')"
2001 hg files "set:grep('bob')"
2010
2002
2011 - search tracked file contents with xargs and grep::
2003 - search tracked file contents with xargs and grep::
2012
2004
2013 hg files -0 | xargs -0 grep foo
2005 hg files -0 | xargs -0 grep foo
2014
2006
2015 See :hg:`help patterns` and :hg:`help filesets` for more information
2007 See :hg:`help patterns` and :hg:`help filesets` for more information
2016 on specifying file patterns.
2008 on specifying file patterns.
2017
2009
2018 Returns 0 if a match is found, 1 otherwise.
2010 Returns 0 if a match is found, 1 otherwise.
2019
2011
2020 """
2012 """
2021
2013
2022 opts = pycompat.byteskwargs(opts)
2014 opts = pycompat.byteskwargs(opts)
2023 rev = opts.get('rev')
2015 rev = opts.get('rev')
2024 if rev:
2016 if rev:
2025 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
2017 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
2026 ctx = scmutil.revsingle(repo, rev, None)
2018 ctx = scmutil.revsingle(repo, rev, None)
2027
2019
2028 end = '\n'
2020 end = '\n'
2029 if opts.get('print0'):
2021 if opts.get('print0'):
2030 end = '\0'
2022 end = '\0'
2031 fmt = '%s' + end
2023 fmt = '%s' + end
2032
2024
2033 m = scmutil.match(ctx, pats, opts)
2025 m = scmutil.match(ctx, pats, opts)
2034 ui.pager('files')
2026 ui.pager('files')
2035 with ui.formatter('files', opts) as fm:
2027 with ui.formatter('files', opts) as fm:
2036 return cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
2028 return cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
2037
2029
2038 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
2030 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
2039 def forget(ui, repo, *pats, **opts):
2031 def forget(ui, repo, *pats, **opts):
2040 """forget the specified files on the next commit
2032 """forget the specified files on the next commit
2041
2033
2042 Mark the specified files so they will no longer be tracked
2034 Mark the specified files so they will no longer be tracked
2043 after the next commit.
2035 after the next commit.
2044
2036
2045 This only removes files from the current branch, not from the
2037 This only removes files from the current branch, not from the
2046 entire project history, and it does not delete them from the
2038 entire project history, and it does not delete them from the
2047 working directory.
2039 working directory.
2048
2040
2049 To delete the file from the working directory, see :hg:`remove`.
2041 To delete the file from the working directory, see :hg:`remove`.
2050
2042
2051 To undo a forget before the next commit, see :hg:`add`.
2043 To undo a forget before the next commit, see :hg:`add`.
2052
2044
2053 .. container:: verbose
2045 .. container:: verbose
2054
2046
2055 Examples:
2047 Examples:
2056
2048
2057 - forget newly-added binary files::
2049 - forget newly-added binary files::
2058
2050
2059 hg forget "set:added() and binary()"
2051 hg forget "set:added() and binary()"
2060
2052
2061 - forget files that would be excluded by .hgignore::
2053 - forget files that would be excluded by .hgignore::
2062
2054
2063 hg forget "set:hgignore()"
2055 hg forget "set:hgignore()"
2064
2056
2065 Returns 0 on success.
2057 Returns 0 on success.
2066 """
2058 """
2067
2059
2068 opts = pycompat.byteskwargs(opts)
2060 opts = pycompat.byteskwargs(opts)
2069 if not pats:
2061 if not pats:
2070 raise error.Abort(_('no files specified'))
2062 raise error.Abort(_('no files specified'))
2071
2063
2072 m = scmutil.match(repo[None], pats, opts)
2064 m = scmutil.match(repo[None], pats, opts)
2073 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2065 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2074 return rejected and 1 or 0
2066 return rejected and 1 or 0
2075
2067
2076 @command(
2068 @command(
2077 'graft',
2069 'graft',
2078 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2070 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2079 ('c', 'continue', False, _('resume interrupted graft')),
2071 ('c', 'continue', False, _('resume interrupted graft')),
2080 ('e', 'edit', False, _('invoke editor on commit messages')),
2072 ('e', 'edit', False, _('invoke editor on commit messages')),
2081 ('', 'log', None, _('append graft info to log message')),
2073 ('', 'log', None, _('append graft info to log message')),
2082 ('f', 'force', False, _('force graft')),
2074 ('f', 'force', False, _('force graft')),
2083 ('D', 'currentdate', False,
2075 ('D', 'currentdate', False,
2084 _('record the current date as commit date')),
2076 _('record the current date as commit date')),
2085 ('U', 'currentuser', False,
2077 ('U', 'currentuser', False,
2086 _('record the current user as committer'), _('DATE'))]
2078 _('record the current user as committer'), _('DATE'))]
2087 + commitopts2 + mergetoolopts + dryrunopts,
2079 + commitopts2 + mergetoolopts + dryrunopts,
2088 _('[OPTION]... [-r REV]... REV...'))
2080 _('[OPTION]... [-r REV]... REV...'))
2089 def graft(ui, repo, *revs, **opts):
2081 def graft(ui, repo, *revs, **opts):
2090 '''copy changes from other branches onto the current branch
2082 '''copy changes from other branches onto the current branch
2091
2083
2092 This command uses Mercurial's merge logic to copy individual
2084 This command uses Mercurial's merge logic to copy individual
2093 changes from other branches without merging branches in the
2085 changes from other branches without merging branches in the
2094 history graph. This is sometimes known as 'backporting' or
2086 history graph. This is sometimes known as 'backporting' or
2095 'cherry-picking'. By default, graft will copy user, date, and
2087 'cherry-picking'. By default, graft will copy user, date, and
2096 description from the source changesets.
2088 description from the source changesets.
2097
2089
2098 Changesets that are ancestors of the current revision, that have
2090 Changesets that are ancestors of the current revision, that have
2099 already been grafted, or that are merges will be skipped.
2091 already been grafted, or that are merges will be skipped.
2100
2092
2101 If --log is specified, log messages will have a comment appended
2093 If --log is specified, log messages will have a comment appended
2102 of the form::
2094 of the form::
2103
2095
2104 (grafted from CHANGESETHASH)
2096 (grafted from CHANGESETHASH)
2105
2097
2106 If --force is specified, revisions will be grafted even if they
2098 If --force is specified, revisions will be grafted even if they
2107 are already ancestors of, or have been grafted to, the destination.
2099 are already ancestors of, or have been grafted to, the destination.
2108 This is useful when the revisions have since been backed out.
2100 This is useful when the revisions have since been backed out.
2109
2101
2110 If a graft merge results in conflicts, the graft process is
2102 If a graft merge results in conflicts, the graft process is
2111 interrupted so that the current merge can be manually resolved.
2103 interrupted so that the current merge can be manually resolved.
2112 Once all conflicts are addressed, the graft process can be
2104 Once all conflicts are addressed, the graft process can be
2113 continued with the -c/--continue option.
2105 continued with the -c/--continue option.
2114
2106
2115 .. note::
2107 .. note::
2116
2108
2117 The -c/--continue option does not reapply earlier options, except
2109 The -c/--continue option does not reapply earlier options, except
2118 for --force.
2110 for --force.
2119
2111
2120 .. container:: verbose
2112 .. container:: verbose
2121
2113
2122 Examples:
2114 Examples:
2123
2115
2124 - copy a single change to the stable branch and edit its description::
2116 - copy a single change to the stable branch and edit its description::
2125
2117
2126 hg update stable
2118 hg update stable
2127 hg graft --edit 9393
2119 hg graft --edit 9393
2128
2120
2129 - graft a range of changesets with one exception, updating dates::
2121 - graft a range of changesets with one exception, updating dates::
2130
2122
2131 hg graft -D "2085::2093 and not 2091"
2123 hg graft -D "2085::2093 and not 2091"
2132
2124
2133 - continue a graft after resolving conflicts::
2125 - continue a graft after resolving conflicts::
2134
2126
2135 hg graft -c
2127 hg graft -c
2136
2128
2137 - show the source of a grafted changeset::
2129 - show the source of a grafted changeset::
2138
2130
2139 hg log --debug -r .
2131 hg log --debug -r .
2140
2132
2141 - show revisions sorted by date::
2133 - show revisions sorted by date::
2142
2134
2143 hg log -r "sort(all(), date)"
2135 hg log -r "sort(all(), date)"
2144
2136
2145 See :hg:`help revisions` for more about specifying revisions.
2137 See :hg:`help revisions` for more about specifying revisions.
2146
2138
2147 Returns 0 on successful completion.
2139 Returns 0 on successful completion.
2148 '''
2140 '''
2149 with repo.wlock():
2141 with repo.wlock():
2150 return _dograft(ui, repo, *revs, **opts)
2142 return _dograft(ui, repo, *revs, **opts)
2151
2143
2152 def _dograft(ui, repo, *revs, **opts):
2144 def _dograft(ui, repo, *revs, **opts):
2153 opts = pycompat.byteskwargs(opts)
2145 opts = pycompat.byteskwargs(opts)
2154 if revs and opts.get('rev'):
2146 if revs and opts.get('rev'):
2155 ui.warn(_('warning: inconsistent use of --rev might give unexpected '
2147 ui.warn(_('warning: inconsistent use of --rev might give unexpected '
2156 'revision ordering!\n'))
2148 'revision ordering!\n'))
2157
2149
2158 revs = list(revs)
2150 revs = list(revs)
2159 revs.extend(opts.get('rev'))
2151 revs.extend(opts.get('rev'))
2160
2152
2161 if not opts.get('user') and opts.get('currentuser'):
2153 if not opts.get('user') and opts.get('currentuser'):
2162 opts['user'] = ui.username()
2154 opts['user'] = ui.username()
2163 if not opts.get('date') and opts.get('currentdate'):
2155 if not opts.get('date') and opts.get('currentdate'):
2164 opts['date'] = "%d %d" % util.makedate()
2156 opts['date'] = "%d %d" % util.makedate()
2165
2157
2166 editor = cmdutil.getcommiteditor(editform='graft',
2158 editor = cmdutil.getcommiteditor(editform='graft',
2167 **pycompat.strkwargs(opts))
2159 **pycompat.strkwargs(opts))
2168
2160
2169 cont = False
2161 cont = False
2170 if opts.get('continue'):
2162 if opts.get('continue'):
2171 cont = True
2163 cont = True
2172 if revs:
2164 if revs:
2173 raise error.Abort(_("can't specify --continue and revisions"))
2165 raise error.Abort(_("can't specify --continue and revisions"))
2174 # read in unfinished revisions
2166 # read in unfinished revisions
2175 try:
2167 try:
2176 nodes = repo.vfs.read('graftstate').splitlines()
2168 nodes = repo.vfs.read('graftstate').splitlines()
2177 revs = [repo[node].rev() for node in nodes]
2169 revs = [repo[node].rev() for node in nodes]
2178 except IOError as inst:
2170 except IOError as inst:
2179 if inst.errno != errno.ENOENT:
2171 if inst.errno != errno.ENOENT:
2180 raise
2172 raise
2181 cmdutil.wrongtooltocontinue(repo, _('graft'))
2173 cmdutil.wrongtooltocontinue(repo, _('graft'))
2182 else:
2174 else:
2183 cmdutil.checkunfinished(repo)
2175 cmdutil.checkunfinished(repo)
2184 cmdutil.bailifchanged(repo)
2176 cmdutil.bailifchanged(repo)
2185 if not revs:
2177 if not revs:
2186 raise error.Abort(_('no revisions specified'))
2178 raise error.Abort(_('no revisions specified'))
2187 revs = scmutil.revrange(repo, revs)
2179 revs = scmutil.revrange(repo, revs)
2188
2180
2189 skipped = set()
2181 skipped = set()
2190 # check for merges
2182 # check for merges
2191 for rev in repo.revs('%ld and merge()', revs):
2183 for rev in repo.revs('%ld and merge()', revs):
2192 ui.warn(_('skipping ungraftable merge revision %d\n') % rev)
2184 ui.warn(_('skipping ungraftable merge revision %d\n') % rev)
2193 skipped.add(rev)
2185 skipped.add(rev)
2194 revs = [r for r in revs if r not in skipped]
2186 revs = [r for r in revs if r not in skipped]
2195 if not revs:
2187 if not revs:
2196 return -1
2188 return -1
2197
2189
2198 # Don't check in the --continue case, in effect retaining --force across
2190 # Don't check in the --continue case, in effect retaining --force across
2199 # --continues. That's because without --force, any revisions we decided to
2191 # --continues. That's because without --force, any revisions we decided to
2200 # skip would have been filtered out here, so they wouldn't have made their
2192 # skip would have been filtered out here, so they wouldn't have made their
2201 # way to the graftstate. With --force, any revisions we would have otherwise
2193 # way to the graftstate. With --force, any revisions we would have otherwise
2202 # skipped would not have been filtered out, and if they hadn't been applied
2194 # skipped would not have been filtered out, and if they hadn't been applied
2203 # already, they'd have been in the graftstate.
2195 # already, they'd have been in the graftstate.
2204 if not (cont or opts.get('force')):
2196 if not (cont or opts.get('force')):
2205 # check for ancestors of dest branch
2197 # check for ancestors of dest branch
2206 crev = repo['.'].rev()
2198 crev = repo['.'].rev()
2207 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2199 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2208 # XXX make this lazy in the future
2200 # XXX make this lazy in the future
2209 # don't mutate while iterating, create a copy
2201 # don't mutate while iterating, create a copy
2210 for rev in list(revs):
2202 for rev in list(revs):
2211 if rev in ancestors:
2203 if rev in ancestors:
2212 ui.warn(_('skipping ancestor revision %d:%s\n') %
2204 ui.warn(_('skipping ancestor revision %d:%s\n') %
2213 (rev, repo[rev]))
2205 (rev, repo[rev]))
2214 # XXX remove on list is slow
2206 # XXX remove on list is slow
2215 revs.remove(rev)
2207 revs.remove(rev)
2216 if not revs:
2208 if not revs:
2217 return -1
2209 return -1
2218
2210
2219 # analyze revs for earlier grafts
2211 # analyze revs for earlier grafts
2220 ids = {}
2212 ids = {}
2221 for ctx in repo.set("%ld", revs):
2213 for ctx in repo.set("%ld", revs):
2222 ids[ctx.hex()] = ctx.rev()
2214 ids[ctx.hex()] = ctx.rev()
2223 n = ctx.extra().get('source')
2215 n = ctx.extra().get('source')
2224 if n:
2216 if n:
2225 ids[n] = ctx.rev()
2217 ids[n] = ctx.rev()
2226
2218
2227 # check ancestors for earlier grafts
2219 # check ancestors for earlier grafts
2228 ui.debug('scanning for duplicate grafts\n')
2220 ui.debug('scanning for duplicate grafts\n')
2229
2221
2230 # The only changesets we can be sure doesn't contain grafts of any
2222 # The only changesets we can be sure doesn't contain grafts of any
2231 # revs, are the ones that are common ancestors of *all* revs:
2223 # revs, are the ones that are common ancestors of *all* revs:
2232 for rev in repo.revs('only(%d,ancestor(%ld))', crev, revs):
2224 for rev in repo.revs('only(%d,ancestor(%ld))', crev, revs):
2233 ctx = repo[rev]
2225 ctx = repo[rev]
2234 n = ctx.extra().get('source')
2226 n = ctx.extra().get('source')
2235 if n in ids:
2227 if n in ids:
2236 try:
2228 try:
2237 r = repo[n].rev()
2229 r = repo[n].rev()
2238 except error.RepoLookupError:
2230 except error.RepoLookupError:
2239 r = None
2231 r = None
2240 if r in revs:
2232 if r in revs:
2241 ui.warn(_('skipping revision %d:%s '
2233 ui.warn(_('skipping revision %d:%s '
2242 '(already grafted to %d:%s)\n')
2234 '(already grafted to %d:%s)\n')
2243 % (r, repo[r], rev, ctx))
2235 % (r, repo[r], rev, ctx))
2244 revs.remove(r)
2236 revs.remove(r)
2245 elif ids[n] in revs:
2237 elif ids[n] in revs:
2246 if r is None:
2238 if r is None:
2247 ui.warn(_('skipping already grafted revision %d:%s '
2239 ui.warn(_('skipping already grafted revision %d:%s '
2248 '(%d:%s also has unknown origin %s)\n')
2240 '(%d:%s also has unknown origin %s)\n')
2249 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
2241 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
2250 else:
2242 else:
2251 ui.warn(_('skipping already grafted revision %d:%s '
2243 ui.warn(_('skipping already grafted revision %d:%s '
2252 '(%d:%s also has origin %d:%s)\n')
2244 '(%d:%s also has origin %d:%s)\n')
2253 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
2245 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
2254 revs.remove(ids[n])
2246 revs.remove(ids[n])
2255 elif ctx.hex() in ids:
2247 elif ctx.hex() in ids:
2256 r = ids[ctx.hex()]
2248 r = ids[ctx.hex()]
2257 ui.warn(_('skipping already grafted revision %d:%s '
2249 ui.warn(_('skipping already grafted revision %d:%s '
2258 '(was grafted from %d:%s)\n') %
2250 '(was grafted from %d:%s)\n') %
2259 (r, repo[r], rev, ctx))
2251 (r, repo[r], rev, ctx))
2260 revs.remove(r)
2252 revs.remove(r)
2261 if not revs:
2253 if not revs:
2262 return -1
2254 return -1
2263
2255
2264 for pos, ctx in enumerate(repo.set("%ld", revs)):
2256 for pos, ctx in enumerate(repo.set("%ld", revs)):
2265 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
2257 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
2266 ctx.description().split('\n', 1)[0])
2258 ctx.description().split('\n', 1)[0])
2267 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
2259 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
2268 if names:
2260 if names:
2269 desc += ' (%s)' % ' '.join(names)
2261 desc += ' (%s)' % ' '.join(names)
2270 ui.status(_('grafting %s\n') % desc)
2262 ui.status(_('grafting %s\n') % desc)
2271 if opts.get('dry_run'):
2263 if opts.get('dry_run'):
2272 continue
2264 continue
2273
2265
2274 source = ctx.extra().get('source')
2266 source = ctx.extra().get('source')
2275 extra = {}
2267 extra = {}
2276 if source:
2268 if source:
2277 extra['source'] = source
2269 extra['source'] = source
2278 extra['intermediate-source'] = ctx.hex()
2270 extra['intermediate-source'] = ctx.hex()
2279 else:
2271 else:
2280 extra['source'] = ctx.hex()
2272 extra['source'] = ctx.hex()
2281 user = ctx.user()
2273 user = ctx.user()
2282 if opts.get('user'):
2274 if opts.get('user'):
2283 user = opts['user']
2275 user = opts['user']
2284 date = ctx.date()
2276 date = ctx.date()
2285 if opts.get('date'):
2277 if opts.get('date'):
2286 date = opts['date']
2278 date = opts['date']
2287 message = ctx.description()
2279 message = ctx.description()
2288 if opts.get('log'):
2280 if opts.get('log'):
2289 message += '\n(grafted from %s)' % ctx.hex()
2281 message += '\n(grafted from %s)' % ctx.hex()
2290
2282
2291 # we don't merge the first commit when continuing
2283 # we don't merge the first commit when continuing
2292 if not cont:
2284 if not cont:
2293 # perform the graft merge with p1(rev) as 'ancestor'
2285 # perform the graft merge with p1(rev) as 'ancestor'
2294 try:
2286 try:
2295 # ui.forcemerge is an internal variable, do not document
2287 # ui.forcemerge is an internal variable, do not document
2296 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
2288 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
2297 'graft')
2289 'graft')
2298 stats = mergemod.graft(repo, ctx, ctx.p1(),
2290 stats = mergemod.graft(repo, ctx, ctx.p1(),
2299 ['local', 'graft'])
2291 ['local', 'graft'])
2300 finally:
2292 finally:
2301 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
2293 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
2302 # report any conflicts
2294 # report any conflicts
2303 if stats and stats[3] > 0:
2295 if stats and stats[3] > 0:
2304 # write out state for --continue
2296 # write out state for --continue
2305 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2297 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2306 repo.vfs.write('graftstate', ''.join(nodelines))
2298 repo.vfs.write('graftstate', ''.join(nodelines))
2307 extra = ''
2299 extra = ''
2308 if opts.get('user'):
2300 if opts.get('user'):
2309 extra += ' --user %s' % util.shellquote(opts['user'])
2301 extra += ' --user %s' % util.shellquote(opts['user'])
2310 if opts.get('date'):
2302 if opts.get('date'):
2311 extra += ' --date %s' % util.shellquote(opts['date'])
2303 extra += ' --date %s' % util.shellquote(opts['date'])
2312 if opts.get('log'):
2304 if opts.get('log'):
2313 extra += ' --log'
2305 extra += ' --log'
2314 hint=_("use 'hg resolve' and 'hg graft --continue%s'") % extra
2306 hint=_("use 'hg resolve' and 'hg graft --continue%s'") % extra
2315 raise error.Abort(
2307 raise error.Abort(
2316 _("unresolved conflicts, can't continue"),
2308 _("unresolved conflicts, can't continue"),
2317 hint=hint)
2309 hint=hint)
2318 else:
2310 else:
2319 cont = False
2311 cont = False
2320
2312
2321 # commit
2313 # commit
2322 node = repo.commit(text=message, user=user,
2314 node = repo.commit(text=message, user=user,
2323 date=date, extra=extra, editor=editor)
2315 date=date, extra=extra, editor=editor)
2324 if node is None:
2316 if node is None:
2325 ui.warn(
2317 ui.warn(
2326 _('note: graft of %d:%s created no changes to commit\n') %
2318 _('note: graft of %d:%s created no changes to commit\n') %
2327 (ctx.rev(), ctx))
2319 (ctx.rev(), ctx))
2328
2320
2329 # remove state when we complete successfully
2321 # remove state when we complete successfully
2330 if not opts.get('dry_run'):
2322 if not opts.get('dry_run'):
2331 repo.vfs.unlinkpath('graftstate', ignoremissing=True)
2323 repo.vfs.unlinkpath('graftstate', ignoremissing=True)
2332
2324
2333 return 0
2325 return 0
2334
2326
2335 @command('grep',
2327 @command('grep',
2336 [('0', 'print0', None, _('end fields with NUL')),
2328 [('0', 'print0', None, _('end fields with NUL')),
2337 ('', 'all', None, _('print all revisions that match')),
2329 ('', 'all', None, _('print all revisions that match')),
2338 ('a', 'text', None, _('treat all files as text')),
2330 ('a', 'text', None, _('treat all files as text')),
2339 ('f', 'follow', None,
2331 ('f', 'follow', None,
2340 _('follow changeset history,'
2332 _('follow changeset history,'
2341 ' or file history across copies and renames')),
2333 ' or file history across copies and renames')),
2342 ('i', 'ignore-case', None, _('ignore case when matching')),
2334 ('i', 'ignore-case', None, _('ignore case when matching')),
2343 ('l', 'files-with-matches', None,
2335 ('l', 'files-with-matches', None,
2344 _('print only filenames and revisions that match')),
2336 _('print only filenames and revisions that match')),
2345 ('n', 'line-number', None, _('print matching line numbers')),
2337 ('n', 'line-number', None, _('print matching line numbers')),
2346 ('r', 'rev', [],
2338 ('r', 'rev', [],
2347 _('only search files changed within revision range'), _('REV')),
2339 _('only search files changed within revision range'), _('REV')),
2348 ('u', 'user', None, _('list the author (long with -v)')),
2340 ('u', 'user', None, _('list the author (long with -v)')),
2349 ('d', 'date', None, _('list the date (short with -q)')),
2341 ('d', 'date', None, _('list the date (short with -q)')),
2350 ] + formatteropts + walkopts,
2342 ] + formatteropts + walkopts,
2351 _('[OPTION]... PATTERN [FILE]...'),
2343 _('[OPTION]... PATTERN [FILE]...'),
2352 inferrepo=True, cmdtype=readonly)
2344 inferrepo=True, cmdtype=readonly)
2353 def grep(ui, repo, pattern, *pats, **opts):
2345 def grep(ui, repo, pattern, *pats, **opts):
2354 """search revision history for a pattern in specified files
2346 """search revision history for a pattern in specified files
2355
2347
2356 Search revision history for a regular expression in the specified
2348 Search revision history for a regular expression in the specified
2357 files or the entire project.
2349 files or the entire project.
2358
2350
2359 By default, grep prints the most recent revision number for each
2351 By default, grep prints the most recent revision number for each
2360 file in which it finds a match. To get it to print every revision
2352 file in which it finds a match. To get it to print every revision
2361 that contains a change in match status ("-" for a match that becomes
2353 that contains a change in match status ("-" for a match that becomes
2362 a non-match, or "+" for a non-match that becomes a match), use the
2354 a non-match, or "+" for a non-match that becomes a match), use the
2363 --all flag.
2355 --all flag.
2364
2356
2365 PATTERN can be any Python (roughly Perl-compatible) regular
2357 PATTERN can be any Python (roughly Perl-compatible) regular
2366 expression.
2358 expression.
2367
2359
2368 If no FILEs are specified (and -f/--follow isn't set), all files in
2360 If no FILEs are specified (and -f/--follow isn't set), all files in
2369 the repository are searched, including those that don't exist in the
2361 the repository are searched, including those that don't exist in the
2370 current branch or have been deleted in a prior changeset.
2362 current branch or have been deleted in a prior changeset.
2371
2363
2372 Returns 0 if a match is found, 1 otherwise.
2364 Returns 0 if a match is found, 1 otherwise.
2373 """
2365 """
2374 opts = pycompat.byteskwargs(opts)
2366 opts = pycompat.byteskwargs(opts)
2375 reflags = re.M
2367 reflags = re.M
2376 if opts.get('ignore_case'):
2368 if opts.get('ignore_case'):
2377 reflags |= re.I
2369 reflags |= re.I
2378 try:
2370 try:
2379 regexp = util.re.compile(pattern, reflags)
2371 regexp = util.re.compile(pattern, reflags)
2380 except re.error as inst:
2372 except re.error as inst:
2381 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2373 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2382 return 1
2374 return 1
2383 sep, eol = ':', '\n'
2375 sep, eol = ':', '\n'
2384 if opts.get('print0'):
2376 if opts.get('print0'):
2385 sep = eol = '\0'
2377 sep = eol = '\0'
2386
2378
2387 getfile = util.lrucachefunc(repo.file)
2379 getfile = util.lrucachefunc(repo.file)
2388
2380
2389 def matchlines(body):
2381 def matchlines(body):
2390 begin = 0
2382 begin = 0
2391 linenum = 0
2383 linenum = 0
2392 while begin < len(body):
2384 while begin < len(body):
2393 match = regexp.search(body, begin)
2385 match = regexp.search(body, begin)
2394 if not match:
2386 if not match:
2395 break
2387 break
2396 mstart, mend = match.span()
2388 mstart, mend = match.span()
2397 linenum += body.count('\n', begin, mstart) + 1
2389 linenum += body.count('\n', begin, mstart) + 1
2398 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2390 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2399 begin = body.find('\n', mend) + 1 or len(body) + 1
2391 begin = body.find('\n', mend) + 1 or len(body) + 1
2400 lend = begin - 1
2392 lend = begin - 1
2401 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2393 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2402
2394
2403 class linestate(object):
2395 class linestate(object):
2404 def __init__(self, line, linenum, colstart, colend):
2396 def __init__(self, line, linenum, colstart, colend):
2405 self.line = line
2397 self.line = line
2406 self.linenum = linenum
2398 self.linenum = linenum
2407 self.colstart = colstart
2399 self.colstart = colstart
2408 self.colend = colend
2400 self.colend = colend
2409
2401
2410 def __hash__(self):
2402 def __hash__(self):
2411 return hash((self.linenum, self.line))
2403 return hash((self.linenum, self.line))
2412
2404
2413 def __eq__(self, other):
2405 def __eq__(self, other):
2414 return self.line == other.line
2406 return self.line == other.line
2415
2407
2416 def findpos(self):
2408 def findpos(self):
2417 """Iterate all (start, end) indices of matches"""
2409 """Iterate all (start, end) indices of matches"""
2418 yield self.colstart, self.colend
2410 yield self.colstart, self.colend
2419 p = self.colend
2411 p = self.colend
2420 while p < len(self.line):
2412 while p < len(self.line):
2421 m = regexp.search(self.line, p)
2413 m = regexp.search(self.line, p)
2422 if not m:
2414 if not m:
2423 break
2415 break
2424 yield m.span()
2416 yield m.span()
2425 p = m.end()
2417 p = m.end()
2426
2418
2427 matches = {}
2419 matches = {}
2428 copies = {}
2420 copies = {}
2429 def grepbody(fn, rev, body):
2421 def grepbody(fn, rev, body):
2430 matches[rev].setdefault(fn, [])
2422 matches[rev].setdefault(fn, [])
2431 m = matches[rev][fn]
2423 m = matches[rev][fn]
2432 for lnum, cstart, cend, line in matchlines(body):
2424 for lnum, cstart, cend, line in matchlines(body):
2433 s = linestate(line, lnum, cstart, cend)
2425 s = linestate(line, lnum, cstart, cend)
2434 m.append(s)
2426 m.append(s)
2435
2427
2436 def difflinestates(a, b):
2428 def difflinestates(a, b):
2437 sm = difflib.SequenceMatcher(None, a, b)
2429 sm = difflib.SequenceMatcher(None, a, b)
2438 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2430 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2439 if tag == 'insert':
2431 if tag == 'insert':
2440 for i in xrange(blo, bhi):
2432 for i in xrange(blo, bhi):
2441 yield ('+', b[i])
2433 yield ('+', b[i])
2442 elif tag == 'delete':
2434 elif tag == 'delete':
2443 for i in xrange(alo, ahi):
2435 for i in xrange(alo, ahi):
2444 yield ('-', a[i])
2436 yield ('-', a[i])
2445 elif tag == 'replace':
2437 elif tag == 'replace':
2446 for i in xrange(alo, ahi):
2438 for i in xrange(alo, ahi):
2447 yield ('-', a[i])
2439 yield ('-', a[i])
2448 for i in xrange(blo, bhi):
2440 for i in xrange(blo, bhi):
2449 yield ('+', b[i])
2441 yield ('+', b[i])
2450
2442
2451 def display(fm, fn, ctx, pstates, states):
2443 def display(fm, fn, ctx, pstates, states):
2452 rev = ctx.rev()
2444 rev = ctx.rev()
2453 if fm.isplain():
2445 if fm.isplain():
2454 formatuser = ui.shortuser
2446 formatuser = ui.shortuser
2455 else:
2447 else:
2456 formatuser = str
2448 formatuser = str
2457 if ui.quiet:
2449 if ui.quiet:
2458 datefmt = '%Y-%m-%d'
2450 datefmt = '%Y-%m-%d'
2459 else:
2451 else:
2460 datefmt = '%a %b %d %H:%M:%S %Y %1%2'
2452 datefmt = '%a %b %d %H:%M:%S %Y %1%2'
2461 found = False
2453 found = False
2462 @util.cachefunc
2454 @util.cachefunc
2463 def binary():
2455 def binary():
2464 flog = getfile(fn)
2456 flog = getfile(fn)
2465 return util.binary(flog.read(ctx.filenode(fn)))
2457 return util.binary(flog.read(ctx.filenode(fn)))
2466
2458
2467 fieldnamemap = {'filename': 'file', 'linenumber': 'line_number'}
2459 fieldnamemap = {'filename': 'file', 'linenumber': 'line_number'}
2468 if opts.get('all'):
2460 if opts.get('all'):
2469 iter = difflinestates(pstates, states)
2461 iter = difflinestates(pstates, states)
2470 else:
2462 else:
2471 iter = [('', l) for l in states]
2463 iter = [('', l) for l in states]
2472 for change, l in iter:
2464 for change, l in iter:
2473 fm.startitem()
2465 fm.startitem()
2474 fm.data(node=fm.hexfunc(ctx.node()))
2466 fm.data(node=fm.hexfunc(ctx.node()))
2475 cols = [
2467 cols = [
2476 ('filename', fn, True),
2468 ('filename', fn, True),
2477 ('rev', rev, True),
2469 ('rev', rev, True),
2478 ('linenumber', l.linenum, opts.get('line_number')),
2470 ('linenumber', l.linenum, opts.get('line_number')),
2479 ]
2471 ]
2480 if opts.get('all'):
2472 if opts.get('all'):
2481 cols.append(('change', change, True))
2473 cols.append(('change', change, True))
2482 cols.extend([
2474 cols.extend([
2483 ('user', formatuser(ctx.user()), opts.get('user')),
2475 ('user', formatuser(ctx.user()), opts.get('user')),
2484 ('date', fm.formatdate(ctx.date(), datefmt), opts.get('date')),
2476 ('date', fm.formatdate(ctx.date(), datefmt), opts.get('date')),
2485 ])
2477 ])
2486 lastcol = next(name for name, data, cond in reversed(cols) if cond)
2478 lastcol = next(name for name, data, cond in reversed(cols) if cond)
2487 for name, data, cond in cols:
2479 for name, data, cond in cols:
2488 field = fieldnamemap.get(name, name)
2480 field = fieldnamemap.get(name, name)
2489 fm.condwrite(cond, field, '%s', data, label='grep.%s' % name)
2481 fm.condwrite(cond, field, '%s', data, label='grep.%s' % name)
2490 if cond and name != lastcol:
2482 if cond and name != lastcol:
2491 fm.plain(sep, label='grep.sep')
2483 fm.plain(sep, label='grep.sep')
2492 if not opts.get('files_with_matches'):
2484 if not opts.get('files_with_matches'):
2493 fm.plain(sep, label='grep.sep')
2485 fm.plain(sep, label='grep.sep')
2494 if not opts.get('text') and binary():
2486 if not opts.get('text') and binary():
2495 fm.plain(_(" Binary file matches"))
2487 fm.plain(_(" Binary file matches"))
2496 else:
2488 else:
2497 displaymatches(fm.nested('texts'), l)
2489 displaymatches(fm.nested('texts'), l)
2498 fm.plain(eol)
2490 fm.plain(eol)
2499 found = True
2491 found = True
2500 if opts.get('files_with_matches'):
2492 if opts.get('files_with_matches'):
2501 break
2493 break
2502 return found
2494 return found
2503
2495
2504 def displaymatches(fm, l):
2496 def displaymatches(fm, l):
2505 p = 0
2497 p = 0
2506 for s, e in l.findpos():
2498 for s, e in l.findpos():
2507 if p < s:
2499 if p < s:
2508 fm.startitem()
2500 fm.startitem()
2509 fm.write('text', '%s', l.line[p:s])
2501 fm.write('text', '%s', l.line[p:s])
2510 fm.data(matched=False)
2502 fm.data(matched=False)
2511 fm.startitem()
2503 fm.startitem()
2512 fm.write('text', '%s', l.line[s:e], label='grep.match')
2504 fm.write('text', '%s', l.line[s:e], label='grep.match')
2513 fm.data(matched=True)
2505 fm.data(matched=True)
2514 p = e
2506 p = e
2515 if p < len(l.line):
2507 if p < len(l.line):
2516 fm.startitem()
2508 fm.startitem()
2517 fm.write('text', '%s', l.line[p:])
2509 fm.write('text', '%s', l.line[p:])
2518 fm.data(matched=False)
2510 fm.data(matched=False)
2519 fm.end()
2511 fm.end()
2520
2512
2521 skip = {}
2513 skip = {}
2522 revfiles = {}
2514 revfiles = {}
2523 match = scmutil.match(repo[None], pats, opts)
2515 match = scmutil.match(repo[None], pats, opts)
2524 found = False
2516 found = False
2525 follow = opts.get('follow')
2517 follow = opts.get('follow')
2526
2518
2527 def prep(ctx, fns):
2519 def prep(ctx, fns):
2528 rev = ctx.rev()
2520 rev = ctx.rev()
2529 pctx = ctx.p1()
2521 pctx = ctx.p1()
2530 parent = pctx.rev()
2522 parent = pctx.rev()
2531 matches.setdefault(rev, {})
2523 matches.setdefault(rev, {})
2532 matches.setdefault(parent, {})
2524 matches.setdefault(parent, {})
2533 files = revfiles.setdefault(rev, [])
2525 files = revfiles.setdefault(rev, [])
2534 for fn in fns:
2526 for fn in fns:
2535 flog = getfile(fn)
2527 flog = getfile(fn)
2536 try:
2528 try:
2537 fnode = ctx.filenode(fn)
2529 fnode = ctx.filenode(fn)
2538 except error.LookupError:
2530 except error.LookupError:
2539 continue
2531 continue
2540
2532
2541 copied = flog.renamed(fnode)
2533 copied = flog.renamed(fnode)
2542 copy = follow and copied and copied[0]
2534 copy = follow and copied and copied[0]
2543 if copy:
2535 if copy:
2544 copies.setdefault(rev, {})[fn] = copy
2536 copies.setdefault(rev, {})[fn] = copy
2545 if fn in skip:
2537 if fn in skip:
2546 if copy:
2538 if copy:
2547 skip[copy] = True
2539 skip[copy] = True
2548 continue
2540 continue
2549 files.append(fn)
2541 files.append(fn)
2550
2542
2551 if fn not in matches[rev]:
2543 if fn not in matches[rev]:
2552 grepbody(fn, rev, flog.read(fnode))
2544 grepbody(fn, rev, flog.read(fnode))
2553
2545
2554 pfn = copy or fn
2546 pfn = copy or fn
2555 if pfn not in matches[parent]:
2547 if pfn not in matches[parent]:
2556 try:
2548 try:
2557 fnode = pctx.filenode(pfn)
2549 fnode = pctx.filenode(pfn)
2558 grepbody(pfn, parent, flog.read(fnode))
2550 grepbody(pfn, parent, flog.read(fnode))
2559 except error.LookupError:
2551 except error.LookupError:
2560 pass
2552 pass
2561
2553
2562 ui.pager('grep')
2554 ui.pager('grep')
2563 fm = ui.formatter('grep', opts)
2555 fm = ui.formatter('grep', opts)
2564 for ctx in cmdutil.walkchangerevs(repo, match, opts, prep):
2556 for ctx in cmdutil.walkchangerevs(repo, match, opts, prep):
2565 rev = ctx.rev()
2557 rev = ctx.rev()
2566 parent = ctx.p1().rev()
2558 parent = ctx.p1().rev()
2567 for fn in sorted(revfiles.get(rev, [])):
2559 for fn in sorted(revfiles.get(rev, [])):
2568 states = matches[rev][fn]
2560 states = matches[rev][fn]
2569 copy = copies.get(rev, {}).get(fn)
2561 copy = copies.get(rev, {}).get(fn)
2570 if fn in skip:
2562 if fn in skip:
2571 if copy:
2563 if copy:
2572 skip[copy] = True
2564 skip[copy] = True
2573 continue
2565 continue
2574 pstates = matches.get(parent, {}).get(copy or fn, [])
2566 pstates = matches.get(parent, {}).get(copy or fn, [])
2575 if pstates or states:
2567 if pstates or states:
2576 r = display(fm, fn, ctx, pstates, states)
2568 r = display(fm, fn, ctx, pstates, states)
2577 found = found or r
2569 found = found or r
2578 if r and not opts.get('all'):
2570 if r and not opts.get('all'):
2579 skip[fn] = True
2571 skip[fn] = True
2580 if copy:
2572 if copy:
2581 skip[copy] = True
2573 skip[copy] = True
2582 del matches[rev]
2574 del matches[rev]
2583 del revfiles[rev]
2575 del revfiles[rev]
2584 fm.end()
2576 fm.end()
2585
2577
2586 return not found
2578 return not found
2587
2579
2588 @command('heads',
2580 @command('heads',
2589 [('r', 'rev', '',
2581 [('r', 'rev', '',
2590 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2582 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2591 ('t', 'topo', False, _('show topological heads only')),
2583 ('t', 'topo', False, _('show topological heads only')),
2592 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2584 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2593 ('c', 'closed', False, _('show normal and closed branch heads')),
2585 ('c', 'closed', False, _('show normal and closed branch heads')),
2594 ] + templateopts,
2586 ] + templateopts,
2595 _('[-ct] [-r STARTREV] [REV]...'), cmdtype=readonly)
2587 _('[-ct] [-r STARTREV] [REV]...'), cmdtype=readonly)
2596 def heads(ui, repo, *branchrevs, **opts):
2588 def heads(ui, repo, *branchrevs, **opts):
2597 """show branch heads
2589 """show branch heads
2598
2590
2599 With no arguments, show all open branch heads in the repository.
2591 With no arguments, show all open branch heads in the repository.
2600 Branch heads are changesets that have no descendants on the
2592 Branch heads are changesets that have no descendants on the
2601 same branch. They are where development generally takes place and
2593 same branch. They are where development generally takes place and
2602 are the usual targets for update and merge operations.
2594 are the usual targets for update and merge operations.
2603
2595
2604 If one or more REVs are given, only open branch heads on the
2596 If one or more REVs are given, only open branch heads on the
2605 branches associated with the specified changesets are shown. This
2597 branches associated with the specified changesets are shown. This
2606 means that you can use :hg:`heads .` to see the heads on the
2598 means that you can use :hg:`heads .` to see the heads on the
2607 currently checked-out branch.
2599 currently checked-out branch.
2608
2600
2609 If -c/--closed is specified, also show branch heads marked closed
2601 If -c/--closed is specified, also show branch heads marked closed
2610 (see :hg:`commit --close-branch`).
2602 (see :hg:`commit --close-branch`).
2611
2603
2612 If STARTREV is specified, only those heads that are descendants of
2604 If STARTREV is specified, only those heads that are descendants of
2613 STARTREV will be displayed.
2605 STARTREV will be displayed.
2614
2606
2615 If -t/--topo is specified, named branch mechanics will be ignored and only
2607 If -t/--topo is specified, named branch mechanics will be ignored and only
2616 topological heads (changesets with no children) will be shown.
2608 topological heads (changesets with no children) will be shown.
2617
2609
2618 Returns 0 if matching heads are found, 1 if not.
2610 Returns 0 if matching heads are found, 1 if not.
2619 """
2611 """
2620
2612
2621 opts = pycompat.byteskwargs(opts)
2613 opts = pycompat.byteskwargs(opts)
2622 start = None
2614 start = None
2623 rev = opts.get('rev')
2615 rev = opts.get('rev')
2624 if rev:
2616 if rev:
2625 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
2617 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
2626 start = scmutil.revsingle(repo, rev, None).node()
2618 start = scmutil.revsingle(repo, rev, None).node()
2627
2619
2628 if opts.get('topo'):
2620 if opts.get('topo'):
2629 heads = [repo[h] for h in repo.heads(start)]
2621 heads = [repo[h] for h in repo.heads(start)]
2630 else:
2622 else:
2631 heads = []
2623 heads = []
2632 for branch in repo.branchmap():
2624 for branch in repo.branchmap():
2633 heads += repo.branchheads(branch, start, opts.get('closed'))
2625 heads += repo.branchheads(branch, start, opts.get('closed'))
2634 heads = [repo[h] for h in heads]
2626 heads = [repo[h] for h in heads]
2635
2627
2636 if branchrevs:
2628 if branchrevs:
2637 branches = set(repo[br].branch() for br in branchrevs)
2629 branches = set(repo[br].branch() for br in branchrevs)
2638 heads = [h for h in heads if h.branch() in branches]
2630 heads = [h for h in heads if h.branch() in branches]
2639
2631
2640 if opts.get('active') and branchrevs:
2632 if opts.get('active') and branchrevs:
2641 dagheads = repo.heads(start)
2633 dagheads = repo.heads(start)
2642 heads = [h for h in heads if h.node() in dagheads]
2634 heads = [h for h in heads if h.node() in dagheads]
2643
2635
2644 if branchrevs:
2636 if branchrevs:
2645 haveheads = set(h.branch() for h in heads)
2637 haveheads = set(h.branch() for h in heads)
2646 if branches - haveheads:
2638 if branches - haveheads:
2647 headless = ', '.join(b for b in branches - haveheads)
2639 headless = ', '.join(b for b in branches - haveheads)
2648 msg = _('no open branch heads found on branches %s')
2640 msg = _('no open branch heads found on branches %s')
2649 if opts.get('rev'):
2641 if opts.get('rev'):
2650 msg += _(' (started at %s)') % opts['rev']
2642 msg += _(' (started at %s)') % opts['rev']
2651 ui.warn((msg + '\n') % headless)
2643 ui.warn((msg + '\n') % headless)
2652
2644
2653 if not heads:
2645 if not heads:
2654 return 1
2646 return 1
2655
2647
2656 ui.pager('heads')
2648 ui.pager('heads')
2657 heads = sorted(heads, key=lambda x: -x.rev())
2649 heads = sorted(heads, key=lambda x: -x.rev())
2658 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
2650 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
2659 for ctx in heads:
2651 for ctx in heads:
2660 displayer.show(ctx)
2652 displayer.show(ctx)
2661 displayer.close()
2653 displayer.close()
2662
2654
2663 @command('help',
2655 @command('help',
2664 [('e', 'extension', None, _('show only help for extensions')),
2656 [('e', 'extension', None, _('show only help for extensions')),
2665 ('c', 'command', None, _('show only help for commands')),
2657 ('c', 'command', None, _('show only help for commands')),
2666 ('k', 'keyword', None, _('show topics matching keyword')),
2658 ('k', 'keyword', None, _('show topics matching keyword')),
2667 ('s', 'system', [], _('show help for specific platform(s)')),
2659 ('s', 'system', [], _('show help for specific platform(s)')),
2668 ],
2660 ],
2669 _('[-ecks] [TOPIC]'),
2661 _('[-ecks] [TOPIC]'),
2670 norepo=True, cmdtype=readonly)
2662 norepo=True, cmdtype=readonly)
2671 def help_(ui, name=None, **opts):
2663 def help_(ui, name=None, **opts):
2672 """show help for a given topic or a help overview
2664 """show help for a given topic or a help overview
2673
2665
2674 With no arguments, print a list of commands with short help messages.
2666 With no arguments, print a list of commands with short help messages.
2675
2667
2676 Given a topic, extension, or command name, print help for that
2668 Given a topic, extension, or command name, print help for that
2677 topic.
2669 topic.
2678
2670
2679 Returns 0 if successful.
2671 Returns 0 if successful.
2680 """
2672 """
2681
2673
2682 keep = opts.get(r'system') or []
2674 keep = opts.get(r'system') or []
2683 if len(keep) == 0:
2675 if len(keep) == 0:
2684 if pycompat.sysplatform.startswith('win'):
2676 if pycompat.sysplatform.startswith('win'):
2685 keep.append('windows')
2677 keep.append('windows')
2686 elif pycompat.sysplatform == 'OpenVMS':
2678 elif pycompat.sysplatform == 'OpenVMS':
2687 keep.append('vms')
2679 keep.append('vms')
2688 elif pycompat.sysplatform == 'plan9':
2680 elif pycompat.sysplatform == 'plan9':
2689 keep.append('plan9')
2681 keep.append('plan9')
2690 else:
2682 else:
2691 keep.append('unix')
2683 keep.append('unix')
2692 keep.append(pycompat.sysplatform.lower())
2684 keep.append(pycompat.sysplatform.lower())
2693 if ui.verbose:
2685 if ui.verbose:
2694 keep.append('verbose')
2686 keep.append('verbose')
2695
2687
2696 commands = sys.modules[__name__]
2688 commands = sys.modules[__name__]
2697 formatted = help.formattedhelp(ui, commands, name, keep=keep, **opts)
2689 formatted = help.formattedhelp(ui, commands, name, keep=keep, **opts)
2698 ui.pager('help')
2690 ui.pager('help')
2699 ui.write(formatted)
2691 ui.write(formatted)
2700
2692
2701
2693
2702 @command('identify|id',
2694 @command('identify|id',
2703 [('r', 'rev', '',
2695 [('r', 'rev', '',
2704 _('identify the specified revision'), _('REV')),
2696 _('identify the specified revision'), _('REV')),
2705 ('n', 'num', None, _('show local revision number')),
2697 ('n', 'num', None, _('show local revision number')),
2706 ('i', 'id', None, _('show global revision id')),
2698 ('i', 'id', None, _('show global revision id')),
2707 ('b', 'branch', None, _('show branch')),
2699 ('b', 'branch', None, _('show branch')),
2708 ('t', 'tags', None, _('show tags')),
2700 ('t', 'tags', None, _('show tags')),
2709 ('B', 'bookmarks', None, _('show bookmarks')),
2701 ('B', 'bookmarks', None, _('show bookmarks')),
2710 ] + remoteopts + formatteropts,
2702 ] + remoteopts + formatteropts,
2711 _('[-nibtB] [-r REV] [SOURCE]'),
2703 _('[-nibtB] [-r REV] [SOURCE]'),
2712 optionalrepo=True, cmdtype=readonly)
2704 optionalrepo=True, cmdtype=readonly)
2713 def identify(ui, repo, source=None, rev=None,
2705 def identify(ui, repo, source=None, rev=None,
2714 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
2706 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
2715 """identify the working directory or specified revision
2707 """identify the working directory or specified revision
2716
2708
2717 Print a summary identifying the repository state at REV using one or
2709 Print a summary identifying the repository state at REV using one or
2718 two parent hash identifiers, followed by a "+" if the working
2710 two parent hash identifiers, followed by a "+" if the working
2719 directory has uncommitted changes, the branch name (if not default),
2711 directory has uncommitted changes, the branch name (if not default),
2720 a list of tags, and a list of bookmarks.
2712 a list of tags, and a list of bookmarks.
2721
2713
2722 When REV is not given, print a summary of the current state of the
2714 When REV is not given, print a summary of the current state of the
2723 repository including the working directory. Specify -r. to get information
2715 repository including the working directory. Specify -r. to get information
2724 of the working directory parent without scanning uncommitted changes.
2716 of the working directory parent without scanning uncommitted changes.
2725
2717
2726 Specifying a path to a repository root or Mercurial bundle will
2718 Specifying a path to a repository root or Mercurial bundle will
2727 cause lookup to operate on that repository/bundle.
2719 cause lookup to operate on that repository/bundle.
2728
2720
2729 .. container:: verbose
2721 .. container:: verbose
2730
2722
2731 Examples:
2723 Examples:
2732
2724
2733 - generate a build identifier for the working directory::
2725 - generate a build identifier for the working directory::
2734
2726
2735 hg id --id > build-id.dat
2727 hg id --id > build-id.dat
2736
2728
2737 - find the revision corresponding to a tag::
2729 - find the revision corresponding to a tag::
2738
2730
2739 hg id -n -r 1.3
2731 hg id -n -r 1.3
2740
2732
2741 - check the most recent revision of a remote repository::
2733 - check the most recent revision of a remote repository::
2742
2734
2743 hg id -r tip https://www.mercurial-scm.org/repo/hg/
2735 hg id -r tip https://www.mercurial-scm.org/repo/hg/
2744
2736
2745 See :hg:`log` for generating more information about specific revisions,
2737 See :hg:`log` for generating more information about specific revisions,
2746 including full hash identifiers.
2738 including full hash identifiers.
2747
2739
2748 Returns 0 if successful.
2740 Returns 0 if successful.
2749 """
2741 """
2750
2742
2751 opts = pycompat.byteskwargs(opts)
2743 opts = pycompat.byteskwargs(opts)
2752 if not repo and not source:
2744 if not repo and not source:
2753 raise error.Abort(_("there is no Mercurial repository here "
2745 raise error.Abort(_("there is no Mercurial repository here "
2754 "(.hg not found)"))
2746 "(.hg not found)"))
2755
2747
2756 if ui.debugflag:
2748 if ui.debugflag:
2757 hexfunc = hex
2749 hexfunc = hex
2758 else:
2750 else:
2759 hexfunc = short
2751 hexfunc = short
2760 default = not (num or id or branch or tags or bookmarks)
2752 default = not (num or id or branch or tags or bookmarks)
2761 output = []
2753 output = []
2762 revs = []
2754 revs = []
2763
2755
2764 if source:
2756 if source:
2765 source, branches = hg.parseurl(ui.expandpath(source))
2757 source, branches = hg.parseurl(ui.expandpath(source))
2766 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
2758 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
2767 repo = peer.local()
2759 repo = peer.local()
2768 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
2760 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
2769
2761
2770 fm = ui.formatter('identify', opts)
2762 fm = ui.formatter('identify', opts)
2771 fm.startitem()
2763 fm.startitem()
2772
2764
2773 if not repo:
2765 if not repo:
2774 if num or branch or tags:
2766 if num or branch or tags:
2775 raise error.Abort(
2767 raise error.Abort(
2776 _("can't query remote revision number, branch, or tags"))
2768 _("can't query remote revision number, branch, or tags"))
2777 if not rev and revs:
2769 if not rev and revs:
2778 rev = revs[0]
2770 rev = revs[0]
2779 if not rev:
2771 if not rev:
2780 rev = "tip"
2772 rev = "tip"
2781
2773
2782 remoterev = peer.lookup(rev)
2774 remoterev = peer.lookup(rev)
2783 hexrev = hexfunc(remoterev)
2775 hexrev = hexfunc(remoterev)
2784 if default or id:
2776 if default or id:
2785 output = [hexrev]
2777 output = [hexrev]
2786 fm.data(id=hexrev)
2778 fm.data(id=hexrev)
2787
2779
2788 def getbms():
2780 def getbms():
2789 bms = []
2781 bms = []
2790
2782
2791 if 'bookmarks' in peer.listkeys('namespaces'):
2783 if 'bookmarks' in peer.listkeys('namespaces'):
2792 hexremoterev = hex(remoterev)
2784 hexremoterev = hex(remoterev)
2793 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
2785 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
2794 if bmr == hexremoterev]
2786 if bmr == hexremoterev]
2795
2787
2796 return sorted(bms)
2788 return sorted(bms)
2797
2789
2798 bms = getbms()
2790 bms = getbms()
2799 if bookmarks:
2791 if bookmarks:
2800 output.extend(bms)
2792 output.extend(bms)
2801 elif default and not ui.quiet:
2793 elif default and not ui.quiet:
2802 # multiple bookmarks for a single parent separated by '/'
2794 # multiple bookmarks for a single parent separated by '/'
2803 bm = '/'.join(bms)
2795 bm = '/'.join(bms)
2804 if bm:
2796 if bm:
2805 output.append(bm)
2797 output.append(bm)
2806
2798
2807 fm.data(node=hex(remoterev))
2799 fm.data(node=hex(remoterev))
2808 fm.data(bookmarks=fm.formatlist(bms, name='bookmark'))
2800 fm.data(bookmarks=fm.formatlist(bms, name='bookmark'))
2809 else:
2801 else:
2810 if rev:
2802 if rev:
2811 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
2803 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
2812 ctx = scmutil.revsingle(repo, rev, None)
2804 ctx = scmutil.revsingle(repo, rev, None)
2813
2805
2814 if ctx.rev() is None:
2806 if ctx.rev() is None:
2815 ctx = repo[None]
2807 ctx = repo[None]
2816 parents = ctx.parents()
2808 parents = ctx.parents()
2817 taglist = []
2809 taglist = []
2818 for p in parents:
2810 for p in parents:
2819 taglist.extend(p.tags())
2811 taglist.extend(p.tags())
2820
2812
2821 dirty = ""
2813 dirty = ""
2822 if ctx.dirty(missing=True, merge=False, branch=False):
2814 if ctx.dirty(missing=True, merge=False, branch=False):
2823 dirty = '+'
2815 dirty = '+'
2824 fm.data(dirty=dirty)
2816 fm.data(dirty=dirty)
2825
2817
2826 hexoutput = [hexfunc(p.node()) for p in parents]
2818 hexoutput = [hexfunc(p.node()) for p in parents]
2827 if default or id:
2819 if default or id:
2828 output = ["%s%s" % ('+'.join(hexoutput), dirty)]
2820 output = ["%s%s" % ('+'.join(hexoutput), dirty)]
2829 fm.data(id="%s%s" % ('+'.join(hexoutput), dirty))
2821 fm.data(id="%s%s" % ('+'.join(hexoutput), dirty))
2830
2822
2831 if num:
2823 if num:
2832 numoutput = ["%d" % p.rev() for p in parents]
2824 numoutput = ["%d" % p.rev() for p in parents]
2833 output.append("%s%s" % ('+'.join(numoutput), dirty))
2825 output.append("%s%s" % ('+'.join(numoutput), dirty))
2834
2826
2835 fn = fm.nested('parents')
2827 fn = fm.nested('parents')
2836 for p in parents:
2828 for p in parents:
2837 fn.startitem()
2829 fn.startitem()
2838 fn.data(rev=p.rev())
2830 fn.data(rev=p.rev())
2839 fn.data(node=p.hex())
2831 fn.data(node=p.hex())
2840 fn.context(ctx=p)
2832 fn.context(ctx=p)
2841 fn.end()
2833 fn.end()
2842 else:
2834 else:
2843 hexoutput = hexfunc(ctx.node())
2835 hexoutput = hexfunc(ctx.node())
2844 if default or id:
2836 if default or id:
2845 output = [hexoutput]
2837 output = [hexoutput]
2846 fm.data(id=hexoutput)
2838 fm.data(id=hexoutput)
2847
2839
2848 if num:
2840 if num:
2849 output.append(pycompat.bytestr(ctx.rev()))
2841 output.append(pycompat.bytestr(ctx.rev()))
2850 taglist = ctx.tags()
2842 taglist = ctx.tags()
2851
2843
2852 if default and not ui.quiet:
2844 if default and not ui.quiet:
2853 b = ctx.branch()
2845 b = ctx.branch()
2854 if b != 'default':
2846 if b != 'default':
2855 output.append("(%s)" % b)
2847 output.append("(%s)" % b)
2856
2848
2857 # multiple tags for a single parent separated by '/'
2849 # multiple tags for a single parent separated by '/'
2858 t = '/'.join(taglist)
2850 t = '/'.join(taglist)
2859 if t:
2851 if t:
2860 output.append(t)
2852 output.append(t)
2861
2853
2862 # multiple bookmarks for a single parent separated by '/'
2854 # multiple bookmarks for a single parent separated by '/'
2863 bm = '/'.join(ctx.bookmarks())
2855 bm = '/'.join(ctx.bookmarks())
2864 if bm:
2856 if bm:
2865 output.append(bm)
2857 output.append(bm)
2866 else:
2858 else:
2867 if branch:
2859 if branch:
2868 output.append(ctx.branch())
2860 output.append(ctx.branch())
2869
2861
2870 if tags:
2862 if tags:
2871 output.extend(taglist)
2863 output.extend(taglist)
2872
2864
2873 if bookmarks:
2865 if bookmarks:
2874 output.extend(ctx.bookmarks())
2866 output.extend(ctx.bookmarks())
2875
2867
2876 fm.data(node=ctx.hex())
2868 fm.data(node=ctx.hex())
2877 fm.data(branch=ctx.branch())
2869 fm.data(branch=ctx.branch())
2878 fm.data(tags=fm.formatlist(taglist, name='tag', sep=':'))
2870 fm.data(tags=fm.formatlist(taglist, name='tag', sep=':'))
2879 fm.data(bookmarks=fm.formatlist(ctx.bookmarks(), name='bookmark'))
2871 fm.data(bookmarks=fm.formatlist(ctx.bookmarks(), name='bookmark'))
2880 fm.context(ctx=ctx)
2872 fm.context(ctx=ctx)
2881
2873
2882 fm.plain("%s\n" % ' '.join(output))
2874 fm.plain("%s\n" % ' '.join(output))
2883 fm.end()
2875 fm.end()
2884
2876
2885 @command('import|patch',
2877 @command('import|patch',
2886 [('p', 'strip', 1,
2878 [('p', 'strip', 1,
2887 _('directory strip option for patch. This has the same '
2879 _('directory strip option for patch. This has the same '
2888 'meaning as the corresponding patch option'), _('NUM')),
2880 'meaning as the corresponding patch option'), _('NUM')),
2889 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
2881 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
2890 ('e', 'edit', False, _('invoke editor on commit messages')),
2882 ('e', 'edit', False, _('invoke editor on commit messages')),
2891 ('f', 'force', None,
2883 ('f', 'force', None,
2892 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
2884 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
2893 ('', 'no-commit', None,
2885 ('', 'no-commit', None,
2894 _("don't commit, just update the working directory")),
2886 _("don't commit, just update the working directory")),
2895 ('', 'bypass', None,
2887 ('', 'bypass', None,
2896 _("apply patch without touching the working directory")),
2888 _("apply patch without touching the working directory")),
2897 ('', 'partial', None,
2889 ('', 'partial', None,
2898 _('commit even if some hunks fail')),
2890 _('commit even if some hunks fail')),
2899 ('', 'exact', None,
2891 ('', 'exact', None,
2900 _('abort if patch would apply lossily')),
2892 _('abort if patch would apply lossily')),
2901 ('', 'prefix', '',
2893 ('', 'prefix', '',
2902 _('apply patch to subdirectory'), _('DIR')),
2894 _('apply patch to subdirectory'), _('DIR')),
2903 ('', 'import-branch', None,
2895 ('', 'import-branch', None,
2904 _('use any branch information in patch (implied by --exact)'))] +
2896 _('use any branch information in patch (implied by --exact)'))] +
2905 commitopts + commitopts2 + similarityopts,
2897 commitopts + commitopts2 + similarityopts,
2906 _('[OPTION]... PATCH...'))
2898 _('[OPTION]... PATCH...'))
2907 def import_(ui, repo, patch1=None, *patches, **opts):
2899 def import_(ui, repo, patch1=None, *patches, **opts):
2908 """import an ordered set of patches
2900 """import an ordered set of patches
2909
2901
2910 Import a list of patches and commit them individually (unless
2902 Import a list of patches and commit them individually (unless
2911 --no-commit is specified).
2903 --no-commit is specified).
2912
2904
2913 To read a patch from standard input (stdin), use "-" as the patch
2905 To read a patch from standard input (stdin), use "-" as the patch
2914 name. If a URL is specified, the patch will be downloaded from
2906 name. If a URL is specified, the patch will be downloaded from
2915 there.
2907 there.
2916
2908
2917 Import first applies changes to the working directory (unless
2909 Import first applies changes to the working directory (unless
2918 --bypass is specified), import will abort if there are outstanding
2910 --bypass is specified), import will abort if there are outstanding
2919 changes.
2911 changes.
2920
2912
2921 Use --bypass to apply and commit patches directly to the
2913 Use --bypass to apply and commit patches directly to the
2922 repository, without affecting the working directory. Without
2914 repository, without affecting the working directory. Without
2923 --exact, patches will be applied on top of the working directory
2915 --exact, patches will be applied on top of the working directory
2924 parent revision.
2916 parent revision.
2925
2917
2926 You can import a patch straight from a mail message. Even patches
2918 You can import a patch straight from a mail message. Even patches
2927 as attachments work (to use the body part, it must have type
2919 as attachments work (to use the body part, it must have type
2928 text/plain or text/x-patch). From and Subject headers of email
2920 text/plain or text/x-patch). From and Subject headers of email
2929 message are used as default committer and commit message. All
2921 message are used as default committer and commit message. All
2930 text/plain body parts before first diff are added to the commit
2922 text/plain body parts before first diff are added to the commit
2931 message.
2923 message.
2932
2924
2933 If the imported patch was generated by :hg:`export`, user and
2925 If the imported patch was generated by :hg:`export`, user and
2934 description from patch override values from message headers and
2926 description from patch override values from message headers and
2935 body. Values given on command line with -m/--message and -u/--user
2927 body. Values given on command line with -m/--message and -u/--user
2936 override these.
2928 override these.
2937
2929
2938 If --exact is specified, import will set the working directory to
2930 If --exact is specified, import will set the working directory to
2939 the parent of each patch before applying it, and will abort if the
2931 the parent of each patch before applying it, and will abort if the
2940 resulting changeset has a different ID than the one recorded in
2932 resulting changeset has a different ID than the one recorded in
2941 the patch. This will guard against various ways that portable
2933 the patch. This will guard against various ways that portable
2942 patch formats and mail systems might fail to transfer Mercurial
2934 patch formats and mail systems might fail to transfer Mercurial
2943 data or metadata. See :hg:`bundle` for lossless transmission.
2935 data or metadata. See :hg:`bundle` for lossless transmission.
2944
2936
2945 Use --partial to ensure a changeset will be created from the patch
2937 Use --partial to ensure a changeset will be created from the patch
2946 even if some hunks fail to apply. Hunks that fail to apply will be
2938 even if some hunks fail to apply. Hunks that fail to apply will be
2947 written to a <target-file>.rej file. Conflicts can then be resolved
2939 written to a <target-file>.rej file. Conflicts can then be resolved
2948 by hand before :hg:`commit --amend` is run to update the created
2940 by hand before :hg:`commit --amend` is run to update the created
2949 changeset. This flag exists to let people import patches that
2941 changeset. This flag exists to let people import patches that
2950 partially apply without losing the associated metadata (author,
2942 partially apply without losing the associated metadata (author,
2951 date, description, ...).
2943 date, description, ...).
2952
2944
2953 .. note::
2945 .. note::
2954
2946
2955 When no hunks apply cleanly, :hg:`import --partial` will create
2947 When no hunks apply cleanly, :hg:`import --partial` will create
2956 an empty changeset, importing only the patch metadata.
2948 an empty changeset, importing only the patch metadata.
2957
2949
2958 With -s/--similarity, hg will attempt to discover renames and
2950 With -s/--similarity, hg will attempt to discover renames and
2959 copies in the patch in the same way as :hg:`addremove`.
2951 copies in the patch in the same way as :hg:`addremove`.
2960
2952
2961 It is possible to use external patch programs to perform the patch
2953 It is possible to use external patch programs to perform the patch
2962 by setting the ``ui.patch`` configuration option. For the default
2954 by setting the ``ui.patch`` configuration option. For the default
2963 internal tool, the fuzz can also be configured via ``patch.fuzz``.
2955 internal tool, the fuzz can also be configured via ``patch.fuzz``.
2964 See :hg:`help config` for more information about configuration
2956 See :hg:`help config` for more information about configuration
2965 files and how to use these options.
2957 files and how to use these options.
2966
2958
2967 See :hg:`help dates` for a list of formats valid for -d/--date.
2959 See :hg:`help dates` for a list of formats valid for -d/--date.
2968
2960
2969 .. container:: verbose
2961 .. container:: verbose
2970
2962
2971 Examples:
2963 Examples:
2972
2964
2973 - import a traditional patch from a website and detect renames::
2965 - import a traditional patch from a website and detect renames::
2974
2966
2975 hg import -s 80 http://example.com/bugfix.patch
2967 hg import -s 80 http://example.com/bugfix.patch
2976
2968
2977 - import a changeset from an hgweb server::
2969 - import a changeset from an hgweb server::
2978
2970
2979 hg import https://www.mercurial-scm.org/repo/hg/rev/5ca8c111e9aa
2971 hg import https://www.mercurial-scm.org/repo/hg/rev/5ca8c111e9aa
2980
2972
2981 - import all the patches in an Unix-style mbox::
2973 - import all the patches in an Unix-style mbox::
2982
2974
2983 hg import incoming-patches.mbox
2975 hg import incoming-patches.mbox
2984
2976
2985 - import patches from stdin::
2977 - import patches from stdin::
2986
2978
2987 hg import -
2979 hg import -
2988
2980
2989 - attempt to exactly restore an exported changeset (not always
2981 - attempt to exactly restore an exported changeset (not always
2990 possible)::
2982 possible)::
2991
2983
2992 hg import --exact proposed-fix.patch
2984 hg import --exact proposed-fix.patch
2993
2985
2994 - use an external tool to apply a patch which is too fuzzy for
2986 - use an external tool to apply a patch which is too fuzzy for
2995 the default internal tool.
2987 the default internal tool.
2996
2988
2997 hg import --config ui.patch="patch --merge" fuzzy.patch
2989 hg import --config ui.patch="patch --merge" fuzzy.patch
2998
2990
2999 - change the default fuzzing from 2 to a less strict 7
2991 - change the default fuzzing from 2 to a less strict 7
3000
2992
3001 hg import --config ui.fuzz=7 fuzz.patch
2993 hg import --config ui.fuzz=7 fuzz.patch
3002
2994
3003 Returns 0 on success, 1 on partial success (see --partial).
2995 Returns 0 on success, 1 on partial success (see --partial).
3004 """
2996 """
3005
2997
3006 opts = pycompat.byteskwargs(opts)
2998 opts = pycompat.byteskwargs(opts)
3007 if not patch1:
2999 if not patch1:
3008 raise error.Abort(_('need at least one patch to import'))
3000 raise error.Abort(_('need at least one patch to import'))
3009
3001
3010 patches = (patch1,) + patches
3002 patches = (patch1,) + patches
3011
3003
3012 date = opts.get('date')
3004 date = opts.get('date')
3013 if date:
3005 if date:
3014 opts['date'] = util.parsedate(date)
3006 opts['date'] = util.parsedate(date)
3015
3007
3016 exact = opts.get('exact')
3008 exact = opts.get('exact')
3017 update = not opts.get('bypass')
3009 update = not opts.get('bypass')
3018 if not update and opts.get('no_commit'):
3010 if not update and opts.get('no_commit'):
3019 raise error.Abort(_('cannot use --no-commit with --bypass'))
3011 raise error.Abort(_('cannot use --no-commit with --bypass'))
3020 try:
3012 try:
3021 sim = float(opts.get('similarity') or 0)
3013 sim = float(opts.get('similarity') or 0)
3022 except ValueError:
3014 except ValueError:
3023 raise error.Abort(_('similarity must be a number'))
3015 raise error.Abort(_('similarity must be a number'))
3024 if sim < 0 or sim > 100:
3016 if sim < 0 or sim > 100:
3025 raise error.Abort(_('similarity must be between 0 and 100'))
3017 raise error.Abort(_('similarity must be between 0 and 100'))
3026 if sim and not update:
3018 if sim and not update:
3027 raise error.Abort(_('cannot use --similarity with --bypass'))
3019 raise error.Abort(_('cannot use --similarity with --bypass'))
3028 if exact:
3020 if exact:
3029 if opts.get('edit'):
3021 if opts.get('edit'):
3030 raise error.Abort(_('cannot use --exact with --edit'))
3022 raise error.Abort(_('cannot use --exact with --edit'))
3031 if opts.get('prefix'):
3023 if opts.get('prefix'):
3032 raise error.Abort(_('cannot use --exact with --prefix'))
3024 raise error.Abort(_('cannot use --exact with --prefix'))
3033
3025
3034 base = opts["base"]
3026 base = opts["base"]
3035 wlock = dsguard = lock = tr = None
3027 wlock = dsguard = lock = tr = None
3036 msgs = []
3028 msgs = []
3037 ret = 0
3029 ret = 0
3038
3030
3039
3031
3040 try:
3032 try:
3041 wlock = repo.wlock()
3033 wlock = repo.wlock()
3042
3034
3043 if update:
3035 if update:
3044 cmdutil.checkunfinished(repo)
3036 cmdutil.checkunfinished(repo)
3045 if (exact or not opts.get('force')):
3037 if (exact or not opts.get('force')):
3046 cmdutil.bailifchanged(repo)
3038 cmdutil.bailifchanged(repo)
3047
3039
3048 if not opts.get('no_commit'):
3040 if not opts.get('no_commit'):
3049 lock = repo.lock()
3041 lock = repo.lock()
3050 tr = repo.transaction('import')
3042 tr = repo.transaction('import')
3051 else:
3043 else:
3052 dsguard = dirstateguard.dirstateguard(repo, 'import')
3044 dsguard = dirstateguard.dirstateguard(repo, 'import')
3053 parents = repo[None].parents()
3045 parents = repo[None].parents()
3054 for patchurl in patches:
3046 for patchurl in patches:
3055 if patchurl == '-':
3047 if patchurl == '-':
3056 ui.status(_('applying patch from stdin\n'))
3048 ui.status(_('applying patch from stdin\n'))
3057 patchfile = ui.fin
3049 patchfile = ui.fin
3058 patchurl = 'stdin' # for error message
3050 patchurl = 'stdin' # for error message
3059 else:
3051 else:
3060 patchurl = os.path.join(base, patchurl)
3052 patchurl = os.path.join(base, patchurl)
3061 ui.status(_('applying %s\n') % patchurl)
3053 ui.status(_('applying %s\n') % patchurl)
3062 patchfile = hg.openpath(ui, patchurl)
3054 patchfile = hg.openpath(ui, patchurl)
3063
3055
3064 haspatch = False
3056 haspatch = False
3065 for hunk in patch.split(patchfile):
3057 for hunk in patch.split(patchfile):
3066 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
3058 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
3067 parents, opts,
3059 parents, opts,
3068 msgs, hg.clean)
3060 msgs, hg.clean)
3069 if msg:
3061 if msg:
3070 haspatch = True
3062 haspatch = True
3071 ui.note(msg + '\n')
3063 ui.note(msg + '\n')
3072 if update or exact:
3064 if update or exact:
3073 parents = repo[None].parents()
3065 parents = repo[None].parents()
3074 else:
3066 else:
3075 parents = [repo[node]]
3067 parents = [repo[node]]
3076 if rej:
3068 if rej:
3077 ui.write_err(_("patch applied partially\n"))
3069 ui.write_err(_("patch applied partially\n"))
3078 ui.write_err(_("(fix the .rej files and run "
3070 ui.write_err(_("(fix the .rej files and run "
3079 "`hg commit --amend`)\n"))
3071 "`hg commit --amend`)\n"))
3080 ret = 1
3072 ret = 1
3081 break
3073 break
3082
3074
3083 if not haspatch:
3075 if not haspatch:
3084 raise error.Abort(_('%s: no diffs found') % patchurl)
3076 raise error.Abort(_('%s: no diffs found') % patchurl)
3085
3077
3086 if tr:
3078 if tr:
3087 tr.close()
3079 tr.close()
3088 if msgs:
3080 if msgs:
3089 repo.savecommitmessage('\n* * *\n'.join(msgs))
3081 repo.savecommitmessage('\n* * *\n'.join(msgs))
3090 if dsguard:
3082 if dsguard:
3091 dsguard.close()
3083 dsguard.close()
3092 return ret
3084 return ret
3093 finally:
3085 finally:
3094 if tr:
3086 if tr:
3095 tr.release()
3087 tr.release()
3096 release(lock, dsguard, wlock)
3088 release(lock, dsguard, wlock)
3097
3089
3098 @command('incoming|in',
3090 @command('incoming|in',
3099 [('f', 'force', None,
3091 [('f', 'force', None,
3100 _('run even if remote repository is unrelated')),
3092 _('run even if remote repository is unrelated')),
3101 ('n', 'newest-first', None, _('show newest record first')),
3093 ('n', 'newest-first', None, _('show newest record first')),
3102 ('', 'bundle', '',
3094 ('', 'bundle', '',
3103 _('file to store the bundles into'), _('FILE')),
3095 _('file to store the bundles into'), _('FILE')),
3104 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3096 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3105 ('B', 'bookmarks', False, _("compare bookmarks")),
3097 ('B', 'bookmarks', False, _("compare bookmarks")),
3106 ('b', 'branch', [],
3098 ('b', 'branch', [],
3107 _('a specific branch you would like to pull'), _('BRANCH')),
3099 _('a specific branch you would like to pull'), _('BRANCH')),
3108 ] + logopts + remoteopts + subrepoopts,
3100 ] + logopts + remoteopts + subrepoopts,
3109 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3101 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3110 def incoming(ui, repo, source="default", **opts):
3102 def incoming(ui, repo, source="default", **opts):
3111 """show new changesets found in source
3103 """show new changesets found in source
3112
3104
3113 Show new changesets found in the specified path/URL or the default
3105 Show new changesets found in the specified path/URL or the default
3114 pull location. These are the changesets that would have been pulled
3106 pull location. These are the changesets that would have been pulled
3115 by :hg:`pull` at the time you issued this command.
3107 by :hg:`pull` at the time you issued this command.
3116
3108
3117 See pull for valid source format details.
3109 See pull for valid source format details.
3118
3110
3119 .. container:: verbose
3111 .. container:: verbose
3120
3112
3121 With -B/--bookmarks, the result of bookmark comparison between
3113 With -B/--bookmarks, the result of bookmark comparison between
3122 local and remote repositories is displayed. With -v/--verbose,
3114 local and remote repositories is displayed. With -v/--verbose,
3123 status is also displayed for each bookmark like below::
3115 status is also displayed for each bookmark like below::
3124
3116
3125 BM1 01234567890a added
3117 BM1 01234567890a added
3126 BM2 1234567890ab advanced
3118 BM2 1234567890ab advanced
3127 BM3 234567890abc diverged
3119 BM3 234567890abc diverged
3128 BM4 34567890abcd changed
3120 BM4 34567890abcd changed
3129
3121
3130 The action taken locally when pulling depends on the
3122 The action taken locally when pulling depends on the
3131 status of each bookmark:
3123 status of each bookmark:
3132
3124
3133 :``added``: pull will create it
3125 :``added``: pull will create it
3134 :``advanced``: pull will update it
3126 :``advanced``: pull will update it
3135 :``diverged``: pull will create a divergent bookmark
3127 :``diverged``: pull will create a divergent bookmark
3136 :``changed``: result depends on remote changesets
3128 :``changed``: result depends on remote changesets
3137
3129
3138 From the point of view of pulling behavior, bookmark
3130 From the point of view of pulling behavior, bookmark
3139 existing only in the remote repository are treated as ``added``,
3131 existing only in the remote repository are treated as ``added``,
3140 even if it is in fact locally deleted.
3132 even if it is in fact locally deleted.
3141
3133
3142 .. container:: verbose
3134 .. container:: verbose
3143
3135
3144 For remote repository, using --bundle avoids downloading the
3136 For remote repository, using --bundle avoids downloading the
3145 changesets twice if the incoming is followed by a pull.
3137 changesets twice if the incoming is followed by a pull.
3146
3138
3147 Examples:
3139 Examples:
3148
3140
3149 - show incoming changes with patches and full description::
3141 - show incoming changes with patches and full description::
3150
3142
3151 hg incoming -vp
3143 hg incoming -vp
3152
3144
3153 - show incoming changes excluding merges, store a bundle::
3145 - show incoming changes excluding merges, store a bundle::
3154
3146
3155 hg in -vpM --bundle incoming.hg
3147 hg in -vpM --bundle incoming.hg
3156 hg pull incoming.hg
3148 hg pull incoming.hg
3157
3149
3158 - briefly list changes inside a bundle::
3150 - briefly list changes inside a bundle::
3159
3151
3160 hg in changes.hg -T "{desc|firstline}\\n"
3152 hg in changes.hg -T "{desc|firstline}\\n"
3161
3153
3162 Returns 0 if there are incoming changes, 1 otherwise.
3154 Returns 0 if there are incoming changes, 1 otherwise.
3163 """
3155 """
3164 opts = pycompat.byteskwargs(opts)
3156 opts = pycompat.byteskwargs(opts)
3165 if opts.get('graph'):
3157 if opts.get('graph'):
3166 logcmdutil.checkunsupportedgraphflags([], opts)
3158 logcmdutil.checkunsupportedgraphflags([], opts)
3167 def display(other, chlist, displayer):
3159 def display(other, chlist, displayer):
3168 revdag = logcmdutil.graphrevs(other, chlist, opts)
3160 revdag = logcmdutil.graphrevs(other, chlist, opts)
3169 logcmdutil.displaygraph(ui, repo, revdag, displayer,
3161 logcmdutil.displaygraph(ui, repo, revdag, displayer,
3170 graphmod.asciiedges)
3162 graphmod.asciiedges)
3171
3163
3172 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3164 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3173 return 0
3165 return 0
3174
3166
3175 if opts.get('bundle') and opts.get('subrepos'):
3167 if opts.get('bundle') and opts.get('subrepos'):
3176 raise error.Abort(_('cannot combine --bundle and --subrepos'))
3168 raise error.Abort(_('cannot combine --bundle and --subrepos'))
3177
3169
3178 if opts.get('bookmarks'):
3170 if opts.get('bookmarks'):
3179 source, branches = hg.parseurl(ui.expandpath(source),
3171 source, branches = hg.parseurl(ui.expandpath(source),
3180 opts.get('branch'))
3172 opts.get('branch'))
3181 other = hg.peer(repo, opts, source)
3173 other = hg.peer(repo, opts, source)
3182 if 'bookmarks' not in other.listkeys('namespaces'):
3174 if 'bookmarks' not in other.listkeys('namespaces'):
3183 ui.warn(_("remote doesn't support bookmarks\n"))
3175 ui.warn(_("remote doesn't support bookmarks\n"))
3184 return 0
3176 return 0
3185 ui.pager('incoming')
3177 ui.pager('incoming')
3186 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3178 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3187 return bookmarks.incoming(ui, repo, other)
3179 return bookmarks.incoming(ui, repo, other)
3188
3180
3189 repo._subtoppath = ui.expandpath(source)
3181 repo._subtoppath = ui.expandpath(source)
3190 try:
3182 try:
3191 return hg.incoming(ui, repo, source, opts)
3183 return hg.incoming(ui, repo, source, opts)
3192 finally:
3184 finally:
3193 del repo._subtoppath
3185 del repo._subtoppath
3194
3186
3195
3187
3196 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
3188 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
3197 norepo=True)
3189 norepo=True)
3198 def init(ui, dest=".", **opts):
3190 def init(ui, dest=".", **opts):
3199 """create a new repository in the given directory
3191 """create a new repository in the given directory
3200
3192
3201 Initialize a new repository in the given directory. If the given
3193 Initialize a new repository in the given directory. If the given
3202 directory does not exist, it will be created.
3194 directory does not exist, it will be created.
3203
3195
3204 If no directory is given, the current directory is used.
3196 If no directory is given, the current directory is used.
3205
3197
3206 It is possible to specify an ``ssh://`` URL as the destination.
3198 It is possible to specify an ``ssh://`` URL as the destination.
3207 See :hg:`help urls` for more information.
3199 See :hg:`help urls` for more information.
3208
3200
3209 Returns 0 on success.
3201 Returns 0 on success.
3210 """
3202 """
3211 opts = pycompat.byteskwargs(opts)
3203 opts = pycompat.byteskwargs(opts)
3212 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3204 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3213
3205
3214 @command('locate',
3206 @command('locate',
3215 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3207 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3216 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3208 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3217 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3209 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3218 ] + walkopts,
3210 ] + walkopts,
3219 _('[OPTION]... [PATTERN]...'))
3211 _('[OPTION]... [PATTERN]...'))
3220 def locate(ui, repo, *pats, **opts):
3212 def locate(ui, repo, *pats, **opts):
3221 """locate files matching specific patterns (DEPRECATED)
3213 """locate files matching specific patterns (DEPRECATED)
3222
3214
3223 Print files under Mercurial control in the working directory whose
3215 Print files under Mercurial control in the working directory whose
3224 names match the given patterns.
3216 names match the given patterns.
3225
3217
3226 By default, this command searches all directories in the working
3218 By default, this command searches all directories in the working
3227 directory. To search just the current directory and its
3219 directory. To search just the current directory and its
3228 subdirectories, use "--include .".
3220 subdirectories, use "--include .".
3229
3221
3230 If no patterns are given to match, this command prints the names
3222 If no patterns are given to match, this command prints the names
3231 of all files under Mercurial control in the working directory.
3223 of all files under Mercurial control in the working directory.
3232
3224
3233 If you want to feed the output of this command into the "xargs"
3225 If you want to feed the output of this command into the "xargs"
3234 command, use the -0 option to both this command and "xargs". This
3226 command, use the -0 option to both this command and "xargs". This
3235 will avoid the problem of "xargs" treating single filenames that
3227 will avoid the problem of "xargs" treating single filenames that
3236 contain whitespace as multiple filenames.
3228 contain whitespace as multiple filenames.
3237
3229
3238 See :hg:`help files` for a more versatile command.
3230 See :hg:`help files` for a more versatile command.
3239
3231
3240 Returns 0 if a match is found, 1 otherwise.
3232 Returns 0 if a match is found, 1 otherwise.
3241 """
3233 """
3242 opts = pycompat.byteskwargs(opts)
3234 opts = pycompat.byteskwargs(opts)
3243 if opts.get('print0'):
3235 if opts.get('print0'):
3244 end = '\0'
3236 end = '\0'
3245 else:
3237 else:
3246 end = '\n'
3238 end = '\n'
3247 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3239 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3248
3240
3249 ret = 1
3241 ret = 1
3250 ctx = repo[rev]
3242 ctx = repo[rev]
3251 m = scmutil.match(ctx, pats, opts, default='relglob',
3243 m = scmutil.match(ctx, pats, opts, default='relglob',
3252 badfn=lambda x, y: False)
3244 badfn=lambda x, y: False)
3253
3245
3254 ui.pager('locate')
3246 ui.pager('locate')
3255 for abs in ctx.matches(m):
3247 for abs in ctx.matches(m):
3256 if opts.get('fullpath'):
3248 if opts.get('fullpath'):
3257 ui.write(repo.wjoin(abs), end)
3249 ui.write(repo.wjoin(abs), end)
3258 else:
3250 else:
3259 ui.write(((pats and m.rel(abs)) or abs), end)
3251 ui.write(((pats and m.rel(abs)) or abs), end)
3260 ret = 0
3252 ret = 0
3261
3253
3262 return ret
3254 return ret
3263
3255
3264 @command('^log|history',
3256 @command('^log|history',
3265 [('f', 'follow', None,
3257 [('f', 'follow', None,
3266 _('follow changeset history, or file history across copies and renames')),
3258 _('follow changeset history, or file history across copies and renames')),
3267 ('', 'follow-first', None,
3259 ('', 'follow-first', None,
3268 _('only follow the first parent of merge changesets (DEPRECATED)')),
3260 _('only follow the first parent of merge changesets (DEPRECATED)')),
3269 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3261 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3270 ('C', 'copies', None, _('show copied files')),
3262 ('C', 'copies', None, _('show copied files')),
3271 ('k', 'keyword', [],
3263 ('k', 'keyword', [],
3272 _('do case-insensitive search for a given text'), _('TEXT')),
3264 _('do case-insensitive search for a given text'), _('TEXT')),
3273 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
3265 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
3274 ('L', 'line-range', [],
3266 ('L', 'line-range', [],
3275 _('follow line range of specified file (EXPERIMENTAL)'),
3267 _('follow line range of specified file (EXPERIMENTAL)'),
3276 _('FILE,RANGE')),
3268 _('FILE,RANGE')),
3277 ('', 'removed', None, _('include revisions where files were removed')),
3269 ('', 'removed', None, _('include revisions where files were removed')),
3278 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3270 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3279 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3271 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3280 ('', 'only-branch', [],
3272 ('', 'only-branch', [],
3281 _('show only changesets within the given named branch (DEPRECATED)'),
3273 _('show only changesets within the given named branch (DEPRECATED)'),
3282 _('BRANCH')),
3274 _('BRANCH')),
3283 ('b', 'branch', [],
3275 ('b', 'branch', [],
3284 _('show changesets within the given named branch'), _('BRANCH')),
3276 _('show changesets within the given named branch'), _('BRANCH')),
3285 ('P', 'prune', [],
3277 ('P', 'prune', [],
3286 _('do not display revision or any of its ancestors'), _('REV')),
3278 _('do not display revision or any of its ancestors'), _('REV')),
3287 ] + logopts + walkopts,
3279 ] + logopts + walkopts,
3288 _('[OPTION]... [FILE]'),
3280 _('[OPTION]... [FILE]'),
3289 inferrepo=True, cmdtype=readonly)
3281 inferrepo=True, cmdtype=readonly)
3290 def log(ui, repo, *pats, **opts):
3282 def log(ui, repo, *pats, **opts):
3291 """show revision history of entire repository or files
3283 """show revision history of entire repository or files
3292
3284
3293 Print the revision history of the specified files or the entire
3285 Print the revision history of the specified files or the entire
3294 project.
3286 project.
3295
3287
3296 If no revision range is specified, the default is ``tip:0`` unless
3288 If no revision range is specified, the default is ``tip:0`` unless
3297 --follow is set, in which case the working directory parent is
3289 --follow is set, in which case the working directory parent is
3298 used as the starting revision.
3290 used as the starting revision.
3299
3291
3300 File history is shown without following rename or copy history of
3292 File history is shown without following rename or copy history of
3301 files. Use -f/--follow with a filename to follow history across
3293 files. Use -f/--follow with a filename to follow history across
3302 renames and copies. --follow without a filename will only show
3294 renames and copies. --follow without a filename will only show
3303 ancestors of the starting revision.
3295 ancestors of the starting revision.
3304
3296
3305 By default this command prints revision number and changeset id,
3297 By default this command prints revision number and changeset id,
3306 tags, non-trivial parents, user, date and time, and a summary for
3298 tags, non-trivial parents, user, date and time, and a summary for
3307 each commit. When the -v/--verbose switch is used, the list of
3299 each commit. When the -v/--verbose switch is used, the list of
3308 changed files and full commit message are shown.
3300 changed files and full commit message are shown.
3309
3301
3310 With --graph the revisions are shown as an ASCII art DAG with the most
3302 With --graph the revisions are shown as an ASCII art DAG with the most
3311 recent changeset at the top.
3303 recent changeset at the top.
3312 'o' is a changeset, '@' is a working directory parent, '_' closes a branch,
3304 'o' is a changeset, '@' is a working directory parent, '_' closes a branch,
3313 'x' is obsolete, '*' is unstable, and '+' represents a fork where the
3305 'x' is obsolete, '*' is unstable, and '+' represents a fork where the
3314 changeset from the lines below is a parent of the 'o' merge on the same
3306 changeset from the lines below is a parent of the 'o' merge on the same
3315 line.
3307 line.
3316 Paths in the DAG are represented with '|', '/' and so forth. ':' in place
3308 Paths in the DAG are represented with '|', '/' and so forth. ':' in place
3317 of a '|' indicates one or more revisions in a path are omitted.
3309 of a '|' indicates one or more revisions in a path are omitted.
3318
3310
3319 .. container:: verbose
3311 .. container:: verbose
3320
3312
3321 Use -L/--line-range FILE,M:N options to follow the history of lines
3313 Use -L/--line-range FILE,M:N options to follow the history of lines
3322 from M to N in FILE. With -p/--patch only diff hunks affecting
3314 from M to N in FILE. With -p/--patch only diff hunks affecting
3323 specified line range will be shown. This option requires --follow;
3315 specified line range will be shown. This option requires --follow;
3324 it can be specified multiple times. Currently, this option is not
3316 it can be specified multiple times. Currently, this option is not
3325 compatible with --graph. This option is experimental.
3317 compatible with --graph. This option is experimental.
3326
3318
3327 .. note::
3319 .. note::
3328
3320
3329 :hg:`log --patch` may generate unexpected diff output for merge
3321 :hg:`log --patch` may generate unexpected diff output for merge
3330 changesets, as it will only compare the merge changeset against
3322 changesets, as it will only compare the merge changeset against
3331 its first parent. Also, only files different from BOTH parents
3323 its first parent. Also, only files different from BOTH parents
3332 will appear in files:.
3324 will appear in files:.
3333
3325
3334 .. note::
3326 .. note::
3335
3327
3336 For performance reasons, :hg:`log FILE` may omit duplicate changes
3328 For performance reasons, :hg:`log FILE` may omit duplicate changes
3337 made on branches and will not show removals or mode changes. To
3329 made on branches and will not show removals or mode changes. To
3338 see all such changes, use the --removed switch.
3330 see all such changes, use the --removed switch.
3339
3331
3340 .. container:: verbose
3332 .. container:: verbose
3341
3333
3342 .. note::
3334 .. note::
3343
3335
3344 The history resulting from -L/--line-range options depends on diff
3336 The history resulting from -L/--line-range options depends on diff
3345 options; for instance if white-spaces are ignored, respective changes
3337 options; for instance if white-spaces are ignored, respective changes
3346 with only white-spaces in specified line range will not be listed.
3338 with only white-spaces in specified line range will not be listed.
3347
3339
3348 .. container:: verbose
3340 .. container:: verbose
3349
3341
3350 Some examples:
3342 Some examples:
3351
3343
3352 - changesets with full descriptions and file lists::
3344 - changesets with full descriptions and file lists::
3353
3345
3354 hg log -v
3346 hg log -v
3355
3347
3356 - changesets ancestral to the working directory::
3348 - changesets ancestral to the working directory::
3357
3349
3358 hg log -f
3350 hg log -f
3359
3351
3360 - last 10 commits on the current branch::
3352 - last 10 commits on the current branch::
3361
3353
3362 hg log -l 10 -b .
3354 hg log -l 10 -b .
3363
3355
3364 - changesets showing all modifications of a file, including removals::
3356 - changesets showing all modifications of a file, including removals::
3365
3357
3366 hg log --removed file.c
3358 hg log --removed file.c
3367
3359
3368 - all changesets that touch a directory, with diffs, excluding merges::
3360 - all changesets that touch a directory, with diffs, excluding merges::
3369
3361
3370 hg log -Mp lib/
3362 hg log -Mp lib/
3371
3363
3372 - all revision numbers that match a keyword::
3364 - all revision numbers that match a keyword::
3373
3365
3374 hg log -k bug --template "{rev}\\n"
3366 hg log -k bug --template "{rev}\\n"
3375
3367
3376 - the full hash identifier of the working directory parent::
3368 - the full hash identifier of the working directory parent::
3377
3369
3378 hg log -r . --template "{node}\\n"
3370 hg log -r . --template "{node}\\n"
3379
3371
3380 - list available log templates::
3372 - list available log templates::
3381
3373
3382 hg log -T list
3374 hg log -T list
3383
3375
3384 - check if a given changeset is included in a tagged release::
3376 - check if a given changeset is included in a tagged release::
3385
3377
3386 hg log -r "a21ccf and ancestor(1.9)"
3378 hg log -r "a21ccf and ancestor(1.9)"
3387
3379
3388 - find all changesets by some user in a date range::
3380 - find all changesets by some user in a date range::
3389
3381
3390 hg log -k alice -d "may 2008 to jul 2008"
3382 hg log -k alice -d "may 2008 to jul 2008"
3391
3383
3392 - summary of all changesets after the last tag::
3384 - summary of all changesets after the last tag::
3393
3385
3394 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3386 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3395
3387
3396 - changesets touching lines 13 to 23 for file.c::
3388 - changesets touching lines 13 to 23 for file.c::
3397
3389
3398 hg log -L file.c,13:23
3390 hg log -L file.c,13:23
3399
3391
3400 - changesets touching lines 13 to 23 for file.c and lines 2 to 6 of
3392 - changesets touching lines 13 to 23 for file.c and lines 2 to 6 of
3401 main.c with patch::
3393 main.c with patch::
3402
3394
3403 hg log -L file.c,13:23 -L main.c,2:6 -p
3395 hg log -L file.c,13:23 -L main.c,2:6 -p
3404
3396
3405 See :hg:`help dates` for a list of formats valid for -d/--date.
3397 See :hg:`help dates` for a list of formats valid for -d/--date.
3406
3398
3407 See :hg:`help revisions` for more about specifying and ordering
3399 See :hg:`help revisions` for more about specifying and ordering
3408 revisions.
3400 revisions.
3409
3401
3410 See :hg:`help templates` for more about pre-packaged styles and
3402 See :hg:`help templates` for more about pre-packaged styles and
3411 specifying custom templates. The default template used by the log
3403 specifying custom templates. The default template used by the log
3412 command can be customized via the ``ui.logtemplate`` configuration
3404 command can be customized via the ``ui.logtemplate`` configuration
3413 setting.
3405 setting.
3414
3406
3415 Returns 0 on success.
3407 Returns 0 on success.
3416
3408
3417 """
3409 """
3418 opts = pycompat.byteskwargs(opts)
3410 opts = pycompat.byteskwargs(opts)
3419 linerange = opts.get('line_range')
3411 linerange = opts.get('line_range')
3420
3412
3421 if linerange and not opts.get('follow'):
3413 if linerange and not opts.get('follow'):
3422 raise error.Abort(_('--line-range requires --follow'))
3414 raise error.Abort(_('--line-range requires --follow'))
3423
3415
3424 if linerange and pats:
3416 if linerange and pats:
3425 # TODO: take pats as patterns with no line-range filter
3417 # TODO: take pats as patterns with no line-range filter
3426 raise error.Abort(
3418 raise error.Abort(
3427 _('FILE arguments are not compatible with --line-range option')
3419 _('FILE arguments are not compatible with --line-range option')
3428 )
3420 )
3429
3421
3430 repo = scmutil.unhidehashlikerevs(repo, opts.get('rev'), 'nowarn')
3422 repo = scmutil.unhidehashlikerevs(repo, opts.get('rev'), 'nowarn')
3431 revs, differ = logcmdutil.getrevs(repo, pats, opts)
3423 revs, differ = logcmdutil.getrevs(repo, pats, opts)
3432 if linerange:
3424 if linerange:
3433 # TODO: should follow file history from logcmdutil._initialrevs(),
3425 # TODO: should follow file history from logcmdutil._initialrevs(),
3434 # then filter the result by logcmdutil._makerevset() and --limit
3426 # then filter the result by logcmdutil._makerevset() and --limit
3435 revs, differ = logcmdutil.getlinerangerevs(repo, revs, opts)
3427 revs, differ = logcmdutil.getlinerangerevs(repo, revs, opts)
3436
3428
3437 getrenamed = None
3429 getrenamed = None
3438 if opts.get('copies'):
3430 if opts.get('copies'):
3439 endrev = None
3431 endrev = None
3440 if opts.get('rev'):
3432 if opts.get('rev'):
3441 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
3433 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
3442 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3434 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3443
3435
3444 ui.pager('log')
3436 ui.pager('log')
3445 displayer = logcmdutil.changesetdisplayer(ui, repo, opts, differ,
3437 displayer = logcmdutil.changesetdisplayer(ui, repo, opts, differ,
3446 buffered=True)
3438 buffered=True)
3447 if opts.get('graph'):
3439 if opts.get('graph'):
3448 displayfn = logcmdutil.displaygraphrevs
3440 displayfn = logcmdutil.displaygraphrevs
3449 else:
3441 else:
3450 displayfn = logcmdutil.displayrevs
3442 displayfn = logcmdutil.displayrevs
3451 displayfn(ui, repo, revs, displayer, getrenamed)
3443 displayfn(ui, repo, revs, displayer, getrenamed)
3452
3444
3453 @command('manifest',
3445 @command('manifest',
3454 [('r', 'rev', '', _('revision to display'), _('REV')),
3446 [('r', 'rev', '', _('revision to display'), _('REV')),
3455 ('', 'all', False, _("list files from all revisions"))]
3447 ('', 'all', False, _("list files from all revisions"))]
3456 + formatteropts,
3448 + formatteropts,
3457 _('[-r REV]'), cmdtype=readonly)
3449 _('[-r REV]'), cmdtype=readonly)
3458 def manifest(ui, repo, node=None, rev=None, **opts):
3450 def manifest(ui, repo, node=None, rev=None, **opts):
3459 """output the current or given revision of the project manifest
3451 """output the current or given revision of the project manifest
3460
3452
3461 Print a list of version controlled files for the given revision.
3453 Print a list of version controlled files for the given revision.
3462 If no revision is given, the first parent of the working directory
3454 If no revision is given, the first parent of the working directory
3463 is used, or the null revision if no revision is checked out.
3455 is used, or the null revision if no revision is checked out.
3464
3456
3465 With -v, print file permissions, symlink and executable bits.
3457 With -v, print file permissions, symlink and executable bits.
3466 With --debug, print file revision hashes.
3458 With --debug, print file revision hashes.
3467
3459
3468 If option --all is specified, the list of all files from all revisions
3460 If option --all is specified, the list of all files from all revisions
3469 is printed. This includes deleted and renamed files.
3461 is printed. This includes deleted and renamed files.
3470
3462
3471 Returns 0 on success.
3463 Returns 0 on success.
3472 """
3464 """
3473 opts = pycompat.byteskwargs(opts)
3465 opts = pycompat.byteskwargs(opts)
3474 fm = ui.formatter('manifest', opts)
3466 fm = ui.formatter('manifest', opts)
3475
3467
3476 if opts.get('all'):
3468 if opts.get('all'):
3477 if rev or node:
3469 if rev or node:
3478 raise error.Abort(_("can't specify a revision with --all"))
3470 raise error.Abort(_("can't specify a revision with --all"))
3479
3471
3480 res = []
3472 res = []
3481 prefix = "data/"
3473 prefix = "data/"
3482 suffix = ".i"
3474 suffix = ".i"
3483 plen = len(prefix)
3475 plen = len(prefix)
3484 slen = len(suffix)
3476 slen = len(suffix)
3485 with repo.lock():
3477 with repo.lock():
3486 for fn, b, size in repo.store.datafiles():
3478 for fn, b, size in repo.store.datafiles():
3487 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
3479 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
3488 res.append(fn[plen:-slen])
3480 res.append(fn[plen:-slen])
3489 ui.pager('manifest')
3481 ui.pager('manifest')
3490 for f in res:
3482 for f in res:
3491 fm.startitem()
3483 fm.startitem()
3492 fm.write("path", '%s\n', f)
3484 fm.write("path", '%s\n', f)
3493 fm.end()
3485 fm.end()
3494 return
3486 return
3495
3487
3496 if rev and node:
3488 if rev and node:
3497 raise error.Abort(_("please specify just one revision"))
3489 raise error.Abort(_("please specify just one revision"))
3498
3490
3499 if not node:
3491 if not node:
3500 node = rev
3492 node = rev
3501
3493
3502 char = {'l': '@', 'x': '*', '': '', 't': 'd'}
3494 char = {'l': '@', 'x': '*', '': '', 't': 'd'}
3503 mode = {'l': '644', 'x': '755', '': '644', 't': '755'}
3495 mode = {'l': '644', 'x': '755', '': '644', 't': '755'}
3504 if node:
3496 if node:
3505 repo = scmutil.unhidehashlikerevs(repo, [node], 'nowarn')
3497 repo = scmutil.unhidehashlikerevs(repo, [node], 'nowarn')
3506 ctx = scmutil.revsingle(repo, node)
3498 ctx = scmutil.revsingle(repo, node)
3507 mf = ctx.manifest()
3499 mf = ctx.manifest()
3508 ui.pager('manifest')
3500 ui.pager('manifest')
3509 for f in ctx:
3501 for f in ctx:
3510 fm.startitem()
3502 fm.startitem()
3511 fl = ctx[f].flags()
3503 fl = ctx[f].flags()
3512 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
3504 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
3513 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
3505 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
3514 fm.write('path', '%s\n', f)
3506 fm.write('path', '%s\n', f)
3515 fm.end()
3507 fm.end()
3516
3508
3517 @command('^merge',
3509 @command('^merge',
3518 [('f', 'force', None,
3510 [('f', 'force', None,
3519 _('force a merge including outstanding changes (DEPRECATED)')),
3511 _('force a merge including outstanding changes (DEPRECATED)')),
3520 ('r', 'rev', '', _('revision to merge'), _('REV')),
3512 ('r', 'rev', '', _('revision to merge'), _('REV')),
3521 ('P', 'preview', None,
3513 ('P', 'preview', None,
3522 _('review revisions to merge (no merge is performed)')),
3514 _('review revisions to merge (no merge is performed)')),
3523 ('', 'abort', None, _('abort the ongoing merge')),
3515 ('', 'abort', None, _('abort the ongoing merge')),
3524 ] + mergetoolopts,
3516 ] + mergetoolopts,
3525 _('[-P] [[-r] REV]'))
3517 _('[-P] [[-r] REV]'))
3526 def merge(ui, repo, node=None, **opts):
3518 def merge(ui, repo, node=None, **opts):
3527 """merge another revision into working directory
3519 """merge another revision into working directory
3528
3520
3529 The current working directory is updated with all changes made in
3521 The current working directory is updated with all changes made in
3530 the requested revision since the last common predecessor revision.
3522 the requested revision since the last common predecessor revision.
3531
3523
3532 Files that changed between either parent are marked as changed for
3524 Files that changed between either parent are marked as changed for
3533 the next commit and a commit must be performed before any further
3525 the next commit and a commit must be performed before any further
3534 updates to the repository are allowed. The next commit will have
3526 updates to the repository are allowed. The next commit will have
3535 two parents.
3527 two parents.
3536
3528
3537 ``--tool`` can be used to specify the merge tool used for file
3529 ``--tool`` can be used to specify the merge tool used for file
3538 merges. It overrides the HGMERGE environment variable and your
3530 merges. It overrides the HGMERGE environment variable and your
3539 configuration files. See :hg:`help merge-tools` for options.
3531 configuration files. See :hg:`help merge-tools` for options.
3540
3532
3541 If no revision is specified, the working directory's parent is a
3533 If no revision is specified, the working directory's parent is a
3542 head revision, and the current branch contains exactly one other
3534 head revision, and the current branch contains exactly one other
3543 head, the other head is merged with by default. Otherwise, an
3535 head, the other head is merged with by default. Otherwise, an
3544 explicit revision with which to merge with must be provided.
3536 explicit revision with which to merge with must be provided.
3545
3537
3546 See :hg:`help resolve` for information on handling file conflicts.
3538 See :hg:`help resolve` for information on handling file conflicts.
3547
3539
3548 To undo an uncommitted merge, use :hg:`merge --abort` which
3540 To undo an uncommitted merge, use :hg:`merge --abort` which
3549 will check out a clean copy of the original merge parent, losing
3541 will check out a clean copy of the original merge parent, losing
3550 all changes.
3542 all changes.
3551
3543
3552 Returns 0 on success, 1 if there are unresolved files.
3544 Returns 0 on success, 1 if there are unresolved files.
3553 """
3545 """
3554
3546
3555 opts = pycompat.byteskwargs(opts)
3547 opts = pycompat.byteskwargs(opts)
3556 abort = opts.get('abort')
3548 abort = opts.get('abort')
3557 if abort and repo.dirstate.p2() == nullid:
3549 if abort and repo.dirstate.p2() == nullid:
3558 cmdutil.wrongtooltocontinue(repo, _('merge'))
3550 cmdutil.wrongtooltocontinue(repo, _('merge'))
3559 if abort:
3551 if abort:
3560 if node:
3552 if node:
3561 raise error.Abort(_("cannot specify a node with --abort"))
3553 raise error.Abort(_("cannot specify a node with --abort"))
3562 if opts.get('rev'):
3554 if opts.get('rev'):
3563 raise error.Abort(_("cannot specify both --rev and --abort"))
3555 raise error.Abort(_("cannot specify both --rev and --abort"))
3564 if opts.get('preview'):
3556 if opts.get('preview'):
3565 raise error.Abort(_("cannot specify --preview with --abort"))
3557 raise error.Abort(_("cannot specify --preview with --abort"))
3566 if opts.get('rev') and node:
3558 if opts.get('rev') and node:
3567 raise error.Abort(_("please specify just one revision"))
3559 raise error.Abort(_("please specify just one revision"))
3568 if not node:
3560 if not node:
3569 node = opts.get('rev')
3561 node = opts.get('rev')
3570
3562
3571 if node:
3563 if node:
3572 node = scmutil.revsingle(repo, node).node()
3564 node = scmutil.revsingle(repo, node).node()
3573
3565
3574 if not node and not abort:
3566 if not node and not abort:
3575 node = repo[destutil.destmerge(repo)].node()
3567 node = repo[destutil.destmerge(repo)].node()
3576
3568
3577 if opts.get('preview'):
3569 if opts.get('preview'):
3578 # find nodes that are ancestors of p2 but not of p1
3570 # find nodes that are ancestors of p2 but not of p1
3579 p1 = repo.lookup('.')
3571 p1 = repo.lookup('.')
3580 p2 = repo.lookup(node)
3572 p2 = repo.lookup(node)
3581 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
3573 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
3582
3574
3583 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
3575 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
3584 for node in nodes:
3576 for node in nodes:
3585 displayer.show(repo[node])
3577 displayer.show(repo[node])
3586 displayer.close()
3578 displayer.close()
3587 return 0
3579 return 0
3588
3580
3589 try:
3581 try:
3590 # ui.forcemerge is an internal variable, do not document
3582 # ui.forcemerge is an internal variable, do not document
3591 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
3583 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
3592 force = opts.get('force')
3584 force = opts.get('force')
3593 labels = ['working copy', 'merge rev']
3585 labels = ['working copy', 'merge rev']
3594 return hg.merge(repo, node, force=force, mergeforce=force,
3586 return hg.merge(repo, node, force=force, mergeforce=force,
3595 labels=labels, abort=abort)
3587 labels=labels, abort=abort)
3596 finally:
3588 finally:
3597 ui.setconfig('ui', 'forcemerge', '', 'merge')
3589 ui.setconfig('ui', 'forcemerge', '', 'merge')
3598
3590
3599 @command('outgoing|out',
3591 @command('outgoing|out',
3600 [('f', 'force', None, _('run even when the destination is unrelated')),
3592 [('f', 'force', None, _('run even when the destination is unrelated')),
3601 ('r', 'rev', [],
3593 ('r', 'rev', [],
3602 _('a changeset intended to be included in the destination'), _('REV')),
3594 _('a changeset intended to be included in the destination'), _('REV')),
3603 ('n', 'newest-first', None, _('show newest record first')),
3595 ('n', 'newest-first', None, _('show newest record first')),
3604 ('B', 'bookmarks', False, _('compare bookmarks')),
3596 ('B', 'bookmarks', False, _('compare bookmarks')),
3605 ('b', 'branch', [], _('a specific branch you would like to push'),
3597 ('b', 'branch', [], _('a specific branch you would like to push'),
3606 _('BRANCH')),
3598 _('BRANCH')),
3607 ] + logopts + remoteopts + subrepoopts,
3599 ] + logopts + remoteopts + subrepoopts,
3608 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
3600 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
3609 def outgoing(ui, repo, dest=None, **opts):
3601 def outgoing(ui, repo, dest=None, **opts):
3610 """show changesets not found in the destination
3602 """show changesets not found in the destination
3611
3603
3612 Show changesets not found in the specified destination repository
3604 Show changesets not found in the specified destination repository
3613 or the default push location. These are the changesets that would
3605 or the default push location. These are the changesets that would
3614 be pushed if a push was requested.
3606 be pushed if a push was requested.
3615
3607
3616 See pull for details of valid destination formats.
3608 See pull for details of valid destination formats.
3617
3609
3618 .. container:: verbose
3610 .. container:: verbose
3619
3611
3620 With -B/--bookmarks, the result of bookmark comparison between
3612 With -B/--bookmarks, the result of bookmark comparison between
3621 local and remote repositories is displayed. With -v/--verbose,
3613 local and remote repositories is displayed. With -v/--verbose,
3622 status is also displayed for each bookmark like below::
3614 status is also displayed for each bookmark like below::
3623
3615
3624 BM1 01234567890a added
3616 BM1 01234567890a added
3625 BM2 deleted
3617 BM2 deleted
3626 BM3 234567890abc advanced
3618 BM3 234567890abc advanced
3627 BM4 34567890abcd diverged
3619 BM4 34567890abcd diverged
3628 BM5 4567890abcde changed
3620 BM5 4567890abcde changed
3629
3621
3630 The action taken when pushing depends on the
3622 The action taken when pushing depends on the
3631 status of each bookmark:
3623 status of each bookmark:
3632
3624
3633 :``added``: push with ``-B`` will create it
3625 :``added``: push with ``-B`` will create it
3634 :``deleted``: push with ``-B`` will delete it
3626 :``deleted``: push with ``-B`` will delete it
3635 :``advanced``: push will update it
3627 :``advanced``: push will update it
3636 :``diverged``: push with ``-B`` will update it
3628 :``diverged``: push with ``-B`` will update it
3637 :``changed``: push with ``-B`` will update it
3629 :``changed``: push with ``-B`` will update it
3638
3630
3639 From the point of view of pushing behavior, bookmarks
3631 From the point of view of pushing behavior, bookmarks
3640 existing only in the remote repository are treated as
3632 existing only in the remote repository are treated as
3641 ``deleted``, even if it is in fact added remotely.
3633 ``deleted``, even if it is in fact added remotely.
3642
3634
3643 Returns 0 if there are outgoing changes, 1 otherwise.
3635 Returns 0 if there are outgoing changes, 1 otherwise.
3644 """
3636 """
3645 opts = pycompat.byteskwargs(opts)
3637 opts = pycompat.byteskwargs(opts)
3646 if opts.get('graph'):
3638 if opts.get('graph'):
3647 logcmdutil.checkunsupportedgraphflags([], opts)
3639 logcmdutil.checkunsupportedgraphflags([], opts)
3648 o, other = hg._outgoing(ui, repo, dest, opts)
3640 o, other = hg._outgoing(ui, repo, dest, opts)
3649 if not o:
3641 if not o:
3650 cmdutil.outgoinghooks(ui, repo, other, opts, o)
3642 cmdutil.outgoinghooks(ui, repo, other, opts, o)
3651 return
3643 return
3652
3644
3653 revdag = logcmdutil.graphrevs(repo, o, opts)
3645 revdag = logcmdutil.graphrevs(repo, o, opts)
3654 ui.pager('outgoing')
3646 ui.pager('outgoing')
3655 displayer = logcmdutil.changesetdisplayer(ui, repo, opts, buffered=True)
3647 displayer = logcmdutil.changesetdisplayer(ui, repo, opts, buffered=True)
3656 logcmdutil.displaygraph(ui, repo, revdag, displayer,
3648 logcmdutil.displaygraph(ui, repo, revdag, displayer,
3657 graphmod.asciiedges)
3649 graphmod.asciiedges)
3658 cmdutil.outgoinghooks(ui, repo, other, opts, o)
3650 cmdutil.outgoinghooks(ui, repo, other, opts, o)
3659 return 0
3651 return 0
3660
3652
3661 if opts.get('bookmarks'):
3653 if opts.get('bookmarks'):
3662 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3654 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3663 dest, branches = hg.parseurl(dest, opts.get('branch'))
3655 dest, branches = hg.parseurl(dest, opts.get('branch'))
3664 other = hg.peer(repo, opts, dest)
3656 other = hg.peer(repo, opts, dest)
3665 if 'bookmarks' not in other.listkeys('namespaces'):
3657 if 'bookmarks' not in other.listkeys('namespaces'):
3666 ui.warn(_("remote doesn't support bookmarks\n"))
3658 ui.warn(_("remote doesn't support bookmarks\n"))
3667 return 0
3659 return 0
3668 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
3660 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
3669 ui.pager('outgoing')
3661 ui.pager('outgoing')
3670 return bookmarks.outgoing(ui, repo, other)
3662 return bookmarks.outgoing(ui, repo, other)
3671
3663
3672 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
3664 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
3673 try:
3665 try:
3674 return hg.outgoing(ui, repo, dest, opts)
3666 return hg.outgoing(ui, repo, dest, opts)
3675 finally:
3667 finally:
3676 del repo._subtoppath
3668 del repo._subtoppath
3677
3669
3678 @command('parents',
3670 @command('parents',
3679 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
3671 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
3680 ] + templateopts,
3672 ] + templateopts,
3681 _('[-r REV] [FILE]'),
3673 _('[-r REV] [FILE]'),
3682 inferrepo=True)
3674 inferrepo=True)
3683 def parents(ui, repo, file_=None, **opts):
3675 def parents(ui, repo, file_=None, **opts):
3684 """show the parents of the working directory or revision (DEPRECATED)
3676 """show the parents of the working directory or revision (DEPRECATED)
3685
3677
3686 Print the working directory's parent revisions. If a revision is
3678 Print the working directory's parent revisions. If a revision is
3687 given via -r/--rev, the parent of that revision will be printed.
3679 given via -r/--rev, the parent of that revision will be printed.
3688 If a file argument is given, the revision in which the file was
3680 If a file argument is given, the revision in which the file was
3689 last changed (before the working directory revision or the
3681 last changed (before the working directory revision or the
3690 argument to --rev if given) is printed.
3682 argument to --rev if given) is printed.
3691
3683
3692 This command is equivalent to::
3684 This command is equivalent to::
3693
3685
3694 hg log -r "p1()+p2()" or
3686 hg log -r "p1()+p2()" or
3695 hg log -r "p1(REV)+p2(REV)" or
3687 hg log -r "p1(REV)+p2(REV)" or
3696 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
3688 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
3697 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
3689 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
3698
3690
3699 See :hg:`summary` and :hg:`help revsets` for related information.
3691 See :hg:`summary` and :hg:`help revsets` for related information.
3700
3692
3701 Returns 0 on success.
3693 Returns 0 on success.
3702 """
3694 """
3703
3695
3704 opts = pycompat.byteskwargs(opts)
3696 opts = pycompat.byteskwargs(opts)
3705 rev = opts.get('rev')
3697 rev = opts.get('rev')
3706 if rev:
3698 if rev:
3707 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
3699 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
3708 ctx = scmutil.revsingle(repo, rev, None)
3700 ctx = scmutil.revsingle(repo, rev, None)
3709
3701
3710 if file_:
3702 if file_:
3711 m = scmutil.match(ctx, (file_,), opts)
3703 m = scmutil.match(ctx, (file_,), opts)
3712 if m.anypats() or len(m.files()) != 1:
3704 if m.anypats() or len(m.files()) != 1:
3713 raise error.Abort(_('can only specify an explicit filename'))
3705 raise error.Abort(_('can only specify an explicit filename'))
3714 file_ = m.files()[0]
3706 file_ = m.files()[0]
3715 filenodes = []
3707 filenodes = []
3716 for cp in ctx.parents():
3708 for cp in ctx.parents():
3717 if not cp:
3709 if not cp:
3718 continue
3710 continue
3719 try:
3711 try:
3720 filenodes.append(cp.filenode(file_))
3712 filenodes.append(cp.filenode(file_))
3721 except error.LookupError:
3713 except error.LookupError:
3722 pass
3714 pass
3723 if not filenodes:
3715 if not filenodes:
3724 raise error.Abort(_("'%s' not found in manifest!") % file_)
3716 raise error.Abort(_("'%s' not found in manifest!") % file_)
3725 p = []
3717 p = []
3726 for fn in filenodes:
3718 for fn in filenodes:
3727 fctx = repo.filectx(file_, fileid=fn)
3719 fctx = repo.filectx(file_, fileid=fn)
3728 p.append(fctx.node())
3720 p.append(fctx.node())
3729 else:
3721 else:
3730 p = [cp.node() for cp in ctx.parents()]
3722 p = [cp.node() for cp in ctx.parents()]
3731
3723
3732 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
3724 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
3733 for n in p:
3725 for n in p:
3734 if n != nullid:
3726 if n != nullid:
3735 displayer.show(repo[n])
3727 displayer.show(repo[n])
3736 displayer.close()
3728 displayer.close()
3737
3729
3738 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True,
3730 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True,
3739 cmdtype=readonly)
3731 cmdtype=readonly)
3740 def paths(ui, repo, search=None, **opts):
3732 def paths(ui, repo, search=None, **opts):
3741 """show aliases for remote repositories
3733 """show aliases for remote repositories
3742
3734
3743 Show definition of symbolic path name NAME. If no name is given,
3735 Show definition of symbolic path name NAME. If no name is given,
3744 show definition of all available names.
3736 show definition of all available names.
3745
3737
3746 Option -q/--quiet suppresses all output when searching for NAME
3738 Option -q/--quiet suppresses all output when searching for NAME
3747 and shows only the path names when listing all definitions.
3739 and shows only the path names when listing all definitions.
3748
3740
3749 Path names are defined in the [paths] section of your
3741 Path names are defined in the [paths] section of your
3750 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
3742 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
3751 repository, ``.hg/hgrc`` is used, too.
3743 repository, ``.hg/hgrc`` is used, too.
3752
3744
3753 The path names ``default`` and ``default-push`` have a special
3745 The path names ``default`` and ``default-push`` have a special
3754 meaning. When performing a push or pull operation, they are used
3746 meaning. When performing a push or pull operation, they are used
3755 as fallbacks if no location is specified on the command-line.
3747 as fallbacks if no location is specified on the command-line.
3756 When ``default-push`` is set, it will be used for push and
3748 When ``default-push`` is set, it will be used for push and
3757 ``default`` will be used for pull; otherwise ``default`` is used
3749 ``default`` will be used for pull; otherwise ``default`` is used
3758 as the fallback for both. When cloning a repository, the clone
3750 as the fallback for both. When cloning a repository, the clone
3759 source is written as ``default`` in ``.hg/hgrc``.
3751 source is written as ``default`` in ``.hg/hgrc``.
3760
3752
3761 .. note::
3753 .. note::
3762
3754
3763 ``default`` and ``default-push`` apply to all inbound (e.g.
3755 ``default`` and ``default-push`` apply to all inbound (e.g.
3764 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
3756 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
3765 and :hg:`bundle`) operations.
3757 and :hg:`bundle`) operations.
3766
3758
3767 See :hg:`help urls` for more information.
3759 See :hg:`help urls` for more information.
3768
3760
3769 Returns 0 on success.
3761 Returns 0 on success.
3770 """
3762 """
3771
3763
3772 opts = pycompat.byteskwargs(opts)
3764 opts = pycompat.byteskwargs(opts)
3773 ui.pager('paths')
3765 ui.pager('paths')
3774 if search:
3766 if search:
3775 pathitems = [(name, path) for name, path in ui.paths.iteritems()
3767 pathitems = [(name, path) for name, path in ui.paths.iteritems()
3776 if name == search]
3768 if name == search]
3777 else:
3769 else:
3778 pathitems = sorted(ui.paths.iteritems())
3770 pathitems = sorted(ui.paths.iteritems())
3779
3771
3780 fm = ui.formatter('paths', opts)
3772 fm = ui.formatter('paths', opts)
3781 if fm.isplain():
3773 if fm.isplain():
3782 hidepassword = util.hidepassword
3774 hidepassword = util.hidepassword
3783 else:
3775 else:
3784 hidepassword = str
3776 hidepassword = str
3785 if ui.quiet:
3777 if ui.quiet:
3786 namefmt = '%s\n'
3778 namefmt = '%s\n'
3787 else:
3779 else:
3788 namefmt = '%s = '
3780 namefmt = '%s = '
3789 showsubopts = not search and not ui.quiet
3781 showsubopts = not search and not ui.quiet
3790
3782
3791 for name, path in pathitems:
3783 for name, path in pathitems:
3792 fm.startitem()
3784 fm.startitem()
3793 fm.condwrite(not search, 'name', namefmt, name)
3785 fm.condwrite(not search, 'name', namefmt, name)
3794 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
3786 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
3795 for subopt, value in sorted(path.suboptions.items()):
3787 for subopt, value in sorted(path.suboptions.items()):
3796 assert subopt not in ('name', 'url')
3788 assert subopt not in ('name', 'url')
3797 if showsubopts:
3789 if showsubopts:
3798 fm.plain('%s:%s = ' % (name, subopt))
3790 fm.plain('%s:%s = ' % (name, subopt))
3799 fm.condwrite(showsubopts, subopt, '%s\n', value)
3791 fm.condwrite(showsubopts, subopt, '%s\n', value)
3800
3792
3801 fm.end()
3793 fm.end()
3802
3794
3803 if search and not pathitems:
3795 if search and not pathitems:
3804 if not ui.quiet:
3796 if not ui.quiet:
3805 ui.warn(_("not found!\n"))
3797 ui.warn(_("not found!\n"))
3806 return 1
3798 return 1
3807 else:
3799 else:
3808 return 0
3800 return 0
3809
3801
3810 @command('phase',
3802 @command('phase',
3811 [('p', 'public', False, _('set changeset phase to public')),
3803 [('p', 'public', False, _('set changeset phase to public')),
3812 ('d', 'draft', False, _('set changeset phase to draft')),
3804 ('d', 'draft', False, _('set changeset phase to draft')),
3813 ('s', 'secret', False, _('set changeset phase to secret')),
3805 ('s', 'secret', False, _('set changeset phase to secret')),
3814 ('f', 'force', False, _('allow to move boundary backward')),
3806 ('f', 'force', False, _('allow to move boundary backward')),
3815 ('r', 'rev', [], _('target revision'), _('REV')),
3807 ('r', 'rev', [], _('target revision'), _('REV')),
3816 ],
3808 ],
3817 _('[-p|-d|-s] [-f] [-r] [REV...]'))
3809 _('[-p|-d|-s] [-f] [-r] [REV...]'))
3818 def phase(ui, repo, *revs, **opts):
3810 def phase(ui, repo, *revs, **opts):
3819 """set or show the current phase name
3811 """set or show the current phase name
3820
3812
3821 With no argument, show the phase name of the current revision(s).
3813 With no argument, show the phase name of the current revision(s).
3822
3814
3823 With one of -p/--public, -d/--draft or -s/--secret, change the
3815 With one of -p/--public, -d/--draft or -s/--secret, change the
3824 phase value of the specified revisions.
3816 phase value of the specified revisions.
3825
3817
3826 Unless -f/--force is specified, :hg:`phase` won't move changesets from a
3818 Unless -f/--force is specified, :hg:`phase` won't move changesets from a
3827 lower phase to a higher phase. Phases are ordered as follows::
3819 lower phase to a higher phase. Phases are ordered as follows::
3828
3820
3829 public < draft < secret
3821 public < draft < secret
3830
3822
3831 Returns 0 on success, 1 if some phases could not be changed.
3823 Returns 0 on success, 1 if some phases could not be changed.
3832
3824
3833 (For more information about the phases concept, see :hg:`help phases`.)
3825 (For more information about the phases concept, see :hg:`help phases`.)
3834 """
3826 """
3835 opts = pycompat.byteskwargs(opts)
3827 opts = pycompat.byteskwargs(opts)
3836 # search for a unique phase argument
3828 # search for a unique phase argument
3837 targetphase = None
3829 targetphase = None
3838 for idx, name in enumerate(phases.phasenames):
3830 for idx, name in enumerate(phases.phasenames):
3839 if opts[name]:
3831 if opts[name]:
3840 if targetphase is not None:
3832 if targetphase is not None:
3841 raise error.Abort(_('only one phase can be specified'))
3833 raise error.Abort(_('only one phase can be specified'))
3842 targetphase = idx
3834 targetphase = idx
3843
3835
3844 # look for specified revision
3836 # look for specified revision
3845 revs = list(revs)
3837 revs = list(revs)
3846 revs.extend(opts['rev'])
3838 revs.extend(opts['rev'])
3847 if not revs:
3839 if not revs:
3848 # display both parents as the second parent phase can influence
3840 # display both parents as the second parent phase can influence
3849 # the phase of a merge commit
3841 # the phase of a merge commit
3850 revs = [c.rev() for c in repo[None].parents()]
3842 revs = [c.rev() for c in repo[None].parents()]
3851
3843
3852 revs = scmutil.revrange(repo, revs)
3844 revs = scmutil.revrange(repo, revs)
3853
3845
3854 ret = 0
3846 ret = 0
3855 if targetphase is None:
3847 if targetphase is None:
3856 # display
3848 # display
3857 for r in revs:
3849 for r in revs:
3858 ctx = repo[r]
3850 ctx = repo[r]
3859 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
3851 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
3860 else:
3852 else:
3861 with repo.lock(), repo.transaction("phase") as tr:
3853 with repo.lock(), repo.transaction("phase") as tr:
3862 # set phase
3854 # set phase
3863 if not revs:
3855 if not revs:
3864 raise error.Abort(_('empty revision set'))
3856 raise error.Abort(_('empty revision set'))
3865 nodes = [repo[r].node() for r in revs]
3857 nodes = [repo[r].node() for r in revs]
3866 # moving revision from public to draft may hide them
3858 # moving revision from public to draft may hide them
3867 # We have to check result on an unfiltered repository
3859 # We have to check result on an unfiltered repository
3868 unfi = repo.unfiltered()
3860 unfi = repo.unfiltered()
3869 getphase = unfi._phasecache.phase
3861 getphase = unfi._phasecache.phase
3870 olddata = [getphase(unfi, r) for r in unfi]
3862 olddata = [getphase(unfi, r) for r in unfi]
3871 phases.advanceboundary(repo, tr, targetphase, nodes)
3863 phases.advanceboundary(repo, tr, targetphase, nodes)
3872 if opts['force']:
3864 if opts['force']:
3873 phases.retractboundary(repo, tr, targetphase, nodes)
3865 phases.retractboundary(repo, tr, targetphase, nodes)
3874 getphase = unfi._phasecache.phase
3866 getphase = unfi._phasecache.phase
3875 newdata = [getphase(unfi, r) for r in unfi]
3867 newdata = [getphase(unfi, r) for r in unfi]
3876 changes = sum(newdata[r] != olddata[r] for r in unfi)
3868 changes = sum(newdata[r] != olddata[r] for r in unfi)
3877 cl = unfi.changelog
3869 cl = unfi.changelog
3878 rejected = [n for n in nodes
3870 rejected = [n for n in nodes
3879 if newdata[cl.rev(n)] < targetphase]
3871 if newdata[cl.rev(n)] < targetphase]
3880 if rejected:
3872 if rejected:
3881 ui.warn(_('cannot move %i changesets to a higher '
3873 ui.warn(_('cannot move %i changesets to a higher '
3882 'phase, use --force\n') % len(rejected))
3874 'phase, use --force\n') % len(rejected))
3883 ret = 1
3875 ret = 1
3884 if changes:
3876 if changes:
3885 msg = _('phase changed for %i changesets\n') % changes
3877 msg = _('phase changed for %i changesets\n') % changes
3886 if ret:
3878 if ret:
3887 ui.status(msg)
3879 ui.status(msg)
3888 else:
3880 else:
3889 ui.note(msg)
3881 ui.note(msg)
3890 else:
3882 else:
3891 ui.warn(_('no phases changed\n'))
3883 ui.warn(_('no phases changed\n'))
3892 return ret
3884 return ret
3893
3885
3894 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
3886 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
3895 """Run after a changegroup has been added via pull/unbundle
3887 """Run after a changegroup has been added via pull/unbundle
3896
3888
3897 This takes arguments below:
3889 This takes arguments below:
3898
3890
3899 :modheads: change of heads by pull/unbundle
3891 :modheads: change of heads by pull/unbundle
3900 :optupdate: updating working directory is needed or not
3892 :optupdate: updating working directory is needed or not
3901 :checkout: update destination revision (or None to default destination)
3893 :checkout: update destination revision (or None to default destination)
3902 :brev: a name, which might be a bookmark to be activated after updating
3894 :brev: a name, which might be a bookmark to be activated after updating
3903 """
3895 """
3904 if modheads == 0:
3896 if modheads == 0:
3905 return
3897 return
3906 if optupdate:
3898 if optupdate:
3907 try:
3899 try:
3908 return hg.updatetotally(ui, repo, checkout, brev)
3900 return hg.updatetotally(ui, repo, checkout, brev)
3909 except error.UpdateAbort as inst:
3901 except error.UpdateAbort as inst:
3910 msg = _("not updating: %s") % str(inst)
3902 msg = _("not updating: %s") % str(inst)
3911 hint = inst.hint
3903 hint = inst.hint
3912 raise error.UpdateAbort(msg, hint=hint)
3904 raise error.UpdateAbort(msg, hint=hint)
3913 if modheads > 1:
3905 if modheads > 1:
3914 currentbranchheads = len(repo.branchheads())
3906 currentbranchheads = len(repo.branchheads())
3915 if currentbranchheads == modheads:
3907 if currentbranchheads == modheads:
3916 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
3908 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
3917 elif currentbranchheads > 1:
3909 elif currentbranchheads > 1:
3918 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
3910 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
3919 "merge)\n"))
3911 "merge)\n"))
3920 else:
3912 else:
3921 ui.status(_("(run 'hg heads' to see heads)\n"))
3913 ui.status(_("(run 'hg heads' to see heads)\n"))
3922 elif not ui.configbool('commands', 'update.requiredest'):
3914 elif not ui.configbool('commands', 'update.requiredest'):
3923 ui.status(_("(run 'hg update' to get a working copy)\n"))
3915 ui.status(_("(run 'hg update' to get a working copy)\n"))
3924
3916
3925 @command('^pull',
3917 @command('^pull',
3926 [('u', 'update', None,
3918 [('u', 'update', None,
3927 _('update to new branch head if new descendants were pulled')),
3919 _('update to new branch head if new descendants were pulled')),
3928 ('f', 'force', None, _('run even when remote repository is unrelated')),
3920 ('f', 'force', None, _('run even when remote repository is unrelated')),
3929 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3921 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3930 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
3922 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
3931 ('b', 'branch', [], _('a specific branch you would like to pull'),
3923 ('b', 'branch', [], _('a specific branch you would like to pull'),
3932 _('BRANCH')),
3924 _('BRANCH')),
3933 ] + remoteopts,
3925 ] + remoteopts,
3934 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
3926 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
3935 def pull(ui, repo, source="default", **opts):
3927 def pull(ui, repo, source="default", **opts):
3936 """pull changes from the specified source
3928 """pull changes from the specified source
3937
3929
3938 Pull changes from a remote repository to a local one.
3930 Pull changes from a remote repository to a local one.
3939
3931
3940 This finds all changes from the repository at the specified path
3932 This finds all changes from the repository at the specified path
3941 or URL and adds them to a local repository (the current one unless
3933 or URL and adds them to a local repository (the current one unless
3942 -R is specified). By default, this does not update the copy of the
3934 -R is specified). By default, this does not update the copy of the
3943 project in the working directory.
3935 project in the working directory.
3944
3936
3945 Use :hg:`incoming` if you want to see what would have been added
3937 Use :hg:`incoming` if you want to see what would have been added
3946 by a pull at the time you issued this command. If you then decide
3938 by a pull at the time you issued this command. If you then decide
3947 to add those changes to the repository, you should use :hg:`pull
3939 to add those changes to the repository, you should use :hg:`pull
3948 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
3940 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
3949
3941
3950 If SOURCE is omitted, the 'default' path will be used.
3942 If SOURCE is omitted, the 'default' path will be used.
3951 See :hg:`help urls` for more information.
3943 See :hg:`help urls` for more information.
3952
3944
3953 Specifying bookmark as ``.`` is equivalent to specifying the active
3945 Specifying bookmark as ``.`` is equivalent to specifying the active
3954 bookmark's name.
3946 bookmark's name.
3955
3947
3956 Returns 0 on success, 1 if an update had unresolved files.
3948 Returns 0 on success, 1 if an update had unresolved files.
3957 """
3949 """
3958
3950
3959 opts = pycompat.byteskwargs(opts)
3951 opts = pycompat.byteskwargs(opts)
3960 if ui.configbool('commands', 'update.requiredest') and opts.get('update'):
3952 if ui.configbool('commands', 'update.requiredest') and opts.get('update'):
3961 msg = _('update destination required by configuration')
3953 msg = _('update destination required by configuration')
3962 hint = _('use hg pull followed by hg update DEST')
3954 hint = _('use hg pull followed by hg update DEST')
3963 raise error.Abort(msg, hint=hint)
3955 raise error.Abort(msg, hint=hint)
3964
3956
3965 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
3957 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
3966 ui.status(_('pulling from %s\n') % util.hidepassword(source))
3958 ui.status(_('pulling from %s\n') % util.hidepassword(source))
3967 other = hg.peer(repo, opts, source)
3959 other = hg.peer(repo, opts, source)
3968 try:
3960 try:
3969 revs, checkout = hg.addbranchrevs(repo, other, branches,
3961 revs, checkout = hg.addbranchrevs(repo, other, branches,
3970 opts.get('rev'))
3962 opts.get('rev'))
3971
3963
3972
3964
3973 pullopargs = {}
3965 pullopargs = {}
3974 if opts.get('bookmark'):
3966 if opts.get('bookmark'):
3975 if not revs:
3967 if not revs:
3976 revs = []
3968 revs = []
3977 # The list of bookmark used here is not the one used to actually
3969 # The list of bookmark used here is not the one used to actually
3978 # update the bookmark name. This can result in the revision pulled
3970 # update the bookmark name. This can result in the revision pulled
3979 # not ending up with the name of the bookmark because of a race
3971 # not ending up with the name of the bookmark because of a race
3980 # condition on the server. (See issue 4689 for details)
3972 # condition on the server. (See issue 4689 for details)
3981 remotebookmarks = other.listkeys('bookmarks')
3973 remotebookmarks = other.listkeys('bookmarks')
3982 remotebookmarks = bookmarks.unhexlifybookmarks(remotebookmarks)
3974 remotebookmarks = bookmarks.unhexlifybookmarks(remotebookmarks)
3983 pullopargs['remotebookmarks'] = remotebookmarks
3975 pullopargs['remotebookmarks'] = remotebookmarks
3984 for b in opts['bookmark']:
3976 for b in opts['bookmark']:
3985 b = repo._bookmarks.expandname(b)
3977 b = repo._bookmarks.expandname(b)
3986 if b not in remotebookmarks:
3978 if b not in remotebookmarks:
3987 raise error.Abort(_('remote bookmark %s not found!') % b)
3979 raise error.Abort(_('remote bookmark %s not found!') % b)
3988 revs.append(hex(remotebookmarks[b]))
3980 revs.append(hex(remotebookmarks[b]))
3989
3981
3990 if revs:
3982 if revs:
3991 try:
3983 try:
3992 # When 'rev' is a bookmark name, we cannot guarantee that it
3984 # When 'rev' is a bookmark name, we cannot guarantee that it
3993 # will be updated with that name because of a race condition
3985 # will be updated with that name because of a race condition
3994 # server side. (See issue 4689 for details)
3986 # server side. (See issue 4689 for details)
3995 oldrevs = revs
3987 oldrevs = revs
3996 revs = [] # actually, nodes
3988 revs = [] # actually, nodes
3997 for r in oldrevs:
3989 for r in oldrevs:
3998 node = other.lookup(r)
3990 node = other.lookup(r)
3999 revs.append(node)
3991 revs.append(node)
4000 if r == checkout:
3992 if r == checkout:
4001 checkout = node
3993 checkout = node
4002 except error.CapabilityError:
3994 except error.CapabilityError:
4003 err = _("other repository doesn't support revision lookup, "
3995 err = _("other repository doesn't support revision lookup, "
4004 "so a rev cannot be specified.")
3996 "so a rev cannot be specified.")
4005 raise error.Abort(err)
3997 raise error.Abort(err)
4006
3998
4007 wlock = util.nullcontextmanager()
3999 wlock = util.nullcontextmanager()
4008 if opts.get('update'):
4000 if opts.get('update'):
4009 wlock = repo.wlock()
4001 wlock = repo.wlock()
4010 with wlock:
4002 with wlock:
4011 pullopargs.update(opts.get('opargs', {}))
4003 pullopargs.update(opts.get('opargs', {}))
4012 modheads = exchange.pull(repo, other, heads=revs,
4004 modheads = exchange.pull(repo, other, heads=revs,
4013 force=opts.get('force'),
4005 force=opts.get('force'),
4014 bookmarks=opts.get('bookmark', ()),
4006 bookmarks=opts.get('bookmark', ()),
4015 opargs=pullopargs).cgresult
4007 opargs=pullopargs).cgresult
4016
4008
4017 # brev is a name, which might be a bookmark to be activated at
4009 # brev is a name, which might be a bookmark to be activated at
4018 # the end of the update. In other words, it is an explicit
4010 # the end of the update. In other words, it is an explicit
4019 # destination of the update
4011 # destination of the update
4020 brev = None
4012 brev = None
4021
4013
4022 if checkout:
4014 if checkout:
4023 checkout = "%d" % repo.changelog.rev(checkout)
4015 checkout = "%d" % repo.changelog.rev(checkout)
4024
4016
4025 # order below depends on implementation of
4017 # order below depends on implementation of
4026 # hg.addbranchrevs(). opts['bookmark'] is ignored,
4018 # hg.addbranchrevs(). opts['bookmark'] is ignored,
4027 # because 'checkout' is determined without it.
4019 # because 'checkout' is determined without it.
4028 if opts.get('rev'):
4020 if opts.get('rev'):
4029 brev = opts['rev'][0]
4021 brev = opts['rev'][0]
4030 elif opts.get('branch'):
4022 elif opts.get('branch'):
4031 brev = opts['branch'][0]
4023 brev = opts['branch'][0]
4032 else:
4024 else:
4033 brev = branches[0]
4025 brev = branches[0]
4034 repo._subtoppath = source
4026 repo._subtoppath = source
4035 try:
4027 try:
4036 ret = postincoming(ui, repo, modheads, opts.get('update'),
4028 ret = postincoming(ui, repo, modheads, opts.get('update'),
4037 checkout, brev)
4029 checkout, brev)
4038
4030
4039 finally:
4031 finally:
4040 del repo._subtoppath
4032 del repo._subtoppath
4041
4033
4042 finally:
4034 finally:
4043 other.close()
4035 other.close()
4044 return ret
4036 return ret
4045
4037
4046 @command('^push',
4038 @command('^push',
4047 [('f', 'force', None, _('force push')),
4039 [('f', 'force', None, _('force push')),
4048 ('r', 'rev', [],
4040 ('r', 'rev', [],
4049 _('a changeset intended to be included in the destination'),
4041 _('a changeset intended to be included in the destination'),
4050 _('REV')),
4042 _('REV')),
4051 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4043 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4052 ('b', 'branch', [],
4044 ('b', 'branch', [],
4053 _('a specific branch you would like to push'), _('BRANCH')),
4045 _('a specific branch you would like to push'), _('BRANCH')),
4054 ('', 'new-branch', False, _('allow pushing a new branch')),
4046 ('', 'new-branch', False, _('allow pushing a new branch')),
4055 ('', 'pushvars', [], _('variables that can be sent to server (ADVANCED)')),
4047 ('', 'pushvars', [], _('variables that can be sent to server (ADVANCED)')),
4056 ] + remoteopts,
4048 ] + remoteopts,
4057 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4049 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4058 def push(ui, repo, dest=None, **opts):
4050 def push(ui, repo, dest=None, **opts):
4059 """push changes to the specified destination
4051 """push changes to the specified destination
4060
4052
4061 Push changesets from the local repository to the specified
4053 Push changesets from the local repository to the specified
4062 destination.
4054 destination.
4063
4055
4064 This operation is symmetrical to pull: it is identical to a pull
4056 This operation is symmetrical to pull: it is identical to a pull
4065 in the destination repository from the current one.
4057 in the destination repository from the current one.
4066
4058
4067 By default, push will not allow creation of new heads at the
4059 By default, push will not allow creation of new heads at the
4068 destination, since multiple heads would make it unclear which head
4060 destination, since multiple heads would make it unclear which head
4069 to use. In this situation, it is recommended to pull and merge
4061 to use. In this situation, it is recommended to pull and merge
4070 before pushing.
4062 before pushing.
4071
4063
4072 Use --new-branch if you want to allow push to create a new named
4064 Use --new-branch if you want to allow push to create a new named
4073 branch that is not present at the destination. This allows you to
4065 branch that is not present at the destination. This allows you to
4074 only create a new branch without forcing other changes.
4066 only create a new branch without forcing other changes.
4075
4067
4076 .. note::
4068 .. note::
4077
4069
4078 Extra care should be taken with the -f/--force option,
4070 Extra care should be taken with the -f/--force option,
4079 which will push all new heads on all branches, an action which will
4071 which will push all new heads on all branches, an action which will
4080 almost always cause confusion for collaborators.
4072 almost always cause confusion for collaborators.
4081
4073
4082 If -r/--rev is used, the specified revision and all its ancestors
4074 If -r/--rev is used, the specified revision and all its ancestors
4083 will be pushed to the remote repository.
4075 will be pushed to the remote repository.
4084
4076
4085 If -B/--bookmark is used, the specified bookmarked revision, its
4077 If -B/--bookmark is used, the specified bookmarked revision, its
4086 ancestors, and the bookmark will be pushed to the remote
4078 ancestors, and the bookmark will be pushed to the remote
4087 repository. Specifying ``.`` is equivalent to specifying the active
4079 repository. Specifying ``.`` is equivalent to specifying the active
4088 bookmark's name.
4080 bookmark's name.
4089
4081
4090 Please see :hg:`help urls` for important details about ``ssh://``
4082 Please see :hg:`help urls` for important details about ``ssh://``
4091 URLs. If DESTINATION is omitted, a default path will be used.
4083 URLs. If DESTINATION is omitted, a default path will be used.
4092
4084
4093 .. container:: verbose
4085 .. container:: verbose
4094
4086
4095 The --pushvars option sends strings to the server that become
4087 The --pushvars option sends strings to the server that become
4096 environment variables prepended with ``HG_USERVAR_``. For example,
4088 environment variables prepended with ``HG_USERVAR_``. For example,
4097 ``--pushvars ENABLE_FEATURE=true``, provides the server side hooks with
4089 ``--pushvars ENABLE_FEATURE=true``, provides the server side hooks with
4098 ``HG_USERVAR_ENABLE_FEATURE=true`` as part of their environment.
4090 ``HG_USERVAR_ENABLE_FEATURE=true`` as part of their environment.
4099
4091
4100 pushvars can provide for user-overridable hooks as well as set debug
4092 pushvars can provide for user-overridable hooks as well as set debug
4101 levels. One example is having a hook that blocks commits containing
4093 levels. One example is having a hook that blocks commits containing
4102 conflict markers, but enables the user to override the hook if the file
4094 conflict markers, but enables the user to override the hook if the file
4103 is using conflict markers for testing purposes or the file format has
4095 is using conflict markers for testing purposes or the file format has
4104 strings that look like conflict markers.
4096 strings that look like conflict markers.
4105
4097
4106 By default, servers will ignore `--pushvars`. To enable it add the
4098 By default, servers will ignore `--pushvars`. To enable it add the
4107 following to your configuration file::
4099 following to your configuration file::
4108
4100
4109 [push]
4101 [push]
4110 pushvars.server = true
4102 pushvars.server = true
4111
4103
4112 Returns 0 if push was successful, 1 if nothing to push.
4104 Returns 0 if push was successful, 1 if nothing to push.
4113 """
4105 """
4114
4106
4115 opts = pycompat.byteskwargs(opts)
4107 opts = pycompat.byteskwargs(opts)
4116 if opts.get('bookmark'):
4108 if opts.get('bookmark'):
4117 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
4109 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
4118 for b in opts['bookmark']:
4110 for b in opts['bookmark']:
4119 # translate -B options to -r so changesets get pushed
4111 # translate -B options to -r so changesets get pushed
4120 b = repo._bookmarks.expandname(b)
4112 b = repo._bookmarks.expandname(b)
4121 if b in repo._bookmarks:
4113 if b in repo._bookmarks:
4122 opts.setdefault('rev', []).append(b)
4114 opts.setdefault('rev', []).append(b)
4123 else:
4115 else:
4124 # if we try to push a deleted bookmark, translate it to null
4116 # if we try to push a deleted bookmark, translate it to null
4125 # this lets simultaneous -r, -b options continue working
4117 # this lets simultaneous -r, -b options continue working
4126 opts.setdefault('rev', []).append("null")
4118 opts.setdefault('rev', []).append("null")
4127
4119
4128 path = ui.paths.getpath(dest, default=('default-push', 'default'))
4120 path = ui.paths.getpath(dest, default=('default-push', 'default'))
4129 if not path:
4121 if not path:
4130 raise error.Abort(_('default repository not configured!'),
4122 raise error.Abort(_('default repository not configured!'),
4131 hint=_("see 'hg help config.paths'"))
4123 hint=_("see 'hg help config.paths'"))
4132 dest = path.pushloc or path.loc
4124 dest = path.pushloc or path.loc
4133 branches = (path.branch, opts.get('branch') or [])
4125 branches = (path.branch, opts.get('branch') or [])
4134 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4126 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4135 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4127 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4136 other = hg.peer(repo, opts, dest)
4128 other = hg.peer(repo, opts, dest)
4137
4129
4138 if revs:
4130 if revs:
4139 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4131 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4140 if not revs:
4132 if not revs:
4141 raise error.Abort(_("specified revisions evaluate to an empty set"),
4133 raise error.Abort(_("specified revisions evaluate to an empty set"),
4142 hint=_("use different revision arguments"))
4134 hint=_("use different revision arguments"))
4143 elif path.pushrev:
4135 elif path.pushrev:
4144 # It doesn't make any sense to specify ancestor revisions. So limit
4136 # It doesn't make any sense to specify ancestor revisions. So limit
4145 # to DAG heads to make discovery simpler.
4137 # to DAG heads to make discovery simpler.
4146 expr = revsetlang.formatspec('heads(%r)', path.pushrev)
4138 expr = revsetlang.formatspec('heads(%r)', path.pushrev)
4147 revs = scmutil.revrange(repo, [expr])
4139 revs = scmutil.revrange(repo, [expr])
4148 revs = [repo[rev].node() for rev in revs]
4140 revs = [repo[rev].node() for rev in revs]
4149 if not revs:
4141 if not revs:
4150 raise error.Abort(_('default push revset for path evaluates to an '
4142 raise error.Abort(_('default push revset for path evaluates to an '
4151 'empty set'))
4143 'empty set'))
4152
4144
4153 repo._subtoppath = dest
4145 repo._subtoppath = dest
4154 try:
4146 try:
4155 # push subrepos depth-first for coherent ordering
4147 # push subrepos depth-first for coherent ordering
4156 c = repo['']
4148 c = repo['']
4157 subs = c.substate # only repos that are committed
4149 subs = c.substate # only repos that are committed
4158 for s in sorted(subs):
4150 for s in sorted(subs):
4159 result = c.sub(s).push(opts)
4151 result = c.sub(s).push(opts)
4160 if result == 0:
4152 if result == 0:
4161 return not result
4153 return not result
4162 finally:
4154 finally:
4163 del repo._subtoppath
4155 del repo._subtoppath
4164
4156
4165 opargs = dict(opts.get('opargs', {})) # copy opargs since we may mutate it
4157 opargs = dict(opts.get('opargs', {})) # copy opargs since we may mutate it
4166 opargs.setdefault('pushvars', []).extend(opts.get('pushvars', []))
4158 opargs.setdefault('pushvars', []).extend(opts.get('pushvars', []))
4167
4159
4168 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
4160 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
4169 newbranch=opts.get('new_branch'),
4161 newbranch=opts.get('new_branch'),
4170 bookmarks=opts.get('bookmark', ()),
4162 bookmarks=opts.get('bookmark', ()),
4171 opargs=opargs)
4163 opargs=opargs)
4172
4164
4173 result = not pushop.cgresult
4165 result = not pushop.cgresult
4174
4166
4175 if pushop.bkresult is not None:
4167 if pushop.bkresult is not None:
4176 if pushop.bkresult == 2:
4168 if pushop.bkresult == 2:
4177 result = 2
4169 result = 2
4178 elif not result and pushop.bkresult:
4170 elif not result and pushop.bkresult:
4179 result = 2
4171 result = 2
4180
4172
4181 return result
4173 return result
4182
4174
4183 @command('recover', [])
4175 @command('recover', [])
4184 def recover(ui, repo):
4176 def recover(ui, repo):
4185 """roll back an interrupted transaction
4177 """roll back an interrupted transaction
4186
4178
4187 Recover from an interrupted commit or pull.
4179 Recover from an interrupted commit or pull.
4188
4180
4189 This command tries to fix the repository status after an
4181 This command tries to fix the repository status after an
4190 interrupted operation. It should only be necessary when Mercurial
4182 interrupted operation. It should only be necessary when Mercurial
4191 suggests it.
4183 suggests it.
4192
4184
4193 Returns 0 if successful, 1 if nothing to recover or verify fails.
4185 Returns 0 if successful, 1 if nothing to recover or verify fails.
4194 """
4186 """
4195 if repo.recover():
4187 if repo.recover():
4196 return hg.verify(repo)
4188 return hg.verify(repo)
4197 return 1
4189 return 1
4198
4190
4199 @command('^remove|rm',
4191 @command('^remove|rm',
4200 [('A', 'after', None, _('record delete for missing files')),
4192 [('A', 'after', None, _('record delete for missing files')),
4201 ('f', 'force', None,
4193 ('f', 'force', None,
4202 _('forget added files, delete modified files')),
4194 _('forget added files, delete modified files')),
4203 ] + subrepoopts + walkopts,
4195 ] + subrepoopts + walkopts,
4204 _('[OPTION]... FILE...'),
4196 _('[OPTION]... FILE...'),
4205 inferrepo=True)
4197 inferrepo=True)
4206 def remove(ui, repo, *pats, **opts):
4198 def remove(ui, repo, *pats, **opts):
4207 """remove the specified files on the next commit
4199 """remove the specified files on the next commit
4208
4200
4209 Schedule the indicated files for removal from the current branch.
4201 Schedule the indicated files for removal from the current branch.
4210
4202
4211 This command schedules the files to be removed at the next commit.
4203 This command schedules the files to be removed at the next commit.
4212 To undo a remove before that, see :hg:`revert`. To undo added
4204 To undo a remove before that, see :hg:`revert`. To undo added
4213 files, see :hg:`forget`.
4205 files, see :hg:`forget`.
4214
4206
4215 .. container:: verbose
4207 .. container:: verbose
4216
4208
4217 -A/--after can be used to remove only files that have already
4209 -A/--after can be used to remove only files that have already
4218 been deleted, -f/--force can be used to force deletion, and -Af
4210 been deleted, -f/--force can be used to force deletion, and -Af
4219 can be used to remove files from the next revision without
4211 can be used to remove files from the next revision without
4220 deleting them from the working directory.
4212 deleting them from the working directory.
4221
4213
4222 The following table details the behavior of remove for different
4214 The following table details the behavior of remove for different
4223 file states (columns) and option combinations (rows). The file
4215 file states (columns) and option combinations (rows). The file
4224 states are Added [A], Clean [C], Modified [M] and Missing [!]
4216 states are Added [A], Clean [C], Modified [M] and Missing [!]
4225 (as reported by :hg:`status`). The actions are Warn, Remove
4217 (as reported by :hg:`status`). The actions are Warn, Remove
4226 (from branch) and Delete (from disk):
4218 (from branch) and Delete (from disk):
4227
4219
4228 ========= == == == ==
4220 ========= == == == ==
4229 opt/state A C M !
4221 opt/state A C M !
4230 ========= == == == ==
4222 ========= == == == ==
4231 none W RD W R
4223 none W RD W R
4232 -f R RD RD R
4224 -f R RD RD R
4233 -A W W W R
4225 -A W W W R
4234 -Af R R R R
4226 -Af R R R R
4235 ========= == == == ==
4227 ========= == == == ==
4236
4228
4237 .. note::
4229 .. note::
4238
4230
4239 :hg:`remove` never deletes files in Added [A] state from the
4231 :hg:`remove` never deletes files in Added [A] state from the
4240 working directory, not even if ``--force`` is specified.
4232 working directory, not even if ``--force`` is specified.
4241
4233
4242 Returns 0 on success, 1 if any warnings encountered.
4234 Returns 0 on success, 1 if any warnings encountered.
4243 """
4235 """
4244
4236
4245 opts = pycompat.byteskwargs(opts)
4237 opts = pycompat.byteskwargs(opts)
4246 after, force = opts.get('after'), opts.get('force')
4238 after, force = opts.get('after'), opts.get('force')
4247 if not pats and not after:
4239 if not pats and not after:
4248 raise error.Abort(_('no files specified'))
4240 raise error.Abort(_('no files specified'))
4249
4241
4250 m = scmutil.match(repo[None], pats, opts)
4242 m = scmutil.match(repo[None], pats, opts)
4251 subrepos = opts.get('subrepos')
4243 subrepos = opts.get('subrepos')
4252 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
4244 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
4253
4245
4254 @command('rename|move|mv',
4246 @command('rename|move|mv',
4255 [('A', 'after', None, _('record a rename that has already occurred')),
4247 [('A', 'after', None, _('record a rename that has already occurred')),
4256 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4248 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4257 ] + walkopts + dryrunopts,
4249 ] + walkopts + dryrunopts,
4258 _('[OPTION]... SOURCE... DEST'))
4250 _('[OPTION]... SOURCE... DEST'))
4259 def rename(ui, repo, *pats, **opts):
4251 def rename(ui, repo, *pats, **opts):
4260 """rename files; equivalent of copy + remove
4252 """rename files; equivalent of copy + remove
4261
4253
4262 Mark dest as copies of sources; mark sources for deletion. If dest
4254 Mark dest as copies of sources; mark sources for deletion. If dest
4263 is a directory, copies are put in that directory. If dest is a
4255 is a directory, copies are put in that directory. If dest is a
4264 file, there can only be one source.
4256 file, there can only be one source.
4265
4257
4266 By default, this command copies the contents of files as they
4258 By default, this command copies the contents of files as they
4267 exist in the working directory. If invoked with -A/--after, the
4259 exist in the working directory. If invoked with -A/--after, the
4268 operation is recorded, but no copying is performed.
4260 operation is recorded, but no copying is performed.
4269
4261
4270 This command takes effect at the next commit. To undo a rename
4262 This command takes effect at the next commit. To undo a rename
4271 before that, see :hg:`revert`.
4263 before that, see :hg:`revert`.
4272
4264
4273 Returns 0 on success, 1 if errors are encountered.
4265 Returns 0 on success, 1 if errors are encountered.
4274 """
4266 """
4275 opts = pycompat.byteskwargs(opts)
4267 opts = pycompat.byteskwargs(opts)
4276 with repo.wlock(False):
4268 with repo.wlock(False):
4277 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4269 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4278
4270
4279 @command('resolve',
4271 @command('resolve',
4280 [('a', 'all', None, _('select all unresolved files')),
4272 [('a', 'all', None, _('select all unresolved files')),
4281 ('l', 'list', None, _('list state of files needing merge')),
4273 ('l', 'list', None, _('list state of files needing merge')),
4282 ('m', 'mark', None, _('mark files as resolved')),
4274 ('m', 'mark', None, _('mark files as resolved')),
4283 ('u', 'unmark', None, _('mark files as unresolved')),
4275 ('u', 'unmark', None, _('mark files as unresolved')),
4284 ('n', 'no-status', None, _('hide status prefix'))]
4276 ('n', 'no-status', None, _('hide status prefix'))]
4285 + mergetoolopts + walkopts + formatteropts,
4277 + mergetoolopts + walkopts + formatteropts,
4286 _('[OPTION]... [FILE]...'),
4278 _('[OPTION]... [FILE]...'),
4287 inferrepo=True)
4279 inferrepo=True)
4288 def resolve(ui, repo, *pats, **opts):
4280 def resolve(ui, repo, *pats, **opts):
4289 """redo merges or set/view the merge status of files
4281 """redo merges or set/view the merge status of files
4290
4282
4291 Merges with unresolved conflicts are often the result of
4283 Merges with unresolved conflicts are often the result of
4292 non-interactive merging using the ``internal:merge`` configuration
4284 non-interactive merging using the ``internal:merge`` configuration
4293 setting, or a command-line merge tool like ``diff3``. The resolve
4285 setting, or a command-line merge tool like ``diff3``. The resolve
4294 command is used to manage the files involved in a merge, after
4286 command is used to manage the files involved in a merge, after
4295 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4287 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4296 working directory must have two parents). See :hg:`help
4288 working directory must have two parents). See :hg:`help
4297 merge-tools` for information on configuring merge tools.
4289 merge-tools` for information on configuring merge tools.
4298
4290
4299 The resolve command can be used in the following ways:
4291 The resolve command can be used in the following ways:
4300
4292
4301 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4293 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4302 files, discarding any previous merge attempts. Re-merging is not
4294 files, discarding any previous merge attempts. Re-merging is not
4303 performed for files already marked as resolved. Use ``--all/-a``
4295 performed for files already marked as resolved. Use ``--all/-a``
4304 to select all unresolved files. ``--tool`` can be used to specify
4296 to select all unresolved files. ``--tool`` can be used to specify
4305 the merge tool used for the given files. It overrides the HGMERGE
4297 the merge tool used for the given files. It overrides the HGMERGE
4306 environment variable and your configuration files. Previous file
4298 environment variable and your configuration files. Previous file
4307 contents are saved with a ``.orig`` suffix.
4299 contents are saved with a ``.orig`` suffix.
4308
4300
4309 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4301 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4310 (e.g. after having manually fixed-up the files). The default is
4302 (e.g. after having manually fixed-up the files). The default is
4311 to mark all unresolved files.
4303 to mark all unresolved files.
4312
4304
4313 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4305 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4314 default is to mark all resolved files.
4306 default is to mark all resolved files.
4315
4307
4316 - :hg:`resolve -l`: list files which had or still have conflicts.
4308 - :hg:`resolve -l`: list files which had or still have conflicts.
4317 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4309 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4318 You can use ``set:unresolved()`` or ``set:resolved()`` to filter
4310 You can use ``set:unresolved()`` or ``set:resolved()`` to filter
4319 the list. See :hg:`help filesets` for details.
4311 the list. See :hg:`help filesets` for details.
4320
4312
4321 .. note::
4313 .. note::
4322
4314
4323 Mercurial will not let you commit files with unresolved merge
4315 Mercurial will not let you commit files with unresolved merge
4324 conflicts. You must use :hg:`resolve -m ...` before you can
4316 conflicts. You must use :hg:`resolve -m ...` before you can
4325 commit after a conflicting merge.
4317 commit after a conflicting merge.
4326
4318
4327 Returns 0 on success, 1 if any files fail a resolve attempt.
4319 Returns 0 on success, 1 if any files fail a resolve attempt.
4328 """
4320 """
4329
4321
4330 opts = pycompat.byteskwargs(opts)
4322 opts = pycompat.byteskwargs(opts)
4331 flaglist = 'all mark unmark list no_status'.split()
4323 flaglist = 'all mark unmark list no_status'.split()
4332 all, mark, unmark, show, nostatus = \
4324 all, mark, unmark, show, nostatus = \
4333 [opts.get(o) for o in flaglist]
4325 [opts.get(o) for o in flaglist]
4334
4326
4335 if (show and (mark or unmark)) or (mark and unmark):
4327 if (show and (mark or unmark)) or (mark and unmark):
4336 raise error.Abort(_("too many options specified"))
4328 raise error.Abort(_("too many options specified"))
4337 if pats and all:
4329 if pats and all:
4338 raise error.Abort(_("can't specify --all and patterns"))
4330 raise error.Abort(_("can't specify --all and patterns"))
4339 if not (all or pats or show or mark or unmark):
4331 if not (all or pats or show or mark or unmark):
4340 raise error.Abort(_('no files or directories specified'),
4332 raise error.Abort(_('no files or directories specified'),
4341 hint=('use --all to re-merge all unresolved files'))
4333 hint=('use --all to re-merge all unresolved files'))
4342
4334
4343 if show:
4335 if show:
4344 ui.pager('resolve')
4336 ui.pager('resolve')
4345 fm = ui.formatter('resolve', opts)
4337 fm = ui.formatter('resolve', opts)
4346 ms = mergemod.mergestate.read(repo)
4338 ms = mergemod.mergestate.read(repo)
4347 m = scmutil.match(repo[None], pats, opts)
4339 m = scmutil.match(repo[None], pats, opts)
4348
4340
4349 # Labels and keys based on merge state. Unresolved path conflicts show
4341 # Labels and keys based on merge state. Unresolved path conflicts show
4350 # as 'P'. Resolved path conflicts show as 'R', the same as normal
4342 # as 'P'. Resolved path conflicts show as 'R', the same as normal
4351 # resolved conflicts.
4343 # resolved conflicts.
4352 mergestateinfo = {
4344 mergestateinfo = {
4353 'u': ('resolve.unresolved', 'U'),
4345 'u': ('resolve.unresolved', 'U'),
4354 'r': ('resolve.resolved', 'R'),
4346 'r': ('resolve.resolved', 'R'),
4355 'pu': ('resolve.unresolved', 'P'),
4347 'pu': ('resolve.unresolved', 'P'),
4356 'pr': ('resolve.resolved', 'R'),
4348 'pr': ('resolve.resolved', 'R'),
4357 'd': ('resolve.driverresolved', 'D'),
4349 'd': ('resolve.driverresolved', 'D'),
4358 }
4350 }
4359
4351
4360 for f in ms:
4352 for f in ms:
4361 if not m(f):
4353 if not m(f):
4362 continue
4354 continue
4363
4355
4364 label, key = mergestateinfo[ms[f]]
4356 label, key = mergestateinfo[ms[f]]
4365 fm.startitem()
4357 fm.startitem()
4366 fm.condwrite(not nostatus, 'status', '%s ', key, label=label)
4358 fm.condwrite(not nostatus, 'status', '%s ', key, label=label)
4367 fm.write('path', '%s\n', f, label=label)
4359 fm.write('path', '%s\n', f, label=label)
4368 fm.end()
4360 fm.end()
4369 return 0
4361 return 0
4370
4362
4371 with repo.wlock():
4363 with repo.wlock():
4372 ms = mergemod.mergestate.read(repo)
4364 ms = mergemod.mergestate.read(repo)
4373
4365
4374 if not (ms.active() or repo.dirstate.p2() != nullid):
4366 if not (ms.active() or repo.dirstate.p2() != nullid):
4375 raise error.Abort(
4367 raise error.Abort(
4376 _('resolve command not applicable when not merging'))
4368 _('resolve command not applicable when not merging'))
4377
4369
4378 wctx = repo[None]
4370 wctx = repo[None]
4379
4371
4380 if ms.mergedriver and ms.mdstate() == 'u':
4372 if ms.mergedriver and ms.mdstate() == 'u':
4381 proceed = mergemod.driverpreprocess(repo, ms, wctx)
4373 proceed = mergemod.driverpreprocess(repo, ms, wctx)
4382 ms.commit()
4374 ms.commit()
4383 # allow mark and unmark to go through
4375 # allow mark and unmark to go through
4384 if not mark and not unmark and not proceed:
4376 if not mark and not unmark and not proceed:
4385 return 1
4377 return 1
4386
4378
4387 m = scmutil.match(wctx, pats, opts)
4379 m = scmutil.match(wctx, pats, opts)
4388 ret = 0
4380 ret = 0
4389 didwork = False
4381 didwork = False
4390 runconclude = False
4382 runconclude = False
4391
4383
4392 tocomplete = []
4384 tocomplete = []
4393 for f in ms:
4385 for f in ms:
4394 if not m(f):
4386 if not m(f):
4395 continue
4387 continue
4396
4388
4397 didwork = True
4389 didwork = True
4398
4390
4399 # don't let driver-resolved files be marked, and run the conclude
4391 # don't let driver-resolved files be marked, and run the conclude
4400 # step if asked to resolve
4392 # step if asked to resolve
4401 if ms[f] == "d":
4393 if ms[f] == "d":
4402 exact = m.exact(f)
4394 exact = m.exact(f)
4403 if mark:
4395 if mark:
4404 if exact:
4396 if exact:
4405 ui.warn(_('not marking %s as it is driver-resolved\n')
4397 ui.warn(_('not marking %s as it is driver-resolved\n')
4406 % f)
4398 % f)
4407 elif unmark:
4399 elif unmark:
4408 if exact:
4400 if exact:
4409 ui.warn(_('not unmarking %s as it is driver-resolved\n')
4401 ui.warn(_('not unmarking %s as it is driver-resolved\n')
4410 % f)
4402 % f)
4411 else:
4403 else:
4412 runconclude = True
4404 runconclude = True
4413 continue
4405 continue
4414
4406
4415 # path conflicts must be resolved manually
4407 # path conflicts must be resolved manually
4416 if ms[f] in ("pu", "pr"):
4408 if ms[f] in ("pu", "pr"):
4417 if mark:
4409 if mark:
4418 ms.mark(f, "pr")
4410 ms.mark(f, "pr")
4419 elif unmark:
4411 elif unmark:
4420 ms.mark(f, "pu")
4412 ms.mark(f, "pu")
4421 elif ms[f] == "pu":
4413 elif ms[f] == "pu":
4422 ui.warn(_('%s: path conflict must be resolved manually\n')
4414 ui.warn(_('%s: path conflict must be resolved manually\n')
4423 % f)
4415 % f)
4424 continue
4416 continue
4425
4417
4426 if mark:
4418 if mark:
4427 ms.mark(f, "r")
4419 ms.mark(f, "r")
4428 elif unmark:
4420 elif unmark:
4429 ms.mark(f, "u")
4421 ms.mark(f, "u")
4430 else:
4422 else:
4431 # backup pre-resolve (merge uses .orig for its own purposes)
4423 # backup pre-resolve (merge uses .orig for its own purposes)
4432 a = repo.wjoin(f)
4424 a = repo.wjoin(f)
4433 try:
4425 try:
4434 util.copyfile(a, a + ".resolve")
4426 util.copyfile(a, a + ".resolve")
4435 except (IOError, OSError) as inst:
4427 except (IOError, OSError) as inst:
4436 if inst.errno != errno.ENOENT:
4428 if inst.errno != errno.ENOENT:
4437 raise
4429 raise
4438
4430
4439 try:
4431 try:
4440 # preresolve file
4432 # preresolve file
4441 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4433 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4442 'resolve')
4434 'resolve')
4443 complete, r = ms.preresolve(f, wctx)
4435 complete, r = ms.preresolve(f, wctx)
4444 if not complete:
4436 if not complete:
4445 tocomplete.append(f)
4437 tocomplete.append(f)
4446 elif r:
4438 elif r:
4447 ret = 1
4439 ret = 1
4448 finally:
4440 finally:
4449 ui.setconfig('ui', 'forcemerge', '', 'resolve')
4441 ui.setconfig('ui', 'forcemerge', '', 'resolve')
4450 ms.commit()
4442 ms.commit()
4451
4443
4452 # replace filemerge's .orig file with our resolve file, but only
4444 # replace filemerge's .orig file with our resolve file, but only
4453 # for merges that are complete
4445 # for merges that are complete
4454 if complete:
4446 if complete:
4455 try:
4447 try:
4456 util.rename(a + ".resolve",
4448 util.rename(a + ".resolve",
4457 scmutil.origpath(ui, repo, a))
4449 scmutil.origpath(ui, repo, a))
4458 except OSError as inst:
4450 except OSError as inst:
4459 if inst.errno != errno.ENOENT:
4451 if inst.errno != errno.ENOENT:
4460 raise
4452 raise
4461
4453
4462 for f in tocomplete:
4454 for f in tocomplete:
4463 try:
4455 try:
4464 # resolve file
4456 # resolve file
4465 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4457 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4466 'resolve')
4458 'resolve')
4467 r = ms.resolve(f, wctx)
4459 r = ms.resolve(f, wctx)
4468 if r:
4460 if r:
4469 ret = 1
4461 ret = 1
4470 finally:
4462 finally:
4471 ui.setconfig('ui', 'forcemerge', '', 'resolve')
4463 ui.setconfig('ui', 'forcemerge', '', 'resolve')
4472 ms.commit()
4464 ms.commit()
4473
4465
4474 # replace filemerge's .orig file with our resolve file
4466 # replace filemerge's .orig file with our resolve file
4475 a = repo.wjoin(f)
4467 a = repo.wjoin(f)
4476 try:
4468 try:
4477 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
4469 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
4478 except OSError as inst:
4470 except OSError as inst:
4479 if inst.errno != errno.ENOENT:
4471 if inst.errno != errno.ENOENT:
4480 raise
4472 raise
4481
4473
4482 ms.commit()
4474 ms.commit()
4483 ms.recordactions()
4475 ms.recordactions()
4484
4476
4485 if not didwork and pats:
4477 if not didwork and pats:
4486 hint = None
4478 hint = None
4487 if not any([p for p in pats if p.find(':') >= 0]):
4479 if not any([p for p in pats if p.find(':') >= 0]):
4488 pats = ['path:%s' % p for p in pats]
4480 pats = ['path:%s' % p for p in pats]
4489 m = scmutil.match(wctx, pats, opts)
4481 m = scmutil.match(wctx, pats, opts)
4490 for f in ms:
4482 for f in ms:
4491 if not m(f):
4483 if not m(f):
4492 continue
4484 continue
4493 flags = ''.join(['-%s ' % o[0] for o in flaglist
4485 flags = ''.join(['-%s ' % o[0] for o in flaglist
4494 if opts.get(o)])
4486 if opts.get(o)])
4495 hint = _("(try: hg resolve %s%s)\n") % (
4487 hint = _("(try: hg resolve %s%s)\n") % (
4496 flags,
4488 flags,
4497 ' '.join(pats))
4489 ' '.join(pats))
4498 break
4490 break
4499 ui.warn(_("arguments do not match paths that need resolving\n"))
4491 ui.warn(_("arguments do not match paths that need resolving\n"))
4500 if hint:
4492 if hint:
4501 ui.warn(hint)
4493 ui.warn(hint)
4502 elif ms.mergedriver and ms.mdstate() != 's':
4494 elif ms.mergedriver and ms.mdstate() != 's':
4503 # run conclude step when either a driver-resolved file is requested
4495 # run conclude step when either a driver-resolved file is requested
4504 # or there are no driver-resolved files
4496 # or there are no driver-resolved files
4505 # we can't use 'ret' to determine whether any files are unresolved
4497 # we can't use 'ret' to determine whether any files are unresolved
4506 # because we might not have tried to resolve some
4498 # because we might not have tried to resolve some
4507 if ((runconclude or not list(ms.driverresolved()))
4499 if ((runconclude or not list(ms.driverresolved()))
4508 and not list(ms.unresolved())):
4500 and not list(ms.unresolved())):
4509 proceed = mergemod.driverconclude(repo, ms, wctx)
4501 proceed = mergemod.driverconclude(repo, ms, wctx)
4510 ms.commit()
4502 ms.commit()
4511 if not proceed:
4503 if not proceed:
4512 return 1
4504 return 1
4513
4505
4514 # Nudge users into finishing an unfinished operation
4506 # Nudge users into finishing an unfinished operation
4515 unresolvedf = list(ms.unresolved())
4507 unresolvedf = list(ms.unresolved())
4516 driverresolvedf = list(ms.driverresolved())
4508 driverresolvedf = list(ms.driverresolved())
4517 if not unresolvedf and not driverresolvedf:
4509 if not unresolvedf and not driverresolvedf:
4518 ui.status(_('(no more unresolved files)\n'))
4510 ui.status(_('(no more unresolved files)\n'))
4519 cmdutil.checkafterresolved(repo)
4511 cmdutil.checkafterresolved(repo)
4520 elif not unresolvedf:
4512 elif not unresolvedf:
4521 ui.status(_('(no more unresolved files -- '
4513 ui.status(_('(no more unresolved files -- '
4522 'run "hg resolve --all" to conclude)\n'))
4514 'run "hg resolve --all" to conclude)\n'))
4523
4515
4524 return ret
4516 return ret
4525
4517
4526 @command('revert',
4518 @command('revert',
4527 [('a', 'all', None, _('revert all changes when no arguments given')),
4519 [('a', 'all', None, _('revert all changes when no arguments given')),
4528 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4520 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4529 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4521 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4530 ('C', 'no-backup', None, _('do not save backup copies of files')),
4522 ('C', 'no-backup', None, _('do not save backup copies of files')),
4531 ('i', 'interactive', None, _('interactively select the changes')),
4523 ('i', 'interactive', None, _('interactively select the changes')),
4532 ] + walkopts + dryrunopts,
4524 ] + walkopts + dryrunopts,
4533 _('[OPTION]... [-r REV] [NAME]...'))
4525 _('[OPTION]... [-r REV] [NAME]...'))
4534 def revert(ui, repo, *pats, **opts):
4526 def revert(ui, repo, *pats, **opts):
4535 """restore files to their checkout state
4527 """restore files to their checkout state
4536
4528
4537 .. note::
4529 .. note::
4538
4530
4539 To check out earlier revisions, you should use :hg:`update REV`.
4531 To check out earlier revisions, you should use :hg:`update REV`.
4540 To cancel an uncommitted merge (and lose your changes),
4532 To cancel an uncommitted merge (and lose your changes),
4541 use :hg:`merge --abort`.
4533 use :hg:`merge --abort`.
4542
4534
4543 With no revision specified, revert the specified files or directories
4535 With no revision specified, revert the specified files or directories
4544 to the contents they had in the parent of the working directory.
4536 to the contents they had in the parent of the working directory.
4545 This restores the contents of files to an unmodified
4537 This restores the contents of files to an unmodified
4546 state and unschedules adds, removes, copies, and renames. If the
4538 state and unschedules adds, removes, copies, and renames. If the
4547 working directory has two parents, you must explicitly specify a
4539 working directory has two parents, you must explicitly specify a
4548 revision.
4540 revision.
4549
4541
4550 Using the -r/--rev or -d/--date options, revert the given files or
4542 Using the -r/--rev or -d/--date options, revert the given files or
4551 directories to their states as of a specific revision. Because
4543 directories to their states as of a specific revision. Because
4552 revert does not change the working directory parents, this will
4544 revert does not change the working directory parents, this will
4553 cause these files to appear modified. This can be helpful to "back
4545 cause these files to appear modified. This can be helpful to "back
4554 out" some or all of an earlier change. See :hg:`backout` for a
4546 out" some or all of an earlier change. See :hg:`backout` for a
4555 related method.
4547 related method.
4556
4548
4557 Modified files are saved with a .orig suffix before reverting.
4549 Modified files are saved with a .orig suffix before reverting.
4558 To disable these backups, use --no-backup. It is possible to store
4550 To disable these backups, use --no-backup. It is possible to store
4559 the backup files in a custom directory relative to the root of the
4551 the backup files in a custom directory relative to the root of the
4560 repository by setting the ``ui.origbackuppath`` configuration
4552 repository by setting the ``ui.origbackuppath`` configuration
4561 option.
4553 option.
4562
4554
4563 See :hg:`help dates` for a list of formats valid for -d/--date.
4555 See :hg:`help dates` for a list of formats valid for -d/--date.
4564
4556
4565 See :hg:`help backout` for a way to reverse the effect of an
4557 See :hg:`help backout` for a way to reverse the effect of an
4566 earlier changeset.
4558 earlier changeset.
4567
4559
4568 Returns 0 on success.
4560 Returns 0 on success.
4569 """
4561 """
4570
4562
4571 opts = pycompat.byteskwargs(opts)
4563 opts = pycompat.byteskwargs(opts)
4572 if opts.get("date"):
4564 if opts.get("date"):
4573 if opts.get("rev"):
4565 if opts.get("rev"):
4574 raise error.Abort(_("you can't specify a revision and a date"))
4566 raise error.Abort(_("you can't specify a revision and a date"))
4575 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4567 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4576
4568
4577 parent, p2 = repo.dirstate.parents()
4569 parent, p2 = repo.dirstate.parents()
4578 if not opts.get('rev') and p2 != nullid:
4570 if not opts.get('rev') and p2 != nullid:
4579 # revert after merge is a trap for new users (issue2915)
4571 # revert after merge is a trap for new users (issue2915)
4580 raise error.Abort(_('uncommitted merge with no revision specified'),
4572 raise error.Abort(_('uncommitted merge with no revision specified'),
4581 hint=_("use 'hg update' or see 'hg help revert'"))
4573 hint=_("use 'hg update' or see 'hg help revert'"))
4582
4574
4583 rev = opts.get('rev')
4575 rev = opts.get('rev')
4584 if rev:
4576 if rev:
4585 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
4577 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
4586 ctx = scmutil.revsingle(repo, rev)
4578 ctx = scmutil.revsingle(repo, rev)
4587
4579
4588 if (not (pats or opts.get('include') or opts.get('exclude') or
4580 if (not (pats or opts.get('include') or opts.get('exclude') or
4589 opts.get('all') or opts.get('interactive'))):
4581 opts.get('all') or opts.get('interactive'))):
4590 msg = _("no files or directories specified")
4582 msg = _("no files or directories specified")
4591 if p2 != nullid:
4583 if p2 != nullid:
4592 hint = _("uncommitted merge, use --all to discard all changes,"
4584 hint = _("uncommitted merge, use --all to discard all changes,"
4593 " or 'hg update -C .' to abort the merge")
4585 " or 'hg update -C .' to abort the merge")
4594 raise error.Abort(msg, hint=hint)
4586 raise error.Abort(msg, hint=hint)
4595 dirty = any(repo.status())
4587 dirty = any(repo.status())
4596 node = ctx.node()
4588 node = ctx.node()
4597 if node != parent:
4589 if node != parent:
4598 if dirty:
4590 if dirty:
4599 hint = _("uncommitted changes, use --all to discard all"
4591 hint = _("uncommitted changes, use --all to discard all"
4600 " changes, or 'hg update %s' to update") % ctx.rev()
4592 " changes, or 'hg update %s' to update") % ctx.rev()
4601 else:
4593 else:
4602 hint = _("use --all to revert all files,"
4594 hint = _("use --all to revert all files,"
4603 " or 'hg update %s' to update") % ctx.rev()
4595 " or 'hg update %s' to update") % ctx.rev()
4604 elif dirty:
4596 elif dirty:
4605 hint = _("uncommitted changes, use --all to discard all changes")
4597 hint = _("uncommitted changes, use --all to discard all changes")
4606 else:
4598 else:
4607 hint = _("use --all to revert all files")
4599 hint = _("use --all to revert all files")
4608 raise error.Abort(msg, hint=hint)
4600 raise error.Abort(msg, hint=hint)
4609
4601
4610 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats,
4602 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats,
4611 **pycompat.strkwargs(opts))
4603 **pycompat.strkwargs(opts))
4612
4604
4613 @command('rollback', dryrunopts +
4605 @command('rollback', dryrunopts +
4614 [('f', 'force', False, _('ignore safety measures'))])
4606 [('f', 'force', False, _('ignore safety measures'))])
4615 def rollback(ui, repo, **opts):
4607 def rollback(ui, repo, **opts):
4616 """roll back the last transaction (DANGEROUS) (DEPRECATED)
4608 """roll back the last transaction (DANGEROUS) (DEPRECATED)
4617
4609
4618 Please use :hg:`commit --amend` instead of rollback to correct
4610 Please use :hg:`commit --amend` instead of rollback to correct
4619 mistakes in the last commit.
4611 mistakes in the last commit.
4620
4612
4621 This command should be used with care. There is only one level of
4613 This command should be used with care. There is only one level of
4622 rollback, and there is no way to undo a rollback. It will also
4614 rollback, and there is no way to undo a rollback. It will also
4623 restore the dirstate at the time of the last transaction, losing
4615 restore the dirstate at the time of the last transaction, losing
4624 any dirstate changes since that time. This command does not alter
4616 any dirstate changes since that time. This command does not alter
4625 the working directory.
4617 the working directory.
4626
4618
4627 Transactions are used to encapsulate the effects of all commands
4619 Transactions are used to encapsulate the effects of all commands
4628 that create new changesets or propagate existing changesets into a
4620 that create new changesets or propagate existing changesets into a
4629 repository.
4621 repository.
4630
4622
4631 .. container:: verbose
4623 .. container:: verbose
4632
4624
4633 For example, the following commands are transactional, and their
4625 For example, the following commands are transactional, and their
4634 effects can be rolled back:
4626 effects can be rolled back:
4635
4627
4636 - commit
4628 - commit
4637 - import
4629 - import
4638 - pull
4630 - pull
4639 - push (with this repository as the destination)
4631 - push (with this repository as the destination)
4640 - unbundle
4632 - unbundle
4641
4633
4642 To avoid permanent data loss, rollback will refuse to rollback a
4634 To avoid permanent data loss, rollback will refuse to rollback a
4643 commit transaction if it isn't checked out. Use --force to
4635 commit transaction if it isn't checked out. Use --force to
4644 override this protection.
4636 override this protection.
4645
4637
4646 The rollback command can be entirely disabled by setting the
4638 The rollback command can be entirely disabled by setting the
4647 ``ui.rollback`` configuration setting to false. If you're here
4639 ``ui.rollback`` configuration setting to false. If you're here
4648 because you want to use rollback and it's disabled, you can
4640 because you want to use rollback and it's disabled, you can
4649 re-enable the command by setting ``ui.rollback`` to true.
4641 re-enable the command by setting ``ui.rollback`` to true.
4650
4642
4651 This command is not intended for use on public repositories. Once
4643 This command is not intended for use on public repositories. Once
4652 changes are visible for pull by other users, rolling a transaction
4644 changes are visible for pull by other users, rolling a transaction
4653 back locally is ineffective (someone else may already have pulled
4645 back locally is ineffective (someone else may already have pulled
4654 the changes). Furthermore, a race is possible with readers of the
4646 the changes). Furthermore, a race is possible with readers of the
4655 repository; for example an in-progress pull from the repository
4647 repository; for example an in-progress pull from the repository
4656 may fail if a rollback is performed.
4648 may fail if a rollback is performed.
4657
4649
4658 Returns 0 on success, 1 if no rollback data is available.
4650 Returns 0 on success, 1 if no rollback data is available.
4659 """
4651 """
4660 if not ui.configbool('ui', 'rollback'):
4652 if not ui.configbool('ui', 'rollback'):
4661 raise error.Abort(_('rollback is disabled because it is unsafe'),
4653 raise error.Abort(_('rollback is disabled because it is unsafe'),
4662 hint=('see `hg help -v rollback` for information'))
4654 hint=('see `hg help -v rollback` for information'))
4663 return repo.rollback(dryrun=opts.get(r'dry_run'),
4655 return repo.rollback(dryrun=opts.get(r'dry_run'),
4664 force=opts.get(r'force'))
4656 force=opts.get(r'force'))
4665
4657
4666 @command('root', [], cmdtype=readonly)
4658 @command('root', [], cmdtype=readonly)
4667 def root(ui, repo):
4659 def root(ui, repo):
4668 """print the root (top) of the current working directory
4660 """print the root (top) of the current working directory
4669
4661
4670 Print the root directory of the current repository.
4662 Print the root directory of the current repository.
4671
4663
4672 Returns 0 on success.
4664 Returns 0 on success.
4673 """
4665 """
4674 ui.write(repo.root + "\n")
4666 ui.write(repo.root + "\n")
4675
4667
4676 @command('^serve',
4668 @command('^serve',
4677 [('A', 'accesslog', '', _('name of access log file to write to'),
4669 [('A', 'accesslog', '', _('name of access log file to write to'),
4678 _('FILE')),
4670 _('FILE')),
4679 ('d', 'daemon', None, _('run server in background')),
4671 ('d', 'daemon', None, _('run server in background')),
4680 ('', 'daemon-postexec', [], _('used internally by daemon mode')),
4672 ('', 'daemon-postexec', [], _('used internally by daemon mode')),
4681 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4673 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4682 # use string type, then we can check if something was passed
4674 # use string type, then we can check if something was passed
4683 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4675 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4684 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4676 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4685 _('ADDR')),
4677 _('ADDR')),
4686 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4678 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4687 _('PREFIX')),
4679 _('PREFIX')),
4688 ('n', 'name', '',
4680 ('n', 'name', '',
4689 _('name to show in web pages (default: working directory)'), _('NAME')),
4681 _('name to show in web pages (default: working directory)'), _('NAME')),
4690 ('', 'web-conf', '',
4682 ('', 'web-conf', '',
4691 _("name of the hgweb config file (see 'hg help hgweb')"), _('FILE')),
4683 _("name of the hgweb config file (see 'hg help hgweb')"), _('FILE')),
4692 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4684 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4693 _('FILE')),
4685 _('FILE')),
4694 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4686 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4695 ('', 'stdio', None, _('for remote clients (ADVANCED)')),
4687 ('', 'stdio', None, _('for remote clients (ADVANCED)')),
4696 ('', 'cmdserver', '', _('for remote clients (ADVANCED)'), _('MODE')),
4688 ('', 'cmdserver', '', _('for remote clients (ADVANCED)'), _('MODE')),
4697 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4689 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4698 ('', 'style', '', _('template style to use'), _('STYLE')),
4690 ('', 'style', '', _('template style to use'), _('STYLE')),
4699 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4691 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4700 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))]
4692 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))]
4701 + subrepoopts,
4693 + subrepoopts,
4702 _('[OPTION]...'),
4694 _('[OPTION]...'),
4703 optionalrepo=True)
4695 optionalrepo=True)
4704 def serve(ui, repo, **opts):
4696 def serve(ui, repo, **opts):
4705 """start stand-alone webserver
4697 """start stand-alone webserver
4706
4698
4707 Start a local HTTP repository browser and pull server. You can use
4699 Start a local HTTP repository browser and pull server. You can use
4708 this for ad-hoc sharing and browsing of repositories. It is
4700 this for ad-hoc sharing and browsing of repositories. It is
4709 recommended to use a real web server to serve a repository for
4701 recommended to use a real web server to serve a repository for
4710 longer periods of time.
4702 longer periods of time.
4711
4703
4712 Please note that the server does not implement access control.
4704 Please note that the server does not implement access control.
4713 This means that, by default, anybody can read from the server and
4705 This means that, by default, anybody can read from the server and
4714 nobody can write to it by default. Set the ``web.allow-push``
4706 nobody can write to it by default. Set the ``web.allow-push``
4715 option to ``*`` to allow everybody to push to the server. You
4707 option to ``*`` to allow everybody to push to the server. You
4716 should use a real web server if you need to authenticate users.
4708 should use a real web server if you need to authenticate users.
4717
4709
4718 By default, the server logs accesses to stdout and errors to
4710 By default, the server logs accesses to stdout and errors to
4719 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
4711 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
4720 files.
4712 files.
4721
4713
4722 To have the server choose a free port number to listen on, specify
4714 To have the server choose a free port number to listen on, specify
4723 a port number of 0; in this case, the server will print the port
4715 a port number of 0; in this case, the server will print the port
4724 number it uses.
4716 number it uses.
4725
4717
4726 Returns 0 on success.
4718 Returns 0 on success.
4727 """
4719 """
4728
4720
4729 opts = pycompat.byteskwargs(opts)
4721 opts = pycompat.byteskwargs(opts)
4730 if opts["stdio"] and opts["cmdserver"]:
4722 if opts["stdio"] and opts["cmdserver"]:
4731 raise error.Abort(_("cannot use --stdio with --cmdserver"))
4723 raise error.Abort(_("cannot use --stdio with --cmdserver"))
4732
4724
4733 if opts["stdio"]:
4725 if opts["stdio"]:
4734 if repo is None:
4726 if repo is None:
4735 raise error.RepoError(_("there is no Mercurial repository here"
4727 raise error.RepoError(_("there is no Mercurial repository here"
4736 " (.hg not found)"))
4728 " (.hg not found)"))
4737 s = wireprotoserver.sshserver(ui, repo)
4729 s = wireprotoserver.sshserver(ui, repo)
4738 s.serve_forever()
4730 s.serve_forever()
4739
4731
4740 service = server.createservice(ui, repo, opts)
4732 service = server.createservice(ui, repo, opts)
4741 return server.runservice(opts, initfn=service.init, runfn=service.run)
4733 return server.runservice(opts, initfn=service.init, runfn=service.run)
4742
4734
4743 @command('^status|st',
4735 @command('^status|st',
4744 [('A', 'all', None, _('show status of all files')),
4736 [('A', 'all', None, _('show status of all files')),
4745 ('m', 'modified', None, _('show only modified files')),
4737 ('m', 'modified', None, _('show only modified files')),
4746 ('a', 'added', None, _('show only added files')),
4738 ('a', 'added', None, _('show only added files')),
4747 ('r', 'removed', None, _('show only removed files')),
4739 ('r', 'removed', None, _('show only removed files')),
4748 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4740 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4749 ('c', 'clean', None, _('show only files without changes')),
4741 ('c', 'clean', None, _('show only files without changes')),
4750 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4742 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4751 ('i', 'ignored', None, _('show only ignored files')),
4743 ('i', 'ignored', None, _('show only ignored files')),
4752 ('n', 'no-status', None, _('hide status prefix')),
4744 ('n', 'no-status', None, _('hide status prefix')),
4753 ('t', 'terse', '', _('show the terse output (EXPERIMENTAL)')),
4745 ('t', 'terse', '', _('show the terse output (EXPERIMENTAL)')),
4754 ('C', 'copies', None, _('show source of copied files')),
4746 ('C', 'copies', None, _('show source of copied files')),
4755 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4747 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4756 ('', 'rev', [], _('show difference from revision'), _('REV')),
4748 ('', 'rev', [], _('show difference from revision'), _('REV')),
4757 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
4749 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
4758 ] + walkopts + subrepoopts + formatteropts,
4750 ] + walkopts + subrepoopts + formatteropts,
4759 _('[OPTION]... [FILE]...'),
4751 _('[OPTION]... [FILE]...'),
4760 inferrepo=True, cmdtype=readonly)
4752 inferrepo=True, cmdtype=readonly)
4761 def status(ui, repo, *pats, **opts):
4753 def status(ui, repo, *pats, **opts):
4762 """show changed files in the working directory
4754 """show changed files in the working directory
4763
4755
4764 Show status of files in the repository. If names are given, only
4756 Show status of files in the repository. If names are given, only
4765 files that match are shown. Files that are clean or ignored or
4757 files that match are shown. Files that are clean or ignored or
4766 the source of a copy/move operation, are not listed unless
4758 the source of a copy/move operation, are not listed unless
4767 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
4759 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
4768 Unless options described with "show only ..." are given, the
4760 Unless options described with "show only ..." are given, the
4769 options -mardu are used.
4761 options -mardu are used.
4770
4762
4771 Option -q/--quiet hides untracked (unknown and ignored) files
4763 Option -q/--quiet hides untracked (unknown and ignored) files
4772 unless explicitly requested with -u/--unknown or -i/--ignored.
4764 unless explicitly requested with -u/--unknown or -i/--ignored.
4773
4765
4774 .. note::
4766 .. note::
4775
4767
4776 :hg:`status` may appear to disagree with diff if permissions have
4768 :hg:`status` may appear to disagree with diff if permissions have
4777 changed or a merge has occurred. The standard diff format does
4769 changed or a merge has occurred. The standard diff format does
4778 not report permission changes and diff only reports changes
4770 not report permission changes and diff only reports changes
4779 relative to one merge parent.
4771 relative to one merge parent.
4780
4772
4781 If one revision is given, it is used as the base revision.
4773 If one revision is given, it is used as the base revision.
4782 If two revisions are given, the differences between them are
4774 If two revisions are given, the differences between them are
4783 shown. The --change option can also be used as a shortcut to list
4775 shown. The --change option can also be used as a shortcut to list
4784 the changed files of a revision from its first parent.
4776 the changed files of a revision from its first parent.
4785
4777
4786 The codes used to show the status of files are::
4778 The codes used to show the status of files are::
4787
4779
4788 M = modified
4780 M = modified
4789 A = added
4781 A = added
4790 R = removed
4782 R = removed
4791 C = clean
4783 C = clean
4792 ! = missing (deleted by non-hg command, but still tracked)
4784 ! = missing (deleted by non-hg command, but still tracked)
4793 ? = not tracked
4785 ? = not tracked
4794 I = ignored
4786 I = ignored
4795 = origin of the previous file (with --copies)
4787 = origin of the previous file (with --copies)
4796
4788
4797 .. container:: verbose
4789 .. container:: verbose
4798
4790
4799 The -t/--terse option abbreviates the output by showing only the directory
4791 The -t/--terse option abbreviates the output by showing only the directory
4800 name if all the files in it share the same status. The option takes an
4792 name if all the files in it share the same status. The option takes an
4801 argument indicating the statuses to abbreviate: 'm' for 'modified', 'a'
4793 argument indicating the statuses to abbreviate: 'm' for 'modified', 'a'
4802 for 'added', 'r' for 'removed', 'd' for 'deleted', 'u' for 'unknown', 'i'
4794 for 'added', 'r' for 'removed', 'd' for 'deleted', 'u' for 'unknown', 'i'
4803 for 'ignored' and 'c' for clean.
4795 for 'ignored' and 'c' for clean.
4804
4796
4805 It abbreviates only those statuses which are passed. Note that clean and
4797 It abbreviates only those statuses which are passed. Note that clean and
4806 ignored files are not displayed with '--terse ic' unless the -c/--clean
4798 ignored files are not displayed with '--terse ic' unless the -c/--clean
4807 and -i/--ignored options are also used.
4799 and -i/--ignored options are also used.
4808
4800
4809 The -v/--verbose option shows information when the repository is in an
4801 The -v/--verbose option shows information when the repository is in an
4810 unfinished merge, shelve, rebase state etc. You can have this behavior
4802 unfinished merge, shelve, rebase state etc. You can have this behavior
4811 turned on by default by enabling the ``commands.status.verbose`` option.
4803 turned on by default by enabling the ``commands.status.verbose`` option.
4812
4804
4813 You can skip displaying some of these states by setting
4805 You can skip displaying some of these states by setting
4814 ``commands.status.skipstates`` to one or more of: 'bisect', 'graft',
4806 ``commands.status.skipstates`` to one or more of: 'bisect', 'graft',
4815 'histedit', 'merge', 'rebase', or 'unshelve'.
4807 'histedit', 'merge', 'rebase', or 'unshelve'.
4816
4808
4817 Examples:
4809 Examples:
4818
4810
4819 - show changes in the working directory relative to a
4811 - show changes in the working directory relative to a
4820 changeset::
4812 changeset::
4821
4813
4822 hg status --rev 9353
4814 hg status --rev 9353
4823
4815
4824 - show changes in the working directory relative to the
4816 - show changes in the working directory relative to the
4825 current directory (see :hg:`help patterns` for more information)::
4817 current directory (see :hg:`help patterns` for more information)::
4826
4818
4827 hg status re:
4819 hg status re:
4828
4820
4829 - show all changes including copies in an existing changeset::
4821 - show all changes including copies in an existing changeset::
4830
4822
4831 hg status --copies --change 9353
4823 hg status --copies --change 9353
4832
4824
4833 - get a NUL separated list of added files, suitable for xargs::
4825 - get a NUL separated list of added files, suitable for xargs::
4834
4826
4835 hg status -an0
4827 hg status -an0
4836
4828
4837 - show more information about the repository status, abbreviating
4829 - show more information about the repository status, abbreviating
4838 added, removed, modified, deleted, and untracked paths::
4830 added, removed, modified, deleted, and untracked paths::
4839
4831
4840 hg status -v -t mardu
4832 hg status -v -t mardu
4841
4833
4842 Returns 0 on success.
4834 Returns 0 on success.
4843
4835
4844 """
4836 """
4845
4837
4846 opts = pycompat.byteskwargs(opts)
4838 opts = pycompat.byteskwargs(opts)
4847 revs = opts.get('rev')
4839 revs = opts.get('rev')
4848 change = opts.get('change')
4840 change = opts.get('change')
4849 terse = opts.get('terse')
4841 terse = opts.get('terse')
4850
4842
4851 if revs and change:
4843 if revs and change:
4852 msg = _('cannot specify --rev and --change at the same time')
4844 msg = _('cannot specify --rev and --change at the same time')
4853 raise error.Abort(msg)
4845 raise error.Abort(msg)
4854 elif revs and terse:
4846 elif revs and terse:
4855 msg = _('cannot use --terse with --rev')
4847 msg = _('cannot use --terse with --rev')
4856 raise error.Abort(msg)
4848 raise error.Abort(msg)
4857 elif change:
4849 elif change:
4858 repo = scmutil.unhidehashlikerevs(repo, [change], 'nowarn')
4850 repo = scmutil.unhidehashlikerevs(repo, [change], 'nowarn')
4859 node2 = scmutil.revsingle(repo, change, None).node()
4851 node2 = scmutil.revsingle(repo, change, None).node()
4860 node1 = repo[node2].p1().node()
4852 node1 = repo[node2].p1().node()
4861 else:
4853 else:
4862 repo = scmutil.unhidehashlikerevs(repo, revs, 'nowarn')
4854 repo = scmutil.unhidehashlikerevs(repo, revs, 'nowarn')
4863 node1, node2 = scmutil.revpair(repo, revs)
4855 node1, node2 = scmutil.revpair(repo, revs)
4864
4856
4865 if pats or ui.configbool('commands', 'status.relative'):
4857 if pats or ui.configbool('commands', 'status.relative'):
4866 cwd = repo.getcwd()
4858 cwd = repo.getcwd()
4867 else:
4859 else:
4868 cwd = ''
4860 cwd = ''
4869
4861
4870 if opts.get('print0'):
4862 if opts.get('print0'):
4871 end = '\0'
4863 end = '\0'
4872 else:
4864 else:
4873 end = '\n'
4865 end = '\n'
4874 copy = {}
4866 copy = {}
4875 states = 'modified added removed deleted unknown ignored clean'.split()
4867 states = 'modified added removed deleted unknown ignored clean'.split()
4876 show = [k for k in states if opts.get(k)]
4868 show = [k for k in states if opts.get(k)]
4877 if opts.get('all'):
4869 if opts.get('all'):
4878 show += ui.quiet and (states[:4] + ['clean']) or states
4870 show += ui.quiet and (states[:4] + ['clean']) or states
4879
4871
4880 if not show:
4872 if not show:
4881 if ui.quiet:
4873 if ui.quiet:
4882 show = states[:4]
4874 show = states[:4]
4883 else:
4875 else:
4884 show = states[:5]
4876 show = states[:5]
4885
4877
4886 m = scmutil.match(repo[node2], pats, opts)
4878 m = scmutil.match(repo[node2], pats, opts)
4887 if terse:
4879 if terse:
4888 # we need to compute clean and unknown to terse
4880 # we need to compute clean and unknown to terse
4889 stat = repo.status(node1, node2, m,
4881 stat = repo.status(node1, node2, m,
4890 'ignored' in show or 'i' in terse,
4882 'ignored' in show or 'i' in terse,
4891 True, True, opts.get('subrepos'))
4883 True, True, opts.get('subrepos'))
4892
4884
4893 stat = cmdutil.tersedir(stat, terse)
4885 stat = cmdutil.tersedir(stat, terse)
4894 else:
4886 else:
4895 stat = repo.status(node1, node2, m,
4887 stat = repo.status(node1, node2, m,
4896 'ignored' in show, 'clean' in show,
4888 'ignored' in show, 'clean' in show,
4897 'unknown' in show, opts.get('subrepos'))
4889 'unknown' in show, opts.get('subrepos'))
4898
4890
4899 changestates = zip(states, pycompat.iterbytestr('MAR!?IC'), stat)
4891 changestates = zip(states, pycompat.iterbytestr('MAR!?IC'), stat)
4900
4892
4901 if (opts.get('all') or opts.get('copies')
4893 if (opts.get('all') or opts.get('copies')
4902 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
4894 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
4903 copy = copies.pathcopies(repo[node1], repo[node2], m)
4895 copy = copies.pathcopies(repo[node1], repo[node2], m)
4904
4896
4905 ui.pager('status')
4897 ui.pager('status')
4906 fm = ui.formatter('status', opts)
4898 fm = ui.formatter('status', opts)
4907 fmt = '%s' + end
4899 fmt = '%s' + end
4908 showchar = not opts.get('no_status')
4900 showchar = not opts.get('no_status')
4909
4901
4910 for state, char, files in changestates:
4902 for state, char, files in changestates:
4911 if state in show:
4903 if state in show:
4912 label = 'status.' + state
4904 label = 'status.' + state
4913 for f in files:
4905 for f in files:
4914 fm.startitem()
4906 fm.startitem()
4915 fm.condwrite(showchar, 'status', '%s ', char, label=label)
4907 fm.condwrite(showchar, 'status', '%s ', char, label=label)
4916 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
4908 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
4917 if f in copy:
4909 if f in copy:
4918 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
4910 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
4919 label='status.copied')
4911 label='status.copied')
4920
4912
4921 if ((ui.verbose or ui.configbool('commands', 'status.verbose'))
4913 if ((ui.verbose or ui.configbool('commands', 'status.verbose'))
4922 and not ui.plain()):
4914 and not ui.plain()):
4923 cmdutil.morestatus(repo, fm)
4915 cmdutil.morestatus(repo, fm)
4924 fm.end()
4916 fm.end()
4925
4917
4926 @command('^summary|sum',
4918 @command('^summary|sum',
4927 [('', 'remote', None, _('check for push and pull'))],
4919 [('', 'remote', None, _('check for push and pull'))],
4928 '[--remote]', cmdtype=readonly)
4920 '[--remote]', cmdtype=readonly)
4929 def summary(ui, repo, **opts):
4921 def summary(ui, repo, **opts):
4930 """summarize working directory state
4922 """summarize working directory state
4931
4923
4932 This generates a brief summary of the working directory state,
4924 This generates a brief summary of the working directory state,
4933 including parents, branch, commit status, phase and available updates.
4925 including parents, branch, commit status, phase and available updates.
4934
4926
4935 With the --remote option, this will check the default paths for
4927 With the --remote option, this will check the default paths for
4936 incoming and outgoing changes. This can be time-consuming.
4928 incoming and outgoing changes. This can be time-consuming.
4937
4929
4938 Returns 0 on success.
4930 Returns 0 on success.
4939 """
4931 """
4940
4932
4941 opts = pycompat.byteskwargs(opts)
4933 opts = pycompat.byteskwargs(opts)
4942 ui.pager('summary')
4934 ui.pager('summary')
4943 ctx = repo[None]
4935 ctx = repo[None]
4944 parents = ctx.parents()
4936 parents = ctx.parents()
4945 pnode = parents[0].node()
4937 pnode = parents[0].node()
4946 marks = []
4938 marks = []
4947
4939
4948 ms = None
4940 ms = None
4949 try:
4941 try:
4950 ms = mergemod.mergestate.read(repo)
4942 ms = mergemod.mergestate.read(repo)
4951 except error.UnsupportedMergeRecords as e:
4943 except error.UnsupportedMergeRecords as e:
4952 s = ' '.join(e.recordtypes)
4944 s = ' '.join(e.recordtypes)
4953 ui.warn(
4945 ui.warn(
4954 _('warning: merge state has unsupported record types: %s\n') % s)
4946 _('warning: merge state has unsupported record types: %s\n') % s)
4955 unresolved = []
4947 unresolved = []
4956 else:
4948 else:
4957 unresolved = list(ms.unresolved())
4949 unresolved = list(ms.unresolved())
4958
4950
4959 for p in parents:
4951 for p in parents:
4960 # label with log.changeset (instead of log.parent) since this
4952 # label with log.changeset (instead of log.parent) since this
4961 # shows a working directory parent *changeset*:
4953 # shows a working directory parent *changeset*:
4962 # i18n: column positioning for "hg summary"
4954 # i18n: column positioning for "hg summary"
4963 ui.write(_('parent: %d:%s ') % (p.rev(), p),
4955 ui.write(_('parent: %d:%s ') % (p.rev(), p),
4964 label=logcmdutil.changesetlabels(p))
4956 label=logcmdutil.changesetlabels(p))
4965 ui.write(' '.join(p.tags()), label='log.tag')
4957 ui.write(' '.join(p.tags()), label='log.tag')
4966 if p.bookmarks():
4958 if p.bookmarks():
4967 marks.extend(p.bookmarks())
4959 marks.extend(p.bookmarks())
4968 if p.rev() == -1:
4960 if p.rev() == -1:
4969 if not len(repo):
4961 if not len(repo):
4970 ui.write(_(' (empty repository)'))
4962 ui.write(_(' (empty repository)'))
4971 else:
4963 else:
4972 ui.write(_(' (no revision checked out)'))
4964 ui.write(_(' (no revision checked out)'))
4973 if p.obsolete():
4965 if p.obsolete():
4974 ui.write(_(' (obsolete)'))
4966 ui.write(_(' (obsolete)'))
4975 if p.isunstable():
4967 if p.isunstable():
4976 instabilities = (ui.label(instability, 'trouble.%s' % instability)
4968 instabilities = (ui.label(instability, 'trouble.%s' % instability)
4977 for instability in p.instabilities())
4969 for instability in p.instabilities())
4978 ui.write(' ('
4970 ui.write(' ('
4979 + ', '.join(instabilities)
4971 + ', '.join(instabilities)
4980 + ')')
4972 + ')')
4981 ui.write('\n')
4973 ui.write('\n')
4982 if p.description():
4974 if p.description():
4983 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
4975 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
4984 label='log.summary')
4976 label='log.summary')
4985
4977
4986 branch = ctx.branch()
4978 branch = ctx.branch()
4987 bheads = repo.branchheads(branch)
4979 bheads = repo.branchheads(branch)
4988 # i18n: column positioning for "hg summary"
4980 # i18n: column positioning for "hg summary"
4989 m = _('branch: %s\n') % branch
4981 m = _('branch: %s\n') % branch
4990 if branch != 'default':
4982 if branch != 'default':
4991 ui.write(m, label='log.branch')
4983 ui.write(m, label='log.branch')
4992 else:
4984 else:
4993 ui.status(m, label='log.branch')
4985 ui.status(m, label='log.branch')
4994
4986
4995 if marks:
4987 if marks:
4996 active = repo._activebookmark
4988 active = repo._activebookmark
4997 # i18n: column positioning for "hg summary"
4989 # i18n: column positioning for "hg summary"
4998 ui.write(_('bookmarks:'), label='log.bookmark')
4990 ui.write(_('bookmarks:'), label='log.bookmark')
4999 if active is not None:
4991 if active is not None:
5000 if active in marks:
4992 if active in marks:
5001 ui.write(' *' + active, label=bookmarks.activebookmarklabel)
4993 ui.write(' *' + active, label=bookmarks.activebookmarklabel)
5002 marks.remove(active)
4994 marks.remove(active)
5003 else:
4995 else:
5004 ui.write(' [%s]' % active, label=bookmarks.activebookmarklabel)
4996 ui.write(' [%s]' % active, label=bookmarks.activebookmarklabel)
5005 for m in marks:
4997 for m in marks:
5006 ui.write(' ' + m, label='log.bookmark')
4998 ui.write(' ' + m, label='log.bookmark')
5007 ui.write('\n', label='log.bookmark')
4999 ui.write('\n', label='log.bookmark')
5008
5000
5009 status = repo.status(unknown=True)
5001 status = repo.status(unknown=True)
5010
5002
5011 c = repo.dirstate.copies()
5003 c = repo.dirstate.copies()
5012 copied, renamed = [], []
5004 copied, renamed = [], []
5013 for d, s in c.iteritems():
5005 for d, s in c.iteritems():
5014 if s in status.removed:
5006 if s in status.removed:
5015 status.removed.remove(s)
5007 status.removed.remove(s)
5016 renamed.append(d)
5008 renamed.append(d)
5017 else:
5009 else:
5018 copied.append(d)
5010 copied.append(d)
5019 if d in status.added:
5011 if d in status.added:
5020 status.added.remove(d)
5012 status.added.remove(d)
5021
5013
5022 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5014 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5023
5015
5024 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
5016 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
5025 (ui.label(_('%d added'), 'status.added'), status.added),
5017 (ui.label(_('%d added'), 'status.added'), status.added),
5026 (ui.label(_('%d removed'), 'status.removed'), status.removed),
5018 (ui.label(_('%d removed'), 'status.removed'), status.removed),
5027 (ui.label(_('%d renamed'), 'status.copied'), renamed),
5019 (ui.label(_('%d renamed'), 'status.copied'), renamed),
5028 (ui.label(_('%d copied'), 'status.copied'), copied),
5020 (ui.label(_('%d copied'), 'status.copied'), copied),
5029 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
5021 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
5030 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
5022 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
5031 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
5023 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
5032 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
5024 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
5033 t = []
5025 t = []
5034 for l, s in labels:
5026 for l, s in labels:
5035 if s:
5027 if s:
5036 t.append(l % len(s))
5028 t.append(l % len(s))
5037
5029
5038 t = ', '.join(t)
5030 t = ', '.join(t)
5039 cleanworkdir = False
5031 cleanworkdir = False
5040
5032
5041 if repo.vfs.exists('graftstate'):
5033 if repo.vfs.exists('graftstate'):
5042 t += _(' (graft in progress)')
5034 t += _(' (graft in progress)')
5043 if repo.vfs.exists('updatestate'):
5035 if repo.vfs.exists('updatestate'):
5044 t += _(' (interrupted update)')
5036 t += _(' (interrupted update)')
5045 elif len(parents) > 1:
5037 elif len(parents) > 1:
5046 t += _(' (merge)')
5038 t += _(' (merge)')
5047 elif branch != parents[0].branch():
5039 elif branch != parents[0].branch():
5048 t += _(' (new branch)')
5040 t += _(' (new branch)')
5049 elif (parents[0].closesbranch() and
5041 elif (parents[0].closesbranch() and
5050 pnode in repo.branchheads(branch, closed=True)):
5042 pnode in repo.branchheads(branch, closed=True)):
5051 t += _(' (head closed)')
5043 t += _(' (head closed)')
5052 elif not (status.modified or status.added or status.removed or renamed or
5044 elif not (status.modified or status.added or status.removed or renamed or
5053 copied or subs):
5045 copied or subs):
5054 t += _(' (clean)')
5046 t += _(' (clean)')
5055 cleanworkdir = True
5047 cleanworkdir = True
5056 elif pnode not in bheads:
5048 elif pnode not in bheads:
5057 t += _(' (new branch head)')
5049 t += _(' (new branch head)')
5058
5050
5059 if parents:
5051 if parents:
5060 pendingphase = max(p.phase() for p in parents)
5052 pendingphase = max(p.phase() for p in parents)
5061 else:
5053 else:
5062 pendingphase = phases.public
5054 pendingphase = phases.public
5063
5055
5064 if pendingphase > phases.newcommitphase(ui):
5056 if pendingphase > phases.newcommitphase(ui):
5065 t += ' (%s)' % phases.phasenames[pendingphase]
5057 t += ' (%s)' % phases.phasenames[pendingphase]
5066
5058
5067 if cleanworkdir:
5059 if cleanworkdir:
5068 # i18n: column positioning for "hg summary"
5060 # i18n: column positioning for "hg summary"
5069 ui.status(_('commit: %s\n') % t.strip())
5061 ui.status(_('commit: %s\n') % t.strip())
5070 else:
5062 else:
5071 # i18n: column positioning for "hg summary"
5063 # i18n: column positioning for "hg summary"
5072 ui.write(_('commit: %s\n') % t.strip())
5064 ui.write(_('commit: %s\n') % t.strip())
5073
5065
5074 # all ancestors of branch heads - all ancestors of parent = new csets
5066 # all ancestors of branch heads - all ancestors of parent = new csets
5075 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
5067 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
5076 bheads))
5068 bheads))
5077
5069
5078 if new == 0:
5070 if new == 0:
5079 # i18n: column positioning for "hg summary"
5071 # i18n: column positioning for "hg summary"
5080 ui.status(_('update: (current)\n'))
5072 ui.status(_('update: (current)\n'))
5081 elif pnode not in bheads:
5073 elif pnode not in bheads:
5082 # i18n: column positioning for "hg summary"
5074 # i18n: column positioning for "hg summary"
5083 ui.write(_('update: %d new changesets (update)\n') % new)
5075 ui.write(_('update: %d new changesets (update)\n') % new)
5084 else:
5076 else:
5085 # i18n: column positioning for "hg summary"
5077 # i18n: column positioning for "hg summary"
5086 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5078 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5087 (new, len(bheads)))
5079 (new, len(bheads)))
5088
5080
5089 t = []
5081 t = []
5090 draft = len(repo.revs('draft()'))
5082 draft = len(repo.revs('draft()'))
5091 if draft:
5083 if draft:
5092 t.append(_('%d draft') % draft)
5084 t.append(_('%d draft') % draft)
5093 secret = len(repo.revs('secret()'))
5085 secret = len(repo.revs('secret()'))
5094 if secret:
5086 if secret:
5095 t.append(_('%d secret') % secret)
5087 t.append(_('%d secret') % secret)
5096
5088
5097 if draft or secret:
5089 if draft or secret:
5098 ui.status(_('phases: %s\n') % ', '.join(t))
5090 ui.status(_('phases: %s\n') % ', '.join(t))
5099
5091
5100 if obsolete.isenabled(repo, obsolete.createmarkersopt):
5092 if obsolete.isenabled(repo, obsolete.createmarkersopt):
5101 for trouble in ("orphan", "contentdivergent", "phasedivergent"):
5093 for trouble in ("orphan", "contentdivergent", "phasedivergent"):
5102 numtrouble = len(repo.revs(trouble + "()"))
5094 numtrouble = len(repo.revs(trouble + "()"))
5103 # We write all the possibilities to ease translation
5095 # We write all the possibilities to ease translation
5104 troublemsg = {
5096 troublemsg = {
5105 "orphan": _("orphan: %d changesets"),
5097 "orphan": _("orphan: %d changesets"),
5106 "contentdivergent": _("content-divergent: %d changesets"),
5098 "contentdivergent": _("content-divergent: %d changesets"),
5107 "phasedivergent": _("phase-divergent: %d changesets"),
5099 "phasedivergent": _("phase-divergent: %d changesets"),
5108 }
5100 }
5109 if numtrouble > 0:
5101 if numtrouble > 0:
5110 ui.status(troublemsg[trouble] % numtrouble + "\n")
5102 ui.status(troublemsg[trouble] % numtrouble + "\n")
5111
5103
5112 cmdutil.summaryhooks(ui, repo)
5104 cmdutil.summaryhooks(ui, repo)
5113
5105
5114 if opts.get('remote'):
5106 if opts.get('remote'):
5115 needsincoming, needsoutgoing = True, True
5107 needsincoming, needsoutgoing = True, True
5116 else:
5108 else:
5117 needsincoming, needsoutgoing = False, False
5109 needsincoming, needsoutgoing = False, False
5118 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5110 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5119 if i:
5111 if i:
5120 needsincoming = True
5112 needsincoming = True
5121 if o:
5113 if o:
5122 needsoutgoing = True
5114 needsoutgoing = True
5123 if not needsincoming and not needsoutgoing:
5115 if not needsincoming and not needsoutgoing:
5124 return
5116 return
5125
5117
5126 def getincoming():
5118 def getincoming():
5127 source, branches = hg.parseurl(ui.expandpath('default'))
5119 source, branches = hg.parseurl(ui.expandpath('default'))
5128 sbranch = branches[0]
5120 sbranch = branches[0]
5129 try:
5121 try:
5130 other = hg.peer(repo, {}, source)
5122 other = hg.peer(repo, {}, source)
5131 except error.RepoError:
5123 except error.RepoError:
5132 if opts.get('remote'):
5124 if opts.get('remote'):
5133 raise
5125 raise
5134 return source, sbranch, None, None, None
5126 return source, sbranch, None, None, None
5135 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5127 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5136 if revs:
5128 if revs:
5137 revs = [other.lookup(rev) for rev in revs]
5129 revs = [other.lookup(rev) for rev in revs]
5138 ui.debug('comparing with %s\n' % util.hidepassword(source))
5130 ui.debug('comparing with %s\n' % util.hidepassword(source))
5139 repo.ui.pushbuffer()
5131 repo.ui.pushbuffer()
5140 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5132 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5141 repo.ui.popbuffer()
5133 repo.ui.popbuffer()
5142 return source, sbranch, other, commoninc, commoninc[1]
5134 return source, sbranch, other, commoninc, commoninc[1]
5143
5135
5144 if needsincoming:
5136 if needsincoming:
5145 source, sbranch, sother, commoninc, incoming = getincoming()
5137 source, sbranch, sother, commoninc, incoming = getincoming()
5146 else:
5138 else:
5147 source = sbranch = sother = commoninc = incoming = None
5139 source = sbranch = sother = commoninc = incoming = None
5148
5140
5149 def getoutgoing():
5141 def getoutgoing():
5150 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5142 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5151 dbranch = branches[0]
5143 dbranch = branches[0]
5152 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5144 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5153 if source != dest:
5145 if source != dest:
5154 try:
5146 try:
5155 dother = hg.peer(repo, {}, dest)
5147 dother = hg.peer(repo, {}, dest)
5156 except error.RepoError:
5148 except error.RepoError:
5157 if opts.get('remote'):
5149 if opts.get('remote'):
5158 raise
5150 raise
5159 return dest, dbranch, None, None
5151 return dest, dbranch, None, None
5160 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5152 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5161 elif sother is None:
5153 elif sother is None:
5162 # there is no explicit destination peer, but source one is invalid
5154 # there is no explicit destination peer, but source one is invalid
5163 return dest, dbranch, None, None
5155 return dest, dbranch, None, None
5164 else:
5156 else:
5165 dother = sother
5157 dother = sother
5166 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5158 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5167 common = None
5159 common = None
5168 else:
5160 else:
5169 common = commoninc
5161 common = commoninc
5170 if revs:
5162 if revs:
5171 revs = [repo.lookup(rev) for rev in revs]
5163 revs = [repo.lookup(rev) for rev in revs]
5172 repo.ui.pushbuffer()
5164 repo.ui.pushbuffer()
5173 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5165 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5174 commoninc=common)
5166 commoninc=common)
5175 repo.ui.popbuffer()
5167 repo.ui.popbuffer()
5176 return dest, dbranch, dother, outgoing
5168 return dest, dbranch, dother, outgoing
5177
5169
5178 if needsoutgoing:
5170 if needsoutgoing:
5179 dest, dbranch, dother, outgoing = getoutgoing()
5171 dest, dbranch, dother, outgoing = getoutgoing()
5180 else:
5172 else:
5181 dest = dbranch = dother = outgoing = None
5173 dest = dbranch = dother = outgoing = None
5182
5174
5183 if opts.get('remote'):
5175 if opts.get('remote'):
5184 t = []
5176 t = []
5185 if incoming:
5177 if incoming:
5186 t.append(_('1 or more incoming'))
5178 t.append(_('1 or more incoming'))
5187 o = outgoing.missing
5179 o = outgoing.missing
5188 if o:
5180 if o:
5189 t.append(_('%d outgoing') % len(o))
5181 t.append(_('%d outgoing') % len(o))
5190 other = dother or sother
5182 other = dother or sother
5191 if 'bookmarks' in other.listkeys('namespaces'):
5183 if 'bookmarks' in other.listkeys('namespaces'):
5192 counts = bookmarks.summary(repo, other)
5184 counts = bookmarks.summary(repo, other)
5193 if counts[0] > 0:
5185 if counts[0] > 0:
5194 t.append(_('%d incoming bookmarks') % counts[0])
5186 t.append(_('%d incoming bookmarks') % counts[0])
5195 if counts[1] > 0:
5187 if counts[1] > 0:
5196 t.append(_('%d outgoing bookmarks') % counts[1])
5188 t.append(_('%d outgoing bookmarks') % counts[1])
5197
5189
5198 if t:
5190 if t:
5199 # i18n: column positioning for "hg summary"
5191 # i18n: column positioning for "hg summary"
5200 ui.write(_('remote: %s\n') % (', '.join(t)))
5192 ui.write(_('remote: %s\n') % (', '.join(t)))
5201 else:
5193 else:
5202 # i18n: column positioning for "hg summary"
5194 # i18n: column positioning for "hg summary"
5203 ui.status(_('remote: (synced)\n'))
5195 ui.status(_('remote: (synced)\n'))
5204
5196
5205 cmdutil.summaryremotehooks(ui, repo, opts,
5197 cmdutil.summaryremotehooks(ui, repo, opts,
5206 ((source, sbranch, sother, commoninc),
5198 ((source, sbranch, sother, commoninc),
5207 (dest, dbranch, dother, outgoing)))
5199 (dest, dbranch, dother, outgoing)))
5208
5200
5209 @command('tag',
5201 @command('tag',
5210 [('f', 'force', None, _('force tag')),
5202 [('f', 'force', None, _('force tag')),
5211 ('l', 'local', None, _('make the tag local')),
5203 ('l', 'local', None, _('make the tag local')),
5212 ('r', 'rev', '', _('revision to tag'), _('REV')),
5204 ('r', 'rev', '', _('revision to tag'), _('REV')),
5213 ('', 'remove', None, _('remove a tag')),
5205 ('', 'remove', None, _('remove a tag')),
5214 # -l/--local is already there, commitopts cannot be used
5206 # -l/--local is already there, commitopts cannot be used
5215 ('e', 'edit', None, _('invoke editor on commit messages')),
5207 ('e', 'edit', None, _('invoke editor on commit messages')),
5216 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5208 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5217 ] + commitopts2,
5209 ] + commitopts2,
5218 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5210 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5219 def tag(ui, repo, name1, *names, **opts):
5211 def tag(ui, repo, name1, *names, **opts):
5220 """add one or more tags for the current or given revision
5212 """add one or more tags for the current or given revision
5221
5213
5222 Name a particular revision using <name>.
5214 Name a particular revision using <name>.
5223
5215
5224 Tags are used to name particular revisions of the repository and are
5216 Tags are used to name particular revisions of the repository and are
5225 very useful to compare different revisions, to go back to significant
5217 very useful to compare different revisions, to go back to significant
5226 earlier versions or to mark branch points as releases, etc. Changing
5218 earlier versions or to mark branch points as releases, etc. Changing
5227 an existing tag is normally disallowed; use -f/--force to override.
5219 an existing tag is normally disallowed; use -f/--force to override.
5228
5220
5229 If no revision is given, the parent of the working directory is
5221 If no revision is given, the parent of the working directory is
5230 used.
5222 used.
5231
5223
5232 To facilitate version control, distribution, and merging of tags,
5224 To facilitate version control, distribution, and merging of tags,
5233 they are stored as a file named ".hgtags" which is managed similarly
5225 they are stored as a file named ".hgtags" which is managed similarly
5234 to other project files and can be hand-edited if necessary. This
5226 to other project files and can be hand-edited if necessary. This
5235 also means that tagging creates a new commit. The file
5227 also means that tagging creates a new commit. The file
5236 ".hg/localtags" is used for local tags (not shared among
5228 ".hg/localtags" is used for local tags (not shared among
5237 repositories).
5229 repositories).
5238
5230
5239 Tag commits are usually made at the head of a branch. If the parent
5231 Tag commits are usually made at the head of a branch. If the parent
5240 of the working directory is not a branch head, :hg:`tag` aborts; use
5232 of the working directory is not a branch head, :hg:`tag` aborts; use
5241 -f/--force to force the tag commit to be based on a non-head
5233 -f/--force to force the tag commit to be based on a non-head
5242 changeset.
5234 changeset.
5243
5235
5244 See :hg:`help dates` for a list of formats valid for -d/--date.
5236 See :hg:`help dates` for a list of formats valid for -d/--date.
5245
5237
5246 Since tag names have priority over branch names during revision
5238 Since tag names have priority over branch names during revision
5247 lookup, using an existing branch name as a tag name is discouraged.
5239 lookup, using an existing branch name as a tag name is discouraged.
5248
5240
5249 Returns 0 on success.
5241 Returns 0 on success.
5250 """
5242 """
5251 opts = pycompat.byteskwargs(opts)
5243 opts = pycompat.byteskwargs(opts)
5252 wlock = lock = None
5244 wlock = lock = None
5253 try:
5245 try:
5254 wlock = repo.wlock()
5246 wlock = repo.wlock()
5255 lock = repo.lock()
5247 lock = repo.lock()
5256 rev_ = "."
5248 rev_ = "."
5257 names = [t.strip() for t in (name1,) + names]
5249 names = [t.strip() for t in (name1,) + names]
5258 if len(names) != len(set(names)):
5250 if len(names) != len(set(names)):
5259 raise error.Abort(_('tag names must be unique'))
5251 raise error.Abort(_('tag names must be unique'))
5260 for n in names:
5252 for n in names:
5261 scmutil.checknewlabel(repo, n, 'tag')
5253 scmutil.checknewlabel(repo, n, 'tag')
5262 if not n:
5254 if not n:
5263 raise error.Abort(_('tag names cannot consist entirely of '
5255 raise error.Abort(_('tag names cannot consist entirely of '
5264 'whitespace'))
5256 'whitespace'))
5265 if opts.get('rev') and opts.get('remove'):
5257 if opts.get('rev') and opts.get('remove'):
5266 raise error.Abort(_("--rev and --remove are incompatible"))
5258 raise error.Abort(_("--rev and --remove are incompatible"))
5267 if opts.get('rev'):
5259 if opts.get('rev'):
5268 rev_ = opts['rev']
5260 rev_ = opts['rev']
5269 message = opts.get('message')
5261 message = opts.get('message')
5270 if opts.get('remove'):
5262 if opts.get('remove'):
5271 if opts.get('local'):
5263 if opts.get('local'):
5272 expectedtype = 'local'
5264 expectedtype = 'local'
5273 else:
5265 else:
5274 expectedtype = 'global'
5266 expectedtype = 'global'
5275
5267
5276 for n in names:
5268 for n in names:
5277 if not repo.tagtype(n):
5269 if not repo.tagtype(n):
5278 raise error.Abort(_("tag '%s' does not exist") % n)
5270 raise error.Abort(_("tag '%s' does not exist") % n)
5279 if repo.tagtype(n) != expectedtype:
5271 if repo.tagtype(n) != expectedtype:
5280 if expectedtype == 'global':
5272 if expectedtype == 'global':
5281 raise error.Abort(_("tag '%s' is not a global tag") % n)
5273 raise error.Abort(_("tag '%s' is not a global tag") % n)
5282 else:
5274 else:
5283 raise error.Abort(_("tag '%s' is not a local tag") % n)
5275 raise error.Abort(_("tag '%s' is not a local tag") % n)
5284 rev_ = 'null'
5276 rev_ = 'null'
5285 if not message:
5277 if not message:
5286 # we don't translate commit messages
5278 # we don't translate commit messages
5287 message = 'Removed tag %s' % ', '.join(names)
5279 message = 'Removed tag %s' % ', '.join(names)
5288 elif not opts.get('force'):
5280 elif not opts.get('force'):
5289 for n in names:
5281 for n in names:
5290 if n in repo.tags():
5282 if n in repo.tags():
5291 raise error.Abort(_("tag '%s' already exists "
5283 raise error.Abort(_("tag '%s' already exists "
5292 "(use -f to force)") % n)
5284 "(use -f to force)") % n)
5293 if not opts.get('local'):
5285 if not opts.get('local'):
5294 p1, p2 = repo.dirstate.parents()
5286 p1, p2 = repo.dirstate.parents()
5295 if p2 != nullid:
5287 if p2 != nullid:
5296 raise error.Abort(_('uncommitted merge'))
5288 raise error.Abort(_('uncommitted merge'))
5297 bheads = repo.branchheads()
5289 bheads = repo.branchheads()
5298 if not opts.get('force') and bheads and p1 not in bheads:
5290 if not opts.get('force') and bheads and p1 not in bheads:
5299 raise error.Abort(_('working directory is not at a branch head '
5291 raise error.Abort(_('working directory is not at a branch head '
5300 '(use -f to force)'))
5292 '(use -f to force)'))
5301 r = scmutil.revsingle(repo, rev_).node()
5293 r = scmutil.revsingle(repo, rev_).node()
5302
5294
5303 if not message:
5295 if not message:
5304 # we don't translate commit messages
5296 # we don't translate commit messages
5305 message = ('Added tag %s for changeset %s' %
5297 message = ('Added tag %s for changeset %s' %
5306 (', '.join(names), short(r)))
5298 (', '.join(names), short(r)))
5307
5299
5308 date = opts.get('date')
5300 date = opts.get('date')
5309 if date:
5301 if date:
5310 date = util.parsedate(date)
5302 date = util.parsedate(date)
5311
5303
5312 if opts.get('remove'):
5304 if opts.get('remove'):
5313 editform = 'tag.remove'
5305 editform = 'tag.remove'
5314 else:
5306 else:
5315 editform = 'tag.add'
5307 editform = 'tag.add'
5316 editor = cmdutil.getcommiteditor(editform=editform,
5308 editor = cmdutil.getcommiteditor(editform=editform,
5317 **pycompat.strkwargs(opts))
5309 **pycompat.strkwargs(opts))
5318
5310
5319 # don't allow tagging the null rev
5311 # don't allow tagging the null rev
5320 if (not opts.get('remove') and
5312 if (not opts.get('remove') and
5321 scmutil.revsingle(repo, rev_).rev() == nullrev):
5313 scmutil.revsingle(repo, rev_).rev() == nullrev):
5322 raise error.Abort(_("cannot tag null revision"))
5314 raise error.Abort(_("cannot tag null revision"))
5323
5315
5324 tagsmod.tag(repo, names, r, message, opts.get('local'),
5316 tagsmod.tag(repo, names, r, message, opts.get('local'),
5325 opts.get('user'), date, editor=editor)
5317 opts.get('user'), date, editor=editor)
5326 finally:
5318 finally:
5327 release(lock, wlock)
5319 release(lock, wlock)
5328
5320
5329 @command('tags', formatteropts, '', cmdtype=readonly)
5321 @command('tags', formatteropts, '', cmdtype=readonly)
5330 def tags(ui, repo, **opts):
5322 def tags(ui, repo, **opts):
5331 """list repository tags
5323 """list repository tags
5332
5324
5333 This lists both regular and local tags. When the -v/--verbose
5325 This lists both regular and local tags. When the -v/--verbose
5334 switch is used, a third column "local" is printed for local tags.
5326 switch is used, a third column "local" is printed for local tags.
5335 When the -q/--quiet switch is used, only the tag name is printed.
5327 When the -q/--quiet switch is used, only the tag name is printed.
5336
5328
5337 Returns 0 on success.
5329 Returns 0 on success.
5338 """
5330 """
5339
5331
5340 opts = pycompat.byteskwargs(opts)
5332 opts = pycompat.byteskwargs(opts)
5341 ui.pager('tags')
5333 ui.pager('tags')
5342 fm = ui.formatter('tags', opts)
5334 fm = ui.formatter('tags', opts)
5343 hexfunc = fm.hexfunc
5335 hexfunc = fm.hexfunc
5344 tagtype = ""
5336 tagtype = ""
5345
5337
5346 for t, n in reversed(repo.tagslist()):
5338 for t, n in reversed(repo.tagslist()):
5347 hn = hexfunc(n)
5339 hn = hexfunc(n)
5348 label = 'tags.normal'
5340 label = 'tags.normal'
5349 tagtype = ''
5341 tagtype = ''
5350 if repo.tagtype(t) == 'local':
5342 if repo.tagtype(t) == 'local':
5351 label = 'tags.local'
5343 label = 'tags.local'
5352 tagtype = 'local'
5344 tagtype = 'local'
5353
5345
5354 fm.startitem()
5346 fm.startitem()
5355 fm.write('tag', '%s', t, label=label)
5347 fm.write('tag', '%s', t, label=label)
5356 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5348 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5357 fm.condwrite(not ui.quiet, 'rev node', fmt,
5349 fm.condwrite(not ui.quiet, 'rev node', fmt,
5358 repo.changelog.rev(n), hn, label=label)
5350 repo.changelog.rev(n), hn, label=label)
5359 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5351 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5360 tagtype, label=label)
5352 tagtype, label=label)
5361 fm.plain('\n')
5353 fm.plain('\n')
5362 fm.end()
5354 fm.end()
5363
5355
5364 @command('tip',
5356 @command('tip',
5365 [('p', 'patch', None, _('show patch')),
5357 [('p', 'patch', None, _('show patch')),
5366 ('g', 'git', None, _('use git extended diff format')),
5358 ('g', 'git', None, _('use git extended diff format')),
5367 ] + templateopts,
5359 ] + templateopts,
5368 _('[-p] [-g]'))
5360 _('[-p] [-g]'))
5369 def tip(ui, repo, **opts):
5361 def tip(ui, repo, **opts):
5370 """show the tip revision (DEPRECATED)
5362 """show the tip revision (DEPRECATED)
5371
5363
5372 The tip revision (usually just called the tip) is the changeset
5364 The tip revision (usually just called the tip) is the changeset
5373 most recently added to the repository (and therefore the most
5365 most recently added to the repository (and therefore the most
5374 recently changed head).
5366 recently changed head).
5375
5367
5376 If you have just made a commit, that commit will be the tip. If
5368 If you have just made a commit, that commit will be the tip. If
5377 you have just pulled changes from another repository, the tip of
5369 you have just pulled changes from another repository, the tip of
5378 that repository becomes the current tip. The "tip" tag is special
5370 that repository becomes the current tip. The "tip" tag is special
5379 and cannot be renamed or assigned to a different changeset.
5371 and cannot be renamed or assigned to a different changeset.
5380
5372
5381 This command is deprecated, please use :hg:`heads` instead.
5373 This command is deprecated, please use :hg:`heads` instead.
5382
5374
5383 Returns 0 on success.
5375 Returns 0 on success.
5384 """
5376 """
5385 opts = pycompat.byteskwargs(opts)
5377 opts = pycompat.byteskwargs(opts)
5386 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
5378 displayer = logcmdutil.changesetdisplayer(ui, repo, opts)
5387 displayer.show(repo['tip'])
5379 displayer.show(repo['tip'])
5388 displayer.close()
5380 displayer.close()
5389
5381
5390 @command('unbundle',
5382 @command('unbundle',
5391 [('u', 'update', None,
5383 [('u', 'update', None,
5392 _('update to new branch head if changesets were unbundled'))],
5384 _('update to new branch head if changesets were unbundled'))],
5393 _('[-u] FILE...'))
5385 _('[-u] FILE...'))
5394 def unbundle(ui, repo, fname1, *fnames, **opts):
5386 def unbundle(ui, repo, fname1, *fnames, **opts):
5395 """apply one or more bundle files
5387 """apply one or more bundle files
5396
5388
5397 Apply one or more bundle files generated by :hg:`bundle`.
5389 Apply one or more bundle files generated by :hg:`bundle`.
5398
5390
5399 Returns 0 on success, 1 if an update has unresolved files.
5391 Returns 0 on success, 1 if an update has unresolved files.
5400 """
5392 """
5401 fnames = (fname1,) + fnames
5393 fnames = (fname1,) + fnames
5402
5394
5403 with repo.lock():
5395 with repo.lock():
5404 for fname in fnames:
5396 for fname in fnames:
5405 f = hg.openpath(ui, fname)
5397 f = hg.openpath(ui, fname)
5406 gen = exchange.readbundle(ui, f, fname)
5398 gen = exchange.readbundle(ui, f, fname)
5407 if isinstance(gen, streamclone.streamcloneapplier):
5399 if isinstance(gen, streamclone.streamcloneapplier):
5408 raise error.Abort(
5400 raise error.Abort(
5409 _('packed bundles cannot be applied with '
5401 _('packed bundles cannot be applied with '
5410 '"hg unbundle"'),
5402 '"hg unbundle"'),
5411 hint=_('use "hg debugapplystreamclonebundle"'))
5403 hint=_('use "hg debugapplystreamclonebundle"'))
5412 url = 'bundle:' + fname
5404 url = 'bundle:' + fname
5413 try:
5405 try:
5414 txnname = 'unbundle'
5406 txnname = 'unbundle'
5415 if not isinstance(gen, bundle2.unbundle20):
5407 if not isinstance(gen, bundle2.unbundle20):
5416 txnname = 'unbundle\n%s' % util.hidepassword(url)
5408 txnname = 'unbundle\n%s' % util.hidepassword(url)
5417 with repo.transaction(txnname) as tr:
5409 with repo.transaction(txnname) as tr:
5418 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
5410 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
5419 url=url)
5411 url=url)
5420 except error.BundleUnknownFeatureError as exc:
5412 except error.BundleUnknownFeatureError as exc:
5421 raise error.Abort(
5413 raise error.Abort(
5422 _('%s: unknown bundle feature, %s') % (fname, exc),
5414 _('%s: unknown bundle feature, %s') % (fname, exc),
5423 hint=_("see https://mercurial-scm.org/"
5415 hint=_("see https://mercurial-scm.org/"
5424 "wiki/BundleFeature for more "
5416 "wiki/BundleFeature for more "
5425 "information"))
5417 "information"))
5426 modheads = bundle2.combinechangegroupresults(op)
5418 modheads = bundle2.combinechangegroupresults(op)
5427
5419
5428 return postincoming(ui, repo, modheads, opts.get(r'update'), None, None)
5420 return postincoming(ui, repo, modheads, opts.get(r'update'), None, None)
5429
5421
5430 @command('^update|up|checkout|co',
5422 @command('^update|up|checkout|co',
5431 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5423 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5432 ('c', 'check', None, _('require clean working directory')),
5424 ('c', 'check', None, _('require clean working directory')),
5433 ('m', 'merge', None, _('merge uncommitted changes')),
5425 ('m', 'merge', None, _('merge uncommitted changes')),
5434 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5426 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5435 ('r', 'rev', '', _('revision'), _('REV'))
5427 ('r', 'rev', '', _('revision'), _('REV'))
5436 ] + mergetoolopts,
5428 ] + mergetoolopts,
5437 _('[-C|-c|-m] [-d DATE] [[-r] REV]'))
5429 _('[-C|-c|-m] [-d DATE] [[-r] REV]'))
5438 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
5430 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
5439 merge=None, tool=None):
5431 merge=None, tool=None):
5440 """update working directory (or switch revisions)
5432 """update working directory (or switch revisions)
5441
5433
5442 Update the repository's working directory to the specified
5434 Update the repository's working directory to the specified
5443 changeset. If no changeset is specified, update to the tip of the
5435 changeset. If no changeset is specified, update to the tip of the
5444 current named branch and move the active bookmark (see :hg:`help
5436 current named branch and move the active bookmark (see :hg:`help
5445 bookmarks`).
5437 bookmarks`).
5446
5438
5447 Update sets the working directory's parent revision to the specified
5439 Update sets the working directory's parent revision to the specified
5448 changeset (see :hg:`help parents`).
5440 changeset (see :hg:`help parents`).
5449
5441
5450 If the changeset is not a descendant or ancestor of the working
5442 If the changeset is not a descendant or ancestor of the working
5451 directory's parent and there are uncommitted changes, the update is
5443 directory's parent and there are uncommitted changes, the update is
5452 aborted. With the -c/--check option, the working directory is checked
5444 aborted. With the -c/--check option, the working directory is checked
5453 for uncommitted changes; if none are found, the working directory is
5445 for uncommitted changes; if none are found, the working directory is
5454 updated to the specified changeset.
5446 updated to the specified changeset.
5455
5447
5456 .. container:: verbose
5448 .. container:: verbose
5457
5449
5458 The -C/--clean, -c/--check, and -m/--merge options control what
5450 The -C/--clean, -c/--check, and -m/--merge options control what
5459 happens if the working directory contains uncommitted changes.
5451 happens if the working directory contains uncommitted changes.
5460 At most of one of them can be specified.
5452 At most of one of them can be specified.
5461
5453
5462 1. If no option is specified, and if
5454 1. If no option is specified, and if
5463 the requested changeset is an ancestor or descendant of
5455 the requested changeset is an ancestor or descendant of
5464 the working directory's parent, the uncommitted changes
5456 the working directory's parent, the uncommitted changes
5465 are merged into the requested changeset and the merged
5457 are merged into the requested changeset and the merged
5466 result is left uncommitted. If the requested changeset is
5458 result is left uncommitted. If the requested changeset is
5467 not an ancestor or descendant (that is, it is on another
5459 not an ancestor or descendant (that is, it is on another
5468 branch), the update is aborted and the uncommitted changes
5460 branch), the update is aborted and the uncommitted changes
5469 are preserved.
5461 are preserved.
5470
5462
5471 2. With the -m/--merge option, the update is allowed even if the
5463 2. With the -m/--merge option, the update is allowed even if the
5472 requested changeset is not an ancestor or descendant of
5464 requested changeset is not an ancestor or descendant of
5473 the working directory's parent.
5465 the working directory's parent.
5474
5466
5475 3. With the -c/--check option, the update is aborted and the
5467 3. With the -c/--check option, the update is aborted and the
5476 uncommitted changes are preserved.
5468 uncommitted changes are preserved.
5477
5469
5478 4. With the -C/--clean option, uncommitted changes are discarded and
5470 4. With the -C/--clean option, uncommitted changes are discarded and
5479 the working directory is updated to the requested changeset.
5471 the working directory is updated to the requested changeset.
5480
5472
5481 To cancel an uncommitted merge (and lose your changes), use
5473 To cancel an uncommitted merge (and lose your changes), use
5482 :hg:`merge --abort`.
5474 :hg:`merge --abort`.
5483
5475
5484 Use null as the changeset to remove the working directory (like
5476 Use null as the changeset to remove the working directory (like
5485 :hg:`clone -U`).
5477 :hg:`clone -U`).
5486
5478
5487 If you want to revert just one file to an older revision, use
5479 If you want to revert just one file to an older revision, use
5488 :hg:`revert [-r REV] NAME`.
5480 :hg:`revert [-r REV] NAME`.
5489
5481
5490 See :hg:`help dates` for a list of formats valid for -d/--date.
5482 See :hg:`help dates` for a list of formats valid for -d/--date.
5491
5483
5492 Returns 0 on success, 1 if there are unresolved files.
5484 Returns 0 on success, 1 if there are unresolved files.
5493 """
5485 """
5494 if rev and node:
5486 if rev and node:
5495 raise error.Abort(_("please specify just one revision"))
5487 raise error.Abort(_("please specify just one revision"))
5496
5488
5497 if ui.configbool('commands', 'update.requiredest'):
5489 if ui.configbool('commands', 'update.requiredest'):
5498 if not node and not rev and not date:
5490 if not node and not rev and not date:
5499 raise error.Abort(_('you must specify a destination'),
5491 raise error.Abort(_('you must specify a destination'),
5500 hint=_('for example: hg update ".::"'))
5492 hint=_('for example: hg update ".::"'))
5501
5493
5502 if rev is None or rev == '':
5494 if rev is None or rev == '':
5503 rev = node
5495 rev = node
5504
5496
5505 if date and rev is not None:
5497 if date and rev is not None:
5506 raise error.Abort(_("you can't specify a revision and a date"))
5498 raise error.Abort(_("you can't specify a revision and a date"))
5507
5499
5508 if len([x for x in (clean, check, merge) if x]) > 1:
5500 if len([x for x in (clean, check, merge) if x]) > 1:
5509 raise error.Abort(_("can only specify one of -C/--clean, -c/--check, "
5501 raise error.Abort(_("can only specify one of -C/--clean, -c/--check, "
5510 "or -m/--merge"))
5502 "or -m/--merge"))
5511
5503
5512 updatecheck = None
5504 updatecheck = None
5513 if check:
5505 if check:
5514 updatecheck = 'abort'
5506 updatecheck = 'abort'
5515 elif merge:
5507 elif merge:
5516 updatecheck = 'none'
5508 updatecheck = 'none'
5517
5509
5518 with repo.wlock():
5510 with repo.wlock():
5519 cmdutil.clearunfinished(repo)
5511 cmdutil.clearunfinished(repo)
5520
5512
5521 if date:
5513 if date:
5522 rev = cmdutil.finddate(ui, repo, date)
5514 rev = cmdutil.finddate(ui, repo, date)
5523
5515
5524 # if we defined a bookmark, we have to remember the original name
5516 # if we defined a bookmark, we have to remember the original name
5525 brev = rev
5517 brev = rev
5526 if rev:
5518 if rev:
5527 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
5519 repo = scmutil.unhidehashlikerevs(repo, [rev], 'nowarn')
5528 ctx = scmutil.revsingle(repo, rev, rev)
5520 ctx = scmutil.revsingle(repo, rev, rev)
5529 rev = ctx.rev()
5521 rev = ctx.rev()
5530 if ctx.hidden():
5522 if ctx.hidden():
5531 ctxstr = ctx.hex()[:12]
5523 ctxstr = ctx.hex()[:12]
5532 ui.warn(_("updating to a hidden changeset %s\n") % ctxstr)
5524 ui.warn(_("updating to a hidden changeset %s\n") % ctxstr)
5533
5525
5534 if ctx.obsolete():
5526 if ctx.obsolete():
5535 obsfatemsg = obsutil._getfilteredreason(repo, ctxstr, ctx)
5527 obsfatemsg = obsutil._getfilteredreason(repo, ctxstr, ctx)
5536 ui.warn("(%s)\n" % obsfatemsg)
5528 ui.warn("(%s)\n" % obsfatemsg)
5537
5529
5538 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
5530 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
5539
5531
5540 return hg.updatetotally(ui, repo, rev, brev, clean=clean,
5532 return hg.updatetotally(ui, repo, rev, brev, clean=clean,
5541 updatecheck=updatecheck)
5533 updatecheck=updatecheck)
5542
5534
5543 @command('verify', [])
5535 @command('verify', [])
5544 def verify(ui, repo):
5536 def verify(ui, repo):
5545 """verify the integrity of the repository
5537 """verify the integrity of the repository
5546
5538
5547 Verify the integrity of the current repository.
5539 Verify the integrity of the current repository.
5548
5540
5549 This will perform an extensive check of the repository's
5541 This will perform an extensive check of the repository's
5550 integrity, validating the hashes and checksums of each entry in
5542 integrity, validating the hashes and checksums of each entry in
5551 the changelog, manifest, and tracked files, as well as the
5543 the changelog, manifest, and tracked files, as well as the
5552 integrity of their crosslinks and indices.
5544 integrity of their crosslinks and indices.
5553
5545
5554 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
5546 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
5555 for more information about recovery from corruption of the
5547 for more information about recovery from corruption of the
5556 repository.
5548 repository.
5557
5549
5558 Returns 0 on success, 1 if errors are encountered.
5550 Returns 0 on success, 1 if errors are encountered.
5559 """
5551 """
5560 return hg.verify(repo)
5552 return hg.verify(repo)
5561
5553
5562 @command('version', [] + formatteropts, norepo=True, cmdtype=readonly)
5554 @command('version', [] + formatteropts, norepo=True, cmdtype=readonly)
5563 def version_(ui, **opts):
5555 def version_(ui, **opts):
5564 """output version and copyright information"""
5556 """output version and copyright information"""
5565 opts = pycompat.byteskwargs(opts)
5557 opts = pycompat.byteskwargs(opts)
5566 if ui.verbose:
5558 if ui.verbose:
5567 ui.pager('version')
5559 ui.pager('version')
5568 fm = ui.formatter("version", opts)
5560 fm = ui.formatter("version", opts)
5569 fm.startitem()
5561 fm.startitem()
5570 fm.write("ver", _("Mercurial Distributed SCM (version %s)\n"),
5562 fm.write("ver", _("Mercurial Distributed SCM (version %s)\n"),
5571 util.version())
5563 util.version())
5572 license = _(
5564 license = _(
5573 "(see https://mercurial-scm.org for more information)\n"
5565 "(see https://mercurial-scm.org for more information)\n"
5574 "\nCopyright (C) 2005-2018 Matt Mackall and others\n"
5566 "\nCopyright (C) 2005-2018 Matt Mackall and others\n"
5575 "This is free software; see the source for copying conditions. "
5567 "This is free software; see the source for copying conditions. "
5576 "There is NO\nwarranty; "
5568 "There is NO\nwarranty; "
5577 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5569 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5578 )
5570 )
5579 if not ui.quiet:
5571 if not ui.quiet:
5580 fm.plain(license)
5572 fm.plain(license)
5581
5573
5582 if ui.verbose:
5574 if ui.verbose:
5583 fm.plain(_("\nEnabled extensions:\n\n"))
5575 fm.plain(_("\nEnabled extensions:\n\n"))
5584 # format names and versions into columns
5576 # format names and versions into columns
5585 names = []
5577 names = []
5586 vers = []
5578 vers = []
5587 isinternals = []
5579 isinternals = []
5588 for name, module in extensions.extensions():
5580 for name, module in extensions.extensions():
5589 names.append(name)
5581 names.append(name)
5590 vers.append(extensions.moduleversion(module) or None)
5582 vers.append(extensions.moduleversion(module) or None)
5591 isinternals.append(extensions.ismoduleinternal(module))
5583 isinternals.append(extensions.ismoduleinternal(module))
5592 fn = fm.nested("extensions")
5584 fn = fm.nested("extensions")
5593 if names:
5585 if names:
5594 namefmt = " %%-%ds " % max(len(n) for n in names)
5586 namefmt = " %%-%ds " % max(len(n) for n in names)
5595 places = [_("external"), _("internal")]
5587 places = [_("external"), _("internal")]
5596 for n, v, p in zip(names, vers, isinternals):
5588 for n, v, p in zip(names, vers, isinternals):
5597 fn.startitem()
5589 fn.startitem()
5598 fn.condwrite(ui.verbose, "name", namefmt, n)
5590 fn.condwrite(ui.verbose, "name", namefmt, n)
5599 if ui.verbose:
5591 if ui.verbose:
5600 fn.plain("%s " % places[p])
5592 fn.plain("%s " % places[p])
5601 fn.data(bundled=p)
5593 fn.data(bundled=p)
5602 fn.condwrite(ui.verbose and v, "ver", "%s", v)
5594 fn.condwrite(ui.verbose and v, "ver", "%s", v)
5603 if ui.verbose:
5595 if ui.verbose:
5604 fn.plain("\n")
5596 fn.plain("\n")
5605 fn.end()
5597 fn.end()
5606 fm.end()
5598 fm.end()
5607
5599
5608 def loadcmdtable(ui, name, cmdtable):
5600 def loadcmdtable(ui, name, cmdtable):
5609 """Load command functions from specified cmdtable
5601 """Load command functions from specified cmdtable
5610 """
5602 """
5611 overrides = [cmd for cmd in cmdtable if cmd in table]
5603 overrides = [cmd for cmd in cmdtable if cmd in table]
5612 if overrides:
5604 if overrides:
5613 ui.warn(_("extension '%s' overrides commands: %s\n")
5605 ui.warn(_("extension '%s' overrides commands: %s\n")
5614 % (name, " ".join(overrides)))
5606 % (name, " ".join(overrides)))
5615 table.update(cmdtable)
5607 table.update(cmdtable)
@@ -1,250 +1,249 b''
1 hide outer repo
1 hide outer repo
2 $ hg init
2 $ hg init
3
3
4 Use hgrc within $TESTTMP
4 Use hgrc within $TESTTMP
5
5
6 $ HGRCPATH=`pwd`/hgrc
6 $ HGRCPATH=`pwd`/hgrc
7 $ export HGRCPATH
7 $ export HGRCPATH
8
8
9 Use an alternate var for scribbling on hgrc to keep check-code from
9 Use an alternate var for scribbling on hgrc to keep check-code from
10 complaining about the important settings we may be overwriting:
10 complaining about the important settings we may be overwriting:
11
11
12 $ HGRC=`pwd`/hgrc
12 $ HGRC=`pwd`/hgrc
13 $ export HGRC
13 $ export HGRC
14
14
15 Basic syntax error
15 Basic syntax error
16
16
17 $ echo "invalid" > $HGRC
17 $ echo "invalid" > $HGRC
18 $ hg version
18 $ hg version
19 hg: parse error at $TESTTMP/hgrc:1: invalid
19 hg: parse error at $TESTTMP/hgrc:1: invalid
20 [255]
20 [255]
21 $ echo "" > $HGRC
21 $ echo "" > $HGRC
22
22
23 Issue1199: Can't use '%' in hgrc (eg url encoded username)
23 Issue1199: Can't use '%' in hgrc (eg url encoded username)
24
24
25 $ hg init "foo%bar"
25 $ hg init "foo%bar"
26 $ hg clone "foo%bar" foobar
26 $ hg clone "foo%bar" foobar
27 updating to branch default
27 updating to branch default
28 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
28 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
29 $ cd foobar
29 $ cd foobar
30 $ cat .hg/hgrc
30 $ cat .hg/hgrc
31 # example repository config (see 'hg help config' for more info)
31 # example repository config (see 'hg help config' for more info)
32 [paths]
32 [paths]
33 default = $TESTTMP/foo%bar
33 default = $TESTTMP/foo%bar
34
34
35 # path aliases to other clones of this repo in URLs or filesystem paths
35 # path aliases to other clones of this repo in URLs or filesystem paths
36 # (see 'hg help config.paths' for more info)
36 # (see 'hg help config.paths' for more info)
37 #
37 #
38 # default:pushurl = ssh://jdoe@example.net/hg/jdoes-fork
38 # default:pushurl = ssh://jdoe@example.net/hg/jdoes-fork
39 # my-fork = ssh://jdoe@example.net/hg/jdoes-fork
39 # my-fork = ssh://jdoe@example.net/hg/jdoes-fork
40 # my-clone = /home/jdoe/jdoes-clone
40 # my-clone = /home/jdoe/jdoes-clone
41
41
42 [ui]
42 [ui]
43 # name and email (local to this repository, optional), e.g.
43 # name and email (local to this repository, optional), e.g.
44 # username = Jane Doe <jdoe@example.com>
44 # username = Jane Doe <jdoe@example.com>
45 $ hg paths
45 $ hg paths
46 default = $TESTTMP/foo%bar
46 default = $TESTTMP/foo%bar
47 $ hg showconfig
47 $ hg showconfig
48 bundle.mainreporoot=$TESTTMP/foobar
48 bundle.mainreporoot=$TESTTMP/foobar
49 paths.default=$TESTTMP/foo%bar
49 paths.default=$TESTTMP/foo%bar
50 $ cd ..
50 $ cd ..
51
51
52 issue1829: wrong indentation
52 issue1829: wrong indentation
53
53
54 $ echo '[foo]' > $HGRC
54 $ echo '[foo]' > $HGRC
55 $ echo ' x = y' >> $HGRC
55 $ echo ' x = y' >> $HGRC
56 $ hg version
56 $ hg version
57 hg: parse error at $TESTTMP/hgrc:2: x = y
57 hg: parse error at $TESTTMP/hgrc:2: x = y
58 unexpected leading whitespace
58 unexpected leading whitespace
59 [255]
59 [255]
60
60
61 $ $PYTHON -c "print '[foo]\nbar = a\n b\n c \n de\n fg \nbaz = bif cb \n'" \
61 $ $PYTHON -c "print '[foo]\nbar = a\n b\n c \n de\n fg \nbaz = bif cb \n'" \
62 > > $HGRC
62 > > $HGRC
63 $ hg showconfig foo
63 $ hg showconfig foo
64 foo.bar=a\nb\nc\nde\nfg
64 foo.bar=a\nb\nc\nde\nfg
65 foo.baz=bif cb
65 foo.baz=bif cb
66
66
67 $ FAKEPATH=/path/to/nowhere
67 $ FAKEPATH=/path/to/nowhere
68 $ export FAKEPATH
68 $ export FAKEPATH
69 $ echo '%include $FAKEPATH/no-such-file' > $HGRC
69 $ echo '%include $FAKEPATH/no-such-file' > $HGRC
70 $ hg version
70 $ hg version
71 Mercurial Distributed SCM (version *) (glob)
71 Mercurial Distributed SCM (version *) (glob)
72 (see https://mercurial-scm.org for more information)
72 (see https://mercurial-scm.org for more information)
73
73
74 Copyright (C) 2005-* Matt Mackall and others (glob)
74 Copyright (C) 2005-* Matt Mackall and others (glob)
75 This is free software; see the source for copying conditions. There is NO
75 This is free software; see the source for copying conditions. There is NO
76 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
76 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
77 $ unset FAKEPATH
77 $ unset FAKEPATH
78
78
79 make sure global options given on the cmdline take precedence
79 make sure global options given on the cmdline take precedence
80
80
81 $ hg showconfig --config ui.verbose=True --quiet
81 $ hg showconfig --config ui.verbose=True --quiet
82 bundle.mainreporoot=$TESTTMP
82 bundle.mainreporoot=$TESTTMP
83 ui.verbose=False
83 ui.verbose=False
84 ui.debug=False
84 ui.debug=False
85 ui.quiet=True
85 ui.quiet=True
86
86
87 $ touch foobar/untracked
87 $ touch foobar/untracked
88 $ cat >> foobar/.hg/hgrc <<EOF
88 $ cat >> foobar/.hg/hgrc <<EOF
89 > [ui]
89 > [ui]
90 > verbose=True
90 > verbose=True
91 > EOF
91 > EOF
92 $ hg -R foobar st -q
92 $ hg -R foobar st -q
93
93
94 username expansion
94 username expansion
95
95
96 $ olduser=$HGUSER
96 $ olduser=$HGUSER
97 $ unset HGUSER
97 $ unset HGUSER
98
98
99 $ FAKEUSER='John Doe'
99 $ FAKEUSER='John Doe'
100 $ export FAKEUSER
100 $ export FAKEUSER
101 $ echo '[ui]' > $HGRC
101 $ echo '[ui]' > $HGRC
102 $ echo 'username = $FAKEUSER' >> $HGRC
102 $ echo 'username = $FAKEUSER' >> $HGRC
103
103
104 $ hg init usertest
104 $ hg init usertest
105 $ cd usertest
105 $ cd usertest
106 $ touch bar
106 $ touch bar
107 $ hg commit --addremove --quiet -m "added bar"
107 $ hg commit --addremove --quiet -m "added bar"
108 $ hg log --template "{author}\n"
108 $ hg log --template "{author}\n"
109 John Doe
109 John Doe
110 $ cd ..
110 $ cd ..
111
111
112 $ hg showconfig
112 $ hg showconfig
113 bundle.mainreporoot=$TESTTMP
113 bundle.mainreporoot=$TESTTMP
114 ui.username=$FAKEUSER
114 ui.username=$FAKEUSER
115
115
116 $ unset FAKEUSER
116 $ unset FAKEUSER
117 $ HGUSER=$olduser
117 $ HGUSER=$olduser
118 $ export HGUSER
118 $ export HGUSER
119
119
120 showconfig with multiple arguments
120 showconfig with multiple arguments
121
121
122 $ echo "[alias]" > $HGRC
122 $ echo "[alias]" > $HGRC
123 $ echo "log = log -g" >> $HGRC
123 $ echo "log = log -g" >> $HGRC
124 $ echo "[defaults]" >> $HGRC
124 $ echo "[defaults]" >> $HGRC
125 $ echo "identify = -n" >> $HGRC
125 $ echo "identify = -n" >> $HGRC
126 $ hg showconfig alias defaults
126 $ hg showconfig alias defaults
127 alias.log=log -g
127 alias.log=log -g
128 defaults.identify=-n
128 defaults.identify=-n
129 $ hg showconfig alias alias
129 $ hg showconfig alias alias
130 alias.log=log -g
130 alias.log=log -g
131 $ hg showconfig alias.log alias.log
131 $ hg showconfig alias.log alias.log
132 abort: only one config item permitted
132 alias.log=log -g
133 [255]
134 $ hg showconfig alias defaults.identify
133 $ hg showconfig alias defaults.identify
135 abort: only one config item permitted
134 alias.log=log -g
136 [255]
135 defaults.identify=-n
137 $ hg showconfig alias.log defaults.identify
136 $ hg showconfig alias.log defaults.identify
138 abort: only one config item permitted
137 alias.log=log -g
139 [255]
138 defaults.identify=-n
140
139
141 HGPLAIN
140 HGPLAIN
142
141
143 $ echo "[ui]" > $HGRC
142 $ echo "[ui]" > $HGRC
144 $ echo "debug=true" >> $HGRC
143 $ echo "debug=true" >> $HGRC
145 $ echo "fallbackencoding=ASCII" >> $HGRC
144 $ echo "fallbackencoding=ASCII" >> $HGRC
146 $ echo "quiet=true" >> $HGRC
145 $ echo "quiet=true" >> $HGRC
147 $ echo "slash=true" >> $HGRC
146 $ echo "slash=true" >> $HGRC
148 $ echo "traceback=true" >> $HGRC
147 $ echo "traceback=true" >> $HGRC
149 $ echo "verbose=true" >> $HGRC
148 $ echo "verbose=true" >> $HGRC
150 $ echo "style=~/.hgstyle" >> $HGRC
149 $ echo "style=~/.hgstyle" >> $HGRC
151 $ echo "logtemplate={node}" >> $HGRC
150 $ echo "logtemplate={node}" >> $HGRC
152 $ echo "[defaults]" >> $HGRC
151 $ echo "[defaults]" >> $HGRC
153 $ echo "identify=-n" >> $HGRC
152 $ echo "identify=-n" >> $HGRC
154 $ echo "[alias]" >> $HGRC
153 $ echo "[alias]" >> $HGRC
155 $ echo "log=log -g" >> $HGRC
154 $ echo "log=log -g" >> $HGRC
156
155
157 customized hgrc
156 customized hgrc
158
157
159 $ hg showconfig
158 $ hg showconfig
160 read config from: $TESTTMP/hgrc
159 read config from: $TESTTMP/hgrc
161 $TESTTMP/hgrc:13: alias.log=log -g
160 $TESTTMP/hgrc:13: alias.log=log -g
162 repo: bundle.mainreporoot=$TESTTMP
161 repo: bundle.mainreporoot=$TESTTMP
163 $TESTTMP/hgrc:11: defaults.identify=-n
162 $TESTTMP/hgrc:11: defaults.identify=-n
164 $TESTTMP/hgrc:2: ui.debug=true
163 $TESTTMP/hgrc:2: ui.debug=true
165 $TESTTMP/hgrc:3: ui.fallbackencoding=ASCII
164 $TESTTMP/hgrc:3: ui.fallbackencoding=ASCII
166 $TESTTMP/hgrc:4: ui.quiet=true
165 $TESTTMP/hgrc:4: ui.quiet=true
167 $TESTTMP/hgrc:5: ui.slash=true
166 $TESTTMP/hgrc:5: ui.slash=true
168 $TESTTMP/hgrc:6: ui.traceback=true
167 $TESTTMP/hgrc:6: ui.traceback=true
169 $TESTTMP/hgrc:7: ui.verbose=true
168 $TESTTMP/hgrc:7: ui.verbose=true
170 $TESTTMP/hgrc:8: ui.style=~/.hgstyle
169 $TESTTMP/hgrc:8: ui.style=~/.hgstyle
171 $TESTTMP/hgrc:9: ui.logtemplate={node}
170 $TESTTMP/hgrc:9: ui.logtemplate={node}
172
171
173 plain hgrc
172 plain hgrc
174
173
175 $ HGPLAIN=; export HGPLAIN
174 $ HGPLAIN=; export HGPLAIN
176 $ hg showconfig --config ui.traceback=True --debug
175 $ hg showconfig --config ui.traceback=True --debug
177 read config from: $TESTTMP/hgrc
176 read config from: $TESTTMP/hgrc
178 repo: bundle.mainreporoot=$TESTTMP
177 repo: bundle.mainreporoot=$TESTTMP
179 --config: ui.traceback=True
178 --config: ui.traceback=True
180 --verbose: ui.verbose=False
179 --verbose: ui.verbose=False
181 --debug: ui.debug=True
180 --debug: ui.debug=True
182 --quiet: ui.quiet=False
181 --quiet: ui.quiet=False
183
182
184 with environment variables
183 with environment variables
185
184
186 $ PAGER=p1 EDITOR=e1 VISUAL=e2 hg showconfig --debug
185 $ PAGER=p1 EDITOR=e1 VISUAL=e2 hg showconfig --debug
187 set config by: $EDITOR
186 set config by: $EDITOR
188 set config by: $VISUAL
187 set config by: $VISUAL
189 set config by: $PAGER
188 set config by: $PAGER
190 read config from: $TESTTMP/hgrc
189 read config from: $TESTTMP/hgrc
191 repo: bundle.mainreporoot=$TESTTMP
190 repo: bundle.mainreporoot=$TESTTMP
192 $PAGER: pager.pager=p1
191 $PAGER: pager.pager=p1
193 $VISUAL: ui.editor=e2
192 $VISUAL: ui.editor=e2
194 --verbose: ui.verbose=False
193 --verbose: ui.verbose=False
195 --debug: ui.debug=True
194 --debug: ui.debug=True
196 --quiet: ui.quiet=False
195 --quiet: ui.quiet=False
197
196
198 plain mode with exceptions
197 plain mode with exceptions
199
198
200 $ cat > plain.py <<EOF
199 $ cat > plain.py <<EOF
201 > from mercurial import commands, extensions
200 > from mercurial import commands, extensions
202 > def _config(orig, ui, repo, *values, **opts):
201 > def _config(orig, ui, repo, *values, **opts):
203 > ui.write('plain: %r\n' % ui.plain())
202 > ui.write('plain: %r\n' % ui.plain())
204 > return orig(ui, repo, *values, **opts)
203 > return orig(ui, repo, *values, **opts)
205 > def uisetup(ui):
204 > def uisetup(ui):
206 > extensions.wrapcommand(commands.table, 'config', _config)
205 > extensions.wrapcommand(commands.table, 'config', _config)
207 > EOF
206 > EOF
208 $ echo "[extensions]" >> $HGRC
207 $ echo "[extensions]" >> $HGRC
209 $ echo "plain=./plain.py" >> $HGRC
208 $ echo "plain=./plain.py" >> $HGRC
210 $ HGPLAINEXCEPT=; export HGPLAINEXCEPT
209 $ HGPLAINEXCEPT=; export HGPLAINEXCEPT
211 $ hg showconfig --config ui.traceback=True --debug
210 $ hg showconfig --config ui.traceback=True --debug
212 plain: True
211 plain: True
213 read config from: $TESTTMP/hgrc
212 read config from: $TESTTMP/hgrc
214 repo: bundle.mainreporoot=$TESTTMP
213 repo: bundle.mainreporoot=$TESTTMP
215 $TESTTMP/hgrc:15: extensions.plain=./plain.py
214 $TESTTMP/hgrc:15: extensions.plain=./plain.py
216 --config: ui.traceback=True
215 --config: ui.traceback=True
217 --verbose: ui.verbose=False
216 --verbose: ui.verbose=False
218 --debug: ui.debug=True
217 --debug: ui.debug=True
219 --quiet: ui.quiet=False
218 --quiet: ui.quiet=False
220 $ unset HGPLAIN
219 $ unset HGPLAIN
221 $ hg showconfig --config ui.traceback=True --debug
220 $ hg showconfig --config ui.traceback=True --debug
222 plain: True
221 plain: True
223 read config from: $TESTTMP/hgrc
222 read config from: $TESTTMP/hgrc
224 repo: bundle.mainreporoot=$TESTTMP
223 repo: bundle.mainreporoot=$TESTTMP
225 $TESTTMP/hgrc:15: extensions.plain=./plain.py
224 $TESTTMP/hgrc:15: extensions.plain=./plain.py
226 --config: ui.traceback=True
225 --config: ui.traceback=True
227 --verbose: ui.verbose=False
226 --verbose: ui.verbose=False
228 --debug: ui.debug=True
227 --debug: ui.debug=True
229 --quiet: ui.quiet=False
228 --quiet: ui.quiet=False
230 $ HGPLAINEXCEPT=i18n; export HGPLAINEXCEPT
229 $ HGPLAINEXCEPT=i18n; export HGPLAINEXCEPT
231 $ hg showconfig --config ui.traceback=True --debug
230 $ hg showconfig --config ui.traceback=True --debug
232 plain: True
231 plain: True
233 read config from: $TESTTMP/hgrc
232 read config from: $TESTTMP/hgrc
234 repo: bundle.mainreporoot=$TESTTMP
233 repo: bundle.mainreporoot=$TESTTMP
235 $TESTTMP/hgrc:15: extensions.plain=./plain.py
234 $TESTTMP/hgrc:15: extensions.plain=./plain.py
236 --config: ui.traceback=True
235 --config: ui.traceback=True
237 --verbose: ui.verbose=False
236 --verbose: ui.verbose=False
238 --debug: ui.debug=True
237 --debug: ui.debug=True
239 --quiet: ui.quiet=False
238 --quiet: ui.quiet=False
240
239
241 source of paths is not mangled
240 source of paths is not mangled
242
241
243 $ cat >> $HGRCPATH <<EOF
242 $ cat >> $HGRCPATH <<EOF
244 > [paths]
243 > [paths]
245 > foo = bar
244 > foo = bar
246 > EOF
245 > EOF
247 $ hg showconfig --debug paths
246 $ hg showconfig --debug paths
248 plain: True
247 plain: True
249 read config from: $TESTTMP/hgrc
248 read config from: $TESTTMP/hgrc
250 $TESTTMP/hgrc:17: paths.foo=$TESTTMP/bar
249 $TESTTMP/hgrc:17: paths.foo=$TESTTMP/bar
General Comments 0
You need to be logged in to leave comments. Login now