##// END OF EJS Templates
heads: enable pager
Martin von Zweigbergk -
r31387:3d310933 default
parent child Browse files
Show More
@@ -1,5451 +1,5452 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
14
15 from .i18n import _
15 from .i18n import _
16 from .node import (
16 from .node import (
17 hex,
17 hex,
18 nullid,
18 nullid,
19 nullrev,
19 nullrev,
20 short,
20 short,
21 )
21 )
22 from . import (
22 from . import (
23 archival,
23 archival,
24 bookmarks,
24 bookmarks,
25 bundle2,
25 bundle2,
26 changegroup,
26 changegroup,
27 cmdutil,
27 cmdutil,
28 copies,
28 copies,
29 destutil,
29 destutil,
30 dirstateguard,
30 dirstateguard,
31 discovery,
31 discovery,
32 encoding,
32 encoding,
33 error,
33 error,
34 exchange,
34 exchange,
35 extensions,
35 extensions,
36 graphmod,
36 graphmod,
37 hbisect,
37 hbisect,
38 help,
38 help,
39 hg,
39 hg,
40 lock as lockmod,
40 lock as lockmod,
41 merge as mergemod,
41 merge as mergemod,
42 obsolete,
42 obsolete,
43 patch,
43 patch,
44 phases,
44 phases,
45 pycompat,
45 pycompat,
46 revsetlang,
46 revsetlang,
47 scmutil,
47 scmutil,
48 server,
48 server,
49 sshserver,
49 sshserver,
50 streamclone,
50 streamclone,
51 templatekw,
51 templatekw,
52 ui as uimod,
52 ui as uimod,
53 util,
53 util,
54 )
54 )
55
55
56 release = lockmod.release
56 release = lockmod.release
57
57
58 table = {}
58 table = {}
59
59
60 command = cmdutil.command(table)
60 command = cmdutil.command(table)
61
61
62 # label constants
62 # label constants
63 # until 3.5, bookmarks.current was the advertised name, not
63 # until 3.5, bookmarks.current was the advertised name, not
64 # bookmarks.active, so we must use both to avoid breaking old
64 # bookmarks.active, so we must use both to avoid breaking old
65 # custom styles
65 # custom styles
66 activebookmarklabel = 'bookmarks.active bookmarks.current'
66 activebookmarklabel = 'bookmarks.active bookmarks.current'
67
67
68 # common command options
68 # common command options
69
69
70 globalopts = [
70 globalopts = [
71 ('R', 'repository', '',
71 ('R', 'repository', '',
72 _('repository root directory or name of overlay bundle file'),
72 _('repository root directory or name of overlay bundle file'),
73 _('REPO')),
73 _('REPO')),
74 ('', 'cwd', '',
74 ('', 'cwd', '',
75 _('change working directory'), _('DIR')),
75 _('change working directory'), _('DIR')),
76 ('y', 'noninteractive', None,
76 ('y', 'noninteractive', None,
77 _('do not prompt, automatically pick the first choice for all prompts')),
77 _('do not prompt, automatically pick the first choice for all prompts')),
78 ('q', 'quiet', None, _('suppress output')),
78 ('q', 'quiet', None, _('suppress output')),
79 ('v', 'verbose', None, _('enable additional output')),
79 ('v', 'verbose', None, _('enable additional output')),
80 ('', 'color', '',
80 ('', 'color', '',
81 # i18n: 'always', 'auto', 'never', and 'debug' are keywords
81 # i18n: 'always', 'auto', 'never', and 'debug' are keywords
82 # and should not be translated
82 # and should not be translated
83 _("when to colorize (boolean, always, auto, never, or debug)"),
83 _("when to colorize (boolean, always, auto, never, or debug)"),
84 _('TYPE')),
84 _('TYPE')),
85 ('', 'config', [],
85 ('', 'config', [],
86 _('set/override config option (use \'section.name=value\')'),
86 _('set/override config option (use \'section.name=value\')'),
87 _('CONFIG')),
87 _('CONFIG')),
88 ('', 'debug', None, _('enable debugging output')),
88 ('', 'debug', None, _('enable debugging output')),
89 ('', 'debugger', None, _('start debugger')),
89 ('', 'debugger', None, _('start debugger')),
90 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
90 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
91 _('ENCODE')),
91 _('ENCODE')),
92 ('', 'encodingmode', encoding.encodingmode,
92 ('', 'encodingmode', encoding.encodingmode,
93 _('set the charset encoding mode'), _('MODE')),
93 _('set the charset encoding mode'), _('MODE')),
94 ('', 'traceback', None, _('always print a traceback on exception')),
94 ('', 'traceback', None, _('always print a traceback on exception')),
95 ('', 'time', None, _('time how long the command takes')),
95 ('', 'time', None, _('time how long the command takes')),
96 ('', 'profile', None, _('print command execution profile')),
96 ('', 'profile', None, _('print command execution profile')),
97 ('', 'version', None, _('output version information and exit')),
97 ('', 'version', None, _('output version information and exit')),
98 ('h', 'help', None, _('display help and exit')),
98 ('h', 'help', None, _('display help and exit')),
99 ('', 'hidden', False, _('consider hidden changesets')),
99 ('', 'hidden', False, _('consider hidden changesets')),
100 ('', 'pager', 'auto',
100 ('', 'pager', 'auto',
101 _("when to paginate (boolean, always, auto, or never)"), _('TYPE')),
101 _("when to paginate (boolean, always, auto, or never)"), _('TYPE')),
102 ]
102 ]
103
103
104 dryrunopts = [('n', 'dry-run', None,
104 dryrunopts = [('n', 'dry-run', None,
105 _('do not perform actions, just print output'))]
105 _('do not perform actions, just print output'))]
106
106
107 remoteopts = [
107 remoteopts = [
108 ('e', 'ssh', '',
108 ('e', 'ssh', '',
109 _('specify ssh command to use'), _('CMD')),
109 _('specify ssh command to use'), _('CMD')),
110 ('', 'remotecmd', '',
110 ('', 'remotecmd', '',
111 _('specify hg command to run on the remote side'), _('CMD')),
111 _('specify hg command to run on the remote side'), _('CMD')),
112 ('', 'insecure', None,
112 ('', 'insecure', None,
113 _('do not verify server certificate (ignoring web.cacerts config)')),
113 _('do not verify server certificate (ignoring web.cacerts config)')),
114 ]
114 ]
115
115
116 walkopts = [
116 walkopts = [
117 ('I', 'include', [],
117 ('I', 'include', [],
118 _('include names matching the given patterns'), _('PATTERN')),
118 _('include names matching the given patterns'), _('PATTERN')),
119 ('X', 'exclude', [],
119 ('X', 'exclude', [],
120 _('exclude names matching the given patterns'), _('PATTERN')),
120 _('exclude names matching the given patterns'), _('PATTERN')),
121 ]
121 ]
122
122
123 commitopts = [
123 commitopts = [
124 ('m', 'message', '',
124 ('m', 'message', '',
125 _('use text as commit message'), _('TEXT')),
125 _('use text as commit message'), _('TEXT')),
126 ('l', 'logfile', '',
126 ('l', 'logfile', '',
127 _('read commit message from file'), _('FILE')),
127 _('read commit message from file'), _('FILE')),
128 ]
128 ]
129
129
130 commitopts2 = [
130 commitopts2 = [
131 ('d', 'date', '',
131 ('d', 'date', '',
132 _('record the specified date as commit date'), _('DATE')),
132 _('record the specified date as commit date'), _('DATE')),
133 ('u', 'user', '',
133 ('u', 'user', '',
134 _('record the specified user as committer'), _('USER')),
134 _('record the specified user as committer'), _('USER')),
135 ]
135 ]
136
136
137 # hidden for now
137 # hidden for now
138 formatteropts = [
138 formatteropts = [
139 ('T', 'template', '',
139 ('T', 'template', '',
140 _('display with template (EXPERIMENTAL)'), _('TEMPLATE')),
140 _('display with template (EXPERIMENTAL)'), _('TEMPLATE')),
141 ]
141 ]
142
142
143 templateopts = [
143 templateopts = [
144 ('', 'style', '',
144 ('', 'style', '',
145 _('display using template map file (DEPRECATED)'), _('STYLE')),
145 _('display using template map file (DEPRECATED)'), _('STYLE')),
146 ('T', 'template', '',
146 ('T', 'template', '',
147 _('display with template'), _('TEMPLATE')),
147 _('display with template'), _('TEMPLATE')),
148 ]
148 ]
149
149
150 logopts = [
150 logopts = [
151 ('p', 'patch', None, _('show patch')),
151 ('p', 'patch', None, _('show patch')),
152 ('g', 'git', None, _('use git extended diff format')),
152 ('g', 'git', None, _('use git extended diff format')),
153 ('l', 'limit', '',
153 ('l', 'limit', '',
154 _('limit number of changes displayed'), _('NUM')),
154 _('limit number of changes displayed'), _('NUM')),
155 ('M', 'no-merges', None, _('do not show merges')),
155 ('M', 'no-merges', None, _('do not show merges')),
156 ('', 'stat', None, _('output diffstat-style summary of changes')),
156 ('', 'stat', None, _('output diffstat-style summary of changes')),
157 ('G', 'graph', None, _("show the revision DAG")),
157 ('G', 'graph', None, _("show the revision DAG")),
158 ] + templateopts
158 ] + templateopts
159
159
160 diffopts = [
160 diffopts = [
161 ('a', 'text', None, _('treat all files as text')),
161 ('a', 'text', None, _('treat all files as text')),
162 ('g', 'git', None, _('use git extended diff format')),
162 ('g', 'git', None, _('use git extended diff format')),
163 ('', 'nodates', None, _('omit dates from diff headers'))
163 ('', 'nodates', None, _('omit dates from diff headers'))
164 ]
164 ]
165
165
166 diffwsopts = [
166 diffwsopts = [
167 ('w', 'ignore-all-space', None,
167 ('w', 'ignore-all-space', None,
168 _('ignore white space when comparing lines')),
168 _('ignore white space when comparing lines')),
169 ('b', 'ignore-space-change', None,
169 ('b', 'ignore-space-change', None,
170 _('ignore changes in the amount of white space')),
170 _('ignore changes in the amount of white space')),
171 ('B', 'ignore-blank-lines', None,
171 ('B', 'ignore-blank-lines', None,
172 _('ignore changes whose lines are all blank')),
172 _('ignore changes whose lines are all blank')),
173 ]
173 ]
174
174
175 diffopts2 = [
175 diffopts2 = [
176 ('', 'noprefix', None, _('omit a/ and b/ prefixes from filenames')),
176 ('', 'noprefix', None, _('omit a/ and b/ prefixes from filenames')),
177 ('p', 'show-function', None, _('show which function each change is in')),
177 ('p', 'show-function', None, _('show which function each change is in')),
178 ('', 'reverse', None, _('produce a diff that undoes the changes')),
178 ('', 'reverse', None, _('produce a diff that undoes the changes')),
179 ] + diffwsopts + [
179 ] + diffwsopts + [
180 ('U', 'unified', '',
180 ('U', 'unified', '',
181 _('number of lines of context to show'), _('NUM')),
181 _('number of lines of context to show'), _('NUM')),
182 ('', 'stat', None, _('output diffstat-style summary of changes')),
182 ('', 'stat', None, _('output diffstat-style summary of changes')),
183 ('', 'root', '', _('produce diffs relative to subdirectory'), _('DIR')),
183 ('', 'root', '', _('produce diffs relative to subdirectory'), _('DIR')),
184 ]
184 ]
185
185
186 mergetoolopts = [
186 mergetoolopts = [
187 ('t', 'tool', '', _('specify merge tool')),
187 ('t', 'tool', '', _('specify merge tool')),
188 ]
188 ]
189
189
190 similarityopts = [
190 similarityopts = [
191 ('s', 'similarity', '',
191 ('s', 'similarity', '',
192 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
192 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
193 ]
193 ]
194
194
195 subrepoopts = [
195 subrepoopts = [
196 ('S', 'subrepos', None,
196 ('S', 'subrepos', None,
197 _('recurse into subrepositories'))
197 _('recurse into subrepositories'))
198 ]
198 ]
199
199
200 debugrevlogopts = [
200 debugrevlogopts = [
201 ('c', 'changelog', False, _('open changelog')),
201 ('c', 'changelog', False, _('open changelog')),
202 ('m', 'manifest', False, _('open manifest')),
202 ('m', 'manifest', False, _('open manifest')),
203 ('', 'dir', '', _('open directory manifest')),
203 ('', 'dir', '', _('open directory manifest')),
204 ]
204 ]
205
205
206 # Commands start here, listed alphabetically
206 # Commands start here, listed alphabetically
207
207
208 @command('^add',
208 @command('^add',
209 walkopts + subrepoopts + dryrunopts,
209 walkopts + subrepoopts + dryrunopts,
210 _('[OPTION]... [FILE]...'),
210 _('[OPTION]... [FILE]...'),
211 inferrepo=True)
211 inferrepo=True)
212 def add(ui, repo, *pats, **opts):
212 def add(ui, repo, *pats, **opts):
213 """add the specified files on the next commit
213 """add the specified files on the next commit
214
214
215 Schedule files to be version controlled and added to the
215 Schedule files to be version controlled and added to the
216 repository.
216 repository.
217
217
218 The files will be added to the repository at the next commit. To
218 The files will be added to the repository at the next commit. To
219 undo an add before that, see :hg:`forget`.
219 undo an add before that, see :hg:`forget`.
220
220
221 If no names are given, add all files to the repository (except
221 If no names are given, add all files to the repository (except
222 files matching ``.hgignore``).
222 files matching ``.hgignore``).
223
223
224 .. container:: verbose
224 .. container:: verbose
225
225
226 Examples:
226 Examples:
227
227
228 - New (unknown) files are added
228 - New (unknown) files are added
229 automatically by :hg:`add`::
229 automatically by :hg:`add`::
230
230
231 $ ls
231 $ ls
232 foo.c
232 foo.c
233 $ hg status
233 $ hg status
234 ? foo.c
234 ? foo.c
235 $ hg add
235 $ hg add
236 adding foo.c
236 adding foo.c
237 $ hg status
237 $ hg status
238 A foo.c
238 A foo.c
239
239
240 - Specific files to be added can be specified::
240 - Specific files to be added can be specified::
241
241
242 $ ls
242 $ ls
243 bar.c foo.c
243 bar.c foo.c
244 $ hg status
244 $ hg status
245 ? bar.c
245 ? bar.c
246 ? foo.c
246 ? foo.c
247 $ hg add bar.c
247 $ hg add bar.c
248 $ hg status
248 $ hg status
249 A bar.c
249 A bar.c
250 ? foo.c
250 ? foo.c
251
251
252 Returns 0 if all files are successfully added.
252 Returns 0 if all files are successfully added.
253 """
253 """
254
254
255 m = scmutil.match(repo[None], pats, opts)
255 m = scmutil.match(repo[None], pats, opts)
256 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
256 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
257 return rejected and 1 or 0
257 return rejected and 1 or 0
258
258
259 @command('addremove',
259 @command('addremove',
260 similarityopts + subrepoopts + walkopts + dryrunopts,
260 similarityopts + subrepoopts + walkopts + dryrunopts,
261 _('[OPTION]... [FILE]...'),
261 _('[OPTION]... [FILE]...'),
262 inferrepo=True)
262 inferrepo=True)
263 def addremove(ui, repo, *pats, **opts):
263 def addremove(ui, repo, *pats, **opts):
264 """add all new files, delete all missing files
264 """add all new files, delete all missing files
265
265
266 Add all new files and remove all missing files from the
266 Add all new files and remove all missing files from the
267 repository.
267 repository.
268
268
269 Unless names are given, new files are ignored if they match any of
269 Unless names are given, new files are ignored if they match any of
270 the patterns in ``.hgignore``. As with add, these changes take
270 the patterns in ``.hgignore``. As with add, these changes take
271 effect at the next commit.
271 effect at the next commit.
272
272
273 Use the -s/--similarity option to detect renamed files. This
273 Use the -s/--similarity option to detect renamed files. This
274 option takes a percentage between 0 (disabled) and 100 (files must
274 option takes a percentage between 0 (disabled) and 100 (files must
275 be identical) as its parameter. With a parameter greater than 0,
275 be identical) as its parameter. With a parameter greater than 0,
276 this compares every removed file with every added file and records
276 this compares every removed file with every added file and records
277 those similar enough as renames. Detecting renamed files this way
277 those similar enough as renames. Detecting renamed files this way
278 can be expensive. After using this option, :hg:`status -C` can be
278 can be expensive. After using this option, :hg:`status -C` can be
279 used to check which files were identified as moved or renamed. If
279 used to check which files were identified as moved or renamed. If
280 not specified, -s/--similarity defaults to 100 and only renames of
280 not specified, -s/--similarity defaults to 100 and only renames of
281 identical files are detected.
281 identical files are detected.
282
282
283 .. container:: verbose
283 .. container:: verbose
284
284
285 Examples:
285 Examples:
286
286
287 - A number of files (bar.c and foo.c) are new,
287 - A number of files (bar.c and foo.c) are new,
288 while foobar.c has been removed (without using :hg:`remove`)
288 while foobar.c has been removed (without using :hg:`remove`)
289 from the repository::
289 from the repository::
290
290
291 $ ls
291 $ ls
292 bar.c foo.c
292 bar.c foo.c
293 $ hg status
293 $ hg status
294 ! foobar.c
294 ! foobar.c
295 ? bar.c
295 ? bar.c
296 ? foo.c
296 ? foo.c
297 $ hg addremove
297 $ hg addremove
298 adding bar.c
298 adding bar.c
299 adding foo.c
299 adding foo.c
300 removing foobar.c
300 removing foobar.c
301 $ hg status
301 $ hg status
302 A bar.c
302 A bar.c
303 A foo.c
303 A foo.c
304 R foobar.c
304 R foobar.c
305
305
306 - A file foobar.c was moved to foo.c without using :hg:`rename`.
306 - A file foobar.c was moved to foo.c without using :hg:`rename`.
307 Afterwards, it was edited slightly::
307 Afterwards, it was edited slightly::
308
308
309 $ ls
309 $ ls
310 foo.c
310 foo.c
311 $ hg status
311 $ hg status
312 ! foobar.c
312 ! foobar.c
313 ? foo.c
313 ? foo.c
314 $ hg addremove --similarity 90
314 $ hg addremove --similarity 90
315 removing foobar.c
315 removing foobar.c
316 adding foo.c
316 adding foo.c
317 recording removal of foobar.c as rename to foo.c (94% similar)
317 recording removal of foobar.c as rename to foo.c (94% similar)
318 $ hg status -C
318 $ hg status -C
319 A foo.c
319 A foo.c
320 foobar.c
320 foobar.c
321 R foobar.c
321 R foobar.c
322
322
323 Returns 0 if all files are successfully added.
323 Returns 0 if all files are successfully added.
324 """
324 """
325 try:
325 try:
326 sim = float(opts.get('similarity') or 100)
326 sim = float(opts.get('similarity') or 100)
327 except ValueError:
327 except ValueError:
328 raise error.Abort(_('similarity must be a number'))
328 raise error.Abort(_('similarity must be a number'))
329 if sim < 0 or sim > 100:
329 if sim < 0 or sim > 100:
330 raise error.Abort(_('similarity must be between 0 and 100'))
330 raise error.Abort(_('similarity must be between 0 and 100'))
331 matcher = scmutil.match(repo[None], pats, opts)
331 matcher = scmutil.match(repo[None], pats, opts)
332 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
332 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
333
333
334 @command('^annotate|blame',
334 @command('^annotate|blame',
335 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
335 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
336 ('', 'follow', None,
336 ('', 'follow', None,
337 _('follow copies/renames and list the filename (DEPRECATED)')),
337 _('follow copies/renames and list the filename (DEPRECATED)')),
338 ('', 'no-follow', None, _("don't follow copies and renames")),
338 ('', 'no-follow', None, _("don't follow copies and renames")),
339 ('a', 'text', None, _('treat all files as text')),
339 ('a', 'text', None, _('treat all files as text')),
340 ('u', 'user', None, _('list the author (long with -v)')),
340 ('u', 'user', None, _('list the author (long with -v)')),
341 ('f', 'file', None, _('list the filename')),
341 ('f', 'file', None, _('list the filename')),
342 ('d', 'date', None, _('list the date (short with -q)')),
342 ('d', 'date', None, _('list the date (short with -q)')),
343 ('n', 'number', None, _('list the revision number (default)')),
343 ('n', 'number', None, _('list the revision number (default)')),
344 ('c', 'changeset', None, _('list the changeset')),
344 ('c', 'changeset', None, _('list the changeset')),
345 ('l', 'line-number', None, _('show line number at the first appearance'))
345 ('l', 'line-number', None, _('show line number at the first appearance'))
346 ] + diffwsopts + walkopts + formatteropts,
346 ] + diffwsopts + walkopts + formatteropts,
347 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
347 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
348 inferrepo=True)
348 inferrepo=True)
349 def annotate(ui, repo, *pats, **opts):
349 def annotate(ui, repo, *pats, **opts):
350 """show changeset information by line for each file
350 """show changeset information by line for each file
351
351
352 List changes in files, showing the revision id responsible for
352 List changes in files, showing the revision id responsible for
353 each line.
353 each line.
354
354
355 This command is useful for discovering when a change was made and
355 This command is useful for discovering when a change was made and
356 by whom.
356 by whom.
357
357
358 If you include --file, --user, or --date, the revision number is
358 If you include --file, --user, or --date, the revision number is
359 suppressed unless you also include --number.
359 suppressed unless you also include --number.
360
360
361 Without the -a/--text option, annotate will avoid processing files
361 Without the -a/--text option, annotate will avoid processing files
362 it detects as binary. With -a, annotate will annotate the file
362 it detects as binary. With -a, annotate will annotate the file
363 anyway, although the results will probably be neither useful
363 anyway, although the results will probably be neither useful
364 nor desirable.
364 nor desirable.
365
365
366 Returns 0 on success.
366 Returns 0 on success.
367 """
367 """
368 if not pats:
368 if not pats:
369 raise error.Abort(_('at least one filename or pattern is required'))
369 raise error.Abort(_('at least one filename or pattern is required'))
370
370
371 if opts.get('follow'):
371 if opts.get('follow'):
372 # --follow is deprecated and now just an alias for -f/--file
372 # --follow is deprecated and now just an alias for -f/--file
373 # to mimic the behavior of Mercurial before version 1.5
373 # to mimic the behavior of Mercurial before version 1.5
374 opts['file'] = True
374 opts['file'] = True
375
375
376 ctx = scmutil.revsingle(repo, opts.get('rev'))
376 ctx = scmutil.revsingle(repo, opts.get('rev'))
377
377
378 fm = ui.formatter('annotate', opts)
378 fm = ui.formatter('annotate', opts)
379 if ui.quiet:
379 if ui.quiet:
380 datefunc = util.shortdate
380 datefunc = util.shortdate
381 else:
381 else:
382 datefunc = util.datestr
382 datefunc = util.datestr
383 if ctx.rev() is None:
383 if ctx.rev() is None:
384 def hexfn(node):
384 def hexfn(node):
385 if node is None:
385 if node is None:
386 return None
386 return None
387 else:
387 else:
388 return fm.hexfunc(node)
388 return fm.hexfunc(node)
389 if opts.get('changeset'):
389 if opts.get('changeset'):
390 # omit "+" suffix which is appended to node hex
390 # omit "+" suffix which is appended to node hex
391 def formatrev(rev):
391 def formatrev(rev):
392 if rev is None:
392 if rev is None:
393 return '%d' % ctx.p1().rev()
393 return '%d' % ctx.p1().rev()
394 else:
394 else:
395 return '%d' % rev
395 return '%d' % rev
396 else:
396 else:
397 def formatrev(rev):
397 def formatrev(rev):
398 if rev is None:
398 if rev is None:
399 return '%d+' % ctx.p1().rev()
399 return '%d+' % ctx.p1().rev()
400 else:
400 else:
401 return '%d ' % rev
401 return '%d ' % rev
402 def formathex(hex):
402 def formathex(hex):
403 if hex is None:
403 if hex is None:
404 return '%s+' % fm.hexfunc(ctx.p1().node())
404 return '%s+' % fm.hexfunc(ctx.p1().node())
405 else:
405 else:
406 return '%s ' % hex
406 return '%s ' % hex
407 else:
407 else:
408 hexfn = fm.hexfunc
408 hexfn = fm.hexfunc
409 formatrev = formathex = str
409 formatrev = formathex = str
410
410
411 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
411 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
412 ('number', ' ', lambda x: x[0].rev(), formatrev),
412 ('number', ' ', lambda x: x[0].rev(), formatrev),
413 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
413 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
414 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
414 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
415 ('file', ' ', lambda x: x[0].path(), str),
415 ('file', ' ', lambda x: x[0].path(), str),
416 ('line_number', ':', lambda x: x[1], str),
416 ('line_number', ':', lambda x: x[1], str),
417 ]
417 ]
418 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
418 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
419
419
420 if (not opts.get('user') and not opts.get('changeset')
420 if (not opts.get('user') and not opts.get('changeset')
421 and not opts.get('date') and not opts.get('file')):
421 and not opts.get('date') and not opts.get('file')):
422 opts['number'] = True
422 opts['number'] = True
423
423
424 linenumber = opts.get('line_number') is not None
424 linenumber = opts.get('line_number') is not None
425 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
425 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
426 raise error.Abort(_('at least one of -n/-c is required for -l'))
426 raise error.Abort(_('at least one of -n/-c is required for -l'))
427
427
428 ui.pager('annotate')
428 ui.pager('annotate')
429
429
430 if fm.isplain():
430 if fm.isplain():
431 def makefunc(get, fmt):
431 def makefunc(get, fmt):
432 return lambda x: fmt(get(x))
432 return lambda x: fmt(get(x))
433 else:
433 else:
434 def makefunc(get, fmt):
434 def makefunc(get, fmt):
435 return get
435 return get
436 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
436 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
437 if opts.get(op)]
437 if opts.get(op)]
438 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
438 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
439 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
439 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
440 if opts.get(op))
440 if opts.get(op))
441
441
442 def bad(x, y):
442 def bad(x, y):
443 raise error.Abort("%s: %s" % (x, y))
443 raise error.Abort("%s: %s" % (x, y))
444
444
445 m = scmutil.match(ctx, pats, opts, badfn=bad)
445 m = scmutil.match(ctx, pats, opts, badfn=bad)
446
446
447 follow = not opts.get('no_follow')
447 follow = not opts.get('no_follow')
448 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
448 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
449 whitespace=True)
449 whitespace=True)
450 for abs in ctx.walk(m):
450 for abs in ctx.walk(m):
451 fctx = ctx[abs]
451 fctx = ctx[abs]
452 if not opts.get('text') and util.binary(fctx.data()):
452 if not opts.get('text') and util.binary(fctx.data()):
453 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
453 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
454 continue
454 continue
455
455
456 lines = fctx.annotate(follow=follow, linenumber=linenumber,
456 lines = fctx.annotate(follow=follow, linenumber=linenumber,
457 diffopts=diffopts)
457 diffopts=diffopts)
458 if not lines:
458 if not lines:
459 continue
459 continue
460 formats = []
460 formats = []
461 pieces = []
461 pieces = []
462
462
463 for f, sep in funcmap:
463 for f, sep in funcmap:
464 l = [f(n) for n, dummy in lines]
464 l = [f(n) for n, dummy in lines]
465 if fm.isplain():
465 if fm.isplain():
466 sizes = [encoding.colwidth(x) for x in l]
466 sizes = [encoding.colwidth(x) for x in l]
467 ml = max(sizes)
467 ml = max(sizes)
468 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
468 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
469 else:
469 else:
470 formats.append(['%s' for x in l])
470 formats.append(['%s' for x in l])
471 pieces.append(l)
471 pieces.append(l)
472
472
473 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
473 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
474 fm.startitem()
474 fm.startitem()
475 fm.write(fields, "".join(f), *p)
475 fm.write(fields, "".join(f), *p)
476 fm.write('line', ": %s", l[1])
476 fm.write('line', ": %s", l[1])
477
477
478 if not lines[-1][1].endswith('\n'):
478 if not lines[-1][1].endswith('\n'):
479 fm.plain('\n')
479 fm.plain('\n')
480
480
481 fm.end()
481 fm.end()
482
482
483 @command('archive',
483 @command('archive',
484 [('', 'no-decode', None, _('do not pass files through decoders')),
484 [('', 'no-decode', None, _('do not pass files through decoders')),
485 ('p', 'prefix', '', _('directory prefix for files in archive'),
485 ('p', 'prefix', '', _('directory prefix for files in archive'),
486 _('PREFIX')),
486 _('PREFIX')),
487 ('r', 'rev', '', _('revision to distribute'), _('REV')),
487 ('r', 'rev', '', _('revision to distribute'), _('REV')),
488 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
488 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
489 ] + subrepoopts + walkopts,
489 ] + subrepoopts + walkopts,
490 _('[OPTION]... DEST'))
490 _('[OPTION]... DEST'))
491 def archive(ui, repo, dest, **opts):
491 def archive(ui, repo, dest, **opts):
492 '''create an unversioned archive of a repository revision
492 '''create an unversioned archive of a repository revision
493
493
494 By default, the revision used is the parent of the working
494 By default, the revision used is the parent of the working
495 directory; use -r/--rev to specify a different revision.
495 directory; use -r/--rev to specify a different revision.
496
496
497 The archive type is automatically detected based on file
497 The archive type is automatically detected based on file
498 extension (to override, use -t/--type).
498 extension (to override, use -t/--type).
499
499
500 .. container:: verbose
500 .. container:: verbose
501
501
502 Examples:
502 Examples:
503
503
504 - create a zip file containing the 1.0 release::
504 - create a zip file containing the 1.0 release::
505
505
506 hg archive -r 1.0 project-1.0.zip
506 hg archive -r 1.0 project-1.0.zip
507
507
508 - create a tarball excluding .hg files::
508 - create a tarball excluding .hg files::
509
509
510 hg archive project.tar.gz -X ".hg*"
510 hg archive project.tar.gz -X ".hg*"
511
511
512 Valid types are:
512 Valid types are:
513
513
514 :``files``: a directory full of files (default)
514 :``files``: a directory full of files (default)
515 :``tar``: tar archive, uncompressed
515 :``tar``: tar archive, uncompressed
516 :``tbz2``: tar archive, compressed using bzip2
516 :``tbz2``: tar archive, compressed using bzip2
517 :``tgz``: tar archive, compressed using gzip
517 :``tgz``: tar archive, compressed using gzip
518 :``uzip``: zip archive, uncompressed
518 :``uzip``: zip archive, uncompressed
519 :``zip``: zip archive, compressed using deflate
519 :``zip``: zip archive, compressed using deflate
520
520
521 The exact name of the destination archive or directory is given
521 The exact name of the destination archive or directory is given
522 using a format string; see :hg:`help export` for details.
522 using a format string; see :hg:`help export` for details.
523
523
524 Each member added to an archive file has a directory prefix
524 Each member added to an archive file has a directory prefix
525 prepended. Use -p/--prefix to specify a format string for the
525 prepended. Use -p/--prefix to specify a format string for the
526 prefix. The default is the basename of the archive, with suffixes
526 prefix. The default is the basename of the archive, with suffixes
527 removed.
527 removed.
528
528
529 Returns 0 on success.
529 Returns 0 on success.
530 '''
530 '''
531
531
532 ctx = scmutil.revsingle(repo, opts.get('rev'))
532 ctx = scmutil.revsingle(repo, opts.get('rev'))
533 if not ctx:
533 if not ctx:
534 raise error.Abort(_('no working directory: please specify a revision'))
534 raise error.Abort(_('no working directory: please specify a revision'))
535 node = ctx.node()
535 node = ctx.node()
536 dest = cmdutil.makefilename(repo, dest, node)
536 dest = cmdutil.makefilename(repo, dest, node)
537 if os.path.realpath(dest) == repo.root:
537 if os.path.realpath(dest) == repo.root:
538 raise error.Abort(_('repository root cannot be destination'))
538 raise error.Abort(_('repository root cannot be destination'))
539
539
540 kind = opts.get('type') or archival.guesskind(dest) or 'files'
540 kind = opts.get('type') or archival.guesskind(dest) or 'files'
541 prefix = opts.get('prefix')
541 prefix = opts.get('prefix')
542
542
543 if dest == '-':
543 if dest == '-':
544 if kind == 'files':
544 if kind == 'files':
545 raise error.Abort(_('cannot archive plain files to stdout'))
545 raise error.Abort(_('cannot archive plain files to stdout'))
546 dest = cmdutil.makefileobj(repo, dest)
546 dest = cmdutil.makefileobj(repo, dest)
547 if not prefix:
547 if not prefix:
548 prefix = os.path.basename(repo.root) + '-%h'
548 prefix = os.path.basename(repo.root) + '-%h'
549
549
550 prefix = cmdutil.makefilename(repo, prefix, node)
550 prefix = cmdutil.makefilename(repo, prefix, node)
551 matchfn = scmutil.match(ctx, [], opts)
551 matchfn = scmutil.match(ctx, [], opts)
552 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
552 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
553 matchfn, prefix, subrepos=opts.get('subrepos'))
553 matchfn, prefix, subrepos=opts.get('subrepos'))
554
554
555 @command('backout',
555 @command('backout',
556 [('', 'merge', None, _('merge with old dirstate parent after backout')),
556 [('', 'merge', None, _('merge with old dirstate parent after backout')),
557 ('', 'commit', None,
557 ('', 'commit', None,
558 _('commit if no conflicts were encountered (DEPRECATED)')),
558 _('commit if no conflicts were encountered (DEPRECATED)')),
559 ('', 'no-commit', None, _('do not commit')),
559 ('', 'no-commit', None, _('do not commit')),
560 ('', 'parent', '',
560 ('', 'parent', '',
561 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
561 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
562 ('r', 'rev', '', _('revision to backout'), _('REV')),
562 ('r', 'rev', '', _('revision to backout'), _('REV')),
563 ('e', 'edit', False, _('invoke editor on commit messages')),
563 ('e', 'edit', False, _('invoke editor on commit messages')),
564 ] + mergetoolopts + walkopts + commitopts + commitopts2,
564 ] + mergetoolopts + walkopts + commitopts + commitopts2,
565 _('[OPTION]... [-r] REV'))
565 _('[OPTION]... [-r] REV'))
566 def backout(ui, repo, node=None, rev=None, **opts):
566 def backout(ui, repo, node=None, rev=None, **opts):
567 '''reverse effect of earlier changeset
567 '''reverse effect of earlier changeset
568
568
569 Prepare a new changeset with the effect of REV undone in the
569 Prepare a new changeset with the effect of REV undone in the
570 current working directory. If no conflicts were encountered,
570 current working directory. If no conflicts were encountered,
571 it will be committed immediately.
571 it will be committed immediately.
572
572
573 If REV is the parent of the working directory, then this new changeset
573 If REV is the parent of the working directory, then this new changeset
574 is committed automatically (unless --no-commit is specified).
574 is committed automatically (unless --no-commit is specified).
575
575
576 .. note::
576 .. note::
577
577
578 :hg:`backout` cannot be used to fix either an unwanted or
578 :hg:`backout` cannot be used to fix either an unwanted or
579 incorrect merge.
579 incorrect merge.
580
580
581 .. container:: verbose
581 .. container:: verbose
582
582
583 Examples:
583 Examples:
584
584
585 - Reverse the effect of the parent of the working directory.
585 - Reverse the effect of the parent of the working directory.
586 This backout will be committed immediately::
586 This backout will be committed immediately::
587
587
588 hg backout -r .
588 hg backout -r .
589
589
590 - Reverse the effect of previous bad revision 23::
590 - Reverse the effect of previous bad revision 23::
591
591
592 hg backout -r 23
592 hg backout -r 23
593
593
594 - Reverse the effect of previous bad revision 23 and
594 - Reverse the effect of previous bad revision 23 and
595 leave changes uncommitted::
595 leave changes uncommitted::
596
596
597 hg backout -r 23 --no-commit
597 hg backout -r 23 --no-commit
598 hg commit -m "Backout revision 23"
598 hg commit -m "Backout revision 23"
599
599
600 By default, the pending changeset will have one parent,
600 By default, the pending changeset will have one parent,
601 maintaining a linear history. With --merge, the pending
601 maintaining a linear history. With --merge, the pending
602 changeset will instead have two parents: the old parent of the
602 changeset will instead have two parents: the old parent of the
603 working directory and a new child of REV that simply undoes REV.
603 working directory and a new child of REV that simply undoes REV.
604
604
605 Before version 1.7, the behavior without --merge was equivalent
605 Before version 1.7, the behavior without --merge was equivalent
606 to specifying --merge followed by :hg:`update --clean .` to
606 to specifying --merge followed by :hg:`update --clean .` to
607 cancel the merge and leave the child of REV as a head to be
607 cancel the merge and leave the child of REV as a head to be
608 merged separately.
608 merged separately.
609
609
610 See :hg:`help dates` for a list of formats valid for -d/--date.
610 See :hg:`help dates` for a list of formats valid for -d/--date.
611
611
612 See :hg:`help revert` for a way to restore files to the state
612 See :hg:`help revert` for a way to restore files to the state
613 of another revision.
613 of another revision.
614
614
615 Returns 0 on success, 1 if nothing to backout or there are unresolved
615 Returns 0 on success, 1 if nothing to backout or there are unresolved
616 files.
616 files.
617 '''
617 '''
618 wlock = lock = None
618 wlock = lock = None
619 try:
619 try:
620 wlock = repo.wlock()
620 wlock = repo.wlock()
621 lock = repo.lock()
621 lock = repo.lock()
622 return _dobackout(ui, repo, node, rev, **opts)
622 return _dobackout(ui, repo, node, rev, **opts)
623 finally:
623 finally:
624 release(lock, wlock)
624 release(lock, wlock)
625
625
626 def _dobackout(ui, repo, node=None, rev=None, **opts):
626 def _dobackout(ui, repo, node=None, rev=None, **opts):
627 if opts.get('commit') and opts.get('no_commit'):
627 if opts.get('commit') and opts.get('no_commit'):
628 raise error.Abort(_("cannot use --commit with --no-commit"))
628 raise error.Abort(_("cannot use --commit with --no-commit"))
629 if opts.get('merge') and opts.get('no_commit'):
629 if opts.get('merge') and opts.get('no_commit'):
630 raise error.Abort(_("cannot use --merge with --no-commit"))
630 raise error.Abort(_("cannot use --merge with --no-commit"))
631
631
632 if rev and node:
632 if rev and node:
633 raise error.Abort(_("please specify just one revision"))
633 raise error.Abort(_("please specify just one revision"))
634
634
635 if not rev:
635 if not rev:
636 rev = node
636 rev = node
637
637
638 if not rev:
638 if not rev:
639 raise error.Abort(_("please specify a revision to backout"))
639 raise error.Abort(_("please specify a revision to backout"))
640
640
641 date = opts.get('date')
641 date = opts.get('date')
642 if date:
642 if date:
643 opts['date'] = util.parsedate(date)
643 opts['date'] = util.parsedate(date)
644
644
645 cmdutil.checkunfinished(repo)
645 cmdutil.checkunfinished(repo)
646 cmdutil.bailifchanged(repo)
646 cmdutil.bailifchanged(repo)
647 node = scmutil.revsingle(repo, rev).node()
647 node = scmutil.revsingle(repo, rev).node()
648
648
649 op1, op2 = repo.dirstate.parents()
649 op1, op2 = repo.dirstate.parents()
650 if not repo.changelog.isancestor(node, op1):
650 if not repo.changelog.isancestor(node, op1):
651 raise error.Abort(_('cannot backout change that is not an ancestor'))
651 raise error.Abort(_('cannot backout change that is not an ancestor'))
652
652
653 p1, p2 = repo.changelog.parents(node)
653 p1, p2 = repo.changelog.parents(node)
654 if p1 == nullid:
654 if p1 == nullid:
655 raise error.Abort(_('cannot backout a change with no parents'))
655 raise error.Abort(_('cannot backout a change with no parents'))
656 if p2 != nullid:
656 if p2 != nullid:
657 if not opts.get('parent'):
657 if not opts.get('parent'):
658 raise error.Abort(_('cannot backout a merge changeset'))
658 raise error.Abort(_('cannot backout a merge changeset'))
659 p = repo.lookup(opts['parent'])
659 p = repo.lookup(opts['parent'])
660 if p not in (p1, p2):
660 if p not in (p1, p2):
661 raise error.Abort(_('%s is not a parent of %s') %
661 raise error.Abort(_('%s is not a parent of %s') %
662 (short(p), short(node)))
662 (short(p), short(node)))
663 parent = p
663 parent = p
664 else:
664 else:
665 if opts.get('parent'):
665 if opts.get('parent'):
666 raise error.Abort(_('cannot use --parent on non-merge changeset'))
666 raise error.Abort(_('cannot use --parent on non-merge changeset'))
667 parent = p1
667 parent = p1
668
668
669 # the backout should appear on the same branch
669 # the backout should appear on the same branch
670 branch = repo.dirstate.branch()
670 branch = repo.dirstate.branch()
671 bheads = repo.branchheads(branch)
671 bheads = repo.branchheads(branch)
672 rctx = scmutil.revsingle(repo, hex(parent))
672 rctx = scmutil.revsingle(repo, hex(parent))
673 if not opts.get('merge') and op1 != node:
673 if not opts.get('merge') and op1 != node:
674 dsguard = dirstateguard.dirstateguard(repo, 'backout')
674 dsguard = dirstateguard.dirstateguard(repo, 'backout')
675 try:
675 try:
676 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
676 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
677 'backout')
677 'backout')
678 stats = mergemod.update(repo, parent, True, True, node, False)
678 stats = mergemod.update(repo, parent, True, True, node, False)
679 repo.setparents(op1, op2)
679 repo.setparents(op1, op2)
680 dsguard.close()
680 dsguard.close()
681 hg._showstats(repo, stats)
681 hg._showstats(repo, stats)
682 if stats[3]:
682 if stats[3]:
683 repo.ui.status(_("use 'hg resolve' to retry unresolved "
683 repo.ui.status(_("use 'hg resolve' to retry unresolved "
684 "file merges\n"))
684 "file merges\n"))
685 return 1
685 return 1
686 finally:
686 finally:
687 ui.setconfig('ui', 'forcemerge', '', '')
687 ui.setconfig('ui', 'forcemerge', '', '')
688 lockmod.release(dsguard)
688 lockmod.release(dsguard)
689 else:
689 else:
690 hg.clean(repo, node, show_stats=False)
690 hg.clean(repo, node, show_stats=False)
691 repo.dirstate.setbranch(branch)
691 repo.dirstate.setbranch(branch)
692 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
692 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
693
693
694 if opts.get('no_commit'):
694 if opts.get('no_commit'):
695 msg = _("changeset %s backed out, "
695 msg = _("changeset %s backed out, "
696 "don't forget to commit.\n")
696 "don't forget to commit.\n")
697 ui.status(msg % short(node))
697 ui.status(msg % short(node))
698 return 0
698 return 0
699
699
700 def commitfunc(ui, repo, message, match, opts):
700 def commitfunc(ui, repo, message, match, opts):
701 editform = 'backout'
701 editform = 'backout'
702 e = cmdutil.getcommiteditor(editform=editform, **opts)
702 e = cmdutil.getcommiteditor(editform=editform, **opts)
703 if not message:
703 if not message:
704 # we don't translate commit messages
704 # we don't translate commit messages
705 message = "Backed out changeset %s" % short(node)
705 message = "Backed out changeset %s" % short(node)
706 e = cmdutil.getcommiteditor(edit=True, editform=editform)
706 e = cmdutil.getcommiteditor(edit=True, editform=editform)
707 return repo.commit(message, opts.get('user'), opts.get('date'),
707 return repo.commit(message, opts.get('user'), opts.get('date'),
708 match, editor=e)
708 match, editor=e)
709 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
709 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
710 if not newnode:
710 if not newnode:
711 ui.status(_("nothing changed\n"))
711 ui.status(_("nothing changed\n"))
712 return 1
712 return 1
713 cmdutil.commitstatus(repo, newnode, branch, bheads)
713 cmdutil.commitstatus(repo, newnode, branch, bheads)
714
714
715 def nice(node):
715 def nice(node):
716 return '%d:%s' % (repo.changelog.rev(node), short(node))
716 return '%d:%s' % (repo.changelog.rev(node), short(node))
717 ui.status(_('changeset %s backs out changeset %s\n') %
717 ui.status(_('changeset %s backs out changeset %s\n') %
718 (nice(repo.changelog.tip()), nice(node)))
718 (nice(repo.changelog.tip()), nice(node)))
719 if opts.get('merge') and op1 != node:
719 if opts.get('merge') and op1 != node:
720 hg.clean(repo, op1, show_stats=False)
720 hg.clean(repo, op1, show_stats=False)
721 ui.status(_('merging with changeset %s\n')
721 ui.status(_('merging with changeset %s\n')
722 % nice(repo.changelog.tip()))
722 % nice(repo.changelog.tip()))
723 try:
723 try:
724 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
724 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
725 'backout')
725 'backout')
726 return hg.merge(repo, hex(repo.changelog.tip()))
726 return hg.merge(repo, hex(repo.changelog.tip()))
727 finally:
727 finally:
728 ui.setconfig('ui', 'forcemerge', '', '')
728 ui.setconfig('ui', 'forcemerge', '', '')
729 return 0
729 return 0
730
730
731 @command('bisect',
731 @command('bisect',
732 [('r', 'reset', False, _('reset bisect state')),
732 [('r', 'reset', False, _('reset bisect state')),
733 ('g', 'good', False, _('mark changeset good')),
733 ('g', 'good', False, _('mark changeset good')),
734 ('b', 'bad', False, _('mark changeset bad')),
734 ('b', 'bad', False, _('mark changeset bad')),
735 ('s', 'skip', False, _('skip testing changeset')),
735 ('s', 'skip', False, _('skip testing changeset')),
736 ('e', 'extend', False, _('extend the bisect range')),
736 ('e', 'extend', False, _('extend the bisect range')),
737 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
737 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
738 ('U', 'noupdate', False, _('do not update to target'))],
738 ('U', 'noupdate', False, _('do not update to target'))],
739 _("[-gbsr] [-U] [-c CMD] [REV]"))
739 _("[-gbsr] [-U] [-c CMD] [REV]"))
740 def bisect(ui, repo, rev=None, extra=None, command=None,
740 def bisect(ui, repo, rev=None, extra=None, command=None,
741 reset=None, good=None, bad=None, skip=None, extend=None,
741 reset=None, good=None, bad=None, skip=None, extend=None,
742 noupdate=None):
742 noupdate=None):
743 """subdivision search of changesets
743 """subdivision search of changesets
744
744
745 This command helps to find changesets which introduce problems. To
745 This command helps to find changesets which introduce problems. To
746 use, mark the earliest changeset you know exhibits the problem as
746 use, mark the earliest changeset you know exhibits the problem as
747 bad, then mark the latest changeset which is free from the problem
747 bad, then mark the latest changeset which is free from the problem
748 as good. Bisect will update your working directory to a revision
748 as good. Bisect will update your working directory to a revision
749 for testing (unless the -U/--noupdate option is specified). Once
749 for testing (unless the -U/--noupdate option is specified). Once
750 you have performed tests, mark the working directory as good or
750 you have performed tests, mark the working directory as good or
751 bad, and bisect will either update to another candidate changeset
751 bad, and bisect will either update to another candidate changeset
752 or announce that it has found the bad revision.
752 or announce that it has found the bad revision.
753
753
754 As a shortcut, you can also use the revision argument to mark a
754 As a shortcut, you can also use the revision argument to mark a
755 revision as good or bad without checking it out first.
755 revision as good or bad without checking it out first.
756
756
757 If you supply a command, it will be used for automatic bisection.
757 If you supply a command, it will be used for automatic bisection.
758 The environment variable HG_NODE will contain the ID of the
758 The environment variable HG_NODE will contain the ID of the
759 changeset being tested. The exit status of the command will be
759 changeset being tested. The exit status of the command will be
760 used to mark revisions as good or bad: status 0 means good, 125
760 used to mark revisions as good or bad: status 0 means good, 125
761 means to skip the revision, 127 (command not found) will abort the
761 means to skip the revision, 127 (command not found) will abort the
762 bisection, and any other non-zero exit status means the revision
762 bisection, and any other non-zero exit status means the revision
763 is bad.
763 is bad.
764
764
765 .. container:: verbose
765 .. container:: verbose
766
766
767 Some examples:
767 Some examples:
768
768
769 - start a bisection with known bad revision 34, and good revision 12::
769 - start a bisection with known bad revision 34, and good revision 12::
770
770
771 hg bisect --bad 34
771 hg bisect --bad 34
772 hg bisect --good 12
772 hg bisect --good 12
773
773
774 - advance the current bisection by marking current revision as good or
774 - advance the current bisection by marking current revision as good or
775 bad::
775 bad::
776
776
777 hg bisect --good
777 hg bisect --good
778 hg bisect --bad
778 hg bisect --bad
779
779
780 - mark the current revision, or a known revision, to be skipped (e.g. if
780 - mark the current revision, or a known revision, to be skipped (e.g. if
781 that revision is not usable because of another issue)::
781 that revision is not usable because of another issue)::
782
782
783 hg bisect --skip
783 hg bisect --skip
784 hg bisect --skip 23
784 hg bisect --skip 23
785
785
786 - skip all revisions that do not touch directories ``foo`` or ``bar``::
786 - skip all revisions that do not touch directories ``foo`` or ``bar``::
787
787
788 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
788 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
789
789
790 - forget the current bisection::
790 - forget the current bisection::
791
791
792 hg bisect --reset
792 hg bisect --reset
793
793
794 - use 'make && make tests' to automatically find the first broken
794 - use 'make && make tests' to automatically find the first broken
795 revision::
795 revision::
796
796
797 hg bisect --reset
797 hg bisect --reset
798 hg bisect --bad 34
798 hg bisect --bad 34
799 hg bisect --good 12
799 hg bisect --good 12
800 hg bisect --command "make && make tests"
800 hg bisect --command "make && make tests"
801
801
802 - see all changesets whose states are already known in the current
802 - see all changesets whose states are already known in the current
803 bisection::
803 bisection::
804
804
805 hg log -r "bisect(pruned)"
805 hg log -r "bisect(pruned)"
806
806
807 - see the changeset currently being bisected (especially useful
807 - see the changeset currently being bisected (especially useful
808 if running with -U/--noupdate)::
808 if running with -U/--noupdate)::
809
809
810 hg log -r "bisect(current)"
810 hg log -r "bisect(current)"
811
811
812 - see all changesets that took part in the current bisection::
812 - see all changesets that took part in the current bisection::
813
813
814 hg log -r "bisect(range)"
814 hg log -r "bisect(range)"
815
815
816 - you can even get a nice graph::
816 - you can even get a nice graph::
817
817
818 hg log --graph -r "bisect(range)"
818 hg log --graph -r "bisect(range)"
819
819
820 See :hg:`help revisions.bisect` for more about the `bisect()` predicate.
820 See :hg:`help revisions.bisect` for more about the `bisect()` predicate.
821
821
822 Returns 0 on success.
822 Returns 0 on success.
823 """
823 """
824 # backward compatibility
824 # backward compatibility
825 if rev in "good bad reset init".split():
825 if rev in "good bad reset init".split():
826 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
826 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
827 cmd, rev, extra = rev, extra, None
827 cmd, rev, extra = rev, extra, None
828 if cmd == "good":
828 if cmd == "good":
829 good = True
829 good = True
830 elif cmd == "bad":
830 elif cmd == "bad":
831 bad = True
831 bad = True
832 else:
832 else:
833 reset = True
833 reset = True
834 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
834 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
835 raise error.Abort(_('incompatible arguments'))
835 raise error.Abort(_('incompatible arguments'))
836
836
837 cmdutil.checkunfinished(repo)
837 cmdutil.checkunfinished(repo)
838
838
839 if reset:
839 if reset:
840 hbisect.resetstate(repo)
840 hbisect.resetstate(repo)
841 return
841 return
842
842
843 state = hbisect.load_state(repo)
843 state = hbisect.load_state(repo)
844
844
845 # update state
845 # update state
846 if good or bad or skip:
846 if good or bad or skip:
847 if rev:
847 if rev:
848 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
848 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
849 else:
849 else:
850 nodes = [repo.lookup('.')]
850 nodes = [repo.lookup('.')]
851 if good:
851 if good:
852 state['good'] += nodes
852 state['good'] += nodes
853 elif bad:
853 elif bad:
854 state['bad'] += nodes
854 state['bad'] += nodes
855 elif skip:
855 elif skip:
856 state['skip'] += nodes
856 state['skip'] += nodes
857 hbisect.save_state(repo, state)
857 hbisect.save_state(repo, state)
858 if not (state['good'] and state['bad']):
858 if not (state['good'] and state['bad']):
859 return
859 return
860
860
861 def mayupdate(repo, node, show_stats=True):
861 def mayupdate(repo, node, show_stats=True):
862 """common used update sequence"""
862 """common used update sequence"""
863 if noupdate:
863 if noupdate:
864 return
864 return
865 cmdutil.bailifchanged(repo)
865 cmdutil.bailifchanged(repo)
866 return hg.clean(repo, node, show_stats=show_stats)
866 return hg.clean(repo, node, show_stats=show_stats)
867
867
868 displayer = cmdutil.show_changeset(ui, repo, {})
868 displayer = cmdutil.show_changeset(ui, repo, {})
869
869
870 if command:
870 if command:
871 changesets = 1
871 changesets = 1
872 if noupdate:
872 if noupdate:
873 try:
873 try:
874 node = state['current'][0]
874 node = state['current'][0]
875 except LookupError:
875 except LookupError:
876 raise error.Abort(_('current bisect revision is unknown - '
876 raise error.Abort(_('current bisect revision is unknown - '
877 'start a new bisect to fix'))
877 'start a new bisect to fix'))
878 else:
878 else:
879 node, p2 = repo.dirstate.parents()
879 node, p2 = repo.dirstate.parents()
880 if p2 != nullid:
880 if p2 != nullid:
881 raise error.Abort(_('current bisect revision is a merge'))
881 raise error.Abort(_('current bisect revision is a merge'))
882 if rev:
882 if rev:
883 node = repo[scmutil.revsingle(repo, rev, node)].node()
883 node = repo[scmutil.revsingle(repo, rev, node)].node()
884 try:
884 try:
885 while changesets:
885 while changesets:
886 # update state
886 # update state
887 state['current'] = [node]
887 state['current'] = [node]
888 hbisect.save_state(repo, state)
888 hbisect.save_state(repo, state)
889 status = ui.system(command, environ={'HG_NODE': hex(node)},
889 status = ui.system(command, environ={'HG_NODE': hex(node)},
890 blockedtag='bisect_check')
890 blockedtag='bisect_check')
891 if status == 125:
891 if status == 125:
892 transition = "skip"
892 transition = "skip"
893 elif status == 0:
893 elif status == 0:
894 transition = "good"
894 transition = "good"
895 # status < 0 means process was killed
895 # status < 0 means process was killed
896 elif status == 127:
896 elif status == 127:
897 raise error.Abort(_("failed to execute %s") % command)
897 raise error.Abort(_("failed to execute %s") % command)
898 elif status < 0:
898 elif status < 0:
899 raise error.Abort(_("%s killed") % command)
899 raise error.Abort(_("%s killed") % command)
900 else:
900 else:
901 transition = "bad"
901 transition = "bad"
902 state[transition].append(node)
902 state[transition].append(node)
903 ctx = repo[node]
903 ctx = repo[node]
904 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
904 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
905 hbisect.checkstate(state)
905 hbisect.checkstate(state)
906 # bisect
906 # bisect
907 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
907 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
908 # update to next check
908 # update to next check
909 node = nodes[0]
909 node = nodes[0]
910 mayupdate(repo, node, show_stats=False)
910 mayupdate(repo, node, show_stats=False)
911 finally:
911 finally:
912 state['current'] = [node]
912 state['current'] = [node]
913 hbisect.save_state(repo, state)
913 hbisect.save_state(repo, state)
914 hbisect.printresult(ui, repo, state, displayer, nodes, bgood)
914 hbisect.printresult(ui, repo, state, displayer, nodes, bgood)
915 return
915 return
916
916
917 hbisect.checkstate(state)
917 hbisect.checkstate(state)
918
918
919 # actually bisect
919 # actually bisect
920 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
920 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
921 if extend:
921 if extend:
922 if not changesets:
922 if not changesets:
923 extendnode = hbisect.extendrange(repo, state, nodes, good)
923 extendnode = hbisect.extendrange(repo, state, nodes, good)
924 if extendnode is not None:
924 if extendnode is not None:
925 ui.write(_("Extending search to changeset %d:%s\n")
925 ui.write(_("Extending search to changeset %d:%s\n")
926 % (extendnode.rev(), extendnode))
926 % (extendnode.rev(), extendnode))
927 state['current'] = [extendnode.node()]
927 state['current'] = [extendnode.node()]
928 hbisect.save_state(repo, state)
928 hbisect.save_state(repo, state)
929 return mayupdate(repo, extendnode.node())
929 return mayupdate(repo, extendnode.node())
930 raise error.Abort(_("nothing to extend"))
930 raise error.Abort(_("nothing to extend"))
931
931
932 if changesets == 0:
932 if changesets == 0:
933 hbisect.printresult(ui, repo, state, displayer, nodes, good)
933 hbisect.printresult(ui, repo, state, displayer, nodes, good)
934 else:
934 else:
935 assert len(nodes) == 1 # only a single node can be tested next
935 assert len(nodes) == 1 # only a single node can be tested next
936 node = nodes[0]
936 node = nodes[0]
937 # compute the approximate number of remaining tests
937 # compute the approximate number of remaining tests
938 tests, size = 0, 2
938 tests, size = 0, 2
939 while size <= changesets:
939 while size <= changesets:
940 tests, size = tests + 1, size * 2
940 tests, size = tests + 1, size * 2
941 rev = repo.changelog.rev(node)
941 rev = repo.changelog.rev(node)
942 ui.write(_("Testing changeset %d:%s "
942 ui.write(_("Testing changeset %d:%s "
943 "(%d changesets remaining, ~%d tests)\n")
943 "(%d changesets remaining, ~%d tests)\n")
944 % (rev, short(node), changesets, tests))
944 % (rev, short(node), changesets, tests))
945 state['current'] = [node]
945 state['current'] = [node]
946 hbisect.save_state(repo, state)
946 hbisect.save_state(repo, state)
947 return mayupdate(repo, node)
947 return mayupdate(repo, node)
948
948
949 @command('bookmarks|bookmark',
949 @command('bookmarks|bookmark',
950 [('f', 'force', False, _('force')),
950 [('f', 'force', False, _('force')),
951 ('r', 'rev', '', _('revision for bookmark action'), _('REV')),
951 ('r', 'rev', '', _('revision for bookmark action'), _('REV')),
952 ('d', 'delete', False, _('delete a given bookmark')),
952 ('d', 'delete', False, _('delete a given bookmark')),
953 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
953 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
954 ('i', 'inactive', False, _('mark a bookmark inactive')),
954 ('i', 'inactive', False, _('mark a bookmark inactive')),
955 ] + formatteropts,
955 ] + formatteropts,
956 _('hg bookmarks [OPTIONS]... [NAME]...'))
956 _('hg bookmarks [OPTIONS]... [NAME]...'))
957 def bookmark(ui, repo, *names, **opts):
957 def bookmark(ui, repo, *names, **opts):
958 '''create a new bookmark or list existing bookmarks
958 '''create a new bookmark or list existing bookmarks
959
959
960 Bookmarks are labels on changesets to help track lines of development.
960 Bookmarks are labels on changesets to help track lines of development.
961 Bookmarks are unversioned and can be moved, renamed and deleted.
961 Bookmarks are unversioned and can be moved, renamed and deleted.
962 Deleting or moving a bookmark has no effect on the associated changesets.
962 Deleting or moving a bookmark has no effect on the associated changesets.
963
963
964 Creating or updating to a bookmark causes it to be marked as 'active'.
964 Creating or updating to a bookmark causes it to be marked as 'active'.
965 The active bookmark is indicated with a '*'.
965 The active bookmark is indicated with a '*'.
966 When a commit is made, the active bookmark will advance to the new commit.
966 When a commit is made, the active bookmark will advance to the new commit.
967 A plain :hg:`update` will also advance an active bookmark, if possible.
967 A plain :hg:`update` will also advance an active bookmark, if possible.
968 Updating away from a bookmark will cause it to be deactivated.
968 Updating away from a bookmark will cause it to be deactivated.
969
969
970 Bookmarks can be pushed and pulled between repositories (see
970 Bookmarks can be pushed and pulled between repositories (see
971 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
971 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
972 diverged, a new 'divergent bookmark' of the form 'name@path' will
972 diverged, a new 'divergent bookmark' of the form 'name@path' will
973 be created. Using :hg:`merge` will resolve the divergence.
973 be created. Using :hg:`merge` will resolve the divergence.
974
974
975 A bookmark named '@' has the special property that :hg:`clone` will
975 A bookmark named '@' has the special property that :hg:`clone` will
976 check it out by default if it exists.
976 check it out by default if it exists.
977
977
978 .. container:: verbose
978 .. container:: verbose
979
979
980 Examples:
980 Examples:
981
981
982 - create an active bookmark for a new line of development::
982 - create an active bookmark for a new line of development::
983
983
984 hg book new-feature
984 hg book new-feature
985
985
986 - create an inactive bookmark as a place marker::
986 - create an inactive bookmark as a place marker::
987
987
988 hg book -i reviewed
988 hg book -i reviewed
989
989
990 - create an inactive bookmark on another changeset::
990 - create an inactive bookmark on another changeset::
991
991
992 hg book -r .^ tested
992 hg book -r .^ tested
993
993
994 - rename bookmark turkey to dinner::
994 - rename bookmark turkey to dinner::
995
995
996 hg book -m turkey dinner
996 hg book -m turkey dinner
997
997
998 - move the '@' bookmark from another branch::
998 - move the '@' bookmark from another branch::
999
999
1000 hg book -f @
1000 hg book -f @
1001 '''
1001 '''
1002 force = opts.get('force')
1002 force = opts.get('force')
1003 rev = opts.get('rev')
1003 rev = opts.get('rev')
1004 delete = opts.get('delete')
1004 delete = opts.get('delete')
1005 rename = opts.get('rename')
1005 rename = opts.get('rename')
1006 inactive = opts.get('inactive')
1006 inactive = opts.get('inactive')
1007
1007
1008 def checkformat(mark):
1008 def checkformat(mark):
1009 mark = mark.strip()
1009 mark = mark.strip()
1010 if not mark:
1010 if not mark:
1011 raise error.Abort(_("bookmark names cannot consist entirely of "
1011 raise error.Abort(_("bookmark names cannot consist entirely of "
1012 "whitespace"))
1012 "whitespace"))
1013 scmutil.checknewlabel(repo, mark, 'bookmark')
1013 scmutil.checknewlabel(repo, mark, 'bookmark')
1014 return mark
1014 return mark
1015
1015
1016 def checkconflict(repo, mark, cur, force=False, target=None):
1016 def checkconflict(repo, mark, cur, force=False, target=None):
1017 if mark in marks and not force:
1017 if mark in marks and not force:
1018 if target:
1018 if target:
1019 if marks[mark] == target and target == cur:
1019 if marks[mark] == target and target == cur:
1020 # re-activating a bookmark
1020 # re-activating a bookmark
1021 return
1021 return
1022 anc = repo.changelog.ancestors([repo[target].rev()])
1022 anc = repo.changelog.ancestors([repo[target].rev()])
1023 bmctx = repo[marks[mark]]
1023 bmctx = repo[marks[mark]]
1024 divs = [repo[b].node() for b in marks
1024 divs = [repo[b].node() for b in marks
1025 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
1025 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
1026
1026
1027 # allow resolving a single divergent bookmark even if moving
1027 # allow resolving a single divergent bookmark even if moving
1028 # the bookmark across branches when a revision is specified
1028 # the bookmark across branches when a revision is specified
1029 # that contains a divergent bookmark
1029 # that contains a divergent bookmark
1030 if bmctx.rev() not in anc and target in divs:
1030 if bmctx.rev() not in anc and target in divs:
1031 bookmarks.deletedivergent(repo, [target], mark)
1031 bookmarks.deletedivergent(repo, [target], mark)
1032 return
1032 return
1033
1033
1034 deletefrom = [b for b in divs
1034 deletefrom = [b for b in divs
1035 if repo[b].rev() in anc or b == target]
1035 if repo[b].rev() in anc or b == target]
1036 bookmarks.deletedivergent(repo, deletefrom, mark)
1036 bookmarks.deletedivergent(repo, deletefrom, mark)
1037 if bookmarks.validdest(repo, bmctx, repo[target]):
1037 if bookmarks.validdest(repo, bmctx, repo[target]):
1038 ui.status(_("moving bookmark '%s' forward from %s\n") %
1038 ui.status(_("moving bookmark '%s' forward from %s\n") %
1039 (mark, short(bmctx.node())))
1039 (mark, short(bmctx.node())))
1040 return
1040 return
1041 raise error.Abort(_("bookmark '%s' already exists "
1041 raise error.Abort(_("bookmark '%s' already exists "
1042 "(use -f to force)") % mark)
1042 "(use -f to force)") % mark)
1043 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
1043 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
1044 and not force):
1044 and not force):
1045 raise error.Abort(
1045 raise error.Abort(
1046 _("a bookmark cannot have the name of an existing branch"))
1046 _("a bookmark cannot have the name of an existing branch"))
1047
1047
1048 if delete and rename:
1048 if delete and rename:
1049 raise error.Abort(_("--delete and --rename are incompatible"))
1049 raise error.Abort(_("--delete and --rename are incompatible"))
1050 if delete and rev:
1050 if delete and rev:
1051 raise error.Abort(_("--rev is incompatible with --delete"))
1051 raise error.Abort(_("--rev is incompatible with --delete"))
1052 if rename and rev:
1052 if rename and rev:
1053 raise error.Abort(_("--rev is incompatible with --rename"))
1053 raise error.Abort(_("--rev is incompatible with --rename"))
1054 if not names and (delete or rev):
1054 if not names and (delete or rev):
1055 raise error.Abort(_("bookmark name required"))
1055 raise error.Abort(_("bookmark name required"))
1056
1056
1057 if delete or rename or names or inactive:
1057 if delete or rename or names or inactive:
1058 wlock = lock = tr = None
1058 wlock = lock = tr = None
1059 try:
1059 try:
1060 wlock = repo.wlock()
1060 wlock = repo.wlock()
1061 lock = repo.lock()
1061 lock = repo.lock()
1062 cur = repo.changectx('.').node()
1062 cur = repo.changectx('.').node()
1063 marks = repo._bookmarks
1063 marks = repo._bookmarks
1064 if delete:
1064 if delete:
1065 tr = repo.transaction('bookmark')
1065 tr = repo.transaction('bookmark')
1066 for mark in names:
1066 for mark in names:
1067 if mark not in marks:
1067 if mark not in marks:
1068 raise error.Abort(_("bookmark '%s' does not exist") %
1068 raise error.Abort(_("bookmark '%s' does not exist") %
1069 mark)
1069 mark)
1070 if mark == repo._activebookmark:
1070 if mark == repo._activebookmark:
1071 bookmarks.deactivate(repo)
1071 bookmarks.deactivate(repo)
1072 del marks[mark]
1072 del marks[mark]
1073
1073
1074 elif rename:
1074 elif rename:
1075 tr = repo.transaction('bookmark')
1075 tr = repo.transaction('bookmark')
1076 if not names:
1076 if not names:
1077 raise error.Abort(_("new bookmark name required"))
1077 raise error.Abort(_("new bookmark name required"))
1078 elif len(names) > 1:
1078 elif len(names) > 1:
1079 raise error.Abort(_("only one new bookmark name allowed"))
1079 raise error.Abort(_("only one new bookmark name allowed"))
1080 mark = checkformat(names[0])
1080 mark = checkformat(names[0])
1081 if rename not in marks:
1081 if rename not in marks:
1082 raise error.Abort(_("bookmark '%s' does not exist")
1082 raise error.Abort(_("bookmark '%s' does not exist")
1083 % rename)
1083 % rename)
1084 checkconflict(repo, mark, cur, force)
1084 checkconflict(repo, mark, cur, force)
1085 marks[mark] = marks[rename]
1085 marks[mark] = marks[rename]
1086 if repo._activebookmark == rename and not inactive:
1086 if repo._activebookmark == rename and not inactive:
1087 bookmarks.activate(repo, mark)
1087 bookmarks.activate(repo, mark)
1088 del marks[rename]
1088 del marks[rename]
1089 elif names:
1089 elif names:
1090 tr = repo.transaction('bookmark')
1090 tr = repo.transaction('bookmark')
1091 newact = None
1091 newact = None
1092 for mark in names:
1092 for mark in names:
1093 mark = checkformat(mark)
1093 mark = checkformat(mark)
1094 if newact is None:
1094 if newact is None:
1095 newact = mark
1095 newact = mark
1096 if inactive and mark == repo._activebookmark:
1096 if inactive and mark == repo._activebookmark:
1097 bookmarks.deactivate(repo)
1097 bookmarks.deactivate(repo)
1098 return
1098 return
1099 tgt = cur
1099 tgt = cur
1100 if rev:
1100 if rev:
1101 tgt = scmutil.revsingle(repo, rev).node()
1101 tgt = scmutil.revsingle(repo, rev).node()
1102 checkconflict(repo, mark, cur, force, tgt)
1102 checkconflict(repo, mark, cur, force, tgt)
1103 marks[mark] = tgt
1103 marks[mark] = tgt
1104 if not inactive and cur == marks[newact] and not rev:
1104 if not inactive and cur == marks[newact] and not rev:
1105 bookmarks.activate(repo, newact)
1105 bookmarks.activate(repo, newact)
1106 elif cur != tgt and newact == repo._activebookmark:
1106 elif cur != tgt and newact == repo._activebookmark:
1107 bookmarks.deactivate(repo)
1107 bookmarks.deactivate(repo)
1108 elif inactive:
1108 elif inactive:
1109 if len(marks) == 0:
1109 if len(marks) == 0:
1110 ui.status(_("no bookmarks set\n"))
1110 ui.status(_("no bookmarks set\n"))
1111 elif not repo._activebookmark:
1111 elif not repo._activebookmark:
1112 ui.status(_("no active bookmark\n"))
1112 ui.status(_("no active bookmark\n"))
1113 else:
1113 else:
1114 bookmarks.deactivate(repo)
1114 bookmarks.deactivate(repo)
1115 if tr is not None:
1115 if tr is not None:
1116 marks.recordchange(tr)
1116 marks.recordchange(tr)
1117 tr.close()
1117 tr.close()
1118 finally:
1118 finally:
1119 lockmod.release(tr, lock, wlock)
1119 lockmod.release(tr, lock, wlock)
1120 else: # show bookmarks
1120 else: # show bookmarks
1121 fm = ui.formatter('bookmarks', opts)
1121 fm = ui.formatter('bookmarks', opts)
1122 hexfn = fm.hexfunc
1122 hexfn = fm.hexfunc
1123 marks = repo._bookmarks
1123 marks = repo._bookmarks
1124 if len(marks) == 0 and fm.isplain():
1124 if len(marks) == 0 and fm.isplain():
1125 ui.status(_("no bookmarks set\n"))
1125 ui.status(_("no bookmarks set\n"))
1126 for bmark, n in sorted(marks.iteritems()):
1126 for bmark, n in sorted(marks.iteritems()):
1127 active = repo._activebookmark
1127 active = repo._activebookmark
1128 if bmark == active:
1128 if bmark == active:
1129 prefix, label = '*', activebookmarklabel
1129 prefix, label = '*', activebookmarklabel
1130 else:
1130 else:
1131 prefix, label = ' ', ''
1131 prefix, label = ' ', ''
1132
1132
1133 fm.startitem()
1133 fm.startitem()
1134 if not ui.quiet:
1134 if not ui.quiet:
1135 fm.plain(' %s ' % prefix, label=label)
1135 fm.plain(' %s ' % prefix, label=label)
1136 fm.write('bookmark', '%s', bmark, label=label)
1136 fm.write('bookmark', '%s', bmark, label=label)
1137 pad = " " * (25 - encoding.colwidth(bmark))
1137 pad = " " * (25 - encoding.colwidth(bmark))
1138 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1138 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1139 repo.changelog.rev(n), hexfn(n), label=label)
1139 repo.changelog.rev(n), hexfn(n), label=label)
1140 fm.data(active=(bmark == active))
1140 fm.data(active=(bmark == active))
1141 fm.plain('\n')
1141 fm.plain('\n')
1142 fm.end()
1142 fm.end()
1143
1143
1144 @command('branch',
1144 @command('branch',
1145 [('f', 'force', None,
1145 [('f', 'force', None,
1146 _('set branch name even if it shadows an existing branch')),
1146 _('set branch name even if it shadows an existing branch')),
1147 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1147 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1148 _('[-fC] [NAME]'))
1148 _('[-fC] [NAME]'))
1149 def branch(ui, repo, label=None, **opts):
1149 def branch(ui, repo, label=None, **opts):
1150 """set or show the current branch name
1150 """set or show the current branch name
1151
1151
1152 .. note::
1152 .. note::
1153
1153
1154 Branch names are permanent and global. Use :hg:`bookmark` to create a
1154 Branch names are permanent and global. Use :hg:`bookmark` to create a
1155 light-weight bookmark instead. See :hg:`help glossary` for more
1155 light-weight bookmark instead. See :hg:`help glossary` for more
1156 information about named branches and bookmarks.
1156 information about named branches and bookmarks.
1157
1157
1158 With no argument, show the current branch name. With one argument,
1158 With no argument, show the current branch name. With one argument,
1159 set the working directory branch name (the branch will not exist
1159 set the working directory branch name (the branch will not exist
1160 in the repository until the next commit). Standard practice
1160 in the repository until the next commit). Standard practice
1161 recommends that primary development take place on the 'default'
1161 recommends that primary development take place on the 'default'
1162 branch.
1162 branch.
1163
1163
1164 Unless -f/--force is specified, branch will not let you set a
1164 Unless -f/--force is specified, branch will not let you set a
1165 branch name that already exists.
1165 branch name that already exists.
1166
1166
1167 Use -C/--clean to reset the working directory branch to that of
1167 Use -C/--clean to reset the working directory branch to that of
1168 the parent of the working directory, negating a previous branch
1168 the parent of the working directory, negating a previous branch
1169 change.
1169 change.
1170
1170
1171 Use the command :hg:`update` to switch to an existing branch. Use
1171 Use the command :hg:`update` to switch to an existing branch. Use
1172 :hg:`commit --close-branch` to mark this branch head as closed.
1172 :hg:`commit --close-branch` to mark this branch head as closed.
1173 When all heads of a branch are closed, the branch will be
1173 When all heads of a branch are closed, the branch will be
1174 considered closed.
1174 considered closed.
1175
1175
1176 Returns 0 on success.
1176 Returns 0 on success.
1177 """
1177 """
1178 if label:
1178 if label:
1179 label = label.strip()
1179 label = label.strip()
1180
1180
1181 if not opts.get('clean') and not label:
1181 if not opts.get('clean') and not label:
1182 ui.write("%s\n" % repo.dirstate.branch())
1182 ui.write("%s\n" % repo.dirstate.branch())
1183 return
1183 return
1184
1184
1185 with repo.wlock():
1185 with repo.wlock():
1186 if opts.get('clean'):
1186 if opts.get('clean'):
1187 label = repo[None].p1().branch()
1187 label = repo[None].p1().branch()
1188 repo.dirstate.setbranch(label)
1188 repo.dirstate.setbranch(label)
1189 ui.status(_('reset working directory to branch %s\n') % label)
1189 ui.status(_('reset working directory to branch %s\n') % label)
1190 elif label:
1190 elif label:
1191 if not opts.get('force') and label in repo.branchmap():
1191 if not opts.get('force') and label in repo.branchmap():
1192 if label not in [p.branch() for p in repo[None].parents()]:
1192 if label not in [p.branch() for p in repo[None].parents()]:
1193 raise error.Abort(_('a branch of the same name already'
1193 raise error.Abort(_('a branch of the same name already'
1194 ' exists'),
1194 ' exists'),
1195 # i18n: "it" refers to an existing branch
1195 # i18n: "it" refers to an existing branch
1196 hint=_("use 'hg update' to switch to it"))
1196 hint=_("use 'hg update' to switch to it"))
1197 scmutil.checknewlabel(repo, label, 'branch')
1197 scmutil.checknewlabel(repo, label, 'branch')
1198 repo.dirstate.setbranch(label)
1198 repo.dirstate.setbranch(label)
1199 ui.status(_('marked working directory as branch %s\n') % label)
1199 ui.status(_('marked working directory as branch %s\n') % label)
1200
1200
1201 # find any open named branches aside from default
1201 # find any open named branches aside from default
1202 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1202 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1203 if n != "default" and not c]
1203 if n != "default" and not c]
1204 if not others:
1204 if not others:
1205 ui.status(_('(branches are permanent and global, '
1205 ui.status(_('(branches are permanent and global, '
1206 'did you want a bookmark?)\n'))
1206 'did you want a bookmark?)\n'))
1207
1207
1208 @command('branches',
1208 @command('branches',
1209 [('a', 'active', False,
1209 [('a', 'active', False,
1210 _('show only branches that have unmerged heads (DEPRECATED)')),
1210 _('show only branches that have unmerged heads (DEPRECATED)')),
1211 ('c', 'closed', False, _('show normal and closed branches')),
1211 ('c', 'closed', False, _('show normal and closed branches')),
1212 ] + formatteropts,
1212 ] + formatteropts,
1213 _('[-c]'))
1213 _('[-c]'))
1214 def branches(ui, repo, active=False, closed=False, **opts):
1214 def branches(ui, repo, active=False, closed=False, **opts):
1215 """list repository named branches
1215 """list repository named branches
1216
1216
1217 List the repository's named branches, indicating which ones are
1217 List the repository's named branches, indicating which ones are
1218 inactive. If -c/--closed is specified, also list branches which have
1218 inactive. If -c/--closed is specified, also list branches which have
1219 been marked closed (see :hg:`commit --close-branch`).
1219 been marked closed (see :hg:`commit --close-branch`).
1220
1220
1221 Use the command :hg:`update` to switch to an existing branch.
1221 Use the command :hg:`update` to switch to an existing branch.
1222
1222
1223 Returns 0.
1223 Returns 0.
1224 """
1224 """
1225
1225
1226 ui.pager('branches')
1226 ui.pager('branches')
1227 fm = ui.formatter('branches', opts)
1227 fm = ui.formatter('branches', opts)
1228 hexfunc = fm.hexfunc
1228 hexfunc = fm.hexfunc
1229
1229
1230 allheads = set(repo.heads())
1230 allheads = set(repo.heads())
1231 branches = []
1231 branches = []
1232 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1232 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1233 isactive = not isclosed and bool(set(heads) & allheads)
1233 isactive = not isclosed and bool(set(heads) & allheads)
1234 branches.append((tag, repo[tip], isactive, not isclosed))
1234 branches.append((tag, repo[tip], isactive, not isclosed))
1235 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1235 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1236 reverse=True)
1236 reverse=True)
1237
1237
1238 for tag, ctx, isactive, isopen in branches:
1238 for tag, ctx, isactive, isopen in branches:
1239 if active and not isactive:
1239 if active and not isactive:
1240 continue
1240 continue
1241 if isactive:
1241 if isactive:
1242 label = 'branches.active'
1242 label = 'branches.active'
1243 notice = ''
1243 notice = ''
1244 elif not isopen:
1244 elif not isopen:
1245 if not closed:
1245 if not closed:
1246 continue
1246 continue
1247 label = 'branches.closed'
1247 label = 'branches.closed'
1248 notice = _(' (closed)')
1248 notice = _(' (closed)')
1249 else:
1249 else:
1250 label = 'branches.inactive'
1250 label = 'branches.inactive'
1251 notice = _(' (inactive)')
1251 notice = _(' (inactive)')
1252 current = (tag == repo.dirstate.branch())
1252 current = (tag == repo.dirstate.branch())
1253 if current:
1253 if current:
1254 label = 'branches.current'
1254 label = 'branches.current'
1255
1255
1256 fm.startitem()
1256 fm.startitem()
1257 fm.write('branch', '%s', tag, label=label)
1257 fm.write('branch', '%s', tag, label=label)
1258 rev = ctx.rev()
1258 rev = ctx.rev()
1259 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1259 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1260 fmt = ' ' * padsize + ' %d:%s'
1260 fmt = ' ' * padsize + ' %d:%s'
1261 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1261 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1262 label='log.changeset changeset.%s' % ctx.phasestr())
1262 label='log.changeset changeset.%s' % ctx.phasestr())
1263 fm.context(ctx=ctx)
1263 fm.context(ctx=ctx)
1264 fm.data(active=isactive, closed=not isopen, current=current)
1264 fm.data(active=isactive, closed=not isopen, current=current)
1265 if not ui.quiet:
1265 if not ui.quiet:
1266 fm.plain(notice)
1266 fm.plain(notice)
1267 fm.plain('\n')
1267 fm.plain('\n')
1268 fm.end()
1268 fm.end()
1269
1269
1270 @command('bundle',
1270 @command('bundle',
1271 [('f', 'force', None, _('run even when the destination is unrelated')),
1271 [('f', 'force', None, _('run even when the destination is unrelated')),
1272 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1272 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1273 _('REV')),
1273 _('REV')),
1274 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1274 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1275 _('BRANCH')),
1275 _('BRANCH')),
1276 ('', 'base', [],
1276 ('', 'base', [],
1277 _('a base changeset assumed to be available at the destination'),
1277 _('a base changeset assumed to be available at the destination'),
1278 _('REV')),
1278 _('REV')),
1279 ('a', 'all', None, _('bundle all changesets in the repository')),
1279 ('a', 'all', None, _('bundle all changesets in the repository')),
1280 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1280 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1281 ] + remoteopts,
1281 ] + remoteopts,
1282 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1282 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1283 def bundle(ui, repo, fname, dest=None, **opts):
1283 def bundle(ui, repo, fname, dest=None, **opts):
1284 """create a changegroup file
1284 """create a changegroup file
1285
1285
1286 Generate a changegroup file collecting changesets to be added
1286 Generate a changegroup file collecting changesets to be added
1287 to a repository.
1287 to a repository.
1288
1288
1289 To create a bundle containing all changesets, use -a/--all
1289 To create a bundle containing all changesets, use -a/--all
1290 (or --base null). Otherwise, hg assumes the destination will have
1290 (or --base null). Otherwise, hg assumes the destination will have
1291 all the nodes you specify with --base parameters. Otherwise, hg
1291 all the nodes you specify with --base parameters. Otherwise, hg
1292 will assume the repository has all the nodes in destination, or
1292 will assume the repository has all the nodes in destination, or
1293 default-push/default if no destination is specified.
1293 default-push/default if no destination is specified.
1294
1294
1295 You can change bundle format with the -t/--type option. You can
1295 You can change bundle format with the -t/--type option. You can
1296 specify a compression, a bundle version or both using a dash
1296 specify a compression, a bundle version or both using a dash
1297 (comp-version). The available compression methods are: none, bzip2,
1297 (comp-version). The available compression methods are: none, bzip2,
1298 and gzip (by default, bundles are compressed using bzip2). The
1298 and gzip (by default, bundles are compressed using bzip2). The
1299 available formats are: v1, v2 (default to most suitable).
1299 available formats are: v1, v2 (default to most suitable).
1300
1300
1301 The bundle file can then be transferred using conventional means
1301 The bundle file can then be transferred using conventional means
1302 and applied to another repository with the unbundle or pull
1302 and applied to another repository with the unbundle or pull
1303 command. This is useful when direct push and pull are not
1303 command. This is useful when direct push and pull are not
1304 available or when exporting an entire repository is undesirable.
1304 available or when exporting an entire repository is undesirable.
1305
1305
1306 Applying bundles preserves all changeset contents including
1306 Applying bundles preserves all changeset contents including
1307 permissions, copy/rename information, and revision history.
1307 permissions, copy/rename information, and revision history.
1308
1308
1309 Returns 0 on success, 1 if no changes found.
1309 Returns 0 on success, 1 if no changes found.
1310 """
1310 """
1311 revs = None
1311 revs = None
1312 if 'rev' in opts:
1312 if 'rev' in opts:
1313 revstrings = opts['rev']
1313 revstrings = opts['rev']
1314 revs = scmutil.revrange(repo, revstrings)
1314 revs = scmutil.revrange(repo, revstrings)
1315 if revstrings and not revs:
1315 if revstrings and not revs:
1316 raise error.Abort(_('no commits to bundle'))
1316 raise error.Abort(_('no commits to bundle'))
1317
1317
1318 bundletype = opts.get('type', 'bzip2').lower()
1318 bundletype = opts.get('type', 'bzip2').lower()
1319 try:
1319 try:
1320 bcompression, cgversion, params = exchange.parsebundlespec(
1320 bcompression, cgversion, params = exchange.parsebundlespec(
1321 repo, bundletype, strict=False)
1321 repo, bundletype, strict=False)
1322 except error.UnsupportedBundleSpecification as e:
1322 except error.UnsupportedBundleSpecification as e:
1323 raise error.Abort(str(e),
1323 raise error.Abort(str(e),
1324 hint=_("see 'hg help bundle' for supported "
1324 hint=_("see 'hg help bundle' for supported "
1325 "values for --type"))
1325 "values for --type"))
1326
1326
1327 # Packed bundles are a pseudo bundle format for now.
1327 # Packed bundles are a pseudo bundle format for now.
1328 if cgversion == 's1':
1328 if cgversion == 's1':
1329 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1329 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1330 hint=_("use 'hg debugcreatestreamclonebundle'"))
1330 hint=_("use 'hg debugcreatestreamclonebundle'"))
1331
1331
1332 if opts.get('all'):
1332 if opts.get('all'):
1333 if dest:
1333 if dest:
1334 raise error.Abort(_("--all is incompatible with specifying "
1334 raise error.Abort(_("--all is incompatible with specifying "
1335 "a destination"))
1335 "a destination"))
1336 if opts.get('base'):
1336 if opts.get('base'):
1337 ui.warn(_("ignoring --base because --all was specified\n"))
1337 ui.warn(_("ignoring --base because --all was specified\n"))
1338 base = ['null']
1338 base = ['null']
1339 else:
1339 else:
1340 base = scmutil.revrange(repo, opts.get('base'))
1340 base = scmutil.revrange(repo, opts.get('base'))
1341 # TODO: get desired bundlecaps from command line.
1341 # TODO: get desired bundlecaps from command line.
1342 bundlecaps = None
1342 bundlecaps = None
1343 if cgversion not in changegroup.supportedoutgoingversions(repo):
1343 if cgversion not in changegroup.supportedoutgoingversions(repo):
1344 raise error.Abort(_("repository does not support bundle version %s") %
1344 raise error.Abort(_("repository does not support bundle version %s") %
1345 cgversion)
1345 cgversion)
1346
1346
1347 if base:
1347 if base:
1348 if dest:
1348 if dest:
1349 raise error.Abort(_("--base is incompatible with specifying "
1349 raise error.Abort(_("--base is incompatible with specifying "
1350 "a destination"))
1350 "a destination"))
1351 common = [repo.lookup(rev) for rev in base]
1351 common = [repo.lookup(rev) for rev in base]
1352 heads = revs and map(repo.lookup, revs) or None
1352 heads = revs and map(repo.lookup, revs) or None
1353 outgoing = discovery.outgoing(repo, common, heads)
1353 outgoing = discovery.outgoing(repo, common, heads)
1354 cg = changegroup.getchangegroup(repo, 'bundle', outgoing,
1354 cg = changegroup.getchangegroup(repo, 'bundle', outgoing,
1355 bundlecaps=bundlecaps,
1355 bundlecaps=bundlecaps,
1356 version=cgversion)
1356 version=cgversion)
1357 outgoing = None
1357 outgoing = None
1358 else:
1358 else:
1359 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1359 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1360 dest, branches = hg.parseurl(dest, opts.get('branch'))
1360 dest, branches = hg.parseurl(dest, opts.get('branch'))
1361 other = hg.peer(repo, opts, dest)
1361 other = hg.peer(repo, opts, dest)
1362 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1362 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1363 heads = revs and map(repo.lookup, revs) or revs
1363 heads = revs and map(repo.lookup, revs) or revs
1364 outgoing = discovery.findcommonoutgoing(repo, other,
1364 outgoing = discovery.findcommonoutgoing(repo, other,
1365 onlyheads=heads,
1365 onlyheads=heads,
1366 force=opts.get('force'),
1366 force=opts.get('force'),
1367 portable=True)
1367 portable=True)
1368 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1368 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1369 bundlecaps, version=cgversion)
1369 bundlecaps, version=cgversion)
1370 if not cg:
1370 if not cg:
1371 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1371 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1372 return 1
1372 return 1
1373
1373
1374 if cgversion == '01': #bundle1
1374 if cgversion == '01': #bundle1
1375 if bcompression is None:
1375 if bcompression is None:
1376 bcompression = 'UN'
1376 bcompression = 'UN'
1377 bversion = 'HG10' + bcompression
1377 bversion = 'HG10' + bcompression
1378 bcompression = None
1378 bcompression = None
1379 else:
1379 else:
1380 assert cgversion == '02'
1380 assert cgversion == '02'
1381 bversion = 'HG20'
1381 bversion = 'HG20'
1382
1382
1383 # TODO compression options should be derived from bundlespec parsing.
1383 # TODO compression options should be derived from bundlespec parsing.
1384 # This is a temporary hack to allow adjusting bundle compression
1384 # This is a temporary hack to allow adjusting bundle compression
1385 # level without a) formalizing the bundlespec changes to declare it
1385 # level without a) formalizing the bundlespec changes to declare it
1386 # b) introducing a command flag.
1386 # b) introducing a command flag.
1387 compopts = {}
1387 compopts = {}
1388 complevel = ui.configint('experimental', 'bundlecomplevel')
1388 complevel = ui.configint('experimental', 'bundlecomplevel')
1389 if complevel is not None:
1389 if complevel is not None:
1390 compopts['level'] = complevel
1390 compopts['level'] = complevel
1391
1391
1392 bundle2.writebundle(ui, cg, fname, bversion, compression=bcompression,
1392 bundle2.writebundle(ui, cg, fname, bversion, compression=bcompression,
1393 compopts=compopts)
1393 compopts=compopts)
1394
1394
1395 @command('cat',
1395 @command('cat',
1396 [('o', 'output', '',
1396 [('o', 'output', '',
1397 _('print output to file with formatted name'), _('FORMAT')),
1397 _('print output to file with formatted name'), _('FORMAT')),
1398 ('r', 'rev', '', _('print the given revision'), _('REV')),
1398 ('r', 'rev', '', _('print the given revision'), _('REV')),
1399 ('', 'decode', None, _('apply any matching decode filter')),
1399 ('', 'decode', None, _('apply any matching decode filter')),
1400 ] + walkopts,
1400 ] + walkopts,
1401 _('[OPTION]... FILE...'),
1401 _('[OPTION]... FILE...'),
1402 inferrepo=True)
1402 inferrepo=True)
1403 def cat(ui, repo, file1, *pats, **opts):
1403 def cat(ui, repo, file1, *pats, **opts):
1404 """output the current or given revision of files
1404 """output the current or given revision of files
1405
1405
1406 Print the specified files as they were at the given revision. If
1406 Print the specified files as they were at the given revision. If
1407 no revision is given, the parent of the working directory is used.
1407 no revision is given, the parent of the working directory is used.
1408
1408
1409 Output may be to a file, in which case the name of the file is
1409 Output may be to a file, in which case the name of the file is
1410 given using a format string. The formatting rules as follows:
1410 given using a format string. The formatting rules as follows:
1411
1411
1412 :``%%``: literal "%" character
1412 :``%%``: literal "%" character
1413 :``%s``: basename of file being printed
1413 :``%s``: basename of file being printed
1414 :``%d``: dirname of file being printed, or '.' if in repository root
1414 :``%d``: dirname of file being printed, or '.' if in repository root
1415 :``%p``: root-relative path name of file being printed
1415 :``%p``: root-relative path name of file being printed
1416 :``%H``: changeset hash (40 hexadecimal digits)
1416 :``%H``: changeset hash (40 hexadecimal digits)
1417 :``%R``: changeset revision number
1417 :``%R``: changeset revision number
1418 :``%h``: short-form changeset hash (12 hexadecimal digits)
1418 :``%h``: short-form changeset hash (12 hexadecimal digits)
1419 :``%r``: zero-padded changeset revision number
1419 :``%r``: zero-padded changeset revision number
1420 :``%b``: basename of the exporting repository
1420 :``%b``: basename of the exporting repository
1421
1421
1422 Returns 0 on success.
1422 Returns 0 on success.
1423 """
1423 """
1424 ctx = scmutil.revsingle(repo, opts.get('rev'))
1424 ctx = scmutil.revsingle(repo, opts.get('rev'))
1425 m = scmutil.match(ctx, (file1,) + pats, opts)
1425 m = scmutil.match(ctx, (file1,) + pats, opts)
1426
1426
1427 ui.pager('cat')
1427 ui.pager('cat')
1428 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1428 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1429
1429
1430 @command('^clone',
1430 @command('^clone',
1431 [('U', 'noupdate', None, _('the clone will include an empty working '
1431 [('U', 'noupdate', None, _('the clone will include an empty working '
1432 'directory (only a repository)')),
1432 'directory (only a repository)')),
1433 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1433 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1434 _('REV')),
1434 _('REV')),
1435 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1435 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1436 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1436 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1437 ('', 'pull', None, _('use pull protocol to copy metadata')),
1437 ('', 'pull', None, _('use pull protocol to copy metadata')),
1438 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1438 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1439 ] + remoteopts,
1439 ] + remoteopts,
1440 _('[OPTION]... SOURCE [DEST]'),
1440 _('[OPTION]... SOURCE [DEST]'),
1441 norepo=True)
1441 norepo=True)
1442 def clone(ui, source, dest=None, **opts):
1442 def clone(ui, source, dest=None, **opts):
1443 """make a copy of an existing repository
1443 """make a copy of an existing repository
1444
1444
1445 Create a copy of an existing repository in a new directory.
1445 Create a copy of an existing repository in a new directory.
1446
1446
1447 If no destination directory name is specified, it defaults to the
1447 If no destination directory name is specified, it defaults to the
1448 basename of the source.
1448 basename of the source.
1449
1449
1450 The location of the source is added to the new repository's
1450 The location of the source is added to the new repository's
1451 ``.hg/hgrc`` file, as the default to be used for future pulls.
1451 ``.hg/hgrc`` file, as the default to be used for future pulls.
1452
1452
1453 Only local paths and ``ssh://`` URLs are supported as
1453 Only local paths and ``ssh://`` URLs are supported as
1454 destinations. For ``ssh://`` destinations, no working directory or
1454 destinations. For ``ssh://`` destinations, no working directory or
1455 ``.hg/hgrc`` will be created on the remote side.
1455 ``.hg/hgrc`` will be created on the remote side.
1456
1456
1457 If the source repository has a bookmark called '@' set, that
1457 If the source repository has a bookmark called '@' set, that
1458 revision will be checked out in the new repository by default.
1458 revision will be checked out in the new repository by default.
1459
1459
1460 To check out a particular version, use -u/--update, or
1460 To check out a particular version, use -u/--update, or
1461 -U/--noupdate to create a clone with no working directory.
1461 -U/--noupdate to create a clone with no working directory.
1462
1462
1463 To pull only a subset of changesets, specify one or more revisions
1463 To pull only a subset of changesets, specify one or more revisions
1464 identifiers with -r/--rev or branches with -b/--branch. The
1464 identifiers with -r/--rev or branches with -b/--branch. The
1465 resulting clone will contain only the specified changesets and
1465 resulting clone will contain only the specified changesets and
1466 their ancestors. These options (or 'clone src#rev dest') imply
1466 their ancestors. These options (or 'clone src#rev dest') imply
1467 --pull, even for local source repositories.
1467 --pull, even for local source repositories.
1468
1468
1469 .. note::
1469 .. note::
1470
1470
1471 Specifying a tag will include the tagged changeset but not the
1471 Specifying a tag will include the tagged changeset but not the
1472 changeset containing the tag.
1472 changeset containing the tag.
1473
1473
1474 .. container:: verbose
1474 .. container:: verbose
1475
1475
1476 For efficiency, hardlinks are used for cloning whenever the
1476 For efficiency, hardlinks are used for cloning whenever the
1477 source and destination are on the same filesystem (note this
1477 source and destination are on the same filesystem (note this
1478 applies only to the repository data, not to the working
1478 applies only to the repository data, not to the working
1479 directory). Some filesystems, such as AFS, implement hardlinking
1479 directory). Some filesystems, such as AFS, implement hardlinking
1480 incorrectly, but do not report errors. In these cases, use the
1480 incorrectly, but do not report errors. In these cases, use the
1481 --pull option to avoid hardlinking.
1481 --pull option to avoid hardlinking.
1482
1482
1483 In some cases, you can clone repositories and the working
1483 In some cases, you can clone repositories and the working
1484 directory using full hardlinks with ::
1484 directory using full hardlinks with ::
1485
1485
1486 $ cp -al REPO REPOCLONE
1486 $ cp -al REPO REPOCLONE
1487
1487
1488 This is the fastest way to clone, but it is not always safe. The
1488 This is the fastest way to clone, but it is not always safe. The
1489 operation is not atomic (making sure REPO is not modified during
1489 operation is not atomic (making sure REPO is not modified during
1490 the operation is up to you) and you have to make sure your
1490 the operation is up to you) and you have to make sure your
1491 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1491 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1492 so). Also, this is not compatible with certain extensions that
1492 so). Also, this is not compatible with certain extensions that
1493 place their metadata under the .hg directory, such as mq.
1493 place their metadata under the .hg directory, such as mq.
1494
1494
1495 Mercurial will update the working directory to the first applicable
1495 Mercurial will update the working directory to the first applicable
1496 revision from this list:
1496 revision from this list:
1497
1497
1498 a) null if -U or the source repository has no changesets
1498 a) null if -U or the source repository has no changesets
1499 b) if -u . and the source repository is local, the first parent of
1499 b) if -u . and the source repository is local, the first parent of
1500 the source repository's working directory
1500 the source repository's working directory
1501 c) the changeset specified with -u (if a branch name, this means the
1501 c) the changeset specified with -u (if a branch name, this means the
1502 latest head of that branch)
1502 latest head of that branch)
1503 d) the changeset specified with -r
1503 d) the changeset specified with -r
1504 e) the tipmost head specified with -b
1504 e) the tipmost head specified with -b
1505 f) the tipmost head specified with the url#branch source syntax
1505 f) the tipmost head specified with the url#branch source syntax
1506 g) the revision marked with the '@' bookmark, if present
1506 g) the revision marked with the '@' bookmark, if present
1507 h) the tipmost head of the default branch
1507 h) the tipmost head of the default branch
1508 i) tip
1508 i) tip
1509
1509
1510 When cloning from servers that support it, Mercurial may fetch
1510 When cloning from servers that support it, Mercurial may fetch
1511 pre-generated data from a server-advertised URL. When this is done,
1511 pre-generated data from a server-advertised URL. When this is done,
1512 hooks operating on incoming changesets and changegroups may fire twice,
1512 hooks operating on incoming changesets and changegroups may fire twice,
1513 once for the bundle fetched from the URL and another for any additional
1513 once for the bundle fetched from the URL and another for any additional
1514 data not fetched from this URL. In addition, if an error occurs, the
1514 data not fetched from this URL. In addition, if an error occurs, the
1515 repository may be rolled back to a partial clone. This behavior may
1515 repository may be rolled back to a partial clone. This behavior may
1516 change in future releases. See :hg:`help -e clonebundles` for more.
1516 change in future releases. See :hg:`help -e clonebundles` for more.
1517
1517
1518 Examples:
1518 Examples:
1519
1519
1520 - clone a remote repository to a new directory named hg/::
1520 - clone a remote repository to a new directory named hg/::
1521
1521
1522 hg clone https://www.mercurial-scm.org/repo/hg/
1522 hg clone https://www.mercurial-scm.org/repo/hg/
1523
1523
1524 - create a lightweight local clone::
1524 - create a lightweight local clone::
1525
1525
1526 hg clone project/ project-feature/
1526 hg clone project/ project-feature/
1527
1527
1528 - clone from an absolute path on an ssh server (note double-slash)::
1528 - clone from an absolute path on an ssh server (note double-slash)::
1529
1529
1530 hg clone ssh://user@server//home/projects/alpha/
1530 hg clone ssh://user@server//home/projects/alpha/
1531
1531
1532 - do a high-speed clone over a LAN while checking out a
1532 - do a high-speed clone over a LAN while checking out a
1533 specified version::
1533 specified version::
1534
1534
1535 hg clone --uncompressed http://server/repo -u 1.5
1535 hg clone --uncompressed http://server/repo -u 1.5
1536
1536
1537 - create a repository without changesets after a particular revision::
1537 - create a repository without changesets after a particular revision::
1538
1538
1539 hg clone -r 04e544 experimental/ good/
1539 hg clone -r 04e544 experimental/ good/
1540
1540
1541 - clone (and track) a particular named branch::
1541 - clone (and track) a particular named branch::
1542
1542
1543 hg clone https://www.mercurial-scm.org/repo/hg/#stable
1543 hg clone https://www.mercurial-scm.org/repo/hg/#stable
1544
1544
1545 See :hg:`help urls` for details on specifying URLs.
1545 See :hg:`help urls` for details on specifying URLs.
1546
1546
1547 Returns 0 on success.
1547 Returns 0 on success.
1548 """
1548 """
1549 if opts.get('noupdate') and opts.get('updaterev'):
1549 if opts.get('noupdate') and opts.get('updaterev'):
1550 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1550 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1551
1551
1552 r = hg.clone(ui, opts, source, dest,
1552 r = hg.clone(ui, opts, source, dest,
1553 pull=opts.get('pull'),
1553 pull=opts.get('pull'),
1554 stream=opts.get('uncompressed'),
1554 stream=opts.get('uncompressed'),
1555 rev=opts.get('rev'),
1555 rev=opts.get('rev'),
1556 update=opts.get('updaterev') or not opts.get('noupdate'),
1556 update=opts.get('updaterev') or not opts.get('noupdate'),
1557 branch=opts.get('branch'),
1557 branch=opts.get('branch'),
1558 shareopts=opts.get('shareopts'))
1558 shareopts=opts.get('shareopts'))
1559
1559
1560 return r is None
1560 return r is None
1561
1561
1562 @command('^commit|ci',
1562 @command('^commit|ci',
1563 [('A', 'addremove', None,
1563 [('A', 'addremove', None,
1564 _('mark new/missing files as added/removed before committing')),
1564 _('mark new/missing files as added/removed before committing')),
1565 ('', 'close-branch', None,
1565 ('', 'close-branch', None,
1566 _('mark a branch head as closed')),
1566 _('mark a branch head as closed')),
1567 ('', 'amend', None, _('amend the parent of the working directory')),
1567 ('', 'amend', None, _('amend the parent of the working directory')),
1568 ('s', 'secret', None, _('use the secret phase for committing')),
1568 ('s', 'secret', None, _('use the secret phase for committing')),
1569 ('e', 'edit', None, _('invoke editor on commit messages')),
1569 ('e', 'edit', None, _('invoke editor on commit messages')),
1570 ('i', 'interactive', None, _('use interactive mode')),
1570 ('i', 'interactive', None, _('use interactive mode')),
1571 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1571 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1572 _('[OPTION]... [FILE]...'),
1572 _('[OPTION]... [FILE]...'),
1573 inferrepo=True)
1573 inferrepo=True)
1574 def commit(ui, repo, *pats, **opts):
1574 def commit(ui, repo, *pats, **opts):
1575 """commit the specified files or all outstanding changes
1575 """commit the specified files or all outstanding changes
1576
1576
1577 Commit changes to the given files into the repository. Unlike a
1577 Commit changes to the given files into the repository. Unlike a
1578 centralized SCM, this operation is a local operation. See
1578 centralized SCM, this operation is a local operation. See
1579 :hg:`push` for a way to actively distribute your changes.
1579 :hg:`push` for a way to actively distribute your changes.
1580
1580
1581 If a list of files is omitted, all changes reported by :hg:`status`
1581 If a list of files is omitted, all changes reported by :hg:`status`
1582 will be committed.
1582 will be committed.
1583
1583
1584 If you are committing the result of a merge, do not provide any
1584 If you are committing the result of a merge, do not provide any
1585 filenames or -I/-X filters.
1585 filenames or -I/-X filters.
1586
1586
1587 If no commit message is specified, Mercurial starts your
1587 If no commit message is specified, Mercurial starts your
1588 configured editor where you can enter a message. In case your
1588 configured editor where you can enter a message. In case your
1589 commit fails, you will find a backup of your message in
1589 commit fails, you will find a backup of your message in
1590 ``.hg/last-message.txt``.
1590 ``.hg/last-message.txt``.
1591
1591
1592 The --close-branch flag can be used to mark the current branch
1592 The --close-branch flag can be used to mark the current branch
1593 head closed. When all heads of a branch are closed, the branch
1593 head closed. When all heads of a branch are closed, the branch
1594 will be considered closed and no longer listed.
1594 will be considered closed and no longer listed.
1595
1595
1596 The --amend flag can be used to amend the parent of the
1596 The --amend flag can be used to amend the parent of the
1597 working directory with a new commit that contains the changes
1597 working directory with a new commit that contains the changes
1598 in the parent in addition to those currently reported by :hg:`status`,
1598 in the parent in addition to those currently reported by :hg:`status`,
1599 if there are any. The old commit is stored in a backup bundle in
1599 if there are any. The old commit is stored in a backup bundle in
1600 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1600 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1601 on how to restore it).
1601 on how to restore it).
1602
1602
1603 Message, user and date are taken from the amended commit unless
1603 Message, user and date are taken from the amended commit unless
1604 specified. When a message isn't specified on the command line,
1604 specified. When a message isn't specified on the command line,
1605 the editor will open with the message of the amended commit.
1605 the editor will open with the message of the amended commit.
1606
1606
1607 It is not possible to amend public changesets (see :hg:`help phases`)
1607 It is not possible to amend public changesets (see :hg:`help phases`)
1608 or changesets that have children.
1608 or changesets that have children.
1609
1609
1610 See :hg:`help dates` for a list of formats valid for -d/--date.
1610 See :hg:`help dates` for a list of formats valid for -d/--date.
1611
1611
1612 Returns 0 on success, 1 if nothing changed.
1612 Returns 0 on success, 1 if nothing changed.
1613
1613
1614 .. container:: verbose
1614 .. container:: verbose
1615
1615
1616 Examples:
1616 Examples:
1617
1617
1618 - commit all files ending in .py::
1618 - commit all files ending in .py::
1619
1619
1620 hg commit --include "set:**.py"
1620 hg commit --include "set:**.py"
1621
1621
1622 - commit all non-binary files::
1622 - commit all non-binary files::
1623
1623
1624 hg commit --exclude "set:binary()"
1624 hg commit --exclude "set:binary()"
1625
1625
1626 - amend the current commit and set the date to now::
1626 - amend the current commit and set the date to now::
1627
1627
1628 hg commit --amend --date now
1628 hg commit --amend --date now
1629 """
1629 """
1630 wlock = lock = None
1630 wlock = lock = None
1631 try:
1631 try:
1632 wlock = repo.wlock()
1632 wlock = repo.wlock()
1633 lock = repo.lock()
1633 lock = repo.lock()
1634 return _docommit(ui, repo, *pats, **opts)
1634 return _docommit(ui, repo, *pats, **opts)
1635 finally:
1635 finally:
1636 release(lock, wlock)
1636 release(lock, wlock)
1637
1637
1638 def _docommit(ui, repo, *pats, **opts):
1638 def _docommit(ui, repo, *pats, **opts):
1639 if opts.get('interactive'):
1639 if opts.get('interactive'):
1640 opts.pop('interactive')
1640 opts.pop('interactive')
1641 ret = cmdutil.dorecord(ui, repo, commit, None, False,
1641 ret = cmdutil.dorecord(ui, repo, commit, None, False,
1642 cmdutil.recordfilter, *pats, **opts)
1642 cmdutil.recordfilter, *pats, **opts)
1643 # ret can be 0 (no changes to record) or the value returned by
1643 # ret can be 0 (no changes to record) or the value returned by
1644 # commit(), 1 if nothing changed or None on success.
1644 # commit(), 1 if nothing changed or None on success.
1645 return 1 if ret == 0 else ret
1645 return 1 if ret == 0 else ret
1646
1646
1647 if opts.get('subrepos'):
1647 if opts.get('subrepos'):
1648 if opts.get('amend'):
1648 if opts.get('amend'):
1649 raise error.Abort(_('cannot amend with --subrepos'))
1649 raise error.Abort(_('cannot amend with --subrepos'))
1650 # Let --subrepos on the command line override config setting.
1650 # Let --subrepos on the command line override config setting.
1651 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1651 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1652
1652
1653 cmdutil.checkunfinished(repo, commit=True)
1653 cmdutil.checkunfinished(repo, commit=True)
1654
1654
1655 branch = repo[None].branch()
1655 branch = repo[None].branch()
1656 bheads = repo.branchheads(branch)
1656 bheads = repo.branchheads(branch)
1657
1657
1658 extra = {}
1658 extra = {}
1659 if opts.get('close_branch'):
1659 if opts.get('close_branch'):
1660 extra['close'] = 1
1660 extra['close'] = 1
1661
1661
1662 if not bheads:
1662 if not bheads:
1663 raise error.Abort(_('can only close branch heads'))
1663 raise error.Abort(_('can only close branch heads'))
1664 elif opts.get('amend'):
1664 elif opts.get('amend'):
1665 if repo[None].parents()[0].p1().branch() != branch and \
1665 if repo[None].parents()[0].p1().branch() != branch and \
1666 repo[None].parents()[0].p2().branch() != branch:
1666 repo[None].parents()[0].p2().branch() != branch:
1667 raise error.Abort(_('can only close branch heads'))
1667 raise error.Abort(_('can only close branch heads'))
1668
1668
1669 if opts.get('amend'):
1669 if opts.get('amend'):
1670 if ui.configbool('ui', 'commitsubrepos'):
1670 if ui.configbool('ui', 'commitsubrepos'):
1671 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1671 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1672
1672
1673 old = repo['.']
1673 old = repo['.']
1674 if not old.mutable():
1674 if not old.mutable():
1675 raise error.Abort(_('cannot amend public changesets'))
1675 raise error.Abort(_('cannot amend public changesets'))
1676 if len(repo[None].parents()) > 1:
1676 if len(repo[None].parents()) > 1:
1677 raise error.Abort(_('cannot amend while merging'))
1677 raise error.Abort(_('cannot amend while merging'))
1678 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1678 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1679 if not allowunstable and old.children():
1679 if not allowunstable and old.children():
1680 raise error.Abort(_('cannot amend changeset with children'))
1680 raise error.Abort(_('cannot amend changeset with children'))
1681
1681
1682 # Currently histedit gets confused if an amend happens while histedit
1682 # Currently histedit gets confused if an amend happens while histedit
1683 # is in progress. Since we have a checkunfinished command, we are
1683 # is in progress. Since we have a checkunfinished command, we are
1684 # temporarily honoring it.
1684 # temporarily honoring it.
1685 #
1685 #
1686 # Note: eventually this guard will be removed. Please do not expect
1686 # Note: eventually this guard will be removed. Please do not expect
1687 # this behavior to remain.
1687 # this behavior to remain.
1688 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
1688 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
1689 cmdutil.checkunfinished(repo)
1689 cmdutil.checkunfinished(repo)
1690
1690
1691 # commitfunc is used only for temporary amend commit by cmdutil.amend
1691 # commitfunc is used only for temporary amend commit by cmdutil.amend
1692 def commitfunc(ui, repo, message, match, opts):
1692 def commitfunc(ui, repo, message, match, opts):
1693 return repo.commit(message,
1693 return repo.commit(message,
1694 opts.get('user') or old.user(),
1694 opts.get('user') or old.user(),
1695 opts.get('date') or old.date(),
1695 opts.get('date') or old.date(),
1696 match,
1696 match,
1697 extra=extra)
1697 extra=extra)
1698
1698
1699 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1699 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1700 if node == old.node():
1700 if node == old.node():
1701 ui.status(_("nothing changed\n"))
1701 ui.status(_("nothing changed\n"))
1702 return 1
1702 return 1
1703 else:
1703 else:
1704 def commitfunc(ui, repo, message, match, opts):
1704 def commitfunc(ui, repo, message, match, opts):
1705 backup = ui.backupconfig('phases', 'new-commit')
1705 backup = ui.backupconfig('phases', 'new-commit')
1706 baseui = repo.baseui
1706 baseui = repo.baseui
1707 basebackup = baseui.backupconfig('phases', 'new-commit')
1707 basebackup = baseui.backupconfig('phases', 'new-commit')
1708 try:
1708 try:
1709 if opts.get('secret'):
1709 if opts.get('secret'):
1710 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1710 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1711 # Propagate to subrepos
1711 # Propagate to subrepos
1712 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1712 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1713
1713
1714 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1714 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1715 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1715 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1716 return repo.commit(message, opts.get('user'), opts.get('date'),
1716 return repo.commit(message, opts.get('user'), opts.get('date'),
1717 match,
1717 match,
1718 editor=editor,
1718 editor=editor,
1719 extra=extra)
1719 extra=extra)
1720 finally:
1720 finally:
1721 ui.restoreconfig(backup)
1721 ui.restoreconfig(backup)
1722 repo.baseui.restoreconfig(basebackup)
1722 repo.baseui.restoreconfig(basebackup)
1723
1723
1724
1724
1725 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1725 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1726
1726
1727 if not node:
1727 if not node:
1728 stat = cmdutil.postcommitstatus(repo, pats, opts)
1728 stat = cmdutil.postcommitstatus(repo, pats, opts)
1729 if stat[3]:
1729 if stat[3]:
1730 ui.status(_("nothing changed (%d missing files, see "
1730 ui.status(_("nothing changed (%d missing files, see "
1731 "'hg status')\n") % len(stat[3]))
1731 "'hg status')\n") % len(stat[3]))
1732 else:
1732 else:
1733 ui.status(_("nothing changed\n"))
1733 ui.status(_("nothing changed\n"))
1734 return 1
1734 return 1
1735
1735
1736 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1736 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1737
1737
1738 @command('config|showconfig|debugconfig',
1738 @command('config|showconfig|debugconfig',
1739 [('u', 'untrusted', None, _('show untrusted configuration options')),
1739 [('u', 'untrusted', None, _('show untrusted configuration options')),
1740 ('e', 'edit', None, _('edit user config')),
1740 ('e', 'edit', None, _('edit user config')),
1741 ('l', 'local', None, _('edit repository config')),
1741 ('l', 'local', None, _('edit repository config')),
1742 ('g', 'global', None, _('edit global config'))] + formatteropts,
1742 ('g', 'global', None, _('edit global config'))] + formatteropts,
1743 _('[-u] [NAME]...'),
1743 _('[-u] [NAME]...'),
1744 optionalrepo=True)
1744 optionalrepo=True)
1745 def config(ui, repo, *values, **opts):
1745 def config(ui, repo, *values, **opts):
1746 """show combined config settings from all hgrc files
1746 """show combined config settings from all hgrc files
1747
1747
1748 With no arguments, print names and values of all config items.
1748 With no arguments, print names and values of all config items.
1749
1749
1750 With one argument of the form section.name, print just the value
1750 With one argument of the form section.name, print just the value
1751 of that config item.
1751 of that config item.
1752
1752
1753 With multiple arguments, print names and values of all config
1753 With multiple arguments, print names and values of all config
1754 items with matching section names.
1754 items with matching section names.
1755
1755
1756 With --edit, start an editor on the user-level config file. With
1756 With --edit, start an editor on the user-level config file. With
1757 --global, edit the system-wide config file. With --local, edit the
1757 --global, edit the system-wide config file. With --local, edit the
1758 repository-level config file.
1758 repository-level config file.
1759
1759
1760 With --debug, the source (filename and line number) is printed
1760 With --debug, the source (filename and line number) is printed
1761 for each config item.
1761 for each config item.
1762
1762
1763 See :hg:`help config` for more information about config files.
1763 See :hg:`help config` for more information about config files.
1764
1764
1765 Returns 0 on success, 1 if NAME does not exist.
1765 Returns 0 on success, 1 if NAME does not exist.
1766
1766
1767 """
1767 """
1768
1768
1769 if opts.get('edit') or opts.get('local') or opts.get('global'):
1769 if opts.get('edit') or opts.get('local') or opts.get('global'):
1770 if opts.get('local') and opts.get('global'):
1770 if opts.get('local') and opts.get('global'):
1771 raise error.Abort(_("can't use --local and --global together"))
1771 raise error.Abort(_("can't use --local and --global together"))
1772
1772
1773 if opts.get('local'):
1773 if opts.get('local'):
1774 if not repo:
1774 if not repo:
1775 raise error.Abort(_("can't use --local outside a repository"))
1775 raise error.Abort(_("can't use --local outside a repository"))
1776 paths = [repo.vfs.join('hgrc')]
1776 paths = [repo.vfs.join('hgrc')]
1777 elif opts.get('global'):
1777 elif opts.get('global'):
1778 paths = scmutil.systemrcpath()
1778 paths = scmutil.systemrcpath()
1779 else:
1779 else:
1780 paths = scmutil.userrcpath()
1780 paths = scmutil.userrcpath()
1781
1781
1782 for f in paths:
1782 for f in paths:
1783 if os.path.exists(f):
1783 if os.path.exists(f):
1784 break
1784 break
1785 else:
1785 else:
1786 if opts.get('global'):
1786 if opts.get('global'):
1787 samplehgrc = uimod.samplehgrcs['global']
1787 samplehgrc = uimod.samplehgrcs['global']
1788 elif opts.get('local'):
1788 elif opts.get('local'):
1789 samplehgrc = uimod.samplehgrcs['local']
1789 samplehgrc = uimod.samplehgrcs['local']
1790 else:
1790 else:
1791 samplehgrc = uimod.samplehgrcs['user']
1791 samplehgrc = uimod.samplehgrcs['user']
1792
1792
1793 f = paths[0]
1793 f = paths[0]
1794 fp = open(f, "w")
1794 fp = open(f, "w")
1795 fp.write(samplehgrc)
1795 fp.write(samplehgrc)
1796 fp.close()
1796 fp.close()
1797
1797
1798 editor = ui.geteditor()
1798 editor = ui.geteditor()
1799 ui.system("%s \"%s\"" % (editor, f),
1799 ui.system("%s \"%s\"" % (editor, f),
1800 onerr=error.Abort, errprefix=_("edit failed"),
1800 onerr=error.Abort, errprefix=_("edit failed"),
1801 blockedtag='config_edit')
1801 blockedtag='config_edit')
1802 return
1802 return
1803 ui.pager('config')
1803 ui.pager('config')
1804 fm = ui.formatter('config', opts)
1804 fm = ui.formatter('config', opts)
1805 for f in scmutil.rcpath():
1805 for f in scmutil.rcpath():
1806 ui.debug('read config from: %s\n' % f)
1806 ui.debug('read config from: %s\n' % f)
1807 untrusted = bool(opts.get('untrusted'))
1807 untrusted = bool(opts.get('untrusted'))
1808 if values:
1808 if values:
1809 sections = [v for v in values if '.' not in v]
1809 sections = [v for v in values if '.' not in v]
1810 items = [v for v in values if '.' in v]
1810 items = [v for v in values if '.' in v]
1811 if len(items) > 1 or items and sections:
1811 if len(items) > 1 or items and sections:
1812 raise error.Abort(_('only one config item permitted'))
1812 raise error.Abort(_('only one config item permitted'))
1813 matched = False
1813 matched = False
1814 for section, name, value in ui.walkconfig(untrusted=untrusted):
1814 for section, name, value in ui.walkconfig(untrusted=untrusted):
1815 source = ui.configsource(section, name, untrusted)
1815 source = ui.configsource(section, name, untrusted)
1816 value = str(value)
1816 value = str(value)
1817 if fm.isplain():
1817 if fm.isplain():
1818 source = source or 'none'
1818 source = source or 'none'
1819 value = value.replace('\n', '\\n')
1819 value = value.replace('\n', '\\n')
1820 entryname = section + '.' + name
1820 entryname = section + '.' + name
1821 if values:
1821 if values:
1822 for v in values:
1822 for v in values:
1823 if v == section:
1823 if v == section:
1824 fm.startitem()
1824 fm.startitem()
1825 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1825 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1826 fm.write('name value', '%s=%s\n', entryname, value)
1826 fm.write('name value', '%s=%s\n', entryname, value)
1827 matched = True
1827 matched = True
1828 elif v == entryname:
1828 elif v == entryname:
1829 fm.startitem()
1829 fm.startitem()
1830 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1830 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1831 fm.write('value', '%s\n', value)
1831 fm.write('value', '%s\n', value)
1832 fm.data(name=entryname)
1832 fm.data(name=entryname)
1833 matched = True
1833 matched = True
1834 else:
1834 else:
1835 fm.startitem()
1835 fm.startitem()
1836 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1836 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1837 fm.write('name value', '%s=%s\n', entryname, value)
1837 fm.write('name value', '%s=%s\n', entryname, value)
1838 matched = True
1838 matched = True
1839 fm.end()
1839 fm.end()
1840 if matched:
1840 if matched:
1841 return 0
1841 return 0
1842 return 1
1842 return 1
1843
1843
1844 @command('copy|cp',
1844 @command('copy|cp',
1845 [('A', 'after', None, _('record a copy that has already occurred')),
1845 [('A', 'after', None, _('record a copy that has already occurred')),
1846 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1846 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1847 ] + walkopts + dryrunopts,
1847 ] + walkopts + dryrunopts,
1848 _('[OPTION]... [SOURCE]... DEST'))
1848 _('[OPTION]... [SOURCE]... DEST'))
1849 def copy(ui, repo, *pats, **opts):
1849 def copy(ui, repo, *pats, **opts):
1850 """mark files as copied for the next commit
1850 """mark files as copied for the next commit
1851
1851
1852 Mark dest as having copies of source files. If dest is a
1852 Mark dest as having copies of source files. If dest is a
1853 directory, copies are put in that directory. If dest is a file,
1853 directory, copies are put in that directory. If dest is a file,
1854 the source must be a single file.
1854 the source must be a single file.
1855
1855
1856 By default, this command copies the contents of files as they
1856 By default, this command copies the contents of files as they
1857 exist in the working directory. If invoked with -A/--after, the
1857 exist in the working directory. If invoked with -A/--after, the
1858 operation is recorded, but no copying is performed.
1858 operation is recorded, but no copying is performed.
1859
1859
1860 This command takes effect with the next commit. To undo a copy
1860 This command takes effect with the next commit. To undo a copy
1861 before that, see :hg:`revert`.
1861 before that, see :hg:`revert`.
1862
1862
1863 Returns 0 on success, 1 if errors are encountered.
1863 Returns 0 on success, 1 if errors are encountered.
1864 """
1864 """
1865 with repo.wlock(False):
1865 with repo.wlock(False):
1866 return cmdutil.copy(ui, repo, pats, opts)
1866 return cmdutil.copy(ui, repo, pats, opts)
1867
1867
1868 @command('^diff',
1868 @command('^diff',
1869 [('r', 'rev', [], _('revision'), _('REV')),
1869 [('r', 'rev', [], _('revision'), _('REV')),
1870 ('c', 'change', '', _('change made by revision'), _('REV'))
1870 ('c', 'change', '', _('change made by revision'), _('REV'))
1871 ] + diffopts + diffopts2 + walkopts + subrepoopts,
1871 ] + diffopts + diffopts2 + walkopts + subrepoopts,
1872 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
1872 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
1873 inferrepo=True)
1873 inferrepo=True)
1874 def diff(ui, repo, *pats, **opts):
1874 def diff(ui, repo, *pats, **opts):
1875 """diff repository (or selected files)
1875 """diff repository (or selected files)
1876
1876
1877 Show differences between revisions for the specified files.
1877 Show differences between revisions for the specified files.
1878
1878
1879 Differences between files are shown using the unified diff format.
1879 Differences between files are shown using the unified diff format.
1880
1880
1881 .. note::
1881 .. note::
1882
1882
1883 :hg:`diff` may generate unexpected results for merges, as it will
1883 :hg:`diff` may generate unexpected results for merges, as it will
1884 default to comparing against the working directory's first
1884 default to comparing against the working directory's first
1885 parent changeset if no revisions are specified.
1885 parent changeset if no revisions are specified.
1886
1886
1887 When two revision arguments are given, then changes are shown
1887 When two revision arguments are given, then changes are shown
1888 between those revisions. If only one revision is specified then
1888 between those revisions. If only one revision is specified then
1889 that revision is compared to the working directory, and, when no
1889 that revision is compared to the working directory, and, when no
1890 revisions are specified, the working directory files are compared
1890 revisions are specified, the working directory files are compared
1891 to its first parent.
1891 to its first parent.
1892
1892
1893 Alternatively you can specify -c/--change with a revision to see
1893 Alternatively you can specify -c/--change with a revision to see
1894 the changes in that changeset relative to its first parent.
1894 the changes in that changeset relative to its first parent.
1895
1895
1896 Without the -a/--text option, diff will avoid generating diffs of
1896 Without the -a/--text option, diff will avoid generating diffs of
1897 files it detects as binary. With -a, diff will generate a diff
1897 files it detects as binary. With -a, diff will generate a diff
1898 anyway, probably with undesirable results.
1898 anyway, probably with undesirable results.
1899
1899
1900 Use the -g/--git option to generate diffs in the git extended diff
1900 Use the -g/--git option to generate diffs in the git extended diff
1901 format. For more information, read :hg:`help diffs`.
1901 format. For more information, read :hg:`help diffs`.
1902
1902
1903 .. container:: verbose
1903 .. container:: verbose
1904
1904
1905 Examples:
1905 Examples:
1906
1906
1907 - compare a file in the current working directory to its parent::
1907 - compare a file in the current working directory to its parent::
1908
1908
1909 hg diff foo.c
1909 hg diff foo.c
1910
1910
1911 - compare two historical versions of a directory, with rename info::
1911 - compare two historical versions of a directory, with rename info::
1912
1912
1913 hg diff --git -r 1.0:1.2 lib/
1913 hg diff --git -r 1.0:1.2 lib/
1914
1914
1915 - get change stats relative to the last change on some date::
1915 - get change stats relative to the last change on some date::
1916
1916
1917 hg diff --stat -r "date('may 2')"
1917 hg diff --stat -r "date('may 2')"
1918
1918
1919 - diff all newly-added files that contain a keyword::
1919 - diff all newly-added files that contain a keyword::
1920
1920
1921 hg diff "set:added() and grep(GNU)"
1921 hg diff "set:added() and grep(GNU)"
1922
1922
1923 - compare a revision and its parents::
1923 - compare a revision and its parents::
1924
1924
1925 hg diff -c 9353 # compare against first parent
1925 hg diff -c 9353 # compare against first parent
1926 hg diff -r 9353^:9353 # same using revset syntax
1926 hg diff -r 9353^:9353 # same using revset syntax
1927 hg diff -r 9353^2:9353 # compare against the second parent
1927 hg diff -r 9353^2:9353 # compare against the second parent
1928
1928
1929 Returns 0 on success.
1929 Returns 0 on success.
1930 """
1930 """
1931
1931
1932 revs = opts.get('rev')
1932 revs = opts.get('rev')
1933 change = opts.get('change')
1933 change = opts.get('change')
1934 stat = opts.get('stat')
1934 stat = opts.get('stat')
1935 reverse = opts.get('reverse')
1935 reverse = opts.get('reverse')
1936
1936
1937 if revs and change:
1937 if revs and change:
1938 msg = _('cannot specify --rev and --change at the same time')
1938 msg = _('cannot specify --rev and --change at the same time')
1939 raise error.Abort(msg)
1939 raise error.Abort(msg)
1940 elif change:
1940 elif change:
1941 node2 = scmutil.revsingle(repo, change, None).node()
1941 node2 = scmutil.revsingle(repo, change, None).node()
1942 node1 = repo[node2].p1().node()
1942 node1 = repo[node2].p1().node()
1943 else:
1943 else:
1944 node1, node2 = scmutil.revpair(repo, revs)
1944 node1, node2 = scmutil.revpair(repo, revs)
1945
1945
1946 if reverse:
1946 if reverse:
1947 node1, node2 = node2, node1
1947 node1, node2 = node2, node1
1948
1948
1949 diffopts = patch.diffallopts(ui, opts)
1949 diffopts = patch.diffallopts(ui, opts)
1950 m = scmutil.match(repo[node2], pats, opts)
1950 m = scmutil.match(repo[node2], pats, opts)
1951 ui.pager('diff')
1951 ui.pager('diff')
1952 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
1952 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
1953 listsubrepos=opts.get('subrepos'),
1953 listsubrepos=opts.get('subrepos'),
1954 root=opts.get('root'))
1954 root=opts.get('root'))
1955
1955
1956 @command('^export',
1956 @command('^export',
1957 [('o', 'output', '',
1957 [('o', 'output', '',
1958 _('print output to file with formatted name'), _('FORMAT')),
1958 _('print output to file with formatted name'), _('FORMAT')),
1959 ('', 'switch-parent', None, _('diff against the second parent')),
1959 ('', 'switch-parent', None, _('diff against the second parent')),
1960 ('r', 'rev', [], _('revisions to export'), _('REV')),
1960 ('r', 'rev', [], _('revisions to export'), _('REV')),
1961 ] + diffopts,
1961 ] + diffopts,
1962 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
1962 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
1963 def export(ui, repo, *changesets, **opts):
1963 def export(ui, repo, *changesets, **opts):
1964 """dump the header and diffs for one or more changesets
1964 """dump the header and diffs for one or more changesets
1965
1965
1966 Print the changeset header and diffs for one or more revisions.
1966 Print the changeset header and diffs for one or more revisions.
1967 If no revision is given, the parent of the working directory is used.
1967 If no revision is given, the parent of the working directory is used.
1968
1968
1969 The information shown in the changeset header is: author, date,
1969 The information shown in the changeset header is: author, date,
1970 branch name (if non-default), changeset hash, parent(s) and commit
1970 branch name (if non-default), changeset hash, parent(s) and commit
1971 comment.
1971 comment.
1972
1972
1973 .. note::
1973 .. note::
1974
1974
1975 :hg:`export` may generate unexpected diff output for merge
1975 :hg:`export` may generate unexpected diff output for merge
1976 changesets, as it will compare the merge changeset against its
1976 changesets, as it will compare the merge changeset against its
1977 first parent only.
1977 first parent only.
1978
1978
1979 Output may be to a file, in which case the name of the file is
1979 Output may be to a file, in which case the name of the file is
1980 given using a format string. The formatting rules are as follows:
1980 given using a format string. The formatting rules are as follows:
1981
1981
1982 :``%%``: literal "%" character
1982 :``%%``: literal "%" character
1983 :``%H``: changeset hash (40 hexadecimal digits)
1983 :``%H``: changeset hash (40 hexadecimal digits)
1984 :``%N``: number of patches being generated
1984 :``%N``: number of patches being generated
1985 :``%R``: changeset revision number
1985 :``%R``: changeset revision number
1986 :``%b``: basename of the exporting repository
1986 :``%b``: basename of the exporting repository
1987 :``%h``: short-form changeset hash (12 hexadecimal digits)
1987 :``%h``: short-form changeset hash (12 hexadecimal digits)
1988 :``%m``: first line of the commit message (only alphanumeric characters)
1988 :``%m``: first line of the commit message (only alphanumeric characters)
1989 :``%n``: zero-padded sequence number, starting at 1
1989 :``%n``: zero-padded sequence number, starting at 1
1990 :``%r``: zero-padded changeset revision number
1990 :``%r``: zero-padded changeset revision number
1991
1991
1992 Without the -a/--text option, export will avoid generating diffs
1992 Without the -a/--text option, export will avoid generating diffs
1993 of files it detects as binary. With -a, export will generate a
1993 of files it detects as binary. With -a, export will generate a
1994 diff anyway, probably with undesirable results.
1994 diff anyway, probably with undesirable results.
1995
1995
1996 Use the -g/--git option to generate diffs in the git extended diff
1996 Use the -g/--git option to generate diffs in the git extended diff
1997 format. See :hg:`help diffs` for more information.
1997 format. See :hg:`help diffs` for more information.
1998
1998
1999 With the --switch-parent option, the diff will be against the
1999 With the --switch-parent option, the diff will be against the
2000 second parent. It can be useful to review a merge.
2000 second parent. It can be useful to review a merge.
2001
2001
2002 .. container:: verbose
2002 .. container:: verbose
2003
2003
2004 Examples:
2004 Examples:
2005
2005
2006 - use export and import to transplant a bugfix to the current
2006 - use export and import to transplant a bugfix to the current
2007 branch::
2007 branch::
2008
2008
2009 hg export -r 9353 | hg import -
2009 hg export -r 9353 | hg import -
2010
2010
2011 - export all the changesets between two revisions to a file with
2011 - export all the changesets between two revisions to a file with
2012 rename information::
2012 rename information::
2013
2013
2014 hg export --git -r 123:150 > changes.txt
2014 hg export --git -r 123:150 > changes.txt
2015
2015
2016 - split outgoing changes into a series of patches with
2016 - split outgoing changes into a series of patches with
2017 descriptive names::
2017 descriptive names::
2018
2018
2019 hg export -r "outgoing()" -o "%n-%m.patch"
2019 hg export -r "outgoing()" -o "%n-%m.patch"
2020
2020
2021 Returns 0 on success.
2021 Returns 0 on success.
2022 """
2022 """
2023 changesets += tuple(opts.get('rev', []))
2023 changesets += tuple(opts.get('rev', []))
2024 if not changesets:
2024 if not changesets:
2025 changesets = ['.']
2025 changesets = ['.']
2026 revs = scmutil.revrange(repo, changesets)
2026 revs = scmutil.revrange(repo, changesets)
2027 if not revs:
2027 if not revs:
2028 raise error.Abort(_("export requires at least one changeset"))
2028 raise error.Abort(_("export requires at least one changeset"))
2029 if len(revs) > 1:
2029 if len(revs) > 1:
2030 ui.note(_('exporting patches:\n'))
2030 ui.note(_('exporting patches:\n'))
2031 else:
2031 else:
2032 ui.note(_('exporting patch:\n'))
2032 ui.note(_('exporting patch:\n'))
2033 ui.pager('export')
2033 ui.pager('export')
2034 cmdutil.export(repo, revs, template=opts.get('output'),
2034 cmdutil.export(repo, revs, template=opts.get('output'),
2035 switch_parent=opts.get('switch_parent'),
2035 switch_parent=opts.get('switch_parent'),
2036 opts=patch.diffallopts(ui, opts))
2036 opts=patch.diffallopts(ui, opts))
2037
2037
2038 @command('files',
2038 @command('files',
2039 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
2039 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
2040 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
2040 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
2041 ] + walkopts + formatteropts + subrepoopts,
2041 ] + walkopts + formatteropts + subrepoopts,
2042 _('[OPTION]... [FILE]...'))
2042 _('[OPTION]... [FILE]...'))
2043 def files(ui, repo, *pats, **opts):
2043 def files(ui, repo, *pats, **opts):
2044 """list tracked files
2044 """list tracked files
2045
2045
2046 Print files under Mercurial control in the working directory or
2046 Print files under Mercurial control in the working directory or
2047 specified revision for given files (excluding removed files).
2047 specified revision for given files (excluding removed files).
2048 Files can be specified as filenames or filesets.
2048 Files can be specified as filenames or filesets.
2049
2049
2050 If no files are given to match, this command prints the names
2050 If no files are given to match, this command prints the names
2051 of all files under Mercurial control.
2051 of all files under Mercurial control.
2052
2052
2053 .. container:: verbose
2053 .. container:: verbose
2054
2054
2055 Examples:
2055 Examples:
2056
2056
2057 - list all files under the current directory::
2057 - list all files under the current directory::
2058
2058
2059 hg files .
2059 hg files .
2060
2060
2061 - shows sizes and flags for current revision::
2061 - shows sizes and flags for current revision::
2062
2062
2063 hg files -vr .
2063 hg files -vr .
2064
2064
2065 - list all files named README::
2065 - list all files named README::
2066
2066
2067 hg files -I "**/README"
2067 hg files -I "**/README"
2068
2068
2069 - list all binary files::
2069 - list all binary files::
2070
2070
2071 hg files "set:binary()"
2071 hg files "set:binary()"
2072
2072
2073 - find files containing a regular expression::
2073 - find files containing a regular expression::
2074
2074
2075 hg files "set:grep('bob')"
2075 hg files "set:grep('bob')"
2076
2076
2077 - search tracked file contents with xargs and grep::
2077 - search tracked file contents with xargs and grep::
2078
2078
2079 hg files -0 | xargs -0 grep foo
2079 hg files -0 | xargs -0 grep foo
2080
2080
2081 See :hg:`help patterns` and :hg:`help filesets` for more information
2081 See :hg:`help patterns` and :hg:`help filesets` for more information
2082 on specifying file patterns.
2082 on specifying file patterns.
2083
2083
2084 Returns 0 if a match is found, 1 otherwise.
2084 Returns 0 if a match is found, 1 otherwise.
2085
2085
2086 """
2086 """
2087 ctx = scmutil.revsingle(repo, opts.get(r'rev'), None)
2087 ctx = scmutil.revsingle(repo, opts.get(r'rev'), None)
2088
2088
2089 end = '\n'
2089 end = '\n'
2090 if opts.get('print0'):
2090 if opts.get('print0'):
2091 end = '\0'
2091 end = '\0'
2092 fmt = '%s' + end
2092 fmt = '%s' + end
2093
2093
2094 m = scmutil.match(ctx, pats, opts)
2094 m = scmutil.match(ctx, pats, opts)
2095 ui.pager('files')
2095 ui.pager('files')
2096 with ui.formatter('files', opts) as fm:
2096 with ui.formatter('files', opts) as fm:
2097 return cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
2097 return cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
2098
2098
2099 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
2099 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
2100 def forget(ui, repo, *pats, **opts):
2100 def forget(ui, repo, *pats, **opts):
2101 """forget the specified files on the next commit
2101 """forget the specified files on the next commit
2102
2102
2103 Mark the specified files so they will no longer be tracked
2103 Mark the specified files so they will no longer be tracked
2104 after the next commit.
2104 after the next commit.
2105
2105
2106 This only removes files from the current branch, not from the
2106 This only removes files from the current branch, not from the
2107 entire project history, and it does not delete them from the
2107 entire project history, and it does not delete them from the
2108 working directory.
2108 working directory.
2109
2109
2110 To delete the file from the working directory, see :hg:`remove`.
2110 To delete the file from the working directory, see :hg:`remove`.
2111
2111
2112 To undo a forget before the next commit, see :hg:`add`.
2112 To undo a forget before the next commit, see :hg:`add`.
2113
2113
2114 .. container:: verbose
2114 .. container:: verbose
2115
2115
2116 Examples:
2116 Examples:
2117
2117
2118 - forget newly-added binary files::
2118 - forget newly-added binary files::
2119
2119
2120 hg forget "set:added() and binary()"
2120 hg forget "set:added() and binary()"
2121
2121
2122 - forget files that would be excluded by .hgignore::
2122 - forget files that would be excluded by .hgignore::
2123
2123
2124 hg forget "set:hgignore()"
2124 hg forget "set:hgignore()"
2125
2125
2126 Returns 0 on success.
2126 Returns 0 on success.
2127 """
2127 """
2128
2128
2129 if not pats:
2129 if not pats:
2130 raise error.Abort(_('no files specified'))
2130 raise error.Abort(_('no files specified'))
2131
2131
2132 m = scmutil.match(repo[None], pats, opts)
2132 m = scmutil.match(repo[None], pats, opts)
2133 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2133 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2134 return rejected and 1 or 0
2134 return rejected and 1 or 0
2135
2135
2136 @command(
2136 @command(
2137 'graft',
2137 'graft',
2138 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2138 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2139 ('c', 'continue', False, _('resume interrupted graft')),
2139 ('c', 'continue', False, _('resume interrupted graft')),
2140 ('e', 'edit', False, _('invoke editor on commit messages')),
2140 ('e', 'edit', False, _('invoke editor on commit messages')),
2141 ('', 'log', None, _('append graft info to log message')),
2141 ('', 'log', None, _('append graft info to log message')),
2142 ('f', 'force', False, _('force graft')),
2142 ('f', 'force', False, _('force graft')),
2143 ('D', 'currentdate', False,
2143 ('D', 'currentdate', False,
2144 _('record the current date as commit date')),
2144 _('record the current date as commit date')),
2145 ('U', 'currentuser', False,
2145 ('U', 'currentuser', False,
2146 _('record the current user as committer'), _('DATE'))]
2146 _('record the current user as committer'), _('DATE'))]
2147 + commitopts2 + mergetoolopts + dryrunopts,
2147 + commitopts2 + mergetoolopts + dryrunopts,
2148 _('[OPTION]... [-r REV]... REV...'))
2148 _('[OPTION]... [-r REV]... REV...'))
2149 def graft(ui, repo, *revs, **opts):
2149 def graft(ui, repo, *revs, **opts):
2150 '''copy changes from other branches onto the current branch
2150 '''copy changes from other branches onto the current branch
2151
2151
2152 This command uses Mercurial's merge logic to copy individual
2152 This command uses Mercurial's merge logic to copy individual
2153 changes from other branches without merging branches in the
2153 changes from other branches without merging branches in the
2154 history graph. This is sometimes known as 'backporting' or
2154 history graph. This is sometimes known as 'backporting' or
2155 'cherry-picking'. By default, graft will copy user, date, and
2155 'cherry-picking'. By default, graft will copy user, date, and
2156 description from the source changesets.
2156 description from the source changesets.
2157
2157
2158 Changesets that are ancestors of the current revision, that have
2158 Changesets that are ancestors of the current revision, that have
2159 already been grafted, or that are merges will be skipped.
2159 already been grafted, or that are merges will be skipped.
2160
2160
2161 If --log is specified, log messages will have a comment appended
2161 If --log is specified, log messages will have a comment appended
2162 of the form::
2162 of the form::
2163
2163
2164 (grafted from CHANGESETHASH)
2164 (grafted from CHANGESETHASH)
2165
2165
2166 If --force is specified, revisions will be grafted even if they
2166 If --force is specified, revisions will be grafted even if they
2167 are already ancestors of or have been grafted to the destination.
2167 are already ancestors of or have been grafted to the destination.
2168 This is useful when the revisions have since been backed out.
2168 This is useful when the revisions have since been backed out.
2169
2169
2170 If a graft merge results in conflicts, the graft process is
2170 If a graft merge results in conflicts, the graft process is
2171 interrupted so that the current merge can be manually resolved.
2171 interrupted so that the current merge can be manually resolved.
2172 Once all conflicts are addressed, the graft process can be
2172 Once all conflicts are addressed, the graft process can be
2173 continued with the -c/--continue option.
2173 continued with the -c/--continue option.
2174
2174
2175 .. note::
2175 .. note::
2176
2176
2177 The -c/--continue option does not reapply earlier options, except
2177 The -c/--continue option does not reapply earlier options, except
2178 for --force.
2178 for --force.
2179
2179
2180 .. container:: verbose
2180 .. container:: verbose
2181
2181
2182 Examples:
2182 Examples:
2183
2183
2184 - copy a single change to the stable branch and edit its description::
2184 - copy a single change to the stable branch and edit its description::
2185
2185
2186 hg update stable
2186 hg update stable
2187 hg graft --edit 9393
2187 hg graft --edit 9393
2188
2188
2189 - graft a range of changesets with one exception, updating dates::
2189 - graft a range of changesets with one exception, updating dates::
2190
2190
2191 hg graft -D "2085::2093 and not 2091"
2191 hg graft -D "2085::2093 and not 2091"
2192
2192
2193 - continue a graft after resolving conflicts::
2193 - continue a graft after resolving conflicts::
2194
2194
2195 hg graft -c
2195 hg graft -c
2196
2196
2197 - show the source of a grafted changeset::
2197 - show the source of a grafted changeset::
2198
2198
2199 hg log --debug -r .
2199 hg log --debug -r .
2200
2200
2201 - show revisions sorted by date::
2201 - show revisions sorted by date::
2202
2202
2203 hg log -r "sort(all(), date)"
2203 hg log -r "sort(all(), date)"
2204
2204
2205 See :hg:`help revisions` for more about specifying revisions.
2205 See :hg:`help revisions` for more about specifying revisions.
2206
2206
2207 Returns 0 on successful completion.
2207 Returns 0 on successful completion.
2208 '''
2208 '''
2209 with repo.wlock():
2209 with repo.wlock():
2210 return _dograft(ui, repo, *revs, **opts)
2210 return _dograft(ui, repo, *revs, **opts)
2211
2211
2212 def _dograft(ui, repo, *revs, **opts):
2212 def _dograft(ui, repo, *revs, **opts):
2213 if revs and opts.get('rev'):
2213 if revs and opts.get('rev'):
2214 ui.warn(_('warning: inconsistent use of --rev might give unexpected '
2214 ui.warn(_('warning: inconsistent use of --rev might give unexpected '
2215 'revision ordering!\n'))
2215 'revision ordering!\n'))
2216
2216
2217 revs = list(revs)
2217 revs = list(revs)
2218 revs.extend(opts.get('rev'))
2218 revs.extend(opts.get('rev'))
2219
2219
2220 if not opts.get('user') and opts.get('currentuser'):
2220 if not opts.get('user') and opts.get('currentuser'):
2221 opts['user'] = ui.username()
2221 opts['user'] = ui.username()
2222 if not opts.get('date') and opts.get('currentdate'):
2222 if not opts.get('date') and opts.get('currentdate'):
2223 opts['date'] = "%d %d" % util.makedate()
2223 opts['date'] = "%d %d" % util.makedate()
2224
2224
2225 editor = cmdutil.getcommiteditor(editform='graft', **opts)
2225 editor = cmdutil.getcommiteditor(editform='graft', **opts)
2226
2226
2227 cont = False
2227 cont = False
2228 if opts.get('continue'):
2228 if opts.get('continue'):
2229 cont = True
2229 cont = True
2230 if revs:
2230 if revs:
2231 raise error.Abort(_("can't specify --continue and revisions"))
2231 raise error.Abort(_("can't specify --continue and revisions"))
2232 # read in unfinished revisions
2232 # read in unfinished revisions
2233 try:
2233 try:
2234 nodes = repo.vfs.read('graftstate').splitlines()
2234 nodes = repo.vfs.read('graftstate').splitlines()
2235 revs = [repo[node].rev() for node in nodes]
2235 revs = [repo[node].rev() for node in nodes]
2236 except IOError as inst:
2236 except IOError as inst:
2237 if inst.errno != errno.ENOENT:
2237 if inst.errno != errno.ENOENT:
2238 raise
2238 raise
2239 cmdutil.wrongtooltocontinue(repo, _('graft'))
2239 cmdutil.wrongtooltocontinue(repo, _('graft'))
2240 else:
2240 else:
2241 cmdutil.checkunfinished(repo)
2241 cmdutil.checkunfinished(repo)
2242 cmdutil.bailifchanged(repo)
2242 cmdutil.bailifchanged(repo)
2243 if not revs:
2243 if not revs:
2244 raise error.Abort(_('no revisions specified'))
2244 raise error.Abort(_('no revisions specified'))
2245 revs = scmutil.revrange(repo, revs)
2245 revs = scmutil.revrange(repo, revs)
2246
2246
2247 skipped = set()
2247 skipped = set()
2248 # check for merges
2248 # check for merges
2249 for rev in repo.revs('%ld and merge()', revs):
2249 for rev in repo.revs('%ld and merge()', revs):
2250 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2250 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2251 skipped.add(rev)
2251 skipped.add(rev)
2252 revs = [r for r in revs if r not in skipped]
2252 revs = [r for r in revs if r not in skipped]
2253 if not revs:
2253 if not revs:
2254 return -1
2254 return -1
2255
2255
2256 # Don't check in the --continue case, in effect retaining --force across
2256 # Don't check in the --continue case, in effect retaining --force across
2257 # --continues. That's because without --force, any revisions we decided to
2257 # --continues. That's because without --force, any revisions we decided to
2258 # skip would have been filtered out here, so they wouldn't have made their
2258 # skip would have been filtered out here, so they wouldn't have made their
2259 # way to the graftstate. With --force, any revisions we would have otherwise
2259 # way to the graftstate. With --force, any revisions we would have otherwise
2260 # skipped would not have been filtered out, and if they hadn't been applied
2260 # skipped would not have been filtered out, and if they hadn't been applied
2261 # already, they'd have been in the graftstate.
2261 # already, they'd have been in the graftstate.
2262 if not (cont or opts.get('force')):
2262 if not (cont or opts.get('force')):
2263 # check for ancestors of dest branch
2263 # check for ancestors of dest branch
2264 crev = repo['.'].rev()
2264 crev = repo['.'].rev()
2265 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2265 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2266 # XXX make this lazy in the future
2266 # XXX make this lazy in the future
2267 # don't mutate while iterating, create a copy
2267 # don't mutate while iterating, create a copy
2268 for rev in list(revs):
2268 for rev in list(revs):
2269 if rev in ancestors:
2269 if rev in ancestors:
2270 ui.warn(_('skipping ancestor revision %d:%s\n') %
2270 ui.warn(_('skipping ancestor revision %d:%s\n') %
2271 (rev, repo[rev]))
2271 (rev, repo[rev]))
2272 # XXX remove on list is slow
2272 # XXX remove on list is slow
2273 revs.remove(rev)
2273 revs.remove(rev)
2274 if not revs:
2274 if not revs:
2275 return -1
2275 return -1
2276
2276
2277 # analyze revs for earlier grafts
2277 # analyze revs for earlier grafts
2278 ids = {}
2278 ids = {}
2279 for ctx in repo.set("%ld", revs):
2279 for ctx in repo.set("%ld", revs):
2280 ids[ctx.hex()] = ctx.rev()
2280 ids[ctx.hex()] = ctx.rev()
2281 n = ctx.extra().get('source')
2281 n = ctx.extra().get('source')
2282 if n:
2282 if n:
2283 ids[n] = ctx.rev()
2283 ids[n] = ctx.rev()
2284
2284
2285 # check ancestors for earlier grafts
2285 # check ancestors for earlier grafts
2286 ui.debug('scanning for duplicate grafts\n')
2286 ui.debug('scanning for duplicate grafts\n')
2287
2287
2288 for rev in repo.changelog.findmissingrevs(revs, [crev]):
2288 for rev in repo.changelog.findmissingrevs(revs, [crev]):
2289 ctx = repo[rev]
2289 ctx = repo[rev]
2290 n = ctx.extra().get('source')
2290 n = ctx.extra().get('source')
2291 if n in ids:
2291 if n in ids:
2292 try:
2292 try:
2293 r = repo[n].rev()
2293 r = repo[n].rev()
2294 except error.RepoLookupError:
2294 except error.RepoLookupError:
2295 r = None
2295 r = None
2296 if r in revs:
2296 if r in revs:
2297 ui.warn(_('skipping revision %d:%s '
2297 ui.warn(_('skipping revision %d:%s '
2298 '(already grafted to %d:%s)\n')
2298 '(already grafted to %d:%s)\n')
2299 % (r, repo[r], rev, ctx))
2299 % (r, repo[r], rev, ctx))
2300 revs.remove(r)
2300 revs.remove(r)
2301 elif ids[n] in revs:
2301 elif ids[n] in revs:
2302 if r is None:
2302 if r is None:
2303 ui.warn(_('skipping already grafted revision %d:%s '
2303 ui.warn(_('skipping already grafted revision %d:%s '
2304 '(%d:%s also has unknown origin %s)\n')
2304 '(%d:%s also has unknown origin %s)\n')
2305 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
2305 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
2306 else:
2306 else:
2307 ui.warn(_('skipping already grafted revision %d:%s '
2307 ui.warn(_('skipping already grafted revision %d:%s '
2308 '(%d:%s also has origin %d:%s)\n')
2308 '(%d:%s also has origin %d:%s)\n')
2309 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
2309 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
2310 revs.remove(ids[n])
2310 revs.remove(ids[n])
2311 elif ctx.hex() in ids:
2311 elif ctx.hex() in ids:
2312 r = ids[ctx.hex()]
2312 r = ids[ctx.hex()]
2313 ui.warn(_('skipping already grafted revision %d:%s '
2313 ui.warn(_('skipping already grafted revision %d:%s '
2314 '(was grafted from %d:%s)\n') %
2314 '(was grafted from %d:%s)\n') %
2315 (r, repo[r], rev, ctx))
2315 (r, repo[r], rev, ctx))
2316 revs.remove(r)
2316 revs.remove(r)
2317 if not revs:
2317 if not revs:
2318 return -1
2318 return -1
2319
2319
2320 for pos, ctx in enumerate(repo.set("%ld", revs)):
2320 for pos, ctx in enumerate(repo.set("%ld", revs)):
2321 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
2321 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
2322 ctx.description().split('\n', 1)[0])
2322 ctx.description().split('\n', 1)[0])
2323 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
2323 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
2324 if names:
2324 if names:
2325 desc += ' (%s)' % ' '.join(names)
2325 desc += ' (%s)' % ' '.join(names)
2326 ui.status(_('grafting %s\n') % desc)
2326 ui.status(_('grafting %s\n') % desc)
2327 if opts.get('dry_run'):
2327 if opts.get('dry_run'):
2328 continue
2328 continue
2329
2329
2330 source = ctx.extra().get('source')
2330 source = ctx.extra().get('source')
2331 extra = {}
2331 extra = {}
2332 if source:
2332 if source:
2333 extra['source'] = source
2333 extra['source'] = source
2334 extra['intermediate-source'] = ctx.hex()
2334 extra['intermediate-source'] = ctx.hex()
2335 else:
2335 else:
2336 extra['source'] = ctx.hex()
2336 extra['source'] = ctx.hex()
2337 user = ctx.user()
2337 user = ctx.user()
2338 if opts.get('user'):
2338 if opts.get('user'):
2339 user = opts['user']
2339 user = opts['user']
2340 date = ctx.date()
2340 date = ctx.date()
2341 if opts.get('date'):
2341 if opts.get('date'):
2342 date = opts['date']
2342 date = opts['date']
2343 message = ctx.description()
2343 message = ctx.description()
2344 if opts.get('log'):
2344 if opts.get('log'):
2345 message += '\n(grafted from %s)' % ctx.hex()
2345 message += '\n(grafted from %s)' % ctx.hex()
2346
2346
2347 # we don't merge the first commit when continuing
2347 # we don't merge the first commit when continuing
2348 if not cont:
2348 if not cont:
2349 # perform the graft merge with p1(rev) as 'ancestor'
2349 # perform the graft merge with p1(rev) as 'ancestor'
2350 try:
2350 try:
2351 # ui.forcemerge is an internal variable, do not document
2351 # ui.forcemerge is an internal variable, do not document
2352 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
2352 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
2353 'graft')
2353 'graft')
2354 stats = mergemod.graft(repo, ctx, ctx.p1(),
2354 stats = mergemod.graft(repo, ctx, ctx.p1(),
2355 ['local', 'graft'])
2355 ['local', 'graft'])
2356 finally:
2356 finally:
2357 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
2357 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
2358 # report any conflicts
2358 # report any conflicts
2359 if stats and stats[3] > 0:
2359 if stats and stats[3] > 0:
2360 # write out state for --continue
2360 # write out state for --continue
2361 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2361 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2362 repo.vfs.write('graftstate', ''.join(nodelines))
2362 repo.vfs.write('graftstate', ''.join(nodelines))
2363 extra = ''
2363 extra = ''
2364 if opts.get('user'):
2364 if opts.get('user'):
2365 extra += ' --user %s' % util.shellquote(opts['user'])
2365 extra += ' --user %s' % util.shellquote(opts['user'])
2366 if opts.get('date'):
2366 if opts.get('date'):
2367 extra += ' --date %s' % util.shellquote(opts['date'])
2367 extra += ' --date %s' % util.shellquote(opts['date'])
2368 if opts.get('log'):
2368 if opts.get('log'):
2369 extra += ' --log'
2369 extra += ' --log'
2370 hint=_("use 'hg resolve' and 'hg graft --continue%s'") % extra
2370 hint=_("use 'hg resolve' and 'hg graft --continue%s'") % extra
2371 raise error.Abort(
2371 raise error.Abort(
2372 _("unresolved conflicts, can't continue"),
2372 _("unresolved conflicts, can't continue"),
2373 hint=hint)
2373 hint=hint)
2374 else:
2374 else:
2375 cont = False
2375 cont = False
2376
2376
2377 # commit
2377 # commit
2378 node = repo.commit(text=message, user=user,
2378 node = repo.commit(text=message, user=user,
2379 date=date, extra=extra, editor=editor)
2379 date=date, extra=extra, editor=editor)
2380 if node is None:
2380 if node is None:
2381 ui.warn(
2381 ui.warn(
2382 _('note: graft of %d:%s created no changes to commit\n') %
2382 _('note: graft of %d:%s created no changes to commit\n') %
2383 (ctx.rev(), ctx))
2383 (ctx.rev(), ctx))
2384
2384
2385 # remove state when we complete successfully
2385 # remove state when we complete successfully
2386 if not opts.get('dry_run'):
2386 if not opts.get('dry_run'):
2387 repo.vfs.unlinkpath('graftstate', ignoremissing=True)
2387 repo.vfs.unlinkpath('graftstate', ignoremissing=True)
2388
2388
2389 return 0
2389 return 0
2390
2390
2391 @command('grep',
2391 @command('grep',
2392 [('0', 'print0', None, _('end fields with NUL')),
2392 [('0', 'print0', None, _('end fields with NUL')),
2393 ('', 'all', None, _('print all revisions that match')),
2393 ('', 'all', None, _('print all revisions that match')),
2394 ('a', 'text', None, _('treat all files as text')),
2394 ('a', 'text', None, _('treat all files as text')),
2395 ('f', 'follow', None,
2395 ('f', 'follow', None,
2396 _('follow changeset history,'
2396 _('follow changeset history,'
2397 ' or file history across copies and renames')),
2397 ' or file history across copies and renames')),
2398 ('i', 'ignore-case', None, _('ignore case when matching')),
2398 ('i', 'ignore-case', None, _('ignore case when matching')),
2399 ('l', 'files-with-matches', None,
2399 ('l', 'files-with-matches', None,
2400 _('print only filenames and revisions that match')),
2400 _('print only filenames and revisions that match')),
2401 ('n', 'line-number', None, _('print matching line numbers')),
2401 ('n', 'line-number', None, _('print matching line numbers')),
2402 ('r', 'rev', [],
2402 ('r', 'rev', [],
2403 _('only search files changed within revision range'), _('REV')),
2403 _('only search files changed within revision range'), _('REV')),
2404 ('u', 'user', None, _('list the author (long with -v)')),
2404 ('u', 'user', None, _('list the author (long with -v)')),
2405 ('d', 'date', None, _('list the date (short with -q)')),
2405 ('d', 'date', None, _('list the date (short with -q)')),
2406 ] + formatteropts + walkopts,
2406 ] + formatteropts + walkopts,
2407 _('[OPTION]... PATTERN [FILE]...'),
2407 _('[OPTION]... PATTERN [FILE]...'),
2408 inferrepo=True)
2408 inferrepo=True)
2409 def grep(ui, repo, pattern, *pats, **opts):
2409 def grep(ui, repo, pattern, *pats, **opts):
2410 """search revision history for a pattern in specified files
2410 """search revision history for a pattern in specified files
2411
2411
2412 Search revision history for a regular expression in the specified
2412 Search revision history for a regular expression in the specified
2413 files or the entire project.
2413 files or the entire project.
2414
2414
2415 By default, grep prints the most recent revision number for each
2415 By default, grep prints the most recent revision number for each
2416 file in which it finds a match. To get it to print every revision
2416 file in which it finds a match. To get it to print every revision
2417 that contains a change in match status ("-" for a match that becomes
2417 that contains a change in match status ("-" for a match that becomes
2418 a non-match, or "+" for a non-match that becomes a match), use the
2418 a non-match, or "+" for a non-match that becomes a match), use the
2419 --all flag.
2419 --all flag.
2420
2420
2421 PATTERN can be any Python (roughly Perl-compatible) regular
2421 PATTERN can be any Python (roughly Perl-compatible) regular
2422 expression.
2422 expression.
2423
2423
2424 If no FILEs are specified (and -f/--follow isn't set), all files in
2424 If no FILEs are specified (and -f/--follow isn't set), all files in
2425 the repository are searched, including those that don't exist in the
2425 the repository are searched, including those that don't exist in the
2426 current branch or have been deleted in a prior changeset.
2426 current branch or have been deleted in a prior changeset.
2427
2427
2428 Returns 0 if a match is found, 1 otherwise.
2428 Returns 0 if a match is found, 1 otherwise.
2429 """
2429 """
2430 reflags = re.M
2430 reflags = re.M
2431 if opts.get('ignore_case'):
2431 if opts.get('ignore_case'):
2432 reflags |= re.I
2432 reflags |= re.I
2433 try:
2433 try:
2434 regexp = util.re.compile(pattern, reflags)
2434 regexp = util.re.compile(pattern, reflags)
2435 except re.error as inst:
2435 except re.error as inst:
2436 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2436 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2437 return 1
2437 return 1
2438 sep, eol = ':', '\n'
2438 sep, eol = ':', '\n'
2439 if opts.get('print0'):
2439 if opts.get('print0'):
2440 sep = eol = '\0'
2440 sep = eol = '\0'
2441
2441
2442 getfile = util.lrucachefunc(repo.file)
2442 getfile = util.lrucachefunc(repo.file)
2443
2443
2444 def matchlines(body):
2444 def matchlines(body):
2445 begin = 0
2445 begin = 0
2446 linenum = 0
2446 linenum = 0
2447 while begin < len(body):
2447 while begin < len(body):
2448 match = regexp.search(body, begin)
2448 match = regexp.search(body, begin)
2449 if not match:
2449 if not match:
2450 break
2450 break
2451 mstart, mend = match.span()
2451 mstart, mend = match.span()
2452 linenum += body.count('\n', begin, mstart) + 1
2452 linenum += body.count('\n', begin, mstart) + 1
2453 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2453 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2454 begin = body.find('\n', mend) + 1 or len(body) + 1
2454 begin = body.find('\n', mend) + 1 or len(body) + 1
2455 lend = begin - 1
2455 lend = begin - 1
2456 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2456 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2457
2457
2458 class linestate(object):
2458 class linestate(object):
2459 def __init__(self, line, linenum, colstart, colend):
2459 def __init__(self, line, linenum, colstart, colend):
2460 self.line = line
2460 self.line = line
2461 self.linenum = linenum
2461 self.linenum = linenum
2462 self.colstart = colstart
2462 self.colstart = colstart
2463 self.colend = colend
2463 self.colend = colend
2464
2464
2465 def __hash__(self):
2465 def __hash__(self):
2466 return hash((self.linenum, self.line))
2466 return hash((self.linenum, self.line))
2467
2467
2468 def __eq__(self, other):
2468 def __eq__(self, other):
2469 return self.line == other.line
2469 return self.line == other.line
2470
2470
2471 def findpos(self):
2471 def findpos(self):
2472 """Iterate all (start, end) indices of matches"""
2472 """Iterate all (start, end) indices of matches"""
2473 yield self.colstart, self.colend
2473 yield self.colstart, self.colend
2474 p = self.colend
2474 p = self.colend
2475 while p < len(self.line):
2475 while p < len(self.line):
2476 m = regexp.search(self.line, p)
2476 m = regexp.search(self.line, p)
2477 if not m:
2477 if not m:
2478 break
2478 break
2479 yield m.span()
2479 yield m.span()
2480 p = m.end()
2480 p = m.end()
2481
2481
2482 matches = {}
2482 matches = {}
2483 copies = {}
2483 copies = {}
2484 def grepbody(fn, rev, body):
2484 def grepbody(fn, rev, body):
2485 matches[rev].setdefault(fn, [])
2485 matches[rev].setdefault(fn, [])
2486 m = matches[rev][fn]
2486 m = matches[rev][fn]
2487 for lnum, cstart, cend, line in matchlines(body):
2487 for lnum, cstart, cend, line in matchlines(body):
2488 s = linestate(line, lnum, cstart, cend)
2488 s = linestate(line, lnum, cstart, cend)
2489 m.append(s)
2489 m.append(s)
2490
2490
2491 def difflinestates(a, b):
2491 def difflinestates(a, b):
2492 sm = difflib.SequenceMatcher(None, a, b)
2492 sm = difflib.SequenceMatcher(None, a, b)
2493 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2493 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2494 if tag == 'insert':
2494 if tag == 'insert':
2495 for i in xrange(blo, bhi):
2495 for i in xrange(blo, bhi):
2496 yield ('+', b[i])
2496 yield ('+', b[i])
2497 elif tag == 'delete':
2497 elif tag == 'delete':
2498 for i in xrange(alo, ahi):
2498 for i in xrange(alo, ahi):
2499 yield ('-', a[i])
2499 yield ('-', a[i])
2500 elif tag == 'replace':
2500 elif tag == 'replace':
2501 for i in xrange(alo, ahi):
2501 for i in xrange(alo, ahi):
2502 yield ('-', a[i])
2502 yield ('-', a[i])
2503 for i in xrange(blo, bhi):
2503 for i in xrange(blo, bhi):
2504 yield ('+', b[i])
2504 yield ('+', b[i])
2505
2505
2506 def display(fm, fn, ctx, pstates, states):
2506 def display(fm, fn, ctx, pstates, states):
2507 rev = ctx.rev()
2507 rev = ctx.rev()
2508 if fm.isplain():
2508 if fm.isplain():
2509 formatuser = ui.shortuser
2509 formatuser = ui.shortuser
2510 else:
2510 else:
2511 formatuser = str
2511 formatuser = str
2512 if ui.quiet:
2512 if ui.quiet:
2513 datefmt = '%Y-%m-%d'
2513 datefmt = '%Y-%m-%d'
2514 else:
2514 else:
2515 datefmt = '%a %b %d %H:%M:%S %Y %1%2'
2515 datefmt = '%a %b %d %H:%M:%S %Y %1%2'
2516 found = False
2516 found = False
2517 @util.cachefunc
2517 @util.cachefunc
2518 def binary():
2518 def binary():
2519 flog = getfile(fn)
2519 flog = getfile(fn)
2520 return util.binary(flog.read(ctx.filenode(fn)))
2520 return util.binary(flog.read(ctx.filenode(fn)))
2521
2521
2522 fieldnamemap = {'filename': 'file', 'linenumber': 'line_number'}
2522 fieldnamemap = {'filename': 'file', 'linenumber': 'line_number'}
2523 if opts.get('all'):
2523 if opts.get('all'):
2524 iter = difflinestates(pstates, states)
2524 iter = difflinestates(pstates, states)
2525 else:
2525 else:
2526 iter = [('', l) for l in states]
2526 iter = [('', l) for l in states]
2527 for change, l in iter:
2527 for change, l in iter:
2528 fm.startitem()
2528 fm.startitem()
2529 fm.data(node=fm.hexfunc(ctx.node()))
2529 fm.data(node=fm.hexfunc(ctx.node()))
2530 cols = [
2530 cols = [
2531 ('filename', fn, True),
2531 ('filename', fn, True),
2532 ('rev', rev, True),
2532 ('rev', rev, True),
2533 ('linenumber', l.linenum, opts.get('line_number')),
2533 ('linenumber', l.linenum, opts.get('line_number')),
2534 ]
2534 ]
2535 if opts.get('all'):
2535 if opts.get('all'):
2536 cols.append(('change', change, True))
2536 cols.append(('change', change, True))
2537 cols.extend([
2537 cols.extend([
2538 ('user', formatuser(ctx.user()), opts.get('user')),
2538 ('user', formatuser(ctx.user()), opts.get('user')),
2539 ('date', fm.formatdate(ctx.date(), datefmt), opts.get('date')),
2539 ('date', fm.formatdate(ctx.date(), datefmt), opts.get('date')),
2540 ])
2540 ])
2541 lastcol = next(name for name, data, cond in reversed(cols) if cond)
2541 lastcol = next(name for name, data, cond in reversed(cols) if cond)
2542 for name, data, cond in cols:
2542 for name, data, cond in cols:
2543 field = fieldnamemap.get(name, name)
2543 field = fieldnamemap.get(name, name)
2544 fm.condwrite(cond, field, '%s', data, label='grep.%s' % name)
2544 fm.condwrite(cond, field, '%s', data, label='grep.%s' % name)
2545 if cond and name != lastcol:
2545 if cond and name != lastcol:
2546 fm.plain(sep, label='grep.sep')
2546 fm.plain(sep, label='grep.sep')
2547 if not opts.get('files_with_matches'):
2547 if not opts.get('files_with_matches'):
2548 fm.plain(sep, label='grep.sep')
2548 fm.plain(sep, label='grep.sep')
2549 if not opts.get('text') and binary():
2549 if not opts.get('text') and binary():
2550 fm.plain(_(" Binary file matches"))
2550 fm.plain(_(" Binary file matches"))
2551 else:
2551 else:
2552 displaymatches(fm.nested('texts'), l)
2552 displaymatches(fm.nested('texts'), l)
2553 fm.plain(eol)
2553 fm.plain(eol)
2554 found = True
2554 found = True
2555 if opts.get('files_with_matches'):
2555 if opts.get('files_with_matches'):
2556 break
2556 break
2557 return found
2557 return found
2558
2558
2559 def displaymatches(fm, l):
2559 def displaymatches(fm, l):
2560 p = 0
2560 p = 0
2561 for s, e in l.findpos():
2561 for s, e in l.findpos():
2562 if p < s:
2562 if p < s:
2563 fm.startitem()
2563 fm.startitem()
2564 fm.write('text', '%s', l.line[p:s])
2564 fm.write('text', '%s', l.line[p:s])
2565 fm.data(matched=False)
2565 fm.data(matched=False)
2566 fm.startitem()
2566 fm.startitem()
2567 fm.write('text', '%s', l.line[s:e], label='grep.match')
2567 fm.write('text', '%s', l.line[s:e], label='grep.match')
2568 fm.data(matched=True)
2568 fm.data(matched=True)
2569 p = e
2569 p = e
2570 if p < len(l.line):
2570 if p < len(l.line):
2571 fm.startitem()
2571 fm.startitem()
2572 fm.write('text', '%s', l.line[p:])
2572 fm.write('text', '%s', l.line[p:])
2573 fm.data(matched=False)
2573 fm.data(matched=False)
2574 fm.end()
2574 fm.end()
2575
2575
2576 skip = {}
2576 skip = {}
2577 revfiles = {}
2577 revfiles = {}
2578 matchfn = scmutil.match(repo[None], pats, opts)
2578 matchfn = scmutil.match(repo[None], pats, opts)
2579 found = False
2579 found = False
2580 follow = opts.get('follow')
2580 follow = opts.get('follow')
2581
2581
2582 def prep(ctx, fns):
2582 def prep(ctx, fns):
2583 rev = ctx.rev()
2583 rev = ctx.rev()
2584 pctx = ctx.p1()
2584 pctx = ctx.p1()
2585 parent = pctx.rev()
2585 parent = pctx.rev()
2586 matches.setdefault(rev, {})
2586 matches.setdefault(rev, {})
2587 matches.setdefault(parent, {})
2587 matches.setdefault(parent, {})
2588 files = revfiles.setdefault(rev, [])
2588 files = revfiles.setdefault(rev, [])
2589 for fn in fns:
2589 for fn in fns:
2590 flog = getfile(fn)
2590 flog = getfile(fn)
2591 try:
2591 try:
2592 fnode = ctx.filenode(fn)
2592 fnode = ctx.filenode(fn)
2593 except error.LookupError:
2593 except error.LookupError:
2594 continue
2594 continue
2595
2595
2596 copied = flog.renamed(fnode)
2596 copied = flog.renamed(fnode)
2597 copy = follow and copied and copied[0]
2597 copy = follow and copied and copied[0]
2598 if copy:
2598 if copy:
2599 copies.setdefault(rev, {})[fn] = copy
2599 copies.setdefault(rev, {})[fn] = copy
2600 if fn in skip:
2600 if fn in skip:
2601 if copy:
2601 if copy:
2602 skip[copy] = True
2602 skip[copy] = True
2603 continue
2603 continue
2604 files.append(fn)
2604 files.append(fn)
2605
2605
2606 if fn not in matches[rev]:
2606 if fn not in matches[rev]:
2607 grepbody(fn, rev, flog.read(fnode))
2607 grepbody(fn, rev, flog.read(fnode))
2608
2608
2609 pfn = copy or fn
2609 pfn = copy or fn
2610 if pfn not in matches[parent]:
2610 if pfn not in matches[parent]:
2611 try:
2611 try:
2612 fnode = pctx.filenode(pfn)
2612 fnode = pctx.filenode(pfn)
2613 grepbody(pfn, parent, flog.read(fnode))
2613 grepbody(pfn, parent, flog.read(fnode))
2614 except error.LookupError:
2614 except error.LookupError:
2615 pass
2615 pass
2616
2616
2617 ui.pager('grep')
2617 ui.pager('grep')
2618 fm = ui.formatter('grep', opts)
2618 fm = ui.formatter('grep', opts)
2619 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2619 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2620 rev = ctx.rev()
2620 rev = ctx.rev()
2621 parent = ctx.p1().rev()
2621 parent = ctx.p1().rev()
2622 for fn in sorted(revfiles.get(rev, [])):
2622 for fn in sorted(revfiles.get(rev, [])):
2623 states = matches[rev][fn]
2623 states = matches[rev][fn]
2624 copy = copies.get(rev, {}).get(fn)
2624 copy = copies.get(rev, {}).get(fn)
2625 if fn in skip:
2625 if fn in skip:
2626 if copy:
2626 if copy:
2627 skip[copy] = True
2627 skip[copy] = True
2628 continue
2628 continue
2629 pstates = matches.get(parent, {}).get(copy or fn, [])
2629 pstates = matches.get(parent, {}).get(copy or fn, [])
2630 if pstates or states:
2630 if pstates or states:
2631 r = display(fm, fn, ctx, pstates, states)
2631 r = display(fm, fn, ctx, pstates, states)
2632 found = found or r
2632 found = found or r
2633 if r and not opts.get('all'):
2633 if r and not opts.get('all'):
2634 skip[fn] = True
2634 skip[fn] = True
2635 if copy:
2635 if copy:
2636 skip[copy] = True
2636 skip[copy] = True
2637 del matches[rev]
2637 del matches[rev]
2638 del revfiles[rev]
2638 del revfiles[rev]
2639 fm.end()
2639 fm.end()
2640
2640
2641 return not found
2641 return not found
2642
2642
2643 @command('heads',
2643 @command('heads',
2644 [('r', 'rev', '',
2644 [('r', 'rev', '',
2645 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2645 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2646 ('t', 'topo', False, _('show topological heads only')),
2646 ('t', 'topo', False, _('show topological heads only')),
2647 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2647 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2648 ('c', 'closed', False, _('show normal and closed branch heads')),
2648 ('c', 'closed', False, _('show normal and closed branch heads')),
2649 ] + templateopts,
2649 ] + templateopts,
2650 _('[-ct] [-r STARTREV] [REV]...'))
2650 _('[-ct] [-r STARTREV] [REV]...'))
2651 def heads(ui, repo, *branchrevs, **opts):
2651 def heads(ui, repo, *branchrevs, **opts):
2652 """show branch heads
2652 """show branch heads
2653
2653
2654 With no arguments, show all open branch heads in the repository.
2654 With no arguments, show all open branch heads in the repository.
2655 Branch heads are changesets that have no descendants on the
2655 Branch heads are changesets that have no descendants on the
2656 same branch. They are where development generally takes place and
2656 same branch. They are where development generally takes place and
2657 are the usual targets for update and merge operations.
2657 are the usual targets for update and merge operations.
2658
2658
2659 If one or more REVs are given, only open branch heads on the
2659 If one or more REVs are given, only open branch heads on the
2660 branches associated with the specified changesets are shown. This
2660 branches associated with the specified changesets are shown. This
2661 means that you can use :hg:`heads .` to see the heads on the
2661 means that you can use :hg:`heads .` to see the heads on the
2662 currently checked-out branch.
2662 currently checked-out branch.
2663
2663
2664 If -c/--closed is specified, also show branch heads marked closed
2664 If -c/--closed is specified, also show branch heads marked closed
2665 (see :hg:`commit --close-branch`).
2665 (see :hg:`commit --close-branch`).
2666
2666
2667 If STARTREV is specified, only those heads that are descendants of
2667 If STARTREV is specified, only those heads that are descendants of
2668 STARTREV will be displayed.
2668 STARTREV will be displayed.
2669
2669
2670 If -t/--topo is specified, named branch mechanics will be ignored and only
2670 If -t/--topo is specified, named branch mechanics will be ignored and only
2671 topological heads (changesets with no children) will be shown.
2671 topological heads (changesets with no children) will be shown.
2672
2672
2673 Returns 0 if matching heads are found, 1 if not.
2673 Returns 0 if matching heads are found, 1 if not.
2674 """
2674 """
2675
2675
2676 start = None
2676 start = None
2677 if 'rev' in opts:
2677 if 'rev' in opts:
2678 start = scmutil.revsingle(repo, opts['rev'], None).node()
2678 start = scmutil.revsingle(repo, opts['rev'], None).node()
2679
2679
2680 if opts.get('topo'):
2680 if opts.get('topo'):
2681 heads = [repo[h] for h in repo.heads(start)]
2681 heads = [repo[h] for h in repo.heads(start)]
2682 else:
2682 else:
2683 heads = []
2683 heads = []
2684 for branch in repo.branchmap():
2684 for branch in repo.branchmap():
2685 heads += repo.branchheads(branch, start, opts.get('closed'))
2685 heads += repo.branchheads(branch, start, opts.get('closed'))
2686 heads = [repo[h] for h in heads]
2686 heads = [repo[h] for h in heads]
2687
2687
2688 if branchrevs:
2688 if branchrevs:
2689 branches = set(repo[br].branch() for br in branchrevs)
2689 branches = set(repo[br].branch() for br in branchrevs)
2690 heads = [h for h in heads if h.branch() in branches]
2690 heads = [h for h in heads if h.branch() in branches]
2691
2691
2692 if opts.get('active') and branchrevs:
2692 if opts.get('active') and branchrevs:
2693 dagheads = repo.heads(start)
2693 dagheads = repo.heads(start)
2694 heads = [h for h in heads if h.node() in dagheads]
2694 heads = [h for h in heads if h.node() in dagheads]
2695
2695
2696 if branchrevs:
2696 if branchrevs:
2697 haveheads = set(h.branch() for h in heads)
2697 haveheads = set(h.branch() for h in heads)
2698 if branches - haveheads:
2698 if branches - haveheads:
2699 headless = ', '.join(b for b in branches - haveheads)
2699 headless = ', '.join(b for b in branches - haveheads)
2700 msg = _('no open branch heads found on branches %s')
2700 msg = _('no open branch heads found on branches %s')
2701 if opts.get('rev'):
2701 if opts.get('rev'):
2702 msg += _(' (started at %s)') % opts['rev']
2702 msg += _(' (started at %s)') % opts['rev']
2703 ui.warn((msg + '\n') % headless)
2703 ui.warn((msg + '\n') % headless)
2704
2704
2705 if not heads:
2705 if not heads:
2706 return 1
2706 return 1
2707
2707
2708 ui.pager('heads')
2708 heads = sorted(heads, key=lambda x: -x.rev())
2709 heads = sorted(heads, key=lambda x: -x.rev())
2709 displayer = cmdutil.show_changeset(ui, repo, opts)
2710 displayer = cmdutil.show_changeset(ui, repo, opts)
2710 for ctx in heads:
2711 for ctx in heads:
2711 displayer.show(ctx)
2712 displayer.show(ctx)
2712 displayer.close()
2713 displayer.close()
2713
2714
2714 @command('help',
2715 @command('help',
2715 [('e', 'extension', None, _('show only help for extensions')),
2716 [('e', 'extension', None, _('show only help for extensions')),
2716 ('c', 'command', None, _('show only help for commands')),
2717 ('c', 'command', None, _('show only help for commands')),
2717 ('k', 'keyword', None, _('show topics matching keyword')),
2718 ('k', 'keyword', None, _('show topics matching keyword')),
2718 ('s', 'system', [], _('show help for specific platform(s)')),
2719 ('s', 'system', [], _('show help for specific platform(s)')),
2719 ],
2720 ],
2720 _('[-ecks] [TOPIC]'),
2721 _('[-ecks] [TOPIC]'),
2721 norepo=True)
2722 norepo=True)
2722 def help_(ui, name=None, **opts):
2723 def help_(ui, name=None, **opts):
2723 """show help for a given topic or a help overview
2724 """show help for a given topic or a help overview
2724
2725
2725 With no arguments, print a list of commands with short help messages.
2726 With no arguments, print a list of commands with short help messages.
2726
2727
2727 Given a topic, extension, or command name, print help for that
2728 Given a topic, extension, or command name, print help for that
2728 topic.
2729 topic.
2729
2730
2730 Returns 0 if successful.
2731 Returns 0 if successful.
2731 """
2732 """
2732
2733
2733 keep = opts.get('system') or []
2734 keep = opts.get('system') or []
2734 if len(keep) == 0:
2735 if len(keep) == 0:
2735 if pycompat.sysplatform.startswith('win'):
2736 if pycompat.sysplatform.startswith('win'):
2736 keep.append('windows')
2737 keep.append('windows')
2737 elif pycompat.sysplatform == 'OpenVMS':
2738 elif pycompat.sysplatform == 'OpenVMS':
2738 keep.append('vms')
2739 keep.append('vms')
2739 elif pycompat.sysplatform == 'plan9':
2740 elif pycompat.sysplatform == 'plan9':
2740 keep.append('plan9')
2741 keep.append('plan9')
2741 else:
2742 else:
2742 keep.append('unix')
2743 keep.append('unix')
2743 keep.append(pycompat.sysplatform.lower())
2744 keep.append(pycompat.sysplatform.lower())
2744 if ui.verbose:
2745 if ui.verbose:
2745 keep.append('verbose')
2746 keep.append('verbose')
2746
2747
2747 formatted = help.formattedhelp(ui, name, keep=keep, **opts)
2748 formatted = help.formattedhelp(ui, name, keep=keep, **opts)
2748 ui.pager('help')
2749 ui.pager('help')
2749 ui.write(formatted)
2750 ui.write(formatted)
2750
2751
2751
2752
2752 @command('identify|id',
2753 @command('identify|id',
2753 [('r', 'rev', '',
2754 [('r', 'rev', '',
2754 _('identify the specified revision'), _('REV')),
2755 _('identify the specified revision'), _('REV')),
2755 ('n', 'num', None, _('show local revision number')),
2756 ('n', 'num', None, _('show local revision number')),
2756 ('i', 'id', None, _('show global revision id')),
2757 ('i', 'id', None, _('show global revision id')),
2757 ('b', 'branch', None, _('show branch')),
2758 ('b', 'branch', None, _('show branch')),
2758 ('t', 'tags', None, _('show tags')),
2759 ('t', 'tags', None, _('show tags')),
2759 ('B', 'bookmarks', None, _('show bookmarks')),
2760 ('B', 'bookmarks', None, _('show bookmarks')),
2760 ] + remoteopts,
2761 ] + remoteopts,
2761 _('[-nibtB] [-r REV] [SOURCE]'),
2762 _('[-nibtB] [-r REV] [SOURCE]'),
2762 optionalrepo=True)
2763 optionalrepo=True)
2763 def identify(ui, repo, source=None, rev=None,
2764 def identify(ui, repo, source=None, rev=None,
2764 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
2765 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
2765 """identify the working directory or specified revision
2766 """identify the working directory or specified revision
2766
2767
2767 Print a summary identifying the repository state at REV using one or
2768 Print a summary identifying the repository state at REV using one or
2768 two parent hash identifiers, followed by a "+" if the working
2769 two parent hash identifiers, followed by a "+" if the working
2769 directory has uncommitted changes, the branch name (if not default),
2770 directory has uncommitted changes, the branch name (if not default),
2770 a list of tags, and a list of bookmarks.
2771 a list of tags, and a list of bookmarks.
2771
2772
2772 When REV is not given, print a summary of the current state of the
2773 When REV is not given, print a summary of the current state of the
2773 repository.
2774 repository.
2774
2775
2775 Specifying a path to a repository root or Mercurial bundle will
2776 Specifying a path to a repository root or Mercurial bundle will
2776 cause lookup to operate on that repository/bundle.
2777 cause lookup to operate on that repository/bundle.
2777
2778
2778 .. container:: verbose
2779 .. container:: verbose
2779
2780
2780 Examples:
2781 Examples:
2781
2782
2782 - generate a build identifier for the working directory::
2783 - generate a build identifier for the working directory::
2783
2784
2784 hg id --id > build-id.dat
2785 hg id --id > build-id.dat
2785
2786
2786 - find the revision corresponding to a tag::
2787 - find the revision corresponding to a tag::
2787
2788
2788 hg id -n -r 1.3
2789 hg id -n -r 1.3
2789
2790
2790 - check the most recent revision of a remote repository::
2791 - check the most recent revision of a remote repository::
2791
2792
2792 hg id -r tip https://www.mercurial-scm.org/repo/hg/
2793 hg id -r tip https://www.mercurial-scm.org/repo/hg/
2793
2794
2794 See :hg:`log` for generating more information about specific revisions,
2795 See :hg:`log` for generating more information about specific revisions,
2795 including full hash identifiers.
2796 including full hash identifiers.
2796
2797
2797 Returns 0 if successful.
2798 Returns 0 if successful.
2798 """
2799 """
2799
2800
2800 if not repo and not source:
2801 if not repo and not source:
2801 raise error.Abort(_("there is no Mercurial repository here "
2802 raise error.Abort(_("there is no Mercurial repository here "
2802 "(.hg not found)"))
2803 "(.hg not found)"))
2803
2804
2804 if ui.debugflag:
2805 if ui.debugflag:
2805 hexfunc = hex
2806 hexfunc = hex
2806 else:
2807 else:
2807 hexfunc = short
2808 hexfunc = short
2808 default = not (num or id or branch or tags or bookmarks)
2809 default = not (num or id or branch or tags or bookmarks)
2809 output = []
2810 output = []
2810 revs = []
2811 revs = []
2811
2812
2812 if source:
2813 if source:
2813 source, branches = hg.parseurl(ui.expandpath(source))
2814 source, branches = hg.parseurl(ui.expandpath(source))
2814 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
2815 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
2815 repo = peer.local()
2816 repo = peer.local()
2816 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
2817 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
2817
2818
2818 if not repo:
2819 if not repo:
2819 if num or branch or tags:
2820 if num or branch or tags:
2820 raise error.Abort(
2821 raise error.Abort(
2821 _("can't query remote revision number, branch, or tags"))
2822 _("can't query remote revision number, branch, or tags"))
2822 if not rev and revs:
2823 if not rev and revs:
2823 rev = revs[0]
2824 rev = revs[0]
2824 if not rev:
2825 if not rev:
2825 rev = "tip"
2826 rev = "tip"
2826
2827
2827 remoterev = peer.lookup(rev)
2828 remoterev = peer.lookup(rev)
2828 if default or id:
2829 if default or id:
2829 output = [hexfunc(remoterev)]
2830 output = [hexfunc(remoterev)]
2830
2831
2831 def getbms():
2832 def getbms():
2832 bms = []
2833 bms = []
2833
2834
2834 if 'bookmarks' in peer.listkeys('namespaces'):
2835 if 'bookmarks' in peer.listkeys('namespaces'):
2835 hexremoterev = hex(remoterev)
2836 hexremoterev = hex(remoterev)
2836 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
2837 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
2837 if bmr == hexremoterev]
2838 if bmr == hexremoterev]
2838
2839
2839 return sorted(bms)
2840 return sorted(bms)
2840
2841
2841 if bookmarks:
2842 if bookmarks:
2842 output.extend(getbms())
2843 output.extend(getbms())
2843 elif default and not ui.quiet:
2844 elif default and not ui.quiet:
2844 # multiple bookmarks for a single parent separated by '/'
2845 # multiple bookmarks for a single parent separated by '/'
2845 bm = '/'.join(getbms())
2846 bm = '/'.join(getbms())
2846 if bm:
2847 if bm:
2847 output.append(bm)
2848 output.append(bm)
2848 else:
2849 else:
2849 ctx = scmutil.revsingle(repo, rev, None)
2850 ctx = scmutil.revsingle(repo, rev, None)
2850
2851
2851 if ctx.rev() is None:
2852 if ctx.rev() is None:
2852 ctx = repo[None]
2853 ctx = repo[None]
2853 parents = ctx.parents()
2854 parents = ctx.parents()
2854 taglist = []
2855 taglist = []
2855 for p in parents:
2856 for p in parents:
2856 taglist.extend(p.tags())
2857 taglist.extend(p.tags())
2857
2858
2858 changed = ""
2859 changed = ""
2859 if default or id or num:
2860 if default or id or num:
2860 if (any(repo.status())
2861 if (any(repo.status())
2861 or any(ctx.sub(s).dirty() for s in ctx.substate)):
2862 or any(ctx.sub(s).dirty() for s in ctx.substate)):
2862 changed = '+'
2863 changed = '+'
2863 if default or id:
2864 if default or id:
2864 output = ["%s%s" %
2865 output = ["%s%s" %
2865 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
2866 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
2866 if num:
2867 if num:
2867 output.append("%s%s" %
2868 output.append("%s%s" %
2868 ('+'.join([str(p.rev()) for p in parents]), changed))
2869 ('+'.join([str(p.rev()) for p in parents]), changed))
2869 else:
2870 else:
2870 if default or id:
2871 if default or id:
2871 output = [hexfunc(ctx.node())]
2872 output = [hexfunc(ctx.node())]
2872 if num:
2873 if num:
2873 output.append(str(ctx.rev()))
2874 output.append(str(ctx.rev()))
2874 taglist = ctx.tags()
2875 taglist = ctx.tags()
2875
2876
2876 if default and not ui.quiet:
2877 if default and not ui.quiet:
2877 b = ctx.branch()
2878 b = ctx.branch()
2878 if b != 'default':
2879 if b != 'default':
2879 output.append("(%s)" % b)
2880 output.append("(%s)" % b)
2880
2881
2881 # multiple tags for a single parent separated by '/'
2882 # multiple tags for a single parent separated by '/'
2882 t = '/'.join(taglist)
2883 t = '/'.join(taglist)
2883 if t:
2884 if t:
2884 output.append(t)
2885 output.append(t)
2885
2886
2886 # multiple bookmarks for a single parent separated by '/'
2887 # multiple bookmarks for a single parent separated by '/'
2887 bm = '/'.join(ctx.bookmarks())
2888 bm = '/'.join(ctx.bookmarks())
2888 if bm:
2889 if bm:
2889 output.append(bm)
2890 output.append(bm)
2890 else:
2891 else:
2891 if branch:
2892 if branch:
2892 output.append(ctx.branch())
2893 output.append(ctx.branch())
2893
2894
2894 if tags:
2895 if tags:
2895 output.extend(taglist)
2896 output.extend(taglist)
2896
2897
2897 if bookmarks:
2898 if bookmarks:
2898 output.extend(ctx.bookmarks())
2899 output.extend(ctx.bookmarks())
2899
2900
2900 ui.write("%s\n" % ' '.join(output))
2901 ui.write("%s\n" % ' '.join(output))
2901
2902
2902 @command('import|patch',
2903 @command('import|patch',
2903 [('p', 'strip', 1,
2904 [('p', 'strip', 1,
2904 _('directory strip option for patch. This has the same '
2905 _('directory strip option for patch. This has the same '
2905 'meaning as the corresponding patch option'), _('NUM')),
2906 'meaning as the corresponding patch option'), _('NUM')),
2906 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
2907 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
2907 ('e', 'edit', False, _('invoke editor on commit messages')),
2908 ('e', 'edit', False, _('invoke editor on commit messages')),
2908 ('f', 'force', None,
2909 ('f', 'force', None,
2909 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
2910 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
2910 ('', 'no-commit', None,
2911 ('', 'no-commit', None,
2911 _("don't commit, just update the working directory")),
2912 _("don't commit, just update the working directory")),
2912 ('', 'bypass', None,
2913 ('', 'bypass', None,
2913 _("apply patch without touching the working directory")),
2914 _("apply patch without touching the working directory")),
2914 ('', 'partial', None,
2915 ('', 'partial', None,
2915 _('commit even if some hunks fail')),
2916 _('commit even if some hunks fail')),
2916 ('', 'exact', None,
2917 ('', 'exact', None,
2917 _('abort if patch would apply lossily')),
2918 _('abort if patch would apply lossily')),
2918 ('', 'prefix', '',
2919 ('', 'prefix', '',
2919 _('apply patch to subdirectory'), _('DIR')),
2920 _('apply patch to subdirectory'), _('DIR')),
2920 ('', 'import-branch', None,
2921 ('', 'import-branch', None,
2921 _('use any branch information in patch (implied by --exact)'))] +
2922 _('use any branch information in patch (implied by --exact)'))] +
2922 commitopts + commitopts2 + similarityopts,
2923 commitopts + commitopts2 + similarityopts,
2923 _('[OPTION]... PATCH...'))
2924 _('[OPTION]... PATCH...'))
2924 def import_(ui, repo, patch1=None, *patches, **opts):
2925 def import_(ui, repo, patch1=None, *patches, **opts):
2925 """import an ordered set of patches
2926 """import an ordered set of patches
2926
2927
2927 Import a list of patches and commit them individually (unless
2928 Import a list of patches and commit them individually (unless
2928 --no-commit is specified).
2929 --no-commit is specified).
2929
2930
2930 To read a patch from standard input (stdin), use "-" as the patch
2931 To read a patch from standard input (stdin), use "-" as the patch
2931 name. If a URL is specified, the patch will be downloaded from
2932 name. If a URL is specified, the patch will be downloaded from
2932 there.
2933 there.
2933
2934
2934 Import first applies changes to the working directory (unless
2935 Import first applies changes to the working directory (unless
2935 --bypass is specified), import will abort if there are outstanding
2936 --bypass is specified), import will abort if there are outstanding
2936 changes.
2937 changes.
2937
2938
2938 Use --bypass to apply and commit patches directly to the
2939 Use --bypass to apply and commit patches directly to the
2939 repository, without affecting the working directory. Without
2940 repository, without affecting the working directory. Without
2940 --exact, patches will be applied on top of the working directory
2941 --exact, patches will be applied on top of the working directory
2941 parent revision.
2942 parent revision.
2942
2943
2943 You can import a patch straight from a mail message. Even patches
2944 You can import a patch straight from a mail message. Even patches
2944 as attachments work (to use the body part, it must have type
2945 as attachments work (to use the body part, it must have type
2945 text/plain or text/x-patch). From and Subject headers of email
2946 text/plain or text/x-patch). From and Subject headers of email
2946 message are used as default committer and commit message. All
2947 message are used as default committer and commit message. All
2947 text/plain body parts before first diff are added to the commit
2948 text/plain body parts before first diff are added to the commit
2948 message.
2949 message.
2949
2950
2950 If the imported patch was generated by :hg:`export`, user and
2951 If the imported patch was generated by :hg:`export`, user and
2951 description from patch override values from message headers and
2952 description from patch override values from message headers and
2952 body. Values given on command line with -m/--message and -u/--user
2953 body. Values given on command line with -m/--message and -u/--user
2953 override these.
2954 override these.
2954
2955
2955 If --exact is specified, import will set the working directory to
2956 If --exact is specified, import will set the working directory to
2956 the parent of each patch before applying it, and will abort if the
2957 the parent of each patch before applying it, and will abort if the
2957 resulting changeset has a different ID than the one recorded in
2958 resulting changeset has a different ID than the one recorded in
2958 the patch. This will guard against various ways that portable
2959 the patch. This will guard against various ways that portable
2959 patch formats and mail systems might fail to transfer Mercurial
2960 patch formats and mail systems might fail to transfer Mercurial
2960 data or metadata. See :hg:`bundle` for lossless transmission.
2961 data or metadata. See :hg:`bundle` for lossless transmission.
2961
2962
2962 Use --partial to ensure a changeset will be created from the patch
2963 Use --partial to ensure a changeset will be created from the patch
2963 even if some hunks fail to apply. Hunks that fail to apply will be
2964 even if some hunks fail to apply. Hunks that fail to apply will be
2964 written to a <target-file>.rej file. Conflicts can then be resolved
2965 written to a <target-file>.rej file. Conflicts can then be resolved
2965 by hand before :hg:`commit --amend` is run to update the created
2966 by hand before :hg:`commit --amend` is run to update the created
2966 changeset. This flag exists to let people import patches that
2967 changeset. This flag exists to let people import patches that
2967 partially apply without losing the associated metadata (author,
2968 partially apply without losing the associated metadata (author,
2968 date, description, ...).
2969 date, description, ...).
2969
2970
2970 .. note::
2971 .. note::
2971
2972
2972 When no hunks apply cleanly, :hg:`import --partial` will create
2973 When no hunks apply cleanly, :hg:`import --partial` will create
2973 an empty changeset, importing only the patch metadata.
2974 an empty changeset, importing only the patch metadata.
2974
2975
2975 With -s/--similarity, hg will attempt to discover renames and
2976 With -s/--similarity, hg will attempt to discover renames and
2976 copies in the patch in the same way as :hg:`addremove`.
2977 copies in the patch in the same way as :hg:`addremove`.
2977
2978
2978 It is possible to use external patch programs to perform the patch
2979 It is possible to use external patch programs to perform the patch
2979 by setting the ``ui.patch`` configuration option. For the default
2980 by setting the ``ui.patch`` configuration option. For the default
2980 internal tool, the fuzz can also be configured via ``patch.fuzz``.
2981 internal tool, the fuzz can also be configured via ``patch.fuzz``.
2981 See :hg:`help config` for more information about configuration
2982 See :hg:`help config` for more information about configuration
2982 files and how to use these options.
2983 files and how to use these options.
2983
2984
2984 See :hg:`help dates` for a list of formats valid for -d/--date.
2985 See :hg:`help dates` for a list of formats valid for -d/--date.
2985
2986
2986 .. container:: verbose
2987 .. container:: verbose
2987
2988
2988 Examples:
2989 Examples:
2989
2990
2990 - import a traditional patch from a website and detect renames::
2991 - import a traditional patch from a website and detect renames::
2991
2992
2992 hg import -s 80 http://example.com/bugfix.patch
2993 hg import -s 80 http://example.com/bugfix.patch
2993
2994
2994 - import a changeset from an hgweb server::
2995 - import a changeset from an hgweb server::
2995
2996
2996 hg import https://www.mercurial-scm.org/repo/hg/rev/5ca8c111e9aa
2997 hg import https://www.mercurial-scm.org/repo/hg/rev/5ca8c111e9aa
2997
2998
2998 - import all the patches in an Unix-style mbox::
2999 - import all the patches in an Unix-style mbox::
2999
3000
3000 hg import incoming-patches.mbox
3001 hg import incoming-patches.mbox
3001
3002
3002 - import patches from stdin::
3003 - import patches from stdin::
3003
3004
3004 hg import -
3005 hg import -
3005
3006
3006 - attempt to exactly restore an exported changeset (not always
3007 - attempt to exactly restore an exported changeset (not always
3007 possible)::
3008 possible)::
3008
3009
3009 hg import --exact proposed-fix.patch
3010 hg import --exact proposed-fix.patch
3010
3011
3011 - use an external tool to apply a patch which is too fuzzy for
3012 - use an external tool to apply a patch which is too fuzzy for
3012 the default internal tool.
3013 the default internal tool.
3013
3014
3014 hg import --config ui.patch="patch --merge" fuzzy.patch
3015 hg import --config ui.patch="patch --merge" fuzzy.patch
3015
3016
3016 - change the default fuzzing from 2 to a less strict 7
3017 - change the default fuzzing from 2 to a less strict 7
3017
3018
3018 hg import --config ui.fuzz=7 fuzz.patch
3019 hg import --config ui.fuzz=7 fuzz.patch
3019
3020
3020 Returns 0 on success, 1 on partial success (see --partial).
3021 Returns 0 on success, 1 on partial success (see --partial).
3021 """
3022 """
3022
3023
3023 if not patch1:
3024 if not patch1:
3024 raise error.Abort(_('need at least one patch to import'))
3025 raise error.Abort(_('need at least one patch to import'))
3025
3026
3026 patches = (patch1,) + patches
3027 patches = (patch1,) + patches
3027
3028
3028 date = opts.get('date')
3029 date = opts.get('date')
3029 if date:
3030 if date:
3030 opts['date'] = util.parsedate(date)
3031 opts['date'] = util.parsedate(date)
3031
3032
3032 exact = opts.get('exact')
3033 exact = opts.get('exact')
3033 update = not opts.get('bypass')
3034 update = not opts.get('bypass')
3034 if not update and opts.get('no_commit'):
3035 if not update and opts.get('no_commit'):
3035 raise error.Abort(_('cannot use --no-commit with --bypass'))
3036 raise error.Abort(_('cannot use --no-commit with --bypass'))
3036 try:
3037 try:
3037 sim = float(opts.get('similarity') or 0)
3038 sim = float(opts.get('similarity') or 0)
3038 except ValueError:
3039 except ValueError:
3039 raise error.Abort(_('similarity must be a number'))
3040 raise error.Abort(_('similarity must be a number'))
3040 if sim < 0 or sim > 100:
3041 if sim < 0 or sim > 100:
3041 raise error.Abort(_('similarity must be between 0 and 100'))
3042 raise error.Abort(_('similarity must be between 0 and 100'))
3042 if sim and not update:
3043 if sim and not update:
3043 raise error.Abort(_('cannot use --similarity with --bypass'))
3044 raise error.Abort(_('cannot use --similarity with --bypass'))
3044 if exact:
3045 if exact:
3045 if opts.get('edit'):
3046 if opts.get('edit'):
3046 raise error.Abort(_('cannot use --exact with --edit'))
3047 raise error.Abort(_('cannot use --exact with --edit'))
3047 if opts.get('prefix'):
3048 if opts.get('prefix'):
3048 raise error.Abort(_('cannot use --exact with --prefix'))
3049 raise error.Abort(_('cannot use --exact with --prefix'))
3049
3050
3050 base = opts["base"]
3051 base = opts["base"]
3051 wlock = dsguard = lock = tr = None
3052 wlock = dsguard = lock = tr = None
3052 msgs = []
3053 msgs = []
3053 ret = 0
3054 ret = 0
3054
3055
3055
3056
3056 try:
3057 try:
3057 wlock = repo.wlock()
3058 wlock = repo.wlock()
3058
3059
3059 if update:
3060 if update:
3060 cmdutil.checkunfinished(repo)
3061 cmdutil.checkunfinished(repo)
3061 if (exact or not opts.get('force')):
3062 if (exact or not opts.get('force')):
3062 cmdutil.bailifchanged(repo)
3063 cmdutil.bailifchanged(repo)
3063
3064
3064 if not opts.get('no_commit'):
3065 if not opts.get('no_commit'):
3065 lock = repo.lock()
3066 lock = repo.lock()
3066 tr = repo.transaction('import')
3067 tr = repo.transaction('import')
3067 else:
3068 else:
3068 dsguard = dirstateguard.dirstateguard(repo, 'import')
3069 dsguard = dirstateguard.dirstateguard(repo, 'import')
3069 parents = repo[None].parents()
3070 parents = repo[None].parents()
3070 for patchurl in patches:
3071 for patchurl in patches:
3071 if patchurl == '-':
3072 if patchurl == '-':
3072 ui.status(_('applying patch from stdin\n'))
3073 ui.status(_('applying patch from stdin\n'))
3073 patchfile = ui.fin
3074 patchfile = ui.fin
3074 patchurl = 'stdin' # for error message
3075 patchurl = 'stdin' # for error message
3075 else:
3076 else:
3076 patchurl = os.path.join(base, patchurl)
3077 patchurl = os.path.join(base, patchurl)
3077 ui.status(_('applying %s\n') % patchurl)
3078 ui.status(_('applying %s\n') % patchurl)
3078 patchfile = hg.openpath(ui, patchurl)
3079 patchfile = hg.openpath(ui, patchurl)
3079
3080
3080 haspatch = False
3081 haspatch = False
3081 for hunk in patch.split(patchfile):
3082 for hunk in patch.split(patchfile):
3082 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
3083 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
3083 parents, opts,
3084 parents, opts,
3084 msgs, hg.clean)
3085 msgs, hg.clean)
3085 if msg:
3086 if msg:
3086 haspatch = True
3087 haspatch = True
3087 ui.note(msg + '\n')
3088 ui.note(msg + '\n')
3088 if update or exact:
3089 if update or exact:
3089 parents = repo[None].parents()
3090 parents = repo[None].parents()
3090 else:
3091 else:
3091 parents = [repo[node]]
3092 parents = [repo[node]]
3092 if rej:
3093 if rej:
3093 ui.write_err(_("patch applied partially\n"))
3094 ui.write_err(_("patch applied partially\n"))
3094 ui.write_err(_("(fix the .rej files and run "
3095 ui.write_err(_("(fix the .rej files and run "
3095 "`hg commit --amend`)\n"))
3096 "`hg commit --amend`)\n"))
3096 ret = 1
3097 ret = 1
3097 break
3098 break
3098
3099
3099 if not haspatch:
3100 if not haspatch:
3100 raise error.Abort(_('%s: no diffs found') % patchurl)
3101 raise error.Abort(_('%s: no diffs found') % patchurl)
3101
3102
3102 if tr:
3103 if tr:
3103 tr.close()
3104 tr.close()
3104 if msgs:
3105 if msgs:
3105 repo.savecommitmessage('\n* * *\n'.join(msgs))
3106 repo.savecommitmessage('\n* * *\n'.join(msgs))
3106 if dsguard:
3107 if dsguard:
3107 dsguard.close()
3108 dsguard.close()
3108 return ret
3109 return ret
3109 finally:
3110 finally:
3110 if tr:
3111 if tr:
3111 tr.release()
3112 tr.release()
3112 release(lock, dsguard, wlock)
3113 release(lock, dsguard, wlock)
3113
3114
3114 @command('incoming|in',
3115 @command('incoming|in',
3115 [('f', 'force', None,
3116 [('f', 'force', None,
3116 _('run even if remote repository is unrelated')),
3117 _('run even if remote repository is unrelated')),
3117 ('n', 'newest-first', None, _('show newest record first')),
3118 ('n', 'newest-first', None, _('show newest record first')),
3118 ('', 'bundle', '',
3119 ('', 'bundle', '',
3119 _('file to store the bundles into'), _('FILE')),
3120 _('file to store the bundles into'), _('FILE')),
3120 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3121 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3121 ('B', 'bookmarks', False, _("compare bookmarks")),
3122 ('B', 'bookmarks', False, _("compare bookmarks")),
3122 ('b', 'branch', [],
3123 ('b', 'branch', [],
3123 _('a specific branch you would like to pull'), _('BRANCH')),
3124 _('a specific branch you would like to pull'), _('BRANCH')),
3124 ] + logopts + remoteopts + subrepoopts,
3125 ] + logopts + remoteopts + subrepoopts,
3125 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3126 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3126 def incoming(ui, repo, source="default", **opts):
3127 def incoming(ui, repo, source="default", **opts):
3127 """show new changesets found in source
3128 """show new changesets found in source
3128
3129
3129 Show new changesets found in the specified path/URL or the default
3130 Show new changesets found in the specified path/URL or the default
3130 pull location. These are the changesets that would have been pulled
3131 pull location. These are the changesets that would have been pulled
3131 if a pull at the time you issued this command.
3132 if a pull at the time you issued this command.
3132
3133
3133 See pull for valid source format details.
3134 See pull for valid source format details.
3134
3135
3135 .. container:: verbose
3136 .. container:: verbose
3136
3137
3137 With -B/--bookmarks, the result of bookmark comparison between
3138 With -B/--bookmarks, the result of bookmark comparison between
3138 local and remote repositories is displayed. With -v/--verbose,
3139 local and remote repositories is displayed. With -v/--verbose,
3139 status is also displayed for each bookmark like below::
3140 status is also displayed for each bookmark like below::
3140
3141
3141 BM1 01234567890a added
3142 BM1 01234567890a added
3142 BM2 1234567890ab advanced
3143 BM2 1234567890ab advanced
3143 BM3 234567890abc diverged
3144 BM3 234567890abc diverged
3144 BM4 34567890abcd changed
3145 BM4 34567890abcd changed
3145
3146
3146 The action taken locally when pulling depends on the
3147 The action taken locally when pulling depends on the
3147 status of each bookmark:
3148 status of each bookmark:
3148
3149
3149 :``added``: pull will create it
3150 :``added``: pull will create it
3150 :``advanced``: pull will update it
3151 :``advanced``: pull will update it
3151 :``diverged``: pull will create a divergent bookmark
3152 :``diverged``: pull will create a divergent bookmark
3152 :``changed``: result depends on remote changesets
3153 :``changed``: result depends on remote changesets
3153
3154
3154 From the point of view of pulling behavior, bookmark
3155 From the point of view of pulling behavior, bookmark
3155 existing only in the remote repository are treated as ``added``,
3156 existing only in the remote repository are treated as ``added``,
3156 even if it is in fact locally deleted.
3157 even if it is in fact locally deleted.
3157
3158
3158 .. container:: verbose
3159 .. container:: verbose
3159
3160
3160 For remote repository, using --bundle avoids downloading the
3161 For remote repository, using --bundle avoids downloading the
3161 changesets twice if the incoming is followed by a pull.
3162 changesets twice if the incoming is followed by a pull.
3162
3163
3163 Examples:
3164 Examples:
3164
3165
3165 - show incoming changes with patches and full description::
3166 - show incoming changes with patches and full description::
3166
3167
3167 hg incoming -vp
3168 hg incoming -vp
3168
3169
3169 - show incoming changes excluding merges, store a bundle::
3170 - show incoming changes excluding merges, store a bundle::
3170
3171
3171 hg in -vpM --bundle incoming.hg
3172 hg in -vpM --bundle incoming.hg
3172 hg pull incoming.hg
3173 hg pull incoming.hg
3173
3174
3174 - briefly list changes inside a bundle::
3175 - briefly list changes inside a bundle::
3175
3176
3176 hg in changes.hg -T "{desc|firstline}\\n"
3177 hg in changes.hg -T "{desc|firstline}\\n"
3177
3178
3178 Returns 0 if there are incoming changes, 1 otherwise.
3179 Returns 0 if there are incoming changes, 1 otherwise.
3179 """
3180 """
3180 if opts.get('graph'):
3181 if opts.get('graph'):
3181 cmdutil.checkunsupportedgraphflags([], opts)
3182 cmdutil.checkunsupportedgraphflags([], opts)
3182 def display(other, chlist, displayer):
3183 def display(other, chlist, displayer):
3183 revdag = cmdutil.graphrevs(other, chlist, opts)
3184 revdag = cmdutil.graphrevs(other, chlist, opts)
3184 cmdutil.displaygraph(ui, repo, revdag, displayer,
3185 cmdutil.displaygraph(ui, repo, revdag, displayer,
3185 graphmod.asciiedges)
3186 graphmod.asciiedges)
3186
3187
3187 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3188 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3188 return 0
3189 return 0
3189
3190
3190 if opts.get('bundle') and opts.get('subrepos'):
3191 if opts.get('bundle') and opts.get('subrepos'):
3191 raise error.Abort(_('cannot combine --bundle and --subrepos'))
3192 raise error.Abort(_('cannot combine --bundle and --subrepos'))
3192
3193
3193 if opts.get('bookmarks'):
3194 if opts.get('bookmarks'):
3194 source, branches = hg.parseurl(ui.expandpath(source),
3195 source, branches = hg.parseurl(ui.expandpath(source),
3195 opts.get('branch'))
3196 opts.get('branch'))
3196 other = hg.peer(repo, opts, source)
3197 other = hg.peer(repo, opts, source)
3197 if 'bookmarks' not in other.listkeys('namespaces'):
3198 if 'bookmarks' not in other.listkeys('namespaces'):
3198 ui.warn(_("remote doesn't support bookmarks\n"))
3199 ui.warn(_("remote doesn't support bookmarks\n"))
3199 return 0
3200 return 0
3200 ui.pager('incoming')
3201 ui.pager('incoming')
3201 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3202 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3202 return bookmarks.incoming(ui, repo, other)
3203 return bookmarks.incoming(ui, repo, other)
3203
3204
3204 repo._subtoppath = ui.expandpath(source)
3205 repo._subtoppath = ui.expandpath(source)
3205 try:
3206 try:
3206 return hg.incoming(ui, repo, source, opts)
3207 return hg.incoming(ui, repo, source, opts)
3207 finally:
3208 finally:
3208 del repo._subtoppath
3209 del repo._subtoppath
3209
3210
3210
3211
3211 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
3212 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
3212 norepo=True)
3213 norepo=True)
3213 def init(ui, dest=".", **opts):
3214 def init(ui, dest=".", **opts):
3214 """create a new repository in the given directory
3215 """create a new repository in the given directory
3215
3216
3216 Initialize a new repository in the given directory. If the given
3217 Initialize a new repository in the given directory. If the given
3217 directory does not exist, it will be created.
3218 directory does not exist, it will be created.
3218
3219
3219 If no directory is given, the current directory is used.
3220 If no directory is given, the current directory is used.
3220
3221
3221 It is possible to specify an ``ssh://`` URL as the destination.
3222 It is possible to specify an ``ssh://`` URL as the destination.
3222 See :hg:`help urls` for more information.
3223 See :hg:`help urls` for more information.
3223
3224
3224 Returns 0 on success.
3225 Returns 0 on success.
3225 """
3226 """
3226 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3227 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3227
3228
3228 @command('locate',
3229 @command('locate',
3229 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3230 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3230 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3231 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3231 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3232 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3232 ] + walkopts,
3233 ] + walkopts,
3233 _('[OPTION]... [PATTERN]...'))
3234 _('[OPTION]... [PATTERN]...'))
3234 def locate(ui, repo, *pats, **opts):
3235 def locate(ui, repo, *pats, **opts):
3235 """locate files matching specific patterns (DEPRECATED)
3236 """locate files matching specific patterns (DEPRECATED)
3236
3237
3237 Print files under Mercurial control in the working directory whose
3238 Print files under Mercurial control in the working directory whose
3238 names match the given patterns.
3239 names match the given patterns.
3239
3240
3240 By default, this command searches all directories in the working
3241 By default, this command searches all directories in the working
3241 directory. To search just the current directory and its
3242 directory. To search just the current directory and its
3242 subdirectories, use "--include .".
3243 subdirectories, use "--include .".
3243
3244
3244 If no patterns are given to match, this command prints the names
3245 If no patterns are given to match, this command prints the names
3245 of all files under Mercurial control in the working directory.
3246 of all files under Mercurial control in the working directory.
3246
3247
3247 If you want to feed the output of this command into the "xargs"
3248 If you want to feed the output of this command into the "xargs"
3248 command, use the -0 option to both this command and "xargs". This
3249 command, use the -0 option to both this command and "xargs". This
3249 will avoid the problem of "xargs" treating single filenames that
3250 will avoid the problem of "xargs" treating single filenames that
3250 contain whitespace as multiple filenames.
3251 contain whitespace as multiple filenames.
3251
3252
3252 See :hg:`help files` for a more versatile command.
3253 See :hg:`help files` for a more versatile command.
3253
3254
3254 Returns 0 if a match is found, 1 otherwise.
3255 Returns 0 if a match is found, 1 otherwise.
3255 """
3256 """
3256 if opts.get('print0'):
3257 if opts.get('print0'):
3257 end = '\0'
3258 end = '\0'
3258 else:
3259 else:
3259 end = '\n'
3260 end = '\n'
3260 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3261 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3261
3262
3262 ret = 1
3263 ret = 1
3263 ctx = repo[rev]
3264 ctx = repo[rev]
3264 m = scmutil.match(ctx, pats, opts, default='relglob',
3265 m = scmutil.match(ctx, pats, opts, default='relglob',
3265 badfn=lambda x, y: False)
3266 badfn=lambda x, y: False)
3266
3267
3267 ui.pager('locate')
3268 ui.pager('locate')
3268 for abs in ctx.matches(m):
3269 for abs in ctx.matches(m):
3269 if opts.get('fullpath'):
3270 if opts.get('fullpath'):
3270 ui.write(repo.wjoin(abs), end)
3271 ui.write(repo.wjoin(abs), end)
3271 else:
3272 else:
3272 ui.write(((pats and m.rel(abs)) or abs), end)
3273 ui.write(((pats and m.rel(abs)) or abs), end)
3273 ret = 0
3274 ret = 0
3274
3275
3275 return ret
3276 return ret
3276
3277
3277 @command('^log|history',
3278 @command('^log|history',
3278 [('f', 'follow', None,
3279 [('f', 'follow', None,
3279 _('follow changeset history, or file history across copies and renames')),
3280 _('follow changeset history, or file history across copies and renames')),
3280 ('', 'follow-first', None,
3281 ('', 'follow-first', None,
3281 _('only follow the first parent of merge changesets (DEPRECATED)')),
3282 _('only follow the first parent of merge changesets (DEPRECATED)')),
3282 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3283 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3283 ('C', 'copies', None, _('show copied files')),
3284 ('C', 'copies', None, _('show copied files')),
3284 ('k', 'keyword', [],
3285 ('k', 'keyword', [],
3285 _('do case-insensitive search for a given text'), _('TEXT')),
3286 _('do case-insensitive search for a given text'), _('TEXT')),
3286 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
3287 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
3287 ('', 'removed', None, _('include revisions where files were removed')),
3288 ('', 'removed', None, _('include revisions where files were removed')),
3288 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3289 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3289 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3290 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3290 ('', 'only-branch', [],
3291 ('', 'only-branch', [],
3291 _('show only changesets within the given named branch (DEPRECATED)'),
3292 _('show only changesets within the given named branch (DEPRECATED)'),
3292 _('BRANCH')),
3293 _('BRANCH')),
3293 ('b', 'branch', [],
3294 ('b', 'branch', [],
3294 _('show changesets within the given named branch'), _('BRANCH')),
3295 _('show changesets within the given named branch'), _('BRANCH')),
3295 ('P', 'prune', [],
3296 ('P', 'prune', [],
3296 _('do not display revision or any of its ancestors'), _('REV')),
3297 _('do not display revision or any of its ancestors'), _('REV')),
3297 ] + logopts + walkopts,
3298 ] + logopts + walkopts,
3298 _('[OPTION]... [FILE]'),
3299 _('[OPTION]... [FILE]'),
3299 inferrepo=True)
3300 inferrepo=True)
3300 def log(ui, repo, *pats, **opts):
3301 def log(ui, repo, *pats, **opts):
3301 """show revision history of entire repository or files
3302 """show revision history of entire repository or files
3302
3303
3303 Print the revision history of the specified files or the entire
3304 Print the revision history of the specified files or the entire
3304 project.
3305 project.
3305
3306
3306 If no revision range is specified, the default is ``tip:0`` unless
3307 If no revision range is specified, the default is ``tip:0`` unless
3307 --follow is set, in which case the working directory parent is
3308 --follow is set, in which case the working directory parent is
3308 used as the starting revision.
3309 used as the starting revision.
3309
3310
3310 File history is shown without following rename or copy history of
3311 File history is shown without following rename or copy history of
3311 files. Use -f/--follow with a filename to follow history across
3312 files. Use -f/--follow with a filename to follow history across
3312 renames and copies. --follow without a filename will only show
3313 renames and copies. --follow without a filename will only show
3313 ancestors or descendants of the starting revision.
3314 ancestors or descendants of the starting revision.
3314
3315
3315 By default this command prints revision number and changeset id,
3316 By default this command prints revision number and changeset id,
3316 tags, non-trivial parents, user, date and time, and a summary for
3317 tags, non-trivial parents, user, date and time, and a summary for
3317 each commit. When the -v/--verbose switch is used, the list of
3318 each commit. When the -v/--verbose switch is used, the list of
3318 changed files and full commit message are shown.
3319 changed files and full commit message are shown.
3319
3320
3320 With --graph the revisions are shown as an ASCII art DAG with the most
3321 With --graph the revisions are shown as an ASCII art DAG with the most
3321 recent changeset at the top.
3322 recent changeset at the top.
3322 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
3323 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
3323 and '+' represents a fork where the changeset from the lines below is a
3324 and '+' represents a fork where the changeset from the lines below is a
3324 parent of the 'o' merge on the same line.
3325 parent of the 'o' merge on the same line.
3325
3326
3326 .. note::
3327 .. note::
3327
3328
3328 :hg:`log --patch` may generate unexpected diff output for merge
3329 :hg:`log --patch` may generate unexpected diff output for merge
3329 changesets, as it will only compare the merge changeset against
3330 changesets, as it will only compare the merge changeset against
3330 its first parent. Also, only files different from BOTH parents
3331 its first parent. Also, only files different from BOTH parents
3331 will appear in files:.
3332 will appear in files:.
3332
3333
3333 .. note::
3334 .. note::
3334
3335
3335 For performance reasons, :hg:`log FILE` may omit duplicate changes
3336 For performance reasons, :hg:`log FILE` may omit duplicate changes
3336 made on branches and will not show removals or mode changes. To
3337 made on branches and will not show removals or mode changes. To
3337 see all such changes, use the --removed switch.
3338 see all such changes, use the --removed switch.
3338
3339
3339 .. container:: verbose
3340 .. container:: verbose
3340
3341
3341 Some examples:
3342 Some examples:
3342
3343
3343 - changesets with full descriptions and file lists::
3344 - changesets with full descriptions and file lists::
3344
3345
3345 hg log -v
3346 hg log -v
3346
3347
3347 - changesets ancestral to the working directory::
3348 - changesets ancestral to the working directory::
3348
3349
3349 hg log -f
3350 hg log -f
3350
3351
3351 - last 10 commits on the current branch::
3352 - last 10 commits on the current branch::
3352
3353
3353 hg log -l 10 -b .
3354 hg log -l 10 -b .
3354
3355
3355 - changesets showing all modifications of a file, including removals::
3356 - changesets showing all modifications of a file, including removals::
3356
3357
3357 hg log --removed file.c
3358 hg log --removed file.c
3358
3359
3359 - all changesets that touch a directory, with diffs, excluding merges::
3360 - all changesets that touch a directory, with diffs, excluding merges::
3360
3361
3361 hg log -Mp lib/
3362 hg log -Mp lib/
3362
3363
3363 - all revision numbers that match a keyword::
3364 - all revision numbers that match a keyword::
3364
3365
3365 hg log -k bug --template "{rev}\\n"
3366 hg log -k bug --template "{rev}\\n"
3366
3367
3367 - the full hash identifier of the working directory parent::
3368 - the full hash identifier of the working directory parent::
3368
3369
3369 hg log -r . --template "{node}\\n"
3370 hg log -r . --template "{node}\\n"
3370
3371
3371 - list available log templates::
3372 - list available log templates::
3372
3373
3373 hg log -T list
3374 hg log -T list
3374
3375
3375 - check if a given changeset is included in a tagged release::
3376 - check if a given changeset is included in a tagged release::
3376
3377
3377 hg log -r "a21ccf and ancestor(1.9)"
3378 hg log -r "a21ccf and ancestor(1.9)"
3378
3379
3379 - find all changesets by some user in a date range::
3380 - find all changesets by some user in a date range::
3380
3381
3381 hg log -k alice -d "may 2008 to jul 2008"
3382 hg log -k alice -d "may 2008 to jul 2008"
3382
3383
3383 - summary of all changesets after the last tag::
3384 - summary of all changesets after the last tag::
3384
3385
3385 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3386 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3386
3387
3387 See :hg:`help dates` for a list of formats valid for -d/--date.
3388 See :hg:`help dates` for a list of formats valid for -d/--date.
3388
3389
3389 See :hg:`help revisions` for more about specifying and ordering
3390 See :hg:`help revisions` for more about specifying and ordering
3390 revisions.
3391 revisions.
3391
3392
3392 See :hg:`help templates` for more about pre-packaged styles and
3393 See :hg:`help templates` for more about pre-packaged styles and
3393 specifying custom templates.
3394 specifying custom templates.
3394
3395
3395 Returns 0 on success.
3396 Returns 0 on success.
3396
3397
3397 """
3398 """
3398 if opts.get('follow') and opts.get('rev'):
3399 if opts.get('follow') and opts.get('rev'):
3399 opts['rev'] = [revsetlang.formatspec('reverse(::%lr)', opts.get('rev'))]
3400 opts['rev'] = [revsetlang.formatspec('reverse(::%lr)', opts.get('rev'))]
3400 del opts['follow']
3401 del opts['follow']
3401
3402
3402 if opts.get('graph'):
3403 if opts.get('graph'):
3403 return cmdutil.graphlog(ui, repo, *pats, **opts)
3404 return cmdutil.graphlog(ui, repo, *pats, **opts)
3404
3405
3405 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
3406 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
3406 limit = cmdutil.loglimit(opts)
3407 limit = cmdutil.loglimit(opts)
3407 count = 0
3408 count = 0
3408
3409
3409 getrenamed = None
3410 getrenamed = None
3410 if opts.get('copies'):
3411 if opts.get('copies'):
3411 endrev = None
3412 endrev = None
3412 if opts.get('rev'):
3413 if opts.get('rev'):
3413 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
3414 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
3414 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3415 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3415
3416
3416 ui.pager('log')
3417 ui.pager('log')
3417 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
3418 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
3418 for rev in revs:
3419 for rev in revs:
3419 if count == limit:
3420 if count == limit:
3420 break
3421 break
3421 ctx = repo[rev]
3422 ctx = repo[rev]
3422 copies = None
3423 copies = None
3423 if getrenamed is not None and rev:
3424 if getrenamed is not None and rev:
3424 copies = []
3425 copies = []
3425 for fn in ctx.files():
3426 for fn in ctx.files():
3426 rename = getrenamed(fn, rev)
3427 rename = getrenamed(fn, rev)
3427 if rename:
3428 if rename:
3428 copies.append((fn, rename[0]))
3429 copies.append((fn, rename[0]))
3429 if filematcher:
3430 if filematcher:
3430 revmatchfn = filematcher(ctx.rev())
3431 revmatchfn = filematcher(ctx.rev())
3431 else:
3432 else:
3432 revmatchfn = None
3433 revmatchfn = None
3433 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
3434 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
3434 if displayer.flush(ctx):
3435 if displayer.flush(ctx):
3435 count += 1
3436 count += 1
3436
3437
3437 displayer.close()
3438 displayer.close()
3438
3439
3439 @command('manifest',
3440 @command('manifest',
3440 [('r', 'rev', '', _('revision to display'), _('REV')),
3441 [('r', 'rev', '', _('revision to display'), _('REV')),
3441 ('', 'all', False, _("list files from all revisions"))]
3442 ('', 'all', False, _("list files from all revisions"))]
3442 + formatteropts,
3443 + formatteropts,
3443 _('[-r REV]'))
3444 _('[-r REV]'))
3444 def manifest(ui, repo, node=None, rev=None, **opts):
3445 def manifest(ui, repo, node=None, rev=None, **opts):
3445 """output the current or given revision of the project manifest
3446 """output the current or given revision of the project manifest
3446
3447
3447 Print a list of version controlled files for the given revision.
3448 Print a list of version controlled files for the given revision.
3448 If no revision is given, the first parent of the working directory
3449 If no revision is given, the first parent of the working directory
3449 is used, or the null revision if no revision is checked out.
3450 is used, or the null revision if no revision is checked out.
3450
3451
3451 With -v, print file permissions, symlink and executable bits.
3452 With -v, print file permissions, symlink and executable bits.
3452 With --debug, print file revision hashes.
3453 With --debug, print file revision hashes.
3453
3454
3454 If option --all is specified, the list of all files from all revisions
3455 If option --all is specified, the list of all files from all revisions
3455 is printed. This includes deleted and renamed files.
3456 is printed. This includes deleted and renamed files.
3456
3457
3457 Returns 0 on success.
3458 Returns 0 on success.
3458 """
3459 """
3459 fm = ui.formatter('manifest', opts)
3460 fm = ui.formatter('manifest', opts)
3460
3461
3461 if opts.get('all'):
3462 if opts.get('all'):
3462 if rev or node:
3463 if rev or node:
3463 raise error.Abort(_("can't specify a revision with --all"))
3464 raise error.Abort(_("can't specify a revision with --all"))
3464
3465
3465 res = []
3466 res = []
3466 prefix = "data/"
3467 prefix = "data/"
3467 suffix = ".i"
3468 suffix = ".i"
3468 plen = len(prefix)
3469 plen = len(prefix)
3469 slen = len(suffix)
3470 slen = len(suffix)
3470 with repo.lock():
3471 with repo.lock():
3471 for fn, b, size in repo.store.datafiles():
3472 for fn, b, size in repo.store.datafiles():
3472 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
3473 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
3473 res.append(fn[plen:-slen])
3474 res.append(fn[plen:-slen])
3474 ui.pager('manifest')
3475 ui.pager('manifest')
3475 for f in res:
3476 for f in res:
3476 fm.startitem()
3477 fm.startitem()
3477 fm.write("path", '%s\n', f)
3478 fm.write("path", '%s\n', f)
3478 fm.end()
3479 fm.end()
3479 return
3480 return
3480
3481
3481 if rev and node:
3482 if rev and node:
3482 raise error.Abort(_("please specify just one revision"))
3483 raise error.Abort(_("please specify just one revision"))
3483
3484
3484 if not node:
3485 if not node:
3485 node = rev
3486 node = rev
3486
3487
3487 char = {'l': '@', 'x': '*', '': ''}
3488 char = {'l': '@', 'x': '*', '': ''}
3488 mode = {'l': '644', 'x': '755', '': '644'}
3489 mode = {'l': '644', 'x': '755', '': '644'}
3489 ctx = scmutil.revsingle(repo, node)
3490 ctx = scmutil.revsingle(repo, node)
3490 mf = ctx.manifest()
3491 mf = ctx.manifest()
3491 ui.pager('manifest')
3492 ui.pager('manifest')
3492 for f in ctx:
3493 for f in ctx:
3493 fm.startitem()
3494 fm.startitem()
3494 fl = ctx[f].flags()
3495 fl = ctx[f].flags()
3495 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
3496 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
3496 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
3497 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
3497 fm.write('path', '%s\n', f)
3498 fm.write('path', '%s\n', f)
3498 fm.end()
3499 fm.end()
3499
3500
3500 @command('^merge',
3501 @command('^merge',
3501 [('f', 'force', None,
3502 [('f', 'force', None,
3502 _('force a merge including outstanding changes (DEPRECATED)')),
3503 _('force a merge including outstanding changes (DEPRECATED)')),
3503 ('r', 'rev', '', _('revision to merge'), _('REV')),
3504 ('r', 'rev', '', _('revision to merge'), _('REV')),
3504 ('P', 'preview', None,
3505 ('P', 'preview', None,
3505 _('review revisions to merge (no merge is performed)'))
3506 _('review revisions to merge (no merge is performed)'))
3506 ] + mergetoolopts,
3507 ] + mergetoolopts,
3507 _('[-P] [[-r] REV]'))
3508 _('[-P] [[-r] REV]'))
3508 def merge(ui, repo, node=None, **opts):
3509 def merge(ui, repo, node=None, **opts):
3509 """merge another revision into working directory
3510 """merge another revision into working directory
3510
3511
3511 The current working directory is updated with all changes made in
3512 The current working directory is updated with all changes made in
3512 the requested revision since the last common predecessor revision.
3513 the requested revision since the last common predecessor revision.
3513
3514
3514 Files that changed between either parent are marked as changed for
3515 Files that changed between either parent are marked as changed for
3515 the next commit and a commit must be performed before any further
3516 the next commit and a commit must be performed before any further
3516 updates to the repository are allowed. The next commit will have
3517 updates to the repository are allowed. The next commit will have
3517 two parents.
3518 two parents.
3518
3519
3519 ``--tool`` can be used to specify the merge tool used for file
3520 ``--tool`` can be used to specify the merge tool used for file
3520 merges. It overrides the HGMERGE environment variable and your
3521 merges. It overrides the HGMERGE environment variable and your
3521 configuration files. See :hg:`help merge-tools` for options.
3522 configuration files. See :hg:`help merge-tools` for options.
3522
3523
3523 If no revision is specified, the working directory's parent is a
3524 If no revision is specified, the working directory's parent is a
3524 head revision, and the current branch contains exactly one other
3525 head revision, and the current branch contains exactly one other
3525 head, the other head is merged with by default. Otherwise, an
3526 head, the other head is merged with by default. Otherwise, an
3526 explicit revision with which to merge with must be provided.
3527 explicit revision with which to merge with must be provided.
3527
3528
3528 See :hg:`help resolve` for information on handling file conflicts.
3529 See :hg:`help resolve` for information on handling file conflicts.
3529
3530
3530 To undo an uncommitted merge, use :hg:`update --clean .` which
3531 To undo an uncommitted merge, use :hg:`update --clean .` which
3531 will check out a clean copy of the original merge parent, losing
3532 will check out a clean copy of the original merge parent, losing
3532 all changes.
3533 all changes.
3533
3534
3534 Returns 0 on success, 1 if there are unresolved files.
3535 Returns 0 on success, 1 if there are unresolved files.
3535 """
3536 """
3536
3537
3537 if opts.get('rev') and node:
3538 if opts.get('rev') and node:
3538 raise error.Abort(_("please specify just one revision"))
3539 raise error.Abort(_("please specify just one revision"))
3539 if not node:
3540 if not node:
3540 node = opts.get('rev')
3541 node = opts.get('rev')
3541
3542
3542 if node:
3543 if node:
3543 node = scmutil.revsingle(repo, node).node()
3544 node = scmutil.revsingle(repo, node).node()
3544
3545
3545 if not node:
3546 if not node:
3546 node = repo[destutil.destmerge(repo)].node()
3547 node = repo[destutil.destmerge(repo)].node()
3547
3548
3548 if opts.get('preview'):
3549 if opts.get('preview'):
3549 # find nodes that are ancestors of p2 but not of p1
3550 # find nodes that are ancestors of p2 but not of p1
3550 p1 = repo.lookup('.')
3551 p1 = repo.lookup('.')
3551 p2 = repo.lookup(node)
3552 p2 = repo.lookup(node)
3552 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
3553 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
3553
3554
3554 displayer = cmdutil.show_changeset(ui, repo, opts)
3555 displayer = cmdutil.show_changeset(ui, repo, opts)
3555 for node in nodes:
3556 for node in nodes:
3556 displayer.show(repo[node])
3557 displayer.show(repo[node])
3557 displayer.close()
3558 displayer.close()
3558 return 0
3559 return 0
3559
3560
3560 try:
3561 try:
3561 # ui.forcemerge is an internal variable, do not document
3562 # ui.forcemerge is an internal variable, do not document
3562 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
3563 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
3563 force = opts.get('force')
3564 force = opts.get('force')
3564 labels = ['working copy', 'merge rev']
3565 labels = ['working copy', 'merge rev']
3565 return hg.merge(repo, node, force=force, mergeforce=force,
3566 return hg.merge(repo, node, force=force, mergeforce=force,
3566 labels=labels)
3567 labels=labels)
3567 finally:
3568 finally:
3568 ui.setconfig('ui', 'forcemerge', '', 'merge')
3569 ui.setconfig('ui', 'forcemerge', '', 'merge')
3569
3570
3570 @command('outgoing|out',
3571 @command('outgoing|out',
3571 [('f', 'force', None, _('run even when the destination is unrelated')),
3572 [('f', 'force', None, _('run even when the destination is unrelated')),
3572 ('r', 'rev', [],
3573 ('r', 'rev', [],
3573 _('a changeset intended to be included in the destination'), _('REV')),
3574 _('a changeset intended to be included in the destination'), _('REV')),
3574 ('n', 'newest-first', None, _('show newest record first')),
3575 ('n', 'newest-first', None, _('show newest record first')),
3575 ('B', 'bookmarks', False, _('compare bookmarks')),
3576 ('B', 'bookmarks', False, _('compare bookmarks')),
3576 ('b', 'branch', [], _('a specific branch you would like to push'),
3577 ('b', 'branch', [], _('a specific branch you would like to push'),
3577 _('BRANCH')),
3578 _('BRANCH')),
3578 ] + logopts + remoteopts + subrepoopts,
3579 ] + logopts + remoteopts + subrepoopts,
3579 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
3580 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
3580 def outgoing(ui, repo, dest=None, **opts):
3581 def outgoing(ui, repo, dest=None, **opts):
3581 """show changesets not found in the destination
3582 """show changesets not found in the destination
3582
3583
3583 Show changesets not found in the specified destination repository
3584 Show changesets not found in the specified destination repository
3584 or the default push location. These are the changesets that would
3585 or the default push location. These are the changesets that would
3585 be pushed if a push was requested.
3586 be pushed if a push was requested.
3586
3587
3587 See pull for details of valid destination formats.
3588 See pull for details of valid destination formats.
3588
3589
3589 .. container:: verbose
3590 .. container:: verbose
3590
3591
3591 With -B/--bookmarks, the result of bookmark comparison between
3592 With -B/--bookmarks, the result of bookmark comparison between
3592 local and remote repositories is displayed. With -v/--verbose,
3593 local and remote repositories is displayed. With -v/--verbose,
3593 status is also displayed for each bookmark like below::
3594 status is also displayed for each bookmark like below::
3594
3595
3595 BM1 01234567890a added
3596 BM1 01234567890a added
3596 BM2 deleted
3597 BM2 deleted
3597 BM3 234567890abc advanced
3598 BM3 234567890abc advanced
3598 BM4 34567890abcd diverged
3599 BM4 34567890abcd diverged
3599 BM5 4567890abcde changed
3600 BM5 4567890abcde changed
3600
3601
3601 The action taken when pushing depends on the
3602 The action taken when pushing depends on the
3602 status of each bookmark:
3603 status of each bookmark:
3603
3604
3604 :``added``: push with ``-B`` will create it
3605 :``added``: push with ``-B`` will create it
3605 :``deleted``: push with ``-B`` will delete it
3606 :``deleted``: push with ``-B`` will delete it
3606 :``advanced``: push will update it
3607 :``advanced``: push will update it
3607 :``diverged``: push with ``-B`` will update it
3608 :``diverged``: push with ``-B`` will update it
3608 :``changed``: push with ``-B`` will update it
3609 :``changed``: push with ``-B`` will update it
3609
3610
3610 From the point of view of pushing behavior, bookmarks
3611 From the point of view of pushing behavior, bookmarks
3611 existing only in the remote repository are treated as
3612 existing only in the remote repository are treated as
3612 ``deleted``, even if it is in fact added remotely.
3613 ``deleted``, even if it is in fact added remotely.
3613
3614
3614 Returns 0 if there are outgoing changes, 1 otherwise.
3615 Returns 0 if there are outgoing changes, 1 otherwise.
3615 """
3616 """
3616 if opts.get('graph'):
3617 if opts.get('graph'):
3617 cmdutil.checkunsupportedgraphflags([], opts)
3618 cmdutil.checkunsupportedgraphflags([], opts)
3618 o, other = hg._outgoing(ui, repo, dest, opts)
3619 o, other = hg._outgoing(ui, repo, dest, opts)
3619 if not o:
3620 if not o:
3620 cmdutil.outgoinghooks(ui, repo, other, opts, o)
3621 cmdutil.outgoinghooks(ui, repo, other, opts, o)
3621 return
3622 return
3622
3623
3623 revdag = cmdutil.graphrevs(repo, o, opts)
3624 revdag = cmdutil.graphrevs(repo, o, opts)
3624 ui.pager('outgoing')
3625 ui.pager('outgoing')
3625 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
3626 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
3626 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
3627 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
3627 cmdutil.outgoinghooks(ui, repo, other, opts, o)
3628 cmdutil.outgoinghooks(ui, repo, other, opts, o)
3628 return 0
3629 return 0
3629
3630
3630 if opts.get('bookmarks'):
3631 if opts.get('bookmarks'):
3631 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3632 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3632 dest, branches = hg.parseurl(dest, opts.get('branch'))
3633 dest, branches = hg.parseurl(dest, opts.get('branch'))
3633 other = hg.peer(repo, opts, dest)
3634 other = hg.peer(repo, opts, dest)
3634 if 'bookmarks' not in other.listkeys('namespaces'):
3635 if 'bookmarks' not in other.listkeys('namespaces'):
3635 ui.warn(_("remote doesn't support bookmarks\n"))
3636 ui.warn(_("remote doesn't support bookmarks\n"))
3636 return 0
3637 return 0
3637 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
3638 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
3638 ui.pager('outgoing')
3639 ui.pager('outgoing')
3639 return bookmarks.outgoing(ui, repo, other)
3640 return bookmarks.outgoing(ui, repo, other)
3640
3641
3641 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
3642 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
3642 try:
3643 try:
3643 return hg.outgoing(ui, repo, dest, opts)
3644 return hg.outgoing(ui, repo, dest, opts)
3644 finally:
3645 finally:
3645 del repo._subtoppath
3646 del repo._subtoppath
3646
3647
3647 @command('parents',
3648 @command('parents',
3648 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
3649 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
3649 ] + templateopts,
3650 ] + templateopts,
3650 _('[-r REV] [FILE]'),
3651 _('[-r REV] [FILE]'),
3651 inferrepo=True)
3652 inferrepo=True)
3652 def parents(ui, repo, file_=None, **opts):
3653 def parents(ui, repo, file_=None, **opts):
3653 """show the parents of the working directory or revision (DEPRECATED)
3654 """show the parents of the working directory or revision (DEPRECATED)
3654
3655
3655 Print the working directory's parent revisions. If a revision is
3656 Print the working directory's parent revisions. If a revision is
3656 given via -r/--rev, the parent of that revision will be printed.
3657 given via -r/--rev, the parent of that revision will be printed.
3657 If a file argument is given, the revision in which the file was
3658 If a file argument is given, the revision in which the file was
3658 last changed (before the working directory revision or the
3659 last changed (before the working directory revision or the
3659 argument to --rev if given) is printed.
3660 argument to --rev if given) is printed.
3660
3661
3661 This command is equivalent to::
3662 This command is equivalent to::
3662
3663
3663 hg log -r "p1()+p2()" or
3664 hg log -r "p1()+p2()" or
3664 hg log -r "p1(REV)+p2(REV)" or
3665 hg log -r "p1(REV)+p2(REV)" or
3665 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
3666 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
3666 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
3667 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
3667
3668
3668 See :hg:`summary` and :hg:`help revsets` for related information.
3669 See :hg:`summary` and :hg:`help revsets` for related information.
3669
3670
3670 Returns 0 on success.
3671 Returns 0 on success.
3671 """
3672 """
3672
3673
3673 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3674 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3674
3675
3675 if file_:
3676 if file_:
3676 m = scmutil.match(ctx, (file_,), opts)
3677 m = scmutil.match(ctx, (file_,), opts)
3677 if m.anypats() or len(m.files()) != 1:
3678 if m.anypats() or len(m.files()) != 1:
3678 raise error.Abort(_('can only specify an explicit filename'))
3679 raise error.Abort(_('can only specify an explicit filename'))
3679 file_ = m.files()[0]
3680 file_ = m.files()[0]
3680 filenodes = []
3681 filenodes = []
3681 for cp in ctx.parents():
3682 for cp in ctx.parents():
3682 if not cp:
3683 if not cp:
3683 continue
3684 continue
3684 try:
3685 try:
3685 filenodes.append(cp.filenode(file_))
3686 filenodes.append(cp.filenode(file_))
3686 except error.LookupError:
3687 except error.LookupError:
3687 pass
3688 pass
3688 if not filenodes:
3689 if not filenodes:
3689 raise error.Abort(_("'%s' not found in manifest!") % file_)
3690 raise error.Abort(_("'%s' not found in manifest!") % file_)
3690 p = []
3691 p = []
3691 for fn in filenodes:
3692 for fn in filenodes:
3692 fctx = repo.filectx(file_, fileid=fn)
3693 fctx = repo.filectx(file_, fileid=fn)
3693 p.append(fctx.node())
3694 p.append(fctx.node())
3694 else:
3695 else:
3695 p = [cp.node() for cp in ctx.parents()]
3696 p = [cp.node() for cp in ctx.parents()]
3696
3697
3697 displayer = cmdutil.show_changeset(ui, repo, opts)
3698 displayer = cmdutil.show_changeset(ui, repo, opts)
3698 for n in p:
3699 for n in p:
3699 if n != nullid:
3700 if n != nullid:
3700 displayer.show(repo[n])
3701 displayer.show(repo[n])
3701 displayer.close()
3702 displayer.close()
3702
3703
3703 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True)
3704 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True)
3704 def paths(ui, repo, search=None, **opts):
3705 def paths(ui, repo, search=None, **opts):
3705 """show aliases for remote repositories
3706 """show aliases for remote repositories
3706
3707
3707 Show definition of symbolic path name NAME. If no name is given,
3708 Show definition of symbolic path name NAME. If no name is given,
3708 show definition of all available names.
3709 show definition of all available names.
3709
3710
3710 Option -q/--quiet suppresses all output when searching for NAME
3711 Option -q/--quiet suppresses all output when searching for NAME
3711 and shows only the path names when listing all definitions.
3712 and shows only the path names when listing all definitions.
3712
3713
3713 Path names are defined in the [paths] section of your
3714 Path names are defined in the [paths] section of your
3714 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
3715 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
3715 repository, ``.hg/hgrc`` is used, too.
3716 repository, ``.hg/hgrc`` is used, too.
3716
3717
3717 The path names ``default`` and ``default-push`` have a special
3718 The path names ``default`` and ``default-push`` have a special
3718 meaning. When performing a push or pull operation, they are used
3719 meaning. When performing a push or pull operation, they are used
3719 as fallbacks if no location is specified on the command-line.
3720 as fallbacks if no location is specified on the command-line.
3720 When ``default-push`` is set, it will be used for push and
3721 When ``default-push`` is set, it will be used for push and
3721 ``default`` will be used for pull; otherwise ``default`` is used
3722 ``default`` will be used for pull; otherwise ``default`` is used
3722 as the fallback for both. When cloning a repository, the clone
3723 as the fallback for both. When cloning a repository, the clone
3723 source is written as ``default`` in ``.hg/hgrc``.
3724 source is written as ``default`` in ``.hg/hgrc``.
3724
3725
3725 .. note::
3726 .. note::
3726
3727
3727 ``default`` and ``default-push`` apply to all inbound (e.g.
3728 ``default`` and ``default-push`` apply to all inbound (e.g.
3728 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
3729 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
3729 and :hg:`bundle`) operations.
3730 and :hg:`bundle`) operations.
3730
3731
3731 See :hg:`help urls` for more information.
3732 See :hg:`help urls` for more information.
3732
3733
3733 Returns 0 on success.
3734 Returns 0 on success.
3734 """
3735 """
3735 ui.pager('paths')
3736 ui.pager('paths')
3736 if search:
3737 if search:
3737 pathitems = [(name, path) for name, path in ui.paths.iteritems()
3738 pathitems = [(name, path) for name, path in ui.paths.iteritems()
3738 if name == search]
3739 if name == search]
3739 else:
3740 else:
3740 pathitems = sorted(ui.paths.iteritems())
3741 pathitems = sorted(ui.paths.iteritems())
3741
3742
3742 fm = ui.formatter('paths', opts)
3743 fm = ui.formatter('paths', opts)
3743 if fm.isplain():
3744 if fm.isplain():
3744 hidepassword = util.hidepassword
3745 hidepassword = util.hidepassword
3745 else:
3746 else:
3746 hidepassword = str
3747 hidepassword = str
3747 if ui.quiet:
3748 if ui.quiet:
3748 namefmt = '%s\n'
3749 namefmt = '%s\n'
3749 else:
3750 else:
3750 namefmt = '%s = '
3751 namefmt = '%s = '
3751 showsubopts = not search and not ui.quiet
3752 showsubopts = not search and not ui.quiet
3752
3753
3753 for name, path in pathitems:
3754 for name, path in pathitems:
3754 fm.startitem()
3755 fm.startitem()
3755 fm.condwrite(not search, 'name', namefmt, name)
3756 fm.condwrite(not search, 'name', namefmt, name)
3756 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
3757 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
3757 for subopt, value in sorted(path.suboptions.items()):
3758 for subopt, value in sorted(path.suboptions.items()):
3758 assert subopt not in ('name', 'url')
3759 assert subopt not in ('name', 'url')
3759 if showsubopts:
3760 if showsubopts:
3760 fm.plain('%s:%s = ' % (name, subopt))
3761 fm.plain('%s:%s = ' % (name, subopt))
3761 fm.condwrite(showsubopts, subopt, '%s\n', value)
3762 fm.condwrite(showsubopts, subopt, '%s\n', value)
3762
3763
3763 fm.end()
3764 fm.end()
3764
3765
3765 if search and not pathitems:
3766 if search and not pathitems:
3766 if not ui.quiet:
3767 if not ui.quiet:
3767 ui.warn(_("not found!\n"))
3768 ui.warn(_("not found!\n"))
3768 return 1
3769 return 1
3769 else:
3770 else:
3770 return 0
3771 return 0
3771
3772
3772 @command('phase',
3773 @command('phase',
3773 [('p', 'public', False, _('set changeset phase to public')),
3774 [('p', 'public', False, _('set changeset phase to public')),
3774 ('d', 'draft', False, _('set changeset phase to draft')),
3775 ('d', 'draft', False, _('set changeset phase to draft')),
3775 ('s', 'secret', False, _('set changeset phase to secret')),
3776 ('s', 'secret', False, _('set changeset phase to secret')),
3776 ('f', 'force', False, _('allow to move boundary backward')),
3777 ('f', 'force', False, _('allow to move boundary backward')),
3777 ('r', 'rev', [], _('target revision'), _('REV')),
3778 ('r', 'rev', [], _('target revision'), _('REV')),
3778 ],
3779 ],
3779 _('[-p|-d|-s] [-f] [-r] [REV...]'))
3780 _('[-p|-d|-s] [-f] [-r] [REV...]'))
3780 def phase(ui, repo, *revs, **opts):
3781 def phase(ui, repo, *revs, **opts):
3781 """set or show the current phase name
3782 """set or show the current phase name
3782
3783
3783 With no argument, show the phase name of the current revision(s).
3784 With no argument, show the phase name of the current revision(s).
3784
3785
3785 With one of -p/--public, -d/--draft or -s/--secret, change the
3786 With one of -p/--public, -d/--draft or -s/--secret, change the
3786 phase value of the specified revisions.
3787 phase value of the specified revisions.
3787
3788
3788 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
3789 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
3789 lower phase to an higher phase. Phases are ordered as follows::
3790 lower phase to an higher phase. Phases are ordered as follows::
3790
3791
3791 public < draft < secret
3792 public < draft < secret
3792
3793
3793 Returns 0 on success, 1 if some phases could not be changed.
3794 Returns 0 on success, 1 if some phases could not be changed.
3794
3795
3795 (For more information about the phases concept, see :hg:`help phases`.)
3796 (For more information about the phases concept, see :hg:`help phases`.)
3796 """
3797 """
3797 # search for a unique phase argument
3798 # search for a unique phase argument
3798 targetphase = None
3799 targetphase = None
3799 for idx, name in enumerate(phases.phasenames):
3800 for idx, name in enumerate(phases.phasenames):
3800 if opts[name]:
3801 if opts[name]:
3801 if targetphase is not None:
3802 if targetphase is not None:
3802 raise error.Abort(_('only one phase can be specified'))
3803 raise error.Abort(_('only one phase can be specified'))
3803 targetphase = idx
3804 targetphase = idx
3804
3805
3805 # look for specified revision
3806 # look for specified revision
3806 revs = list(revs)
3807 revs = list(revs)
3807 revs.extend(opts['rev'])
3808 revs.extend(opts['rev'])
3808 if not revs:
3809 if not revs:
3809 # display both parents as the second parent phase can influence
3810 # display both parents as the second parent phase can influence
3810 # the phase of a merge commit
3811 # the phase of a merge commit
3811 revs = [c.rev() for c in repo[None].parents()]
3812 revs = [c.rev() for c in repo[None].parents()]
3812
3813
3813 revs = scmutil.revrange(repo, revs)
3814 revs = scmutil.revrange(repo, revs)
3814
3815
3815 lock = None
3816 lock = None
3816 ret = 0
3817 ret = 0
3817 if targetphase is None:
3818 if targetphase is None:
3818 # display
3819 # display
3819 for r in revs:
3820 for r in revs:
3820 ctx = repo[r]
3821 ctx = repo[r]
3821 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
3822 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
3822 else:
3823 else:
3823 tr = None
3824 tr = None
3824 lock = repo.lock()
3825 lock = repo.lock()
3825 try:
3826 try:
3826 tr = repo.transaction("phase")
3827 tr = repo.transaction("phase")
3827 # set phase
3828 # set phase
3828 if not revs:
3829 if not revs:
3829 raise error.Abort(_('empty revision set'))
3830 raise error.Abort(_('empty revision set'))
3830 nodes = [repo[r].node() for r in revs]
3831 nodes = [repo[r].node() for r in revs]
3831 # moving revision from public to draft may hide them
3832 # moving revision from public to draft may hide them
3832 # We have to check result on an unfiltered repository
3833 # We have to check result on an unfiltered repository
3833 unfi = repo.unfiltered()
3834 unfi = repo.unfiltered()
3834 getphase = unfi._phasecache.phase
3835 getphase = unfi._phasecache.phase
3835 olddata = [getphase(unfi, r) for r in unfi]
3836 olddata = [getphase(unfi, r) for r in unfi]
3836 phases.advanceboundary(repo, tr, targetphase, nodes)
3837 phases.advanceboundary(repo, tr, targetphase, nodes)
3837 if opts['force']:
3838 if opts['force']:
3838 phases.retractboundary(repo, tr, targetphase, nodes)
3839 phases.retractboundary(repo, tr, targetphase, nodes)
3839 tr.close()
3840 tr.close()
3840 finally:
3841 finally:
3841 if tr is not None:
3842 if tr is not None:
3842 tr.release()
3843 tr.release()
3843 lock.release()
3844 lock.release()
3844 getphase = unfi._phasecache.phase
3845 getphase = unfi._phasecache.phase
3845 newdata = [getphase(unfi, r) for r in unfi]
3846 newdata = [getphase(unfi, r) for r in unfi]
3846 changes = sum(newdata[r] != olddata[r] for r in unfi)
3847 changes = sum(newdata[r] != olddata[r] for r in unfi)
3847 cl = unfi.changelog
3848 cl = unfi.changelog
3848 rejected = [n for n in nodes
3849 rejected = [n for n in nodes
3849 if newdata[cl.rev(n)] < targetphase]
3850 if newdata[cl.rev(n)] < targetphase]
3850 if rejected:
3851 if rejected:
3851 ui.warn(_('cannot move %i changesets to a higher '
3852 ui.warn(_('cannot move %i changesets to a higher '
3852 'phase, use --force\n') % len(rejected))
3853 'phase, use --force\n') % len(rejected))
3853 ret = 1
3854 ret = 1
3854 if changes:
3855 if changes:
3855 msg = _('phase changed for %i changesets\n') % changes
3856 msg = _('phase changed for %i changesets\n') % changes
3856 if ret:
3857 if ret:
3857 ui.status(msg)
3858 ui.status(msg)
3858 else:
3859 else:
3859 ui.note(msg)
3860 ui.note(msg)
3860 else:
3861 else:
3861 ui.warn(_('no phases changed\n'))
3862 ui.warn(_('no phases changed\n'))
3862 return ret
3863 return ret
3863
3864
3864 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
3865 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
3865 """Run after a changegroup has been added via pull/unbundle
3866 """Run after a changegroup has been added via pull/unbundle
3866
3867
3867 This takes arguments below:
3868 This takes arguments below:
3868
3869
3869 :modheads: change of heads by pull/unbundle
3870 :modheads: change of heads by pull/unbundle
3870 :optupdate: updating working directory is needed or not
3871 :optupdate: updating working directory is needed or not
3871 :checkout: update destination revision (or None to default destination)
3872 :checkout: update destination revision (or None to default destination)
3872 :brev: a name, which might be a bookmark to be activated after updating
3873 :brev: a name, which might be a bookmark to be activated after updating
3873 """
3874 """
3874 if modheads == 0:
3875 if modheads == 0:
3875 return
3876 return
3876 if optupdate:
3877 if optupdate:
3877 try:
3878 try:
3878 return hg.updatetotally(ui, repo, checkout, brev)
3879 return hg.updatetotally(ui, repo, checkout, brev)
3879 except error.UpdateAbort as inst:
3880 except error.UpdateAbort as inst:
3880 msg = _("not updating: %s") % str(inst)
3881 msg = _("not updating: %s") % str(inst)
3881 hint = inst.hint
3882 hint = inst.hint
3882 raise error.UpdateAbort(msg, hint=hint)
3883 raise error.UpdateAbort(msg, hint=hint)
3883 if modheads > 1:
3884 if modheads > 1:
3884 currentbranchheads = len(repo.branchheads())
3885 currentbranchheads = len(repo.branchheads())
3885 if currentbranchheads == modheads:
3886 if currentbranchheads == modheads:
3886 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
3887 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
3887 elif currentbranchheads > 1:
3888 elif currentbranchheads > 1:
3888 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
3889 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
3889 "merge)\n"))
3890 "merge)\n"))
3890 else:
3891 else:
3891 ui.status(_("(run 'hg heads' to see heads)\n"))
3892 ui.status(_("(run 'hg heads' to see heads)\n"))
3892 else:
3893 else:
3893 ui.status(_("(run 'hg update' to get a working copy)\n"))
3894 ui.status(_("(run 'hg update' to get a working copy)\n"))
3894
3895
3895 @command('^pull',
3896 @command('^pull',
3896 [('u', 'update', None,
3897 [('u', 'update', None,
3897 _('update to new branch head if changesets were pulled')),
3898 _('update to new branch head if changesets were pulled')),
3898 ('f', 'force', None, _('run even when remote repository is unrelated')),
3899 ('f', 'force', None, _('run even when remote repository is unrelated')),
3899 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3900 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3900 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
3901 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
3901 ('b', 'branch', [], _('a specific branch you would like to pull'),
3902 ('b', 'branch', [], _('a specific branch you would like to pull'),
3902 _('BRANCH')),
3903 _('BRANCH')),
3903 ] + remoteopts,
3904 ] + remoteopts,
3904 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
3905 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
3905 def pull(ui, repo, source="default", **opts):
3906 def pull(ui, repo, source="default", **opts):
3906 """pull changes from the specified source
3907 """pull changes from the specified source
3907
3908
3908 Pull changes from a remote repository to a local one.
3909 Pull changes from a remote repository to a local one.
3909
3910
3910 This finds all changes from the repository at the specified path
3911 This finds all changes from the repository at the specified path
3911 or URL and adds them to a local repository (the current one unless
3912 or URL and adds them to a local repository (the current one unless
3912 -R is specified). By default, this does not update the copy of the
3913 -R is specified). By default, this does not update the copy of the
3913 project in the working directory.
3914 project in the working directory.
3914
3915
3915 Use :hg:`incoming` if you want to see what would have been added
3916 Use :hg:`incoming` if you want to see what would have been added
3916 by a pull at the time you issued this command. If you then decide
3917 by a pull at the time you issued this command. If you then decide
3917 to add those changes to the repository, you should use :hg:`pull
3918 to add those changes to the repository, you should use :hg:`pull
3918 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
3919 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
3919
3920
3920 If SOURCE is omitted, the 'default' path will be used.
3921 If SOURCE is omitted, the 'default' path will be used.
3921 See :hg:`help urls` for more information.
3922 See :hg:`help urls` for more information.
3922
3923
3923 Specifying bookmark as ``.`` is equivalent to specifying the active
3924 Specifying bookmark as ``.`` is equivalent to specifying the active
3924 bookmark's name.
3925 bookmark's name.
3925
3926
3926 Returns 0 on success, 1 if an update had unresolved files.
3927 Returns 0 on success, 1 if an update had unresolved files.
3927 """
3928 """
3928 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
3929 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
3929 ui.status(_('pulling from %s\n') % util.hidepassword(source))
3930 ui.status(_('pulling from %s\n') % util.hidepassword(source))
3930 other = hg.peer(repo, opts, source)
3931 other = hg.peer(repo, opts, source)
3931 try:
3932 try:
3932 revs, checkout = hg.addbranchrevs(repo, other, branches,
3933 revs, checkout = hg.addbranchrevs(repo, other, branches,
3933 opts.get('rev'))
3934 opts.get('rev'))
3934
3935
3935
3936
3936 pullopargs = {}
3937 pullopargs = {}
3937 if opts.get('bookmark'):
3938 if opts.get('bookmark'):
3938 if not revs:
3939 if not revs:
3939 revs = []
3940 revs = []
3940 # The list of bookmark used here is not the one used to actually
3941 # The list of bookmark used here is not the one used to actually
3941 # update the bookmark name. This can result in the revision pulled
3942 # update the bookmark name. This can result in the revision pulled
3942 # not ending up with the name of the bookmark because of a race
3943 # not ending up with the name of the bookmark because of a race
3943 # condition on the server. (See issue 4689 for details)
3944 # condition on the server. (See issue 4689 for details)
3944 remotebookmarks = other.listkeys('bookmarks')
3945 remotebookmarks = other.listkeys('bookmarks')
3945 pullopargs['remotebookmarks'] = remotebookmarks
3946 pullopargs['remotebookmarks'] = remotebookmarks
3946 for b in opts['bookmark']:
3947 for b in opts['bookmark']:
3947 b = repo._bookmarks.expandname(b)
3948 b = repo._bookmarks.expandname(b)
3948 if b not in remotebookmarks:
3949 if b not in remotebookmarks:
3949 raise error.Abort(_('remote bookmark %s not found!') % b)
3950 raise error.Abort(_('remote bookmark %s not found!') % b)
3950 revs.append(remotebookmarks[b])
3951 revs.append(remotebookmarks[b])
3951
3952
3952 if revs:
3953 if revs:
3953 try:
3954 try:
3954 # When 'rev' is a bookmark name, we cannot guarantee that it
3955 # When 'rev' is a bookmark name, we cannot guarantee that it
3955 # will be updated with that name because of a race condition
3956 # will be updated with that name because of a race condition
3956 # server side. (See issue 4689 for details)
3957 # server side. (See issue 4689 for details)
3957 oldrevs = revs
3958 oldrevs = revs
3958 revs = [] # actually, nodes
3959 revs = [] # actually, nodes
3959 for r in oldrevs:
3960 for r in oldrevs:
3960 node = other.lookup(r)
3961 node = other.lookup(r)
3961 revs.append(node)
3962 revs.append(node)
3962 if r == checkout:
3963 if r == checkout:
3963 checkout = node
3964 checkout = node
3964 except error.CapabilityError:
3965 except error.CapabilityError:
3965 err = _("other repository doesn't support revision lookup, "
3966 err = _("other repository doesn't support revision lookup, "
3966 "so a rev cannot be specified.")
3967 "so a rev cannot be specified.")
3967 raise error.Abort(err)
3968 raise error.Abort(err)
3968
3969
3969 pullopargs.update(opts.get('opargs', {}))
3970 pullopargs.update(opts.get('opargs', {}))
3970 modheads = exchange.pull(repo, other, heads=revs,
3971 modheads = exchange.pull(repo, other, heads=revs,
3971 force=opts.get('force'),
3972 force=opts.get('force'),
3972 bookmarks=opts.get('bookmark', ()),
3973 bookmarks=opts.get('bookmark', ()),
3973 opargs=pullopargs).cgresult
3974 opargs=pullopargs).cgresult
3974
3975
3975 # brev is a name, which might be a bookmark to be activated at
3976 # brev is a name, which might be a bookmark to be activated at
3976 # the end of the update. In other words, it is an explicit
3977 # the end of the update. In other words, it is an explicit
3977 # destination of the update
3978 # destination of the update
3978 brev = None
3979 brev = None
3979
3980
3980 if checkout:
3981 if checkout:
3981 checkout = str(repo.changelog.rev(checkout))
3982 checkout = str(repo.changelog.rev(checkout))
3982
3983
3983 # order below depends on implementation of
3984 # order below depends on implementation of
3984 # hg.addbranchrevs(). opts['bookmark'] is ignored,
3985 # hg.addbranchrevs(). opts['bookmark'] is ignored,
3985 # because 'checkout' is determined without it.
3986 # because 'checkout' is determined without it.
3986 if opts.get('rev'):
3987 if opts.get('rev'):
3987 brev = opts['rev'][0]
3988 brev = opts['rev'][0]
3988 elif opts.get('branch'):
3989 elif opts.get('branch'):
3989 brev = opts['branch'][0]
3990 brev = opts['branch'][0]
3990 else:
3991 else:
3991 brev = branches[0]
3992 brev = branches[0]
3992 repo._subtoppath = source
3993 repo._subtoppath = source
3993 try:
3994 try:
3994 ret = postincoming(ui, repo, modheads, opts.get('update'),
3995 ret = postincoming(ui, repo, modheads, opts.get('update'),
3995 checkout, brev)
3996 checkout, brev)
3996
3997
3997 finally:
3998 finally:
3998 del repo._subtoppath
3999 del repo._subtoppath
3999
4000
4000 finally:
4001 finally:
4001 other.close()
4002 other.close()
4002 return ret
4003 return ret
4003
4004
4004 @command('^push',
4005 @command('^push',
4005 [('f', 'force', None, _('force push')),
4006 [('f', 'force', None, _('force push')),
4006 ('r', 'rev', [],
4007 ('r', 'rev', [],
4007 _('a changeset intended to be included in the destination'),
4008 _('a changeset intended to be included in the destination'),
4008 _('REV')),
4009 _('REV')),
4009 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4010 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4010 ('b', 'branch', [],
4011 ('b', 'branch', [],
4011 _('a specific branch you would like to push'), _('BRANCH')),
4012 _('a specific branch you would like to push'), _('BRANCH')),
4012 ('', 'new-branch', False, _('allow pushing a new branch')),
4013 ('', 'new-branch', False, _('allow pushing a new branch')),
4013 ] + remoteopts,
4014 ] + remoteopts,
4014 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4015 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4015 def push(ui, repo, dest=None, **opts):
4016 def push(ui, repo, dest=None, **opts):
4016 """push changes to the specified destination
4017 """push changes to the specified destination
4017
4018
4018 Push changesets from the local repository to the specified
4019 Push changesets from the local repository to the specified
4019 destination.
4020 destination.
4020
4021
4021 This operation is symmetrical to pull: it is identical to a pull
4022 This operation is symmetrical to pull: it is identical to a pull
4022 in the destination repository from the current one.
4023 in the destination repository from the current one.
4023
4024
4024 By default, push will not allow creation of new heads at the
4025 By default, push will not allow creation of new heads at the
4025 destination, since multiple heads would make it unclear which head
4026 destination, since multiple heads would make it unclear which head
4026 to use. In this situation, it is recommended to pull and merge
4027 to use. In this situation, it is recommended to pull and merge
4027 before pushing.
4028 before pushing.
4028
4029
4029 Use --new-branch if you want to allow push to create a new named
4030 Use --new-branch if you want to allow push to create a new named
4030 branch that is not present at the destination. This allows you to
4031 branch that is not present at the destination. This allows you to
4031 only create a new branch without forcing other changes.
4032 only create a new branch without forcing other changes.
4032
4033
4033 .. note::
4034 .. note::
4034
4035
4035 Extra care should be taken with the -f/--force option,
4036 Extra care should be taken with the -f/--force option,
4036 which will push all new heads on all branches, an action which will
4037 which will push all new heads on all branches, an action which will
4037 almost always cause confusion for collaborators.
4038 almost always cause confusion for collaborators.
4038
4039
4039 If -r/--rev is used, the specified revision and all its ancestors
4040 If -r/--rev is used, the specified revision and all its ancestors
4040 will be pushed to the remote repository.
4041 will be pushed to the remote repository.
4041
4042
4042 If -B/--bookmark is used, the specified bookmarked revision, its
4043 If -B/--bookmark is used, the specified bookmarked revision, its
4043 ancestors, and the bookmark will be pushed to the remote
4044 ancestors, and the bookmark will be pushed to the remote
4044 repository. Specifying ``.`` is equivalent to specifying the active
4045 repository. Specifying ``.`` is equivalent to specifying the active
4045 bookmark's name.
4046 bookmark's name.
4046
4047
4047 Please see :hg:`help urls` for important details about ``ssh://``
4048 Please see :hg:`help urls` for important details about ``ssh://``
4048 URLs. If DESTINATION is omitted, a default path will be used.
4049 URLs. If DESTINATION is omitted, a default path will be used.
4049
4050
4050 Returns 0 if push was successful, 1 if nothing to push.
4051 Returns 0 if push was successful, 1 if nothing to push.
4051 """
4052 """
4052
4053
4053 if opts.get('bookmark'):
4054 if opts.get('bookmark'):
4054 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
4055 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
4055 for b in opts['bookmark']:
4056 for b in opts['bookmark']:
4056 # translate -B options to -r so changesets get pushed
4057 # translate -B options to -r so changesets get pushed
4057 b = repo._bookmarks.expandname(b)
4058 b = repo._bookmarks.expandname(b)
4058 if b in repo._bookmarks:
4059 if b in repo._bookmarks:
4059 opts.setdefault('rev', []).append(b)
4060 opts.setdefault('rev', []).append(b)
4060 else:
4061 else:
4061 # if we try to push a deleted bookmark, translate it to null
4062 # if we try to push a deleted bookmark, translate it to null
4062 # this lets simultaneous -r, -b options continue working
4063 # this lets simultaneous -r, -b options continue working
4063 opts.setdefault('rev', []).append("null")
4064 opts.setdefault('rev', []).append("null")
4064
4065
4065 path = ui.paths.getpath(dest, default=('default-push', 'default'))
4066 path = ui.paths.getpath(dest, default=('default-push', 'default'))
4066 if not path:
4067 if not path:
4067 raise error.Abort(_('default repository not configured!'),
4068 raise error.Abort(_('default repository not configured!'),
4068 hint=_("see 'hg help config.paths'"))
4069 hint=_("see 'hg help config.paths'"))
4069 dest = path.pushloc or path.loc
4070 dest = path.pushloc or path.loc
4070 branches = (path.branch, opts.get('branch') or [])
4071 branches = (path.branch, opts.get('branch') or [])
4071 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4072 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4072 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4073 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4073 other = hg.peer(repo, opts, dest)
4074 other = hg.peer(repo, opts, dest)
4074
4075
4075 if revs:
4076 if revs:
4076 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4077 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4077 if not revs:
4078 if not revs:
4078 raise error.Abort(_("specified revisions evaluate to an empty set"),
4079 raise error.Abort(_("specified revisions evaluate to an empty set"),
4079 hint=_("use different revision arguments"))
4080 hint=_("use different revision arguments"))
4080 elif path.pushrev:
4081 elif path.pushrev:
4081 # It doesn't make any sense to specify ancestor revisions. So limit
4082 # It doesn't make any sense to specify ancestor revisions. So limit
4082 # to DAG heads to make discovery simpler.
4083 # to DAG heads to make discovery simpler.
4083 expr = revsetlang.formatspec('heads(%r)', path.pushrev)
4084 expr = revsetlang.formatspec('heads(%r)', path.pushrev)
4084 revs = scmutil.revrange(repo, [expr])
4085 revs = scmutil.revrange(repo, [expr])
4085 revs = [repo[rev].node() for rev in revs]
4086 revs = [repo[rev].node() for rev in revs]
4086 if not revs:
4087 if not revs:
4087 raise error.Abort(_('default push revset for path evaluates to an '
4088 raise error.Abort(_('default push revset for path evaluates to an '
4088 'empty set'))
4089 'empty set'))
4089
4090
4090 repo._subtoppath = dest
4091 repo._subtoppath = dest
4091 try:
4092 try:
4092 # push subrepos depth-first for coherent ordering
4093 # push subrepos depth-first for coherent ordering
4093 c = repo['']
4094 c = repo['']
4094 subs = c.substate # only repos that are committed
4095 subs = c.substate # only repos that are committed
4095 for s in sorted(subs):
4096 for s in sorted(subs):
4096 result = c.sub(s).push(opts)
4097 result = c.sub(s).push(opts)
4097 if result == 0:
4098 if result == 0:
4098 return not result
4099 return not result
4099 finally:
4100 finally:
4100 del repo._subtoppath
4101 del repo._subtoppath
4101 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
4102 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
4102 newbranch=opts.get('new_branch'),
4103 newbranch=opts.get('new_branch'),
4103 bookmarks=opts.get('bookmark', ()),
4104 bookmarks=opts.get('bookmark', ()),
4104 opargs=opts.get('opargs'))
4105 opargs=opts.get('opargs'))
4105
4106
4106 result = not pushop.cgresult
4107 result = not pushop.cgresult
4107
4108
4108 if pushop.bkresult is not None:
4109 if pushop.bkresult is not None:
4109 if pushop.bkresult == 2:
4110 if pushop.bkresult == 2:
4110 result = 2
4111 result = 2
4111 elif not result and pushop.bkresult:
4112 elif not result and pushop.bkresult:
4112 result = 2
4113 result = 2
4113
4114
4114 return result
4115 return result
4115
4116
4116 @command('recover', [])
4117 @command('recover', [])
4117 def recover(ui, repo):
4118 def recover(ui, repo):
4118 """roll back an interrupted transaction
4119 """roll back an interrupted transaction
4119
4120
4120 Recover from an interrupted commit or pull.
4121 Recover from an interrupted commit or pull.
4121
4122
4122 This command tries to fix the repository status after an
4123 This command tries to fix the repository status after an
4123 interrupted operation. It should only be necessary when Mercurial
4124 interrupted operation. It should only be necessary when Mercurial
4124 suggests it.
4125 suggests it.
4125
4126
4126 Returns 0 if successful, 1 if nothing to recover or verify fails.
4127 Returns 0 if successful, 1 if nothing to recover or verify fails.
4127 """
4128 """
4128 if repo.recover():
4129 if repo.recover():
4129 return hg.verify(repo)
4130 return hg.verify(repo)
4130 return 1
4131 return 1
4131
4132
4132 @command('^remove|rm',
4133 @command('^remove|rm',
4133 [('A', 'after', None, _('record delete for missing files')),
4134 [('A', 'after', None, _('record delete for missing files')),
4134 ('f', 'force', None,
4135 ('f', 'force', None,
4135 _('forget added files, delete modified files')),
4136 _('forget added files, delete modified files')),
4136 ] + subrepoopts + walkopts,
4137 ] + subrepoopts + walkopts,
4137 _('[OPTION]... FILE...'),
4138 _('[OPTION]... FILE...'),
4138 inferrepo=True)
4139 inferrepo=True)
4139 def remove(ui, repo, *pats, **opts):
4140 def remove(ui, repo, *pats, **opts):
4140 """remove the specified files on the next commit
4141 """remove the specified files on the next commit
4141
4142
4142 Schedule the indicated files for removal from the current branch.
4143 Schedule the indicated files for removal from the current branch.
4143
4144
4144 This command schedules the files to be removed at the next commit.
4145 This command schedules the files to be removed at the next commit.
4145 To undo a remove before that, see :hg:`revert`. To undo added
4146 To undo a remove before that, see :hg:`revert`. To undo added
4146 files, see :hg:`forget`.
4147 files, see :hg:`forget`.
4147
4148
4148 .. container:: verbose
4149 .. container:: verbose
4149
4150
4150 -A/--after can be used to remove only files that have already
4151 -A/--after can be used to remove only files that have already
4151 been deleted, -f/--force can be used to force deletion, and -Af
4152 been deleted, -f/--force can be used to force deletion, and -Af
4152 can be used to remove files from the next revision without
4153 can be used to remove files from the next revision without
4153 deleting them from the working directory.
4154 deleting them from the working directory.
4154
4155
4155 The following table details the behavior of remove for different
4156 The following table details the behavior of remove for different
4156 file states (columns) and option combinations (rows). The file
4157 file states (columns) and option combinations (rows). The file
4157 states are Added [A], Clean [C], Modified [M] and Missing [!]
4158 states are Added [A], Clean [C], Modified [M] and Missing [!]
4158 (as reported by :hg:`status`). The actions are Warn, Remove
4159 (as reported by :hg:`status`). The actions are Warn, Remove
4159 (from branch) and Delete (from disk):
4160 (from branch) and Delete (from disk):
4160
4161
4161 ========= == == == ==
4162 ========= == == == ==
4162 opt/state A C M !
4163 opt/state A C M !
4163 ========= == == == ==
4164 ========= == == == ==
4164 none W RD W R
4165 none W RD W R
4165 -f R RD RD R
4166 -f R RD RD R
4166 -A W W W R
4167 -A W W W R
4167 -Af R R R R
4168 -Af R R R R
4168 ========= == == == ==
4169 ========= == == == ==
4169
4170
4170 .. note::
4171 .. note::
4171
4172
4172 :hg:`remove` never deletes files in Added [A] state from the
4173 :hg:`remove` never deletes files in Added [A] state from the
4173 working directory, not even if ``--force`` is specified.
4174 working directory, not even if ``--force`` is specified.
4174
4175
4175 Returns 0 on success, 1 if any warnings encountered.
4176 Returns 0 on success, 1 if any warnings encountered.
4176 """
4177 """
4177
4178
4178 after, force = opts.get('after'), opts.get('force')
4179 after, force = opts.get('after'), opts.get('force')
4179 if not pats and not after:
4180 if not pats and not after:
4180 raise error.Abort(_('no files specified'))
4181 raise error.Abort(_('no files specified'))
4181
4182
4182 m = scmutil.match(repo[None], pats, opts)
4183 m = scmutil.match(repo[None], pats, opts)
4183 subrepos = opts.get('subrepos')
4184 subrepos = opts.get('subrepos')
4184 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
4185 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
4185
4186
4186 @command('rename|move|mv',
4187 @command('rename|move|mv',
4187 [('A', 'after', None, _('record a rename that has already occurred')),
4188 [('A', 'after', None, _('record a rename that has already occurred')),
4188 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4189 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4189 ] + walkopts + dryrunopts,
4190 ] + walkopts + dryrunopts,
4190 _('[OPTION]... SOURCE... DEST'))
4191 _('[OPTION]... SOURCE... DEST'))
4191 def rename(ui, repo, *pats, **opts):
4192 def rename(ui, repo, *pats, **opts):
4192 """rename files; equivalent of copy + remove
4193 """rename files; equivalent of copy + remove
4193
4194
4194 Mark dest as copies of sources; mark sources for deletion. If dest
4195 Mark dest as copies of sources; mark sources for deletion. If dest
4195 is a directory, copies are put in that directory. If dest is a
4196 is a directory, copies are put in that directory. If dest is a
4196 file, there can only be one source.
4197 file, there can only be one source.
4197
4198
4198 By default, this command copies the contents of files as they
4199 By default, this command copies the contents of files as they
4199 exist in the working directory. If invoked with -A/--after, the
4200 exist in the working directory. If invoked with -A/--after, the
4200 operation is recorded, but no copying is performed.
4201 operation is recorded, but no copying is performed.
4201
4202
4202 This command takes effect at the next commit. To undo a rename
4203 This command takes effect at the next commit. To undo a rename
4203 before that, see :hg:`revert`.
4204 before that, see :hg:`revert`.
4204
4205
4205 Returns 0 on success, 1 if errors are encountered.
4206 Returns 0 on success, 1 if errors are encountered.
4206 """
4207 """
4207 with repo.wlock(False):
4208 with repo.wlock(False):
4208 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4209 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4209
4210
4210 @command('resolve',
4211 @command('resolve',
4211 [('a', 'all', None, _('select all unresolved files')),
4212 [('a', 'all', None, _('select all unresolved files')),
4212 ('l', 'list', None, _('list state of files needing merge')),
4213 ('l', 'list', None, _('list state of files needing merge')),
4213 ('m', 'mark', None, _('mark files as resolved')),
4214 ('m', 'mark', None, _('mark files as resolved')),
4214 ('u', 'unmark', None, _('mark files as unresolved')),
4215 ('u', 'unmark', None, _('mark files as unresolved')),
4215 ('n', 'no-status', None, _('hide status prefix'))]
4216 ('n', 'no-status', None, _('hide status prefix'))]
4216 + mergetoolopts + walkopts + formatteropts,
4217 + mergetoolopts + walkopts + formatteropts,
4217 _('[OPTION]... [FILE]...'),
4218 _('[OPTION]... [FILE]...'),
4218 inferrepo=True)
4219 inferrepo=True)
4219 def resolve(ui, repo, *pats, **opts):
4220 def resolve(ui, repo, *pats, **opts):
4220 """redo merges or set/view the merge status of files
4221 """redo merges or set/view the merge status of files
4221
4222
4222 Merges with unresolved conflicts are often the result of
4223 Merges with unresolved conflicts are often the result of
4223 non-interactive merging using the ``internal:merge`` configuration
4224 non-interactive merging using the ``internal:merge`` configuration
4224 setting, or a command-line merge tool like ``diff3``. The resolve
4225 setting, or a command-line merge tool like ``diff3``. The resolve
4225 command is used to manage the files involved in a merge, after
4226 command is used to manage the files involved in a merge, after
4226 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4227 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4227 working directory must have two parents). See :hg:`help
4228 working directory must have two parents). See :hg:`help
4228 merge-tools` for information on configuring merge tools.
4229 merge-tools` for information on configuring merge tools.
4229
4230
4230 The resolve command can be used in the following ways:
4231 The resolve command can be used in the following ways:
4231
4232
4232 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4233 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4233 files, discarding any previous merge attempts. Re-merging is not
4234 files, discarding any previous merge attempts. Re-merging is not
4234 performed for files already marked as resolved. Use ``--all/-a``
4235 performed for files already marked as resolved. Use ``--all/-a``
4235 to select all unresolved files. ``--tool`` can be used to specify
4236 to select all unresolved files. ``--tool`` can be used to specify
4236 the merge tool used for the given files. It overrides the HGMERGE
4237 the merge tool used for the given files. It overrides the HGMERGE
4237 environment variable and your configuration files. Previous file
4238 environment variable and your configuration files. Previous file
4238 contents are saved with a ``.orig`` suffix.
4239 contents are saved with a ``.orig`` suffix.
4239
4240
4240 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4241 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4241 (e.g. after having manually fixed-up the files). The default is
4242 (e.g. after having manually fixed-up the files). The default is
4242 to mark all unresolved files.
4243 to mark all unresolved files.
4243
4244
4244 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4245 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4245 default is to mark all resolved files.
4246 default is to mark all resolved files.
4246
4247
4247 - :hg:`resolve -l`: list files which had or still have conflicts.
4248 - :hg:`resolve -l`: list files which had or still have conflicts.
4248 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4249 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4249 You can use ``set:unresolved()`` or ``set:resolved()`` to filter
4250 You can use ``set:unresolved()`` or ``set:resolved()`` to filter
4250 the list. See :hg:`help filesets` for details.
4251 the list. See :hg:`help filesets` for details.
4251
4252
4252 .. note::
4253 .. note::
4253
4254
4254 Mercurial will not let you commit files with unresolved merge
4255 Mercurial will not let you commit files with unresolved merge
4255 conflicts. You must use :hg:`resolve -m ...` before you can
4256 conflicts. You must use :hg:`resolve -m ...` before you can
4256 commit after a conflicting merge.
4257 commit after a conflicting merge.
4257
4258
4258 Returns 0 on success, 1 if any files fail a resolve attempt.
4259 Returns 0 on success, 1 if any files fail a resolve attempt.
4259 """
4260 """
4260
4261
4261 flaglist = 'all mark unmark list no_status'.split()
4262 flaglist = 'all mark unmark list no_status'.split()
4262 all, mark, unmark, show, nostatus = \
4263 all, mark, unmark, show, nostatus = \
4263 [opts.get(o) for o in flaglist]
4264 [opts.get(o) for o in flaglist]
4264
4265
4265 if (show and (mark or unmark)) or (mark and unmark):
4266 if (show and (mark or unmark)) or (mark and unmark):
4266 raise error.Abort(_("too many options specified"))
4267 raise error.Abort(_("too many options specified"))
4267 if pats and all:
4268 if pats and all:
4268 raise error.Abort(_("can't specify --all and patterns"))
4269 raise error.Abort(_("can't specify --all and patterns"))
4269 if not (all or pats or show or mark or unmark):
4270 if not (all or pats or show or mark or unmark):
4270 raise error.Abort(_('no files or directories specified'),
4271 raise error.Abort(_('no files or directories specified'),
4271 hint=('use --all to re-merge all unresolved files'))
4272 hint=('use --all to re-merge all unresolved files'))
4272
4273
4273 if show:
4274 if show:
4274 ui.pager('resolve')
4275 ui.pager('resolve')
4275 fm = ui.formatter('resolve', opts)
4276 fm = ui.formatter('resolve', opts)
4276 ms = mergemod.mergestate.read(repo)
4277 ms = mergemod.mergestate.read(repo)
4277 m = scmutil.match(repo[None], pats, opts)
4278 m = scmutil.match(repo[None], pats, opts)
4278 for f in ms:
4279 for f in ms:
4279 if not m(f):
4280 if not m(f):
4280 continue
4281 continue
4281 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
4282 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
4282 'd': 'driverresolved'}[ms[f]]
4283 'd': 'driverresolved'}[ms[f]]
4283 fm.startitem()
4284 fm.startitem()
4284 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
4285 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
4285 fm.write('path', '%s\n', f, label=l)
4286 fm.write('path', '%s\n', f, label=l)
4286 fm.end()
4287 fm.end()
4287 return 0
4288 return 0
4288
4289
4289 with repo.wlock():
4290 with repo.wlock():
4290 ms = mergemod.mergestate.read(repo)
4291 ms = mergemod.mergestate.read(repo)
4291
4292
4292 if not (ms.active() or repo.dirstate.p2() != nullid):
4293 if not (ms.active() or repo.dirstate.p2() != nullid):
4293 raise error.Abort(
4294 raise error.Abort(
4294 _('resolve command not applicable when not merging'))
4295 _('resolve command not applicable when not merging'))
4295
4296
4296 wctx = repo[None]
4297 wctx = repo[None]
4297
4298
4298 if ms.mergedriver and ms.mdstate() == 'u':
4299 if ms.mergedriver and ms.mdstate() == 'u':
4299 proceed = mergemod.driverpreprocess(repo, ms, wctx)
4300 proceed = mergemod.driverpreprocess(repo, ms, wctx)
4300 ms.commit()
4301 ms.commit()
4301 # allow mark and unmark to go through
4302 # allow mark and unmark to go through
4302 if not mark and not unmark and not proceed:
4303 if not mark and not unmark and not proceed:
4303 return 1
4304 return 1
4304
4305
4305 m = scmutil.match(wctx, pats, opts)
4306 m = scmutil.match(wctx, pats, opts)
4306 ret = 0
4307 ret = 0
4307 didwork = False
4308 didwork = False
4308 runconclude = False
4309 runconclude = False
4309
4310
4310 tocomplete = []
4311 tocomplete = []
4311 for f in ms:
4312 for f in ms:
4312 if not m(f):
4313 if not m(f):
4313 continue
4314 continue
4314
4315
4315 didwork = True
4316 didwork = True
4316
4317
4317 # don't let driver-resolved files be marked, and run the conclude
4318 # don't let driver-resolved files be marked, and run the conclude
4318 # step if asked to resolve
4319 # step if asked to resolve
4319 if ms[f] == "d":
4320 if ms[f] == "d":
4320 exact = m.exact(f)
4321 exact = m.exact(f)
4321 if mark:
4322 if mark:
4322 if exact:
4323 if exact:
4323 ui.warn(_('not marking %s as it is driver-resolved\n')
4324 ui.warn(_('not marking %s as it is driver-resolved\n')
4324 % f)
4325 % f)
4325 elif unmark:
4326 elif unmark:
4326 if exact:
4327 if exact:
4327 ui.warn(_('not unmarking %s as it is driver-resolved\n')
4328 ui.warn(_('not unmarking %s as it is driver-resolved\n')
4328 % f)
4329 % f)
4329 else:
4330 else:
4330 runconclude = True
4331 runconclude = True
4331 continue
4332 continue
4332
4333
4333 if mark:
4334 if mark:
4334 ms.mark(f, "r")
4335 ms.mark(f, "r")
4335 elif unmark:
4336 elif unmark:
4336 ms.mark(f, "u")
4337 ms.mark(f, "u")
4337 else:
4338 else:
4338 # backup pre-resolve (merge uses .orig for its own purposes)
4339 # backup pre-resolve (merge uses .orig for its own purposes)
4339 a = repo.wjoin(f)
4340 a = repo.wjoin(f)
4340 try:
4341 try:
4341 util.copyfile(a, a + ".resolve")
4342 util.copyfile(a, a + ".resolve")
4342 except (IOError, OSError) as inst:
4343 except (IOError, OSError) as inst:
4343 if inst.errno != errno.ENOENT:
4344 if inst.errno != errno.ENOENT:
4344 raise
4345 raise
4345
4346
4346 try:
4347 try:
4347 # preresolve file
4348 # preresolve file
4348 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4349 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4349 'resolve')
4350 'resolve')
4350 complete, r = ms.preresolve(f, wctx)
4351 complete, r = ms.preresolve(f, wctx)
4351 if not complete:
4352 if not complete:
4352 tocomplete.append(f)
4353 tocomplete.append(f)
4353 elif r:
4354 elif r:
4354 ret = 1
4355 ret = 1
4355 finally:
4356 finally:
4356 ui.setconfig('ui', 'forcemerge', '', 'resolve')
4357 ui.setconfig('ui', 'forcemerge', '', 'resolve')
4357 ms.commit()
4358 ms.commit()
4358
4359
4359 # replace filemerge's .orig file with our resolve file, but only
4360 # replace filemerge's .orig file with our resolve file, but only
4360 # for merges that are complete
4361 # for merges that are complete
4361 if complete:
4362 if complete:
4362 try:
4363 try:
4363 util.rename(a + ".resolve",
4364 util.rename(a + ".resolve",
4364 scmutil.origpath(ui, repo, a))
4365 scmutil.origpath(ui, repo, a))
4365 except OSError as inst:
4366 except OSError as inst:
4366 if inst.errno != errno.ENOENT:
4367 if inst.errno != errno.ENOENT:
4367 raise
4368 raise
4368
4369
4369 for f in tocomplete:
4370 for f in tocomplete:
4370 try:
4371 try:
4371 # resolve file
4372 # resolve file
4372 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4373 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4373 'resolve')
4374 'resolve')
4374 r = ms.resolve(f, wctx)
4375 r = ms.resolve(f, wctx)
4375 if r:
4376 if r:
4376 ret = 1
4377 ret = 1
4377 finally:
4378 finally:
4378 ui.setconfig('ui', 'forcemerge', '', 'resolve')
4379 ui.setconfig('ui', 'forcemerge', '', 'resolve')
4379 ms.commit()
4380 ms.commit()
4380
4381
4381 # replace filemerge's .orig file with our resolve file
4382 # replace filemerge's .orig file with our resolve file
4382 a = repo.wjoin(f)
4383 a = repo.wjoin(f)
4383 try:
4384 try:
4384 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
4385 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
4385 except OSError as inst:
4386 except OSError as inst:
4386 if inst.errno != errno.ENOENT:
4387 if inst.errno != errno.ENOENT:
4387 raise
4388 raise
4388
4389
4389 ms.commit()
4390 ms.commit()
4390 ms.recordactions()
4391 ms.recordactions()
4391
4392
4392 if not didwork and pats:
4393 if not didwork and pats:
4393 hint = None
4394 hint = None
4394 if not any([p for p in pats if p.find(':') >= 0]):
4395 if not any([p for p in pats if p.find(':') >= 0]):
4395 pats = ['path:%s' % p for p in pats]
4396 pats = ['path:%s' % p for p in pats]
4396 m = scmutil.match(wctx, pats, opts)
4397 m = scmutil.match(wctx, pats, opts)
4397 for f in ms:
4398 for f in ms:
4398 if not m(f):
4399 if not m(f):
4399 continue
4400 continue
4400 flags = ''.join(['-%s ' % o[0] for o in flaglist
4401 flags = ''.join(['-%s ' % o[0] for o in flaglist
4401 if opts.get(o)])
4402 if opts.get(o)])
4402 hint = _("(try: hg resolve %s%s)\n") % (
4403 hint = _("(try: hg resolve %s%s)\n") % (
4403 flags,
4404 flags,
4404 ' '.join(pats))
4405 ' '.join(pats))
4405 break
4406 break
4406 ui.warn(_("arguments do not match paths that need resolving\n"))
4407 ui.warn(_("arguments do not match paths that need resolving\n"))
4407 if hint:
4408 if hint:
4408 ui.warn(hint)
4409 ui.warn(hint)
4409 elif ms.mergedriver and ms.mdstate() != 's':
4410 elif ms.mergedriver and ms.mdstate() != 's':
4410 # run conclude step when either a driver-resolved file is requested
4411 # run conclude step when either a driver-resolved file is requested
4411 # or there are no driver-resolved files
4412 # or there are no driver-resolved files
4412 # we can't use 'ret' to determine whether any files are unresolved
4413 # we can't use 'ret' to determine whether any files are unresolved
4413 # because we might not have tried to resolve some
4414 # because we might not have tried to resolve some
4414 if ((runconclude or not list(ms.driverresolved()))
4415 if ((runconclude or not list(ms.driverresolved()))
4415 and not list(ms.unresolved())):
4416 and not list(ms.unresolved())):
4416 proceed = mergemod.driverconclude(repo, ms, wctx)
4417 proceed = mergemod.driverconclude(repo, ms, wctx)
4417 ms.commit()
4418 ms.commit()
4418 if not proceed:
4419 if not proceed:
4419 return 1
4420 return 1
4420
4421
4421 # Nudge users into finishing an unfinished operation
4422 # Nudge users into finishing an unfinished operation
4422 unresolvedf = list(ms.unresolved())
4423 unresolvedf = list(ms.unresolved())
4423 driverresolvedf = list(ms.driverresolved())
4424 driverresolvedf = list(ms.driverresolved())
4424 if not unresolvedf and not driverresolvedf:
4425 if not unresolvedf and not driverresolvedf:
4425 ui.status(_('(no more unresolved files)\n'))
4426 ui.status(_('(no more unresolved files)\n'))
4426 cmdutil.checkafterresolved(repo)
4427 cmdutil.checkafterresolved(repo)
4427 elif not unresolvedf:
4428 elif not unresolvedf:
4428 ui.status(_('(no more unresolved files -- '
4429 ui.status(_('(no more unresolved files -- '
4429 'run "hg resolve --all" to conclude)\n'))
4430 'run "hg resolve --all" to conclude)\n'))
4430
4431
4431 return ret
4432 return ret
4432
4433
4433 @command('revert',
4434 @command('revert',
4434 [('a', 'all', None, _('revert all changes when no arguments given')),
4435 [('a', 'all', None, _('revert all changes when no arguments given')),
4435 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4436 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4436 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4437 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4437 ('C', 'no-backup', None, _('do not save backup copies of files')),
4438 ('C', 'no-backup', None, _('do not save backup copies of files')),
4438 ('i', 'interactive', None,
4439 ('i', 'interactive', None,
4439 _('interactively select the changes (EXPERIMENTAL)')),
4440 _('interactively select the changes (EXPERIMENTAL)')),
4440 ] + walkopts + dryrunopts,
4441 ] + walkopts + dryrunopts,
4441 _('[OPTION]... [-r REV] [NAME]...'))
4442 _('[OPTION]... [-r REV] [NAME]...'))
4442 def revert(ui, repo, *pats, **opts):
4443 def revert(ui, repo, *pats, **opts):
4443 """restore files to their checkout state
4444 """restore files to their checkout state
4444
4445
4445 .. note::
4446 .. note::
4446
4447
4447 To check out earlier revisions, you should use :hg:`update REV`.
4448 To check out earlier revisions, you should use :hg:`update REV`.
4448 To cancel an uncommitted merge (and lose your changes),
4449 To cancel an uncommitted merge (and lose your changes),
4449 use :hg:`update --clean .`.
4450 use :hg:`update --clean .`.
4450
4451
4451 With no revision specified, revert the specified files or directories
4452 With no revision specified, revert the specified files or directories
4452 to the contents they had in the parent of the working directory.
4453 to the contents they had in the parent of the working directory.
4453 This restores the contents of files to an unmodified
4454 This restores the contents of files to an unmodified
4454 state and unschedules adds, removes, copies, and renames. If the
4455 state and unschedules adds, removes, copies, and renames. If the
4455 working directory has two parents, you must explicitly specify a
4456 working directory has two parents, you must explicitly specify a
4456 revision.
4457 revision.
4457
4458
4458 Using the -r/--rev or -d/--date options, revert the given files or
4459 Using the -r/--rev or -d/--date options, revert the given files or
4459 directories to their states as of a specific revision. Because
4460 directories to their states as of a specific revision. Because
4460 revert does not change the working directory parents, this will
4461 revert does not change the working directory parents, this will
4461 cause these files to appear modified. This can be helpful to "back
4462 cause these files to appear modified. This can be helpful to "back
4462 out" some or all of an earlier change. See :hg:`backout` for a
4463 out" some or all of an earlier change. See :hg:`backout` for a
4463 related method.
4464 related method.
4464
4465
4465 Modified files are saved with a .orig suffix before reverting.
4466 Modified files are saved with a .orig suffix before reverting.
4466 To disable these backups, use --no-backup. It is possible to store
4467 To disable these backups, use --no-backup. It is possible to store
4467 the backup files in a custom directory relative to the root of the
4468 the backup files in a custom directory relative to the root of the
4468 repository by setting the ``ui.origbackuppath`` configuration
4469 repository by setting the ``ui.origbackuppath`` configuration
4469 option.
4470 option.
4470
4471
4471 See :hg:`help dates` for a list of formats valid for -d/--date.
4472 See :hg:`help dates` for a list of formats valid for -d/--date.
4472
4473
4473 See :hg:`help backout` for a way to reverse the effect of an
4474 See :hg:`help backout` for a way to reverse the effect of an
4474 earlier changeset.
4475 earlier changeset.
4475
4476
4476 Returns 0 on success.
4477 Returns 0 on success.
4477 """
4478 """
4478
4479
4479 if opts.get("date"):
4480 if opts.get("date"):
4480 if opts.get("rev"):
4481 if opts.get("rev"):
4481 raise error.Abort(_("you can't specify a revision and a date"))
4482 raise error.Abort(_("you can't specify a revision and a date"))
4482 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4483 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4483
4484
4484 parent, p2 = repo.dirstate.parents()
4485 parent, p2 = repo.dirstate.parents()
4485 if not opts.get('rev') and p2 != nullid:
4486 if not opts.get('rev') and p2 != nullid:
4486 # revert after merge is a trap for new users (issue2915)
4487 # revert after merge is a trap for new users (issue2915)
4487 raise error.Abort(_('uncommitted merge with no revision specified'),
4488 raise error.Abort(_('uncommitted merge with no revision specified'),
4488 hint=_("use 'hg update' or see 'hg help revert'"))
4489 hint=_("use 'hg update' or see 'hg help revert'"))
4489
4490
4490 ctx = scmutil.revsingle(repo, opts.get('rev'))
4491 ctx = scmutil.revsingle(repo, opts.get('rev'))
4491
4492
4492 if (not (pats or opts.get('include') or opts.get('exclude') or
4493 if (not (pats or opts.get('include') or opts.get('exclude') or
4493 opts.get('all') or opts.get('interactive'))):
4494 opts.get('all') or opts.get('interactive'))):
4494 msg = _("no files or directories specified")
4495 msg = _("no files or directories specified")
4495 if p2 != nullid:
4496 if p2 != nullid:
4496 hint = _("uncommitted merge, use --all to discard all changes,"
4497 hint = _("uncommitted merge, use --all to discard all changes,"
4497 " or 'hg update -C .' to abort the merge")
4498 " or 'hg update -C .' to abort the merge")
4498 raise error.Abort(msg, hint=hint)
4499 raise error.Abort(msg, hint=hint)
4499 dirty = any(repo.status())
4500 dirty = any(repo.status())
4500 node = ctx.node()
4501 node = ctx.node()
4501 if node != parent:
4502 if node != parent:
4502 if dirty:
4503 if dirty:
4503 hint = _("uncommitted changes, use --all to discard all"
4504 hint = _("uncommitted changes, use --all to discard all"
4504 " changes, or 'hg update %s' to update") % ctx.rev()
4505 " changes, or 'hg update %s' to update") % ctx.rev()
4505 else:
4506 else:
4506 hint = _("use --all to revert all files,"
4507 hint = _("use --all to revert all files,"
4507 " or 'hg update %s' to update") % ctx.rev()
4508 " or 'hg update %s' to update") % ctx.rev()
4508 elif dirty:
4509 elif dirty:
4509 hint = _("uncommitted changes, use --all to discard all changes")
4510 hint = _("uncommitted changes, use --all to discard all changes")
4510 else:
4511 else:
4511 hint = _("use --all to revert all files")
4512 hint = _("use --all to revert all files")
4512 raise error.Abort(msg, hint=hint)
4513 raise error.Abort(msg, hint=hint)
4513
4514
4514 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
4515 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
4515
4516
4516 @command('rollback', dryrunopts +
4517 @command('rollback', dryrunopts +
4517 [('f', 'force', False, _('ignore safety measures'))])
4518 [('f', 'force', False, _('ignore safety measures'))])
4518 def rollback(ui, repo, **opts):
4519 def rollback(ui, repo, **opts):
4519 """roll back the last transaction (DANGEROUS) (DEPRECATED)
4520 """roll back the last transaction (DANGEROUS) (DEPRECATED)
4520
4521
4521 Please use :hg:`commit --amend` instead of rollback to correct
4522 Please use :hg:`commit --amend` instead of rollback to correct
4522 mistakes in the last commit.
4523 mistakes in the last commit.
4523
4524
4524 This command should be used with care. There is only one level of
4525 This command should be used with care. There is only one level of
4525 rollback, and there is no way to undo a rollback. It will also
4526 rollback, and there is no way to undo a rollback. It will also
4526 restore the dirstate at the time of the last transaction, losing
4527 restore the dirstate at the time of the last transaction, losing
4527 any dirstate changes since that time. This command does not alter
4528 any dirstate changes since that time. This command does not alter
4528 the working directory.
4529 the working directory.
4529
4530
4530 Transactions are used to encapsulate the effects of all commands
4531 Transactions are used to encapsulate the effects of all commands
4531 that create new changesets or propagate existing changesets into a
4532 that create new changesets or propagate existing changesets into a
4532 repository.
4533 repository.
4533
4534
4534 .. container:: verbose
4535 .. container:: verbose
4535
4536
4536 For example, the following commands are transactional, and their
4537 For example, the following commands are transactional, and their
4537 effects can be rolled back:
4538 effects can be rolled back:
4538
4539
4539 - commit
4540 - commit
4540 - import
4541 - import
4541 - pull
4542 - pull
4542 - push (with this repository as the destination)
4543 - push (with this repository as the destination)
4543 - unbundle
4544 - unbundle
4544
4545
4545 To avoid permanent data loss, rollback will refuse to rollback a
4546 To avoid permanent data loss, rollback will refuse to rollback a
4546 commit transaction if it isn't checked out. Use --force to
4547 commit transaction if it isn't checked out. Use --force to
4547 override this protection.
4548 override this protection.
4548
4549
4549 The rollback command can be entirely disabled by setting the
4550 The rollback command can be entirely disabled by setting the
4550 ``ui.rollback`` configuration setting to false. If you're here
4551 ``ui.rollback`` configuration setting to false. If you're here
4551 because you want to use rollback and it's disabled, you can
4552 because you want to use rollback and it's disabled, you can
4552 re-enable the command by setting ``ui.rollback`` to true.
4553 re-enable the command by setting ``ui.rollback`` to true.
4553
4554
4554 This command is not intended for use on public repositories. Once
4555 This command is not intended for use on public repositories. Once
4555 changes are visible for pull by other users, rolling a transaction
4556 changes are visible for pull by other users, rolling a transaction
4556 back locally is ineffective (someone else may already have pulled
4557 back locally is ineffective (someone else may already have pulled
4557 the changes). Furthermore, a race is possible with readers of the
4558 the changes). Furthermore, a race is possible with readers of the
4558 repository; for example an in-progress pull from the repository
4559 repository; for example an in-progress pull from the repository
4559 may fail if a rollback is performed.
4560 may fail if a rollback is performed.
4560
4561
4561 Returns 0 on success, 1 if no rollback data is available.
4562 Returns 0 on success, 1 if no rollback data is available.
4562 """
4563 """
4563 if not ui.configbool('ui', 'rollback', True):
4564 if not ui.configbool('ui', 'rollback', True):
4564 raise error.Abort(_('rollback is disabled because it is unsafe'),
4565 raise error.Abort(_('rollback is disabled because it is unsafe'),
4565 hint=('see `hg help -v rollback` for information'))
4566 hint=('see `hg help -v rollback` for information'))
4566 return repo.rollback(dryrun=opts.get('dry_run'),
4567 return repo.rollback(dryrun=opts.get('dry_run'),
4567 force=opts.get('force'))
4568 force=opts.get('force'))
4568
4569
4569 @command('root', [])
4570 @command('root', [])
4570 def root(ui, repo):
4571 def root(ui, repo):
4571 """print the root (top) of the current working directory
4572 """print the root (top) of the current working directory
4572
4573
4573 Print the root directory of the current repository.
4574 Print the root directory of the current repository.
4574
4575
4575 Returns 0 on success.
4576 Returns 0 on success.
4576 """
4577 """
4577 ui.write(repo.root + "\n")
4578 ui.write(repo.root + "\n")
4578
4579
4579 @command('^serve',
4580 @command('^serve',
4580 [('A', 'accesslog', '', _('name of access log file to write to'),
4581 [('A', 'accesslog', '', _('name of access log file to write to'),
4581 _('FILE')),
4582 _('FILE')),
4582 ('d', 'daemon', None, _('run server in background')),
4583 ('d', 'daemon', None, _('run server in background')),
4583 ('', 'daemon-postexec', [], _('used internally by daemon mode')),
4584 ('', 'daemon-postexec', [], _('used internally by daemon mode')),
4584 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4585 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4585 # use string type, then we can check if something was passed
4586 # use string type, then we can check if something was passed
4586 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4587 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4587 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4588 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4588 _('ADDR')),
4589 _('ADDR')),
4589 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4590 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4590 _('PREFIX')),
4591 _('PREFIX')),
4591 ('n', 'name', '',
4592 ('n', 'name', '',
4592 _('name to show in web pages (default: working directory)'), _('NAME')),
4593 _('name to show in web pages (default: working directory)'), _('NAME')),
4593 ('', 'web-conf', '',
4594 ('', 'web-conf', '',
4594 _("name of the hgweb config file (see 'hg help hgweb')"), _('FILE')),
4595 _("name of the hgweb config file (see 'hg help hgweb')"), _('FILE')),
4595 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4596 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4596 _('FILE')),
4597 _('FILE')),
4597 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4598 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4598 ('', 'stdio', None, _('for remote clients (ADVANCED)')),
4599 ('', 'stdio', None, _('for remote clients (ADVANCED)')),
4599 ('', 'cmdserver', '', _('for remote clients (ADVANCED)'), _('MODE')),
4600 ('', 'cmdserver', '', _('for remote clients (ADVANCED)'), _('MODE')),
4600 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4601 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4601 ('', 'style', '', _('template style to use'), _('STYLE')),
4602 ('', 'style', '', _('template style to use'), _('STYLE')),
4602 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4603 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4603 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
4604 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
4604 _('[OPTION]...'),
4605 _('[OPTION]...'),
4605 optionalrepo=True)
4606 optionalrepo=True)
4606 def serve(ui, repo, **opts):
4607 def serve(ui, repo, **opts):
4607 """start stand-alone webserver
4608 """start stand-alone webserver
4608
4609
4609 Start a local HTTP repository browser and pull server. You can use
4610 Start a local HTTP repository browser and pull server. You can use
4610 this for ad-hoc sharing and browsing of repositories. It is
4611 this for ad-hoc sharing and browsing of repositories. It is
4611 recommended to use a real web server to serve a repository for
4612 recommended to use a real web server to serve a repository for
4612 longer periods of time.
4613 longer periods of time.
4613
4614
4614 Please note that the server does not implement access control.
4615 Please note that the server does not implement access control.
4615 This means that, by default, anybody can read from the server and
4616 This means that, by default, anybody can read from the server and
4616 nobody can write to it by default. Set the ``web.allow_push``
4617 nobody can write to it by default. Set the ``web.allow_push``
4617 option to ``*`` to allow everybody to push to the server. You
4618 option to ``*`` to allow everybody to push to the server. You
4618 should use a real web server if you need to authenticate users.
4619 should use a real web server if you need to authenticate users.
4619
4620
4620 By default, the server logs accesses to stdout and errors to
4621 By default, the server logs accesses to stdout and errors to
4621 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
4622 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
4622 files.
4623 files.
4623
4624
4624 To have the server choose a free port number to listen on, specify
4625 To have the server choose a free port number to listen on, specify
4625 a port number of 0; in this case, the server will print the port
4626 a port number of 0; in this case, the server will print the port
4626 number it uses.
4627 number it uses.
4627
4628
4628 Returns 0 on success.
4629 Returns 0 on success.
4629 """
4630 """
4630
4631
4631 if opts["stdio"] and opts["cmdserver"]:
4632 if opts["stdio"] and opts["cmdserver"]:
4632 raise error.Abort(_("cannot use --stdio with --cmdserver"))
4633 raise error.Abort(_("cannot use --stdio with --cmdserver"))
4633
4634
4634 if opts["stdio"]:
4635 if opts["stdio"]:
4635 if repo is None:
4636 if repo is None:
4636 raise error.RepoError(_("there is no Mercurial repository here"
4637 raise error.RepoError(_("there is no Mercurial repository here"
4637 " (.hg not found)"))
4638 " (.hg not found)"))
4638 s = sshserver.sshserver(ui, repo)
4639 s = sshserver.sshserver(ui, repo)
4639 s.serve_forever()
4640 s.serve_forever()
4640
4641
4641 service = server.createservice(ui, repo, opts)
4642 service = server.createservice(ui, repo, opts)
4642 return server.runservice(opts, initfn=service.init, runfn=service.run)
4643 return server.runservice(opts, initfn=service.init, runfn=service.run)
4643
4644
4644 @command('^status|st',
4645 @command('^status|st',
4645 [('A', 'all', None, _('show status of all files')),
4646 [('A', 'all', None, _('show status of all files')),
4646 ('m', 'modified', None, _('show only modified files')),
4647 ('m', 'modified', None, _('show only modified files')),
4647 ('a', 'added', None, _('show only added files')),
4648 ('a', 'added', None, _('show only added files')),
4648 ('r', 'removed', None, _('show only removed files')),
4649 ('r', 'removed', None, _('show only removed files')),
4649 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4650 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4650 ('c', 'clean', None, _('show only files without changes')),
4651 ('c', 'clean', None, _('show only files without changes')),
4651 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4652 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4652 ('i', 'ignored', None, _('show only ignored files')),
4653 ('i', 'ignored', None, _('show only ignored files')),
4653 ('n', 'no-status', None, _('hide status prefix')),
4654 ('n', 'no-status', None, _('hide status prefix')),
4654 ('C', 'copies', None, _('show source of copied files')),
4655 ('C', 'copies', None, _('show source of copied files')),
4655 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4656 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4656 ('', 'rev', [], _('show difference from revision'), _('REV')),
4657 ('', 'rev', [], _('show difference from revision'), _('REV')),
4657 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
4658 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
4658 ] + walkopts + subrepoopts + formatteropts,
4659 ] + walkopts + subrepoopts + formatteropts,
4659 _('[OPTION]... [FILE]...'),
4660 _('[OPTION]... [FILE]...'),
4660 inferrepo=True)
4661 inferrepo=True)
4661 def status(ui, repo, *pats, **opts):
4662 def status(ui, repo, *pats, **opts):
4662 """show changed files in the working directory
4663 """show changed files in the working directory
4663
4664
4664 Show status of files in the repository. If names are given, only
4665 Show status of files in the repository. If names are given, only
4665 files that match are shown. Files that are clean or ignored or
4666 files that match are shown. Files that are clean or ignored or
4666 the source of a copy/move operation, are not listed unless
4667 the source of a copy/move operation, are not listed unless
4667 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
4668 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
4668 Unless options described with "show only ..." are given, the
4669 Unless options described with "show only ..." are given, the
4669 options -mardu are used.
4670 options -mardu are used.
4670
4671
4671 Option -q/--quiet hides untracked (unknown and ignored) files
4672 Option -q/--quiet hides untracked (unknown and ignored) files
4672 unless explicitly requested with -u/--unknown or -i/--ignored.
4673 unless explicitly requested with -u/--unknown or -i/--ignored.
4673
4674
4674 .. note::
4675 .. note::
4675
4676
4676 :hg:`status` may appear to disagree with diff if permissions have
4677 :hg:`status` may appear to disagree with diff if permissions have
4677 changed or a merge has occurred. The standard diff format does
4678 changed or a merge has occurred. The standard diff format does
4678 not report permission changes and diff only reports changes
4679 not report permission changes and diff only reports changes
4679 relative to one merge parent.
4680 relative to one merge parent.
4680
4681
4681 If one revision is given, it is used as the base revision.
4682 If one revision is given, it is used as the base revision.
4682 If two revisions are given, the differences between them are
4683 If two revisions are given, the differences between them are
4683 shown. The --change option can also be used as a shortcut to list
4684 shown. The --change option can also be used as a shortcut to list
4684 the changed files of a revision from its first parent.
4685 the changed files of a revision from its first parent.
4685
4686
4686 The codes used to show the status of files are::
4687 The codes used to show the status of files are::
4687
4688
4688 M = modified
4689 M = modified
4689 A = added
4690 A = added
4690 R = removed
4691 R = removed
4691 C = clean
4692 C = clean
4692 ! = missing (deleted by non-hg command, but still tracked)
4693 ! = missing (deleted by non-hg command, but still tracked)
4693 ? = not tracked
4694 ? = not tracked
4694 I = ignored
4695 I = ignored
4695 = origin of the previous file (with --copies)
4696 = origin of the previous file (with --copies)
4696
4697
4697 .. container:: verbose
4698 .. container:: verbose
4698
4699
4699 Examples:
4700 Examples:
4700
4701
4701 - show changes in the working directory relative to a
4702 - show changes in the working directory relative to a
4702 changeset::
4703 changeset::
4703
4704
4704 hg status --rev 9353
4705 hg status --rev 9353
4705
4706
4706 - show changes in the working directory relative to the
4707 - show changes in the working directory relative to the
4707 current directory (see :hg:`help patterns` for more information)::
4708 current directory (see :hg:`help patterns` for more information)::
4708
4709
4709 hg status re:
4710 hg status re:
4710
4711
4711 - show all changes including copies in an existing changeset::
4712 - show all changes including copies in an existing changeset::
4712
4713
4713 hg status --copies --change 9353
4714 hg status --copies --change 9353
4714
4715
4715 - get a NUL separated list of added files, suitable for xargs::
4716 - get a NUL separated list of added files, suitable for xargs::
4716
4717
4717 hg status -an0
4718 hg status -an0
4718
4719
4719 Returns 0 on success.
4720 Returns 0 on success.
4720 """
4721 """
4721
4722
4722 revs = opts.get('rev')
4723 revs = opts.get('rev')
4723 change = opts.get('change')
4724 change = opts.get('change')
4724
4725
4725 if revs and change:
4726 if revs and change:
4726 msg = _('cannot specify --rev and --change at the same time')
4727 msg = _('cannot specify --rev and --change at the same time')
4727 raise error.Abort(msg)
4728 raise error.Abort(msg)
4728 elif change:
4729 elif change:
4729 node2 = scmutil.revsingle(repo, change, None).node()
4730 node2 = scmutil.revsingle(repo, change, None).node()
4730 node1 = repo[node2].p1().node()
4731 node1 = repo[node2].p1().node()
4731 else:
4732 else:
4732 node1, node2 = scmutil.revpair(repo, revs)
4733 node1, node2 = scmutil.revpair(repo, revs)
4733
4734
4734 if pats:
4735 if pats:
4735 cwd = repo.getcwd()
4736 cwd = repo.getcwd()
4736 else:
4737 else:
4737 cwd = ''
4738 cwd = ''
4738
4739
4739 if opts.get('print0'):
4740 if opts.get('print0'):
4740 end = '\0'
4741 end = '\0'
4741 else:
4742 else:
4742 end = '\n'
4743 end = '\n'
4743 copy = {}
4744 copy = {}
4744 states = 'modified added removed deleted unknown ignored clean'.split()
4745 states = 'modified added removed deleted unknown ignored clean'.split()
4745 show = [k for k in states if opts.get(k)]
4746 show = [k for k in states if opts.get(k)]
4746 if opts.get('all'):
4747 if opts.get('all'):
4747 show += ui.quiet and (states[:4] + ['clean']) or states
4748 show += ui.quiet and (states[:4] + ['clean']) or states
4748 if not show:
4749 if not show:
4749 if ui.quiet:
4750 if ui.quiet:
4750 show = states[:4]
4751 show = states[:4]
4751 else:
4752 else:
4752 show = states[:5]
4753 show = states[:5]
4753
4754
4754 m = scmutil.match(repo[node2], pats, opts)
4755 m = scmutil.match(repo[node2], pats, opts)
4755 stat = repo.status(node1, node2, m,
4756 stat = repo.status(node1, node2, m,
4756 'ignored' in show, 'clean' in show, 'unknown' in show,
4757 'ignored' in show, 'clean' in show, 'unknown' in show,
4757 opts.get('subrepos'))
4758 opts.get('subrepos'))
4758 changestates = zip(states, 'MAR!?IC', stat)
4759 changestates = zip(states, 'MAR!?IC', stat)
4759
4760
4760 if (opts.get('all') or opts.get('copies')
4761 if (opts.get('all') or opts.get('copies')
4761 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
4762 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
4762 copy = copies.pathcopies(repo[node1], repo[node2], m)
4763 copy = copies.pathcopies(repo[node1], repo[node2], m)
4763
4764
4764 ui.pager('status')
4765 ui.pager('status')
4765 fm = ui.formatter('status', opts)
4766 fm = ui.formatter('status', opts)
4766 fmt = '%s' + end
4767 fmt = '%s' + end
4767 showchar = not opts.get('no_status')
4768 showchar = not opts.get('no_status')
4768
4769
4769 for state, char, files in changestates:
4770 for state, char, files in changestates:
4770 if state in show:
4771 if state in show:
4771 label = 'status.' + state
4772 label = 'status.' + state
4772 for f in files:
4773 for f in files:
4773 fm.startitem()
4774 fm.startitem()
4774 fm.condwrite(showchar, 'status', '%s ', char, label=label)
4775 fm.condwrite(showchar, 'status', '%s ', char, label=label)
4775 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
4776 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
4776 if f in copy:
4777 if f in copy:
4777 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
4778 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
4778 label='status.copied')
4779 label='status.copied')
4779 fm.end()
4780 fm.end()
4780
4781
4781 @command('^summary|sum',
4782 @command('^summary|sum',
4782 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
4783 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
4783 def summary(ui, repo, **opts):
4784 def summary(ui, repo, **opts):
4784 """summarize working directory state
4785 """summarize working directory state
4785
4786
4786 This generates a brief summary of the working directory state,
4787 This generates a brief summary of the working directory state,
4787 including parents, branch, commit status, phase and available updates.
4788 including parents, branch, commit status, phase and available updates.
4788
4789
4789 With the --remote option, this will check the default paths for
4790 With the --remote option, this will check the default paths for
4790 incoming and outgoing changes. This can be time-consuming.
4791 incoming and outgoing changes. This can be time-consuming.
4791
4792
4792 Returns 0 on success.
4793 Returns 0 on success.
4793 """
4794 """
4794
4795
4795 ui.pager('summary')
4796 ui.pager('summary')
4796 ctx = repo[None]
4797 ctx = repo[None]
4797 parents = ctx.parents()
4798 parents = ctx.parents()
4798 pnode = parents[0].node()
4799 pnode = parents[0].node()
4799 marks = []
4800 marks = []
4800
4801
4801 ms = None
4802 ms = None
4802 try:
4803 try:
4803 ms = mergemod.mergestate.read(repo)
4804 ms = mergemod.mergestate.read(repo)
4804 except error.UnsupportedMergeRecords as e:
4805 except error.UnsupportedMergeRecords as e:
4805 s = ' '.join(e.recordtypes)
4806 s = ' '.join(e.recordtypes)
4806 ui.warn(
4807 ui.warn(
4807 _('warning: merge state has unsupported record types: %s\n') % s)
4808 _('warning: merge state has unsupported record types: %s\n') % s)
4808 unresolved = 0
4809 unresolved = 0
4809 else:
4810 else:
4810 unresolved = [f for f in ms if ms[f] == 'u']
4811 unresolved = [f for f in ms if ms[f] == 'u']
4811
4812
4812 for p in parents:
4813 for p in parents:
4813 # label with log.changeset (instead of log.parent) since this
4814 # label with log.changeset (instead of log.parent) since this
4814 # shows a working directory parent *changeset*:
4815 # shows a working directory parent *changeset*:
4815 # i18n: column positioning for "hg summary"
4816 # i18n: column positioning for "hg summary"
4816 ui.write(_('parent: %d:%s ') % (p.rev(), p),
4817 ui.write(_('parent: %d:%s ') % (p.rev(), p),
4817 label=cmdutil._changesetlabels(p))
4818 label=cmdutil._changesetlabels(p))
4818 ui.write(' '.join(p.tags()), label='log.tag')
4819 ui.write(' '.join(p.tags()), label='log.tag')
4819 if p.bookmarks():
4820 if p.bookmarks():
4820 marks.extend(p.bookmarks())
4821 marks.extend(p.bookmarks())
4821 if p.rev() == -1:
4822 if p.rev() == -1:
4822 if not len(repo):
4823 if not len(repo):
4823 ui.write(_(' (empty repository)'))
4824 ui.write(_(' (empty repository)'))
4824 else:
4825 else:
4825 ui.write(_(' (no revision checked out)'))
4826 ui.write(_(' (no revision checked out)'))
4826 if p.troubled():
4827 if p.troubled():
4827 ui.write(' ('
4828 ui.write(' ('
4828 + ', '.join(ui.label(trouble, 'trouble.%s' % trouble)
4829 + ', '.join(ui.label(trouble, 'trouble.%s' % trouble)
4829 for trouble in p.troubles())
4830 for trouble in p.troubles())
4830 + ')')
4831 + ')')
4831 ui.write('\n')
4832 ui.write('\n')
4832 if p.description():
4833 if p.description():
4833 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
4834 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
4834 label='log.summary')
4835 label='log.summary')
4835
4836
4836 branch = ctx.branch()
4837 branch = ctx.branch()
4837 bheads = repo.branchheads(branch)
4838 bheads = repo.branchheads(branch)
4838 # i18n: column positioning for "hg summary"
4839 # i18n: column positioning for "hg summary"
4839 m = _('branch: %s\n') % branch
4840 m = _('branch: %s\n') % branch
4840 if branch != 'default':
4841 if branch != 'default':
4841 ui.write(m, label='log.branch')
4842 ui.write(m, label='log.branch')
4842 else:
4843 else:
4843 ui.status(m, label='log.branch')
4844 ui.status(m, label='log.branch')
4844
4845
4845 if marks:
4846 if marks:
4846 active = repo._activebookmark
4847 active = repo._activebookmark
4847 # i18n: column positioning for "hg summary"
4848 # i18n: column positioning for "hg summary"
4848 ui.write(_('bookmarks:'), label='log.bookmark')
4849 ui.write(_('bookmarks:'), label='log.bookmark')
4849 if active is not None:
4850 if active is not None:
4850 if active in marks:
4851 if active in marks:
4851 ui.write(' *' + active, label=activebookmarklabel)
4852 ui.write(' *' + active, label=activebookmarklabel)
4852 marks.remove(active)
4853 marks.remove(active)
4853 else:
4854 else:
4854 ui.write(' [%s]' % active, label=activebookmarklabel)
4855 ui.write(' [%s]' % active, label=activebookmarklabel)
4855 for m in marks:
4856 for m in marks:
4856 ui.write(' ' + m, label='log.bookmark')
4857 ui.write(' ' + m, label='log.bookmark')
4857 ui.write('\n', label='log.bookmark')
4858 ui.write('\n', label='log.bookmark')
4858
4859
4859 status = repo.status(unknown=True)
4860 status = repo.status(unknown=True)
4860
4861
4861 c = repo.dirstate.copies()
4862 c = repo.dirstate.copies()
4862 copied, renamed = [], []
4863 copied, renamed = [], []
4863 for d, s in c.iteritems():
4864 for d, s in c.iteritems():
4864 if s in status.removed:
4865 if s in status.removed:
4865 status.removed.remove(s)
4866 status.removed.remove(s)
4866 renamed.append(d)
4867 renamed.append(d)
4867 else:
4868 else:
4868 copied.append(d)
4869 copied.append(d)
4869 if d in status.added:
4870 if d in status.added:
4870 status.added.remove(d)
4871 status.added.remove(d)
4871
4872
4872 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
4873 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
4873
4874
4874 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
4875 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
4875 (ui.label(_('%d added'), 'status.added'), status.added),
4876 (ui.label(_('%d added'), 'status.added'), status.added),
4876 (ui.label(_('%d removed'), 'status.removed'), status.removed),
4877 (ui.label(_('%d removed'), 'status.removed'), status.removed),
4877 (ui.label(_('%d renamed'), 'status.copied'), renamed),
4878 (ui.label(_('%d renamed'), 'status.copied'), renamed),
4878 (ui.label(_('%d copied'), 'status.copied'), copied),
4879 (ui.label(_('%d copied'), 'status.copied'), copied),
4879 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
4880 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
4880 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
4881 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
4881 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
4882 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
4882 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
4883 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
4883 t = []
4884 t = []
4884 for l, s in labels:
4885 for l, s in labels:
4885 if s:
4886 if s:
4886 t.append(l % len(s))
4887 t.append(l % len(s))
4887
4888
4888 t = ', '.join(t)
4889 t = ', '.join(t)
4889 cleanworkdir = False
4890 cleanworkdir = False
4890
4891
4891 if repo.vfs.exists('graftstate'):
4892 if repo.vfs.exists('graftstate'):
4892 t += _(' (graft in progress)')
4893 t += _(' (graft in progress)')
4893 if repo.vfs.exists('updatestate'):
4894 if repo.vfs.exists('updatestate'):
4894 t += _(' (interrupted update)')
4895 t += _(' (interrupted update)')
4895 elif len(parents) > 1:
4896 elif len(parents) > 1:
4896 t += _(' (merge)')
4897 t += _(' (merge)')
4897 elif branch != parents[0].branch():
4898 elif branch != parents[0].branch():
4898 t += _(' (new branch)')
4899 t += _(' (new branch)')
4899 elif (parents[0].closesbranch() and
4900 elif (parents[0].closesbranch() and
4900 pnode in repo.branchheads(branch, closed=True)):
4901 pnode in repo.branchheads(branch, closed=True)):
4901 t += _(' (head closed)')
4902 t += _(' (head closed)')
4902 elif not (status.modified or status.added or status.removed or renamed or
4903 elif not (status.modified or status.added or status.removed or renamed or
4903 copied or subs):
4904 copied or subs):
4904 t += _(' (clean)')
4905 t += _(' (clean)')
4905 cleanworkdir = True
4906 cleanworkdir = True
4906 elif pnode not in bheads:
4907 elif pnode not in bheads:
4907 t += _(' (new branch head)')
4908 t += _(' (new branch head)')
4908
4909
4909 if parents:
4910 if parents:
4910 pendingphase = max(p.phase() for p in parents)
4911 pendingphase = max(p.phase() for p in parents)
4911 else:
4912 else:
4912 pendingphase = phases.public
4913 pendingphase = phases.public
4913
4914
4914 if pendingphase > phases.newcommitphase(ui):
4915 if pendingphase > phases.newcommitphase(ui):
4915 t += ' (%s)' % phases.phasenames[pendingphase]
4916 t += ' (%s)' % phases.phasenames[pendingphase]
4916
4917
4917 if cleanworkdir:
4918 if cleanworkdir:
4918 # i18n: column positioning for "hg summary"
4919 # i18n: column positioning for "hg summary"
4919 ui.status(_('commit: %s\n') % t.strip())
4920 ui.status(_('commit: %s\n') % t.strip())
4920 else:
4921 else:
4921 # i18n: column positioning for "hg summary"
4922 # i18n: column positioning for "hg summary"
4922 ui.write(_('commit: %s\n') % t.strip())
4923 ui.write(_('commit: %s\n') % t.strip())
4923
4924
4924 # all ancestors of branch heads - all ancestors of parent = new csets
4925 # all ancestors of branch heads - all ancestors of parent = new csets
4925 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
4926 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
4926 bheads))
4927 bheads))
4927
4928
4928 if new == 0:
4929 if new == 0:
4929 # i18n: column positioning for "hg summary"
4930 # i18n: column positioning for "hg summary"
4930 ui.status(_('update: (current)\n'))
4931 ui.status(_('update: (current)\n'))
4931 elif pnode not in bheads:
4932 elif pnode not in bheads:
4932 # i18n: column positioning for "hg summary"
4933 # i18n: column positioning for "hg summary"
4933 ui.write(_('update: %d new changesets (update)\n') % new)
4934 ui.write(_('update: %d new changesets (update)\n') % new)
4934 else:
4935 else:
4935 # i18n: column positioning for "hg summary"
4936 # i18n: column positioning for "hg summary"
4936 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
4937 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
4937 (new, len(bheads)))
4938 (new, len(bheads)))
4938
4939
4939 t = []
4940 t = []
4940 draft = len(repo.revs('draft()'))
4941 draft = len(repo.revs('draft()'))
4941 if draft:
4942 if draft:
4942 t.append(_('%d draft') % draft)
4943 t.append(_('%d draft') % draft)
4943 secret = len(repo.revs('secret()'))
4944 secret = len(repo.revs('secret()'))
4944 if secret:
4945 if secret:
4945 t.append(_('%d secret') % secret)
4946 t.append(_('%d secret') % secret)
4946
4947
4947 if draft or secret:
4948 if draft or secret:
4948 ui.status(_('phases: %s\n') % ', '.join(t))
4949 ui.status(_('phases: %s\n') % ', '.join(t))
4949
4950
4950 if obsolete.isenabled(repo, obsolete.createmarkersopt):
4951 if obsolete.isenabled(repo, obsolete.createmarkersopt):
4951 for trouble in ("unstable", "divergent", "bumped"):
4952 for trouble in ("unstable", "divergent", "bumped"):
4952 numtrouble = len(repo.revs(trouble + "()"))
4953 numtrouble = len(repo.revs(trouble + "()"))
4953 # We write all the possibilities to ease translation
4954 # We write all the possibilities to ease translation
4954 troublemsg = {
4955 troublemsg = {
4955 "unstable": _("unstable: %d changesets"),
4956 "unstable": _("unstable: %d changesets"),
4956 "divergent": _("divergent: %d changesets"),
4957 "divergent": _("divergent: %d changesets"),
4957 "bumped": _("bumped: %d changesets"),
4958 "bumped": _("bumped: %d changesets"),
4958 }
4959 }
4959 if numtrouble > 0:
4960 if numtrouble > 0:
4960 ui.status(troublemsg[trouble] % numtrouble + "\n")
4961 ui.status(troublemsg[trouble] % numtrouble + "\n")
4961
4962
4962 cmdutil.summaryhooks(ui, repo)
4963 cmdutil.summaryhooks(ui, repo)
4963
4964
4964 if opts.get('remote'):
4965 if opts.get('remote'):
4965 needsincoming, needsoutgoing = True, True
4966 needsincoming, needsoutgoing = True, True
4966 else:
4967 else:
4967 needsincoming, needsoutgoing = False, False
4968 needsincoming, needsoutgoing = False, False
4968 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
4969 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
4969 if i:
4970 if i:
4970 needsincoming = True
4971 needsincoming = True
4971 if o:
4972 if o:
4972 needsoutgoing = True
4973 needsoutgoing = True
4973 if not needsincoming and not needsoutgoing:
4974 if not needsincoming and not needsoutgoing:
4974 return
4975 return
4975
4976
4976 def getincoming():
4977 def getincoming():
4977 source, branches = hg.parseurl(ui.expandpath('default'))
4978 source, branches = hg.parseurl(ui.expandpath('default'))
4978 sbranch = branches[0]
4979 sbranch = branches[0]
4979 try:
4980 try:
4980 other = hg.peer(repo, {}, source)
4981 other = hg.peer(repo, {}, source)
4981 except error.RepoError:
4982 except error.RepoError:
4982 if opts.get('remote'):
4983 if opts.get('remote'):
4983 raise
4984 raise
4984 return source, sbranch, None, None, None
4985 return source, sbranch, None, None, None
4985 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
4986 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
4986 if revs:
4987 if revs:
4987 revs = [other.lookup(rev) for rev in revs]
4988 revs = [other.lookup(rev) for rev in revs]
4988 ui.debug('comparing with %s\n' % util.hidepassword(source))
4989 ui.debug('comparing with %s\n' % util.hidepassword(source))
4989 repo.ui.pushbuffer()
4990 repo.ui.pushbuffer()
4990 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
4991 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
4991 repo.ui.popbuffer()
4992 repo.ui.popbuffer()
4992 return source, sbranch, other, commoninc, commoninc[1]
4993 return source, sbranch, other, commoninc, commoninc[1]
4993
4994
4994 if needsincoming:
4995 if needsincoming:
4995 source, sbranch, sother, commoninc, incoming = getincoming()
4996 source, sbranch, sother, commoninc, incoming = getincoming()
4996 else:
4997 else:
4997 source = sbranch = sother = commoninc = incoming = None
4998 source = sbranch = sother = commoninc = incoming = None
4998
4999
4999 def getoutgoing():
5000 def getoutgoing():
5000 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5001 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5001 dbranch = branches[0]
5002 dbranch = branches[0]
5002 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5003 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5003 if source != dest:
5004 if source != dest:
5004 try:
5005 try:
5005 dother = hg.peer(repo, {}, dest)
5006 dother = hg.peer(repo, {}, dest)
5006 except error.RepoError:
5007 except error.RepoError:
5007 if opts.get('remote'):
5008 if opts.get('remote'):
5008 raise
5009 raise
5009 return dest, dbranch, None, None
5010 return dest, dbranch, None, None
5010 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5011 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5011 elif sother is None:
5012 elif sother is None:
5012 # there is no explicit destination peer, but source one is invalid
5013 # there is no explicit destination peer, but source one is invalid
5013 return dest, dbranch, None, None
5014 return dest, dbranch, None, None
5014 else:
5015 else:
5015 dother = sother
5016 dother = sother
5016 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5017 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5017 common = None
5018 common = None
5018 else:
5019 else:
5019 common = commoninc
5020 common = commoninc
5020 if revs:
5021 if revs:
5021 revs = [repo.lookup(rev) for rev in revs]
5022 revs = [repo.lookup(rev) for rev in revs]
5022 repo.ui.pushbuffer()
5023 repo.ui.pushbuffer()
5023 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5024 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5024 commoninc=common)
5025 commoninc=common)
5025 repo.ui.popbuffer()
5026 repo.ui.popbuffer()
5026 return dest, dbranch, dother, outgoing
5027 return dest, dbranch, dother, outgoing
5027
5028
5028 if needsoutgoing:
5029 if needsoutgoing:
5029 dest, dbranch, dother, outgoing = getoutgoing()
5030 dest, dbranch, dother, outgoing = getoutgoing()
5030 else:
5031 else:
5031 dest = dbranch = dother = outgoing = None
5032 dest = dbranch = dother = outgoing = None
5032
5033
5033 if opts.get('remote'):
5034 if opts.get('remote'):
5034 t = []
5035 t = []
5035 if incoming:
5036 if incoming:
5036 t.append(_('1 or more incoming'))
5037 t.append(_('1 or more incoming'))
5037 o = outgoing.missing
5038 o = outgoing.missing
5038 if o:
5039 if o:
5039 t.append(_('%d outgoing') % len(o))
5040 t.append(_('%d outgoing') % len(o))
5040 other = dother or sother
5041 other = dother or sother
5041 if 'bookmarks' in other.listkeys('namespaces'):
5042 if 'bookmarks' in other.listkeys('namespaces'):
5042 counts = bookmarks.summary(repo, other)
5043 counts = bookmarks.summary(repo, other)
5043 if counts[0] > 0:
5044 if counts[0] > 0:
5044 t.append(_('%d incoming bookmarks') % counts[0])
5045 t.append(_('%d incoming bookmarks') % counts[0])
5045 if counts[1] > 0:
5046 if counts[1] > 0:
5046 t.append(_('%d outgoing bookmarks') % counts[1])
5047 t.append(_('%d outgoing bookmarks') % counts[1])
5047
5048
5048 if t:
5049 if t:
5049 # i18n: column positioning for "hg summary"
5050 # i18n: column positioning for "hg summary"
5050 ui.write(_('remote: %s\n') % (', '.join(t)))
5051 ui.write(_('remote: %s\n') % (', '.join(t)))
5051 else:
5052 else:
5052 # i18n: column positioning for "hg summary"
5053 # i18n: column positioning for "hg summary"
5053 ui.status(_('remote: (synced)\n'))
5054 ui.status(_('remote: (synced)\n'))
5054
5055
5055 cmdutil.summaryremotehooks(ui, repo, opts,
5056 cmdutil.summaryremotehooks(ui, repo, opts,
5056 ((source, sbranch, sother, commoninc),
5057 ((source, sbranch, sother, commoninc),
5057 (dest, dbranch, dother, outgoing)))
5058 (dest, dbranch, dother, outgoing)))
5058
5059
5059 @command('tag',
5060 @command('tag',
5060 [('f', 'force', None, _('force tag')),
5061 [('f', 'force', None, _('force tag')),
5061 ('l', 'local', None, _('make the tag local')),
5062 ('l', 'local', None, _('make the tag local')),
5062 ('r', 'rev', '', _('revision to tag'), _('REV')),
5063 ('r', 'rev', '', _('revision to tag'), _('REV')),
5063 ('', 'remove', None, _('remove a tag')),
5064 ('', 'remove', None, _('remove a tag')),
5064 # -l/--local is already there, commitopts cannot be used
5065 # -l/--local is already there, commitopts cannot be used
5065 ('e', 'edit', None, _('invoke editor on commit messages')),
5066 ('e', 'edit', None, _('invoke editor on commit messages')),
5066 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5067 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5067 ] + commitopts2,
5068 ] + commitopts2,
5068 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5069 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5069 def tag(ui, repo, name1, *names, **opts):
5070 def tag(ui, repo, name1, *names, **opts):
5070 """add one or more tags for the current or given revision
5071 """add one or more tags for the current or given revision
5071
5072
5072 Name a particular revision using <name>.
5073 Name a particular revision using <name>.
5073
5074
5074 Tags are used to name particular revisions of the repository and are
5075 Tags are used to name particular revisions of the repository and are
5075 very useful to compare different revisions, to go back to significant
5076 very useful to compare different revisions, to go back to significant
5076 earlier versions or to mark branch points as releases, etc. Changing
5077 earlier versions or to mark branch points as releases, etc. Changing
5077 an existing tag is normally disallowed; use -f/--force to override.
5078 an existing tag is normally disallowed; use -f/--force to override.
5078
5079
5079 If no revision is given, the parent of the working directory is
5080 If no revision is given, the parent of the working directory is
5080 used.
5081 used.
5081
5082
5082 To facilitate version control, distribution, and merging of tags,
5083 To facilitate version control, distribution, and merging of tags,
5083 they are stored as a file named ".hgtags" which is managed similarly
5084 they are stored as a file named ".hgtags" which is managed similarly
5084 to other project files and can be hand-edited if necessary. This
5085 to other project files and can be hand-edited if necessary. This
5085 also means that tagging creates a new commit. The file
5086 also means that tagging creates a new commit. The file
5086 ".hg/localtags" is used for local tags (not shared among
5087 ".hg/localtags" is used for local tags (not shared among
5087 repositories).
5088 repositories).
5088
5089
5089 Tag commits are usually made at the head of a branch. If the parent
5090 Tag commits are usually made at the head of a branch. If the parent
5090 of the working directory is not a branch head, :hg:`tag` aborts; use
5091 of the working directory is not a branch head, :hg:`tag` aborts; use
5091 -f/--force to force the tag commit to be based on a non-head
5092 -f/--force to force the tag commit to be based on a non-head
5092 changeset.
5093 changeset.
5093
5094
5094 See :hg:`help dates` for a list of formats valid for -d/--date.
5095 See :hg:`help dates` for a list of formats valid for -d/--date.
5095
5096
5096 Since tag names have priority over branch names during revision
5097 Since tag names have priority over branch names during revision
5097 lookup, using an existing branch name as a tag name is discouraged.
5098 lookup, using an existing branch name as a tag name is discouraged.
5098
5099
5099 Returns 0 on success.
5100 Returns 0 on success.
5100 """
5101 """
5101 wlock = lock = None
5102 wlock = lock = None
5102 try:
5103 try:
5103 wlock = repo.wlock()
5104 wlock = repo.wlock()
5104 lock = repo.lock()
5105 lock = repo.lock()
5105 rev_ = "."
5106 rev_ = "."
5106 names = [t.strip() for t in (name1,) + names]
5107 names = [t.strip() for t in (name1,) + names]
5107 if len(names) != len(set(names)):
5108 if len(names) != len(set(names)):
5108 raise error.Abort(_('tag names must be unique'))
5109 raise error.Abort(_('tag names must be unique'))
5109 for n in names:
5110 for n in names:
5110 scmutil.checknewlabel(repo, n, 'tag')
5111 scmutil.checknewlabel(repo, n, 'tag')
5111 if not n:
5112 if not n:
5112 raise error.Abort(_('tag names cannot consist entirely of '
5113 raise error.Abort(_('tag names cannot consist entirely of '
5113 'whitespace'))
5114 'whitespace'))
5114 if opts.get('rev') and opts.get('remove'):
5115 if opts.get('rev') and opts.get('remove'):
5115 raise error.Abort(_("--rev and --remove are incompatible"))
5116 raise error.Abort(_("--rev and --remove are incompatible"))
5116 if opts.get('rev'):
5117 if opts.get('rev'):
5117 rev_ = opts['rev']
5118 rev_ = opts['rev']
5118 message = opts.get('message')
5119 message = opts.get('message')
5119 if opts.get('remove'):
5120 if opts.get('remove'):
5120 if opts.get('local'):
5121 if opts.get('local'):
5121 expectedtype = 'local'
5122 expectedtype = 'local'
5122 else:
5123 else:
5123 expectedtype = 'global'
5124 expectedtype = 'global'
5124
5125
5125 for n in names:
5126 for n in names:
5126 if not repo.tagtype(n):
5127 if not repo.tagtype(n):
5127 raise error.Abort(_("tag '%s' does not exist") % n)
5128 raise error.Abort(_("tag '%s' does not exist") % n)
5128 if repo.tagtype(n) != expectedtype:
5129 if repo.tagtype(n) != expectedtype:
5129 if expectedtype == 'global':
5130 if expectedtype == 'global':
5130 raise error.Abort(_("tag '%s' is not a global tag") % n)
5131 raise error.Abort(_("tag '%s' is not a global tag") % n)
5131 else:
5132 else:
5132 raise error.Abort(_("tag '%s' is not a local tag") % n)
5133 raise error.Abort(_("tag '%s' is not a local tag") % n)
5133 rev_ = 'null'
5134 rev_ = 'null'
5134 if not message:
5135 if not message:
5135 # we don't translate commit messages
5136 # we don't translate commit messages
5136 message = 'Removed tag %s' % ', '.join(names)
5137 message = 'Removed tag %s' % ', '.join(names)
5137 elif not opts.get('force'):
5138 elif not opts.get('force'):
5138 for n in names:
5139 for n in names:
5139 if n in repo.tags():
5140 if n in repo.tags():
5140 raise error.Abort(_("tag '%s' already exists "
5141 raise error.Abort(_("tag '%s' already exists "
5141 "(use -f to force)") % n)
5142 "(use -f to force)") % n)
5142 if not opts.get('local'):
5143 if not opts.get('local'):
5143 p1, p2 = repo.dirstate.parents()
5144 p1, p2 = repo.dirstate.parents()
5144 if p2 != nullid:
5145 if p2 != nullid:
5145 raise error.Abort(_('uncommitted merge'))
5146 raise error.Abort(_('uncommitted merge'))
5146 bheads = repo.branchheads()
5147 bheads = repo.branchheads()
5147 if not opts.get('force') and bheads and p1 not in bheads:
5148 if not opts.get('force') and bheads and p1 not in bheads:
5148 raise error.Abort(_('working directory is not at a branch head '
5149 raise error.Abort(_('working directory is not at a branch head '
5149 '(use -f to force)'))
5150 '(use -f to force)'))
5150 r = scmutil.revsingle(repo, rev_).node()
5151 r = scmutil.revsingle(repo, rev_).node()
5151
5152
5152 if not message:
5153 if not message:
5153 # we don't translate commit messages
5154 # we don't translate commit messages
5154 message = ('Added tag %s for changeset %s' %
5155 message = ('Added tag %s for changeset %s' %
5155 (', '.join(names), short(r)))
5156 (', '.join(names), short(r)))
5156
5157
5157 date = opts.get('date')
5158 date = opts.get('date')
5158 if date:
5159 if date:
5159 date = util.parsedate(date)
5160 date = util.parsedate(date)
5160
5161
5161 if opts.get('remove'):
5162 if opts.get('remove'):
5162 editform = 'tag.remove'
5163 editform = 'tag.remove'
5163 else:
5164 else:
5164 editform = 'tag.add'
5165 editform = 'tag.add'
5165 editor = cmdutil.getcommiteditor(editform=editform, **opts)
5166 editor = cmdutil.getcommiteditor(editform=editform, **opts)
5166
5167
5167 # don't allow tagging the null rev
5168 # don't allow tagging the null rev
5168 if (not opts.get('remove') and
5169 if (not opts.get('remove') and
5169 scmutil.revsingle(repo, rev_).rev() == nullrev):
5170 scmutil.revsingle(repo, rev_).rev() == nullrev):
5170 raise error.Abort(_("cannot tag null revision"))
5171 raise error.Abort(_("cannot tag null revision"))
5171
5172
5172 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
5173 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
5173 editor=editor)
5174 editor=editor)
5174 finally:
5175 finally:
5175 release(lock, wlock)
5176 release(lock, wlock)
5176
5177
5177 @command('tags', formatteropts, '')
5178 @command('tags', formatteropts, '')
5178 def tags(ui, repo, **opts):
5179 def tags(ui, repo, **opts):
5179 """list repository tags
5180 """list repository tags
5180
5181
5181 This lists both regular and local tags. When the -v/--verbose
5182 This lists both regular and local tags. When the -v/--verbose
5182 switch is used, a third column "local" is printed for local tags.
5183 switch is used, a third column "local" is printed for local tags.
5183 When the -q/--quiet switch is used, only the tag name is printed.
5184 When the -q/--quiet switch is used, only the tag name is printed.
5184
5185
5185 Returns 0 on success.
5186 Returns 0 on success.
5186 """
5187 """
5187
5188
5188 ui.pager('tags')
5189 ui.pager('tags')
5189 fm = ui.formatter('tags', opts)
5190 fm = ui.formatter('tags', opts)
5190 hexfunc = fm.hexfunc
5191 hexfunc = fm.hexfunc
5191 tagtype = ""
5192 tagtype = ""
5192
5193
5193 for t, n in reversed(repo.tagslist()):
5194 for t, n in reversed(repo.tagslist()):
5194 hn = hexfunc(n)
5195 hn = hexfunc(n)
5195 label = 'tags.normal'
5196 label = 'tags.normal'
5196 tagtype = ''
5197 tagtype = ''
5197 if repo.tagtype(t) == 'local':
5198 if repo.tagtype(t) == 'local':
5198 label = 'tags.local'
5199 label = 'tags.local'
5199 tagtype = 'local'
5200 tagtype = 'local'
5200
5201
5201 fm.startitem()
5202 fm.startitem()
5202 fm.write('tag', '%s', t, label=label)
5203 fm.write('tag', '%s', t, label=label)
5203 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5204 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5204 fm.condwrite(not ui.quiet, 'rev node', fmt,
5205 fm.condwrite(not ui.quiet, 'rev node', fmt,
5205 repo.changelog.rev(n), hn, label=label)
5206 repo.changelog.rev(n), hn, label=label)
5206 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5207 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5207 tagtype, label=label)
5208 tagtype, label=label)
5208 fm.plain('\n')
5209 fm.plain('\n')
5209 fm.end()
5210 fm.end()
5210
5211
5211 @command('tip',
5212 @command('tip',
5212 [('p', 'patch', None, _('show patch')),
5213 [('p', 'patch', None, _('show patch')),
5213 ('g', 'git', None, _('use git extended diff format')),
5214 ('g', 'git', None, _('use git extended diff format')),
5214 ] + templateopts,
5215 ] + templateopts,
5215 _('[-p] [-g]'))
5216 _('[-p] [-g]'))
5216 def tip(ui, repo, **opts):
5217 def tip(ui, repo, **opts):
5217 """show the tip revision (DEPRECATED)
5218 """show the tip revision (DEPRECATED)
5218
5219
5219 The tip revision (usually just called the tip) is the changeset
5220 The tip revision (usually just called the tip) is the changeset
5220 most recently added to the repository (and therefore the most
5221 most recently added to the repository (and therefore the most
5221 recently changed head).
5222 recently changed head).
5222
5223
5223 If you have just made a commit, that commit will be the tip. If
5224 If you have just made a commit, that commit will be the tip. If
5224 you have just pulled changes from another repository, the tip of
5225 you have just pulled changes from another repository, the tip of
5225 that repository becomes the current tip. The "tip" tag is special
5226 that repository becomes the current tip. The "tip" tag is special
5226 and cannot be renamed or assigned to a different changeset.
5227 and cannot be renamed or assigned to a different changeset.
5227
5228
5228 This command is deprecated, please use :hg:`heads` instead.
5229 This command is deprecated, please use :hg:`heads` instead.
5229
5230
5230 Returns 0 on success.
5231 Returns 0 on success.
5231 """
5232 """
5232 displayer = cmdutil.show_changeset(ui, repo, opts)
5233 displayer = cmdutil.show_changeset(ui, repo, opts)
5233 displayer.show(repo['tip'])
5234 displayer.show(repo['tip'])
5234 displayer.close()
5235 displayer.close()
5235
5236
5236 @command('unbundle',
5237 @command('unbundle',
5237 [('u', 'update', None,
5238 [('u', 'update', None,
5238 _('update to new branch head if changesets were unbundled'))],
5239 _('update to new branch head if changesets were unbundled'))],
5239 _('[-u] FILE...'))
5240 _('[-u] FILE...'))
5240 def unbundle(ui, repo, fname1, *fnames, **opts):
5241 def unbundle(ui, repo, fname1, *fnames, **opts):
5241 """apply one or more changegroup files
5242 """apply one or more changegroup files
5242
5243
5243 Apply one or more compressed changegroup files generated by the
5244 Apply one or more compressed changegroup files generated by the
5244 bundle command.
5245 bundle command.
5245
5246
5246 Returns 0 on success, 1 if an update has unresolved files.
5247 Returns 0 on success, 1 if an update has unresolved files.
5247 """
5248 """
5248 fnames = (fname1,) + fnames
5249 fnames = (fname1,) + fnames
5249
5250
5250 with repo.lock():
5251 with repo.lock():
5251 for fname in fnames:
5252 for fname in fnames:
5252 f = hg.openpath(ui, fname)
5253 f = hg.openpath(ui, fname)
5253 gen = exchange.readbundle(ui, f, fname)
5254 gen = exchange.readbundle(ui, f, fname)
5254 if isinstance(gen, bundle2.unbundle20):
5255 if isinstance(gen, bundle2.unbundle20):
5255 tr = repo.transaction('unbundle')
5256 tr = repo.transaction('unbundle')
5256 try:
5257 try:
5257 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
5258 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
5258 url='bundle:' + fname)
5259 url='bundle:' + fname)
5259 tr.close()
5260 tr.close()
5260 except error.BundleUnknownFeatureError as exc:
5261 except error.BundleUnknownFeatureError as exc:
5261 raise error.Abort(_('%s: unknown bundle feature, %s')
5262 raise error.Abort(_('%s: unknown bundle feature, %s')
5262 % (fname, exc),
5263 % (fname, exc),
5263 hint=_("see https://mercurial-scm.org/"
5264 hint=_("see https://mercurial-scm.org/"
5264 "wiki/BundleFeature for more "
5265 "wiki/BundleFeature for more "
5265 "information"))
5266 "information"))
5266 finally:
5267 finally:
5267 if tr:
5268 if tr:
5268 tr.release()
5269 tr.release()
5269 changes = [r.get('return', 0)
5270 changes = [r.get('return', 0)
5270 for r in op.records['changegroup']]
5271 for r in op.records['changegroup']]
5271 modheads = changegroup.combineresults(changes)
5272 modheads = changegroup.combineresults(changes)
5272 elif isinstance(gen, streamclone.streamcloneapplier):
5273 elif isinstance(gen, streamclone.streamcloneapplier):
5273 raise error.Abort(
5274 raise error.Abort(
5274 _('packed bundles cannot be applied with '
5275 _('packed bundles cannot be applied with '
5275 '"hg unbundle"'),
5276 '"hg unbundle"'),
5276 hint=_('use "hg debugapplystreamclonebundle"'))
5277 hint=_('use "hg debugapplystreamclonebundle"'))
5277 else:
5278 else:
5278 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
5279 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
5279
5280
5280 return postincoming(ui, repo, modheads, opts.get('update'), None, None)
5281 return postincoming(ui, repo, modheads, opts.get('update'), None, None)
5281
5282
5282 @command('^update|up|checkout|co',
5283 @command('^update|up|checkout|co',
5283 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5284 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5284 ('c', 'check', None, _('require clean working directory')),
5285 ('c', 'check', None, _('require clean working directory')),
5285 ('m', 'merge', None, _('merge uncommitted changes')),
5286 ('m', 'merge', None, _('merge uncommitted changes')),
5286 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5287 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5287 ('r', 'rev', '', _('revision'), _('REV'))
5288 ('r', 'rev', '', _('revision'), _('REV'))
5288 ] + mergetoolopts,
5289 ] + mergetoolopts,
5289 _('[-C|-c|-m] [-d DATE] [[-r] REV]'))
5290 _('[-C|-c|-m] [-d DATE] [[-r] REV]'))
5290 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
5291 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
5291 merge=None, tool=None):
5292 merge=None, tool=None):
5292 """update working directory (or switch revisions)
5293 """update working directory (or switch revisions)
5293
5294
5294 Update the repository's working directory to the specified
5295 Update the repository's working directory to the specified
5295 changeset. If no changeset is specified, update to the tip of the
5296 changeset. If no changeset is specified, update to the tip of the
5296 current named branch and move the active bookmark (see :hg:`help
5297 current named branch and move the active bookmark (see :hg:`help
5297 bookmarks`).
5298 bookmarks`).
5298
5299
5299 Update sets the working directory's parent revision to the specified
5300 Update sets the working directory's parent revision to the specified
5300 changeset (see :hg:`help parents`).
5301 changeset (see :hg:`help parents`).
5301
5302
5302 If the changeset is not a descendant or ancestor of the working
5303 If the changeset is not a descendant or ancestor of the working
5303 directory's parent and there are uncommitted changes, the update is
5304 directory's parent and there are uncommitted changes, the update is
5304 aborted. With the -c/--check option, the working directory is checked
5305 aborted. With the -c/--check option, the working directory is checked
5305 for uncommitted changes; if none are found, the working directory is
5306 for uncommitted changes; if none are found, the working directory is
5306 updated to the specified changeset.
5307 updated to the specified changeset.
5307
5308
5308 .. container:: verbose
5309 .. container:: verbose
5309
5310
5310 The -C/--clean, -c/--check, and -m/--merge options control what
5311 The -C/--clean, -c/--check, and -m/--merge options control what
5311 happens if the working directory contains uncommitted changes.
5312 happens if the working directory contains uncommitted changes.
5312 At most of one of them can be specified.
5313 At most of one of them can be specified.
5313
5314
5314 1. If no option is specified, and if
5315 1. If no option is specified, and if
5315 the requested changeset is an ancestor or descendant of
5316 the requested changeset is an ancestor or descendant of
5316 the working directory's parent, the uncommitted changes
5317 the working directory's parent, the uncommitted changes
5317 are merged into the requested changeset and the merged
5318 are merged into the requested changeset and the merged
5318 result is left uncommitted. If the requested changeset is
5319 result is left uncommitted. If the requested changeset is
5319 not an ancestor or descendant (that is, it is on another
5320 not an ancestor or descendant (that is, it is on another
5320 branch), the update is aborted and the uncommitted changes
5321 branch), the update is aborted and the uncommitted changes
5321 are preserved.
5322 are preserved.
5322
5323
5323 2. With the -m/--merge option, the update is allowed even if the
5324 2. With the -m/--merge option, the update is allowed even if the
5324 requested changeset is not an ancestor or descendant of
5325 requested changeset is not an ancestor or descendant of
5325 the working directory's parent.
5326 the working directory's parent.
5326
5327
5327 3. With the -c/--check option, the update is aborted and the
5328 3. With the -c/--check option, the update is aborted and the
5328 uncommitted changes are preserved.
5329 uncommitted changes are preserved.
5329
5330
5330 4. With the -C/--clean option, uncommitted changes are discarded and
5331 4. With the -C/--clean option, uncommitted changes are discarded and
5331 the working directory is updated to the requested changeset.
5332 the working directory is updated to the requested changeset.
5332
5333
5333 To cancel an uncommitted merge (and lose your changes), use
5334 To cancel an uncommitted merge (and lose your changes), use
5334 :hg:`update --clean .`.
5335 :hg:`update --clean .`.
5335
5336
5336 Use null as the changeset to remove the working directory (like
5337 Use null as the changeset to remove the working directory (like
5337 :hg:`clone -U`).
5338 :hg:`clone -U`).
5338
5339
5339 If you want to revert just one file to an older revision, use
5340 If you want to revert just one file to an older revision, use
5340 :hg:`revert [-r REV] NAME`.
5341 :hg:`revert [-r REV] NAME`.
5341
5342
5342 See :hg:`help dates` for a list of formats valid for -d/--date.
5343 See :hg:`help dates` for a list of formats valid for -d/--date.
5343
5344
5344 Returns 0 on success, 1 if there are unresolved files.
5345 Returns 0 on success, 1 if there are unresolved files.
5345 """
5346 """
5346 if rev and node:
5347 if rev and node:
5347 raise error.Abort(_("please specify just one revision"))
5348 raise error.Abort(_("please specify just one revision"))
5348
5349
5349 if rev is None or rev == '':
5350 if rev is None or rev == '':
5350 rev = node
5351 rev = node
5351
5352
5352 if date and rev is not None:
5353 if date and rev is not None:
5353 raise error.Abort(_("you can't specify a revision and a date"))
5354 raise error.Abort(_("you can't specify a revision and a date"))
5354
5355
5355 if len([x for x in (clean, check, merge) if x]) > 1:
5356 if len([x for x in (clean, check, merge) if x]) > 1:
5356 raise error.Abort(_("can only specify one of -C/--clean, -c/--check, "
5357 raise error.Abort(_("can only specify one of -C/--clean, -c/--check, "
5357 "or -m/merge"))
5358 "or -m/merge"))
5358
5359
5359 updatecheck = None
5360 updatecheck = None
5360 if check:
5361 if check:
5361 updatecheck = 'abort'
5362 updatecheck = 'abort'
5362 elif merge:
5363 elif merge:
5363 updatecheck = 'none'
5364 updatecheck = 'none'
5364
5365
5365 with repo.wlock():
5366 with repo.wlock():
5366 cmdutil.clearunfinished(repo)
5367 cmdutil.clearunfinished(repo)
5367
5368
5368 if date:
5369 if date:
5369 rev = cmdutil.finddate(ui, repo, date)
5370 rev = cmdutil.finddate(ui, repo, date)
5370
5371
5371 # if we defined a bookmark, we have to remember the original name
5372 # if we defined a bookmark, we have to remember the original name
5372 brev = rev
5373 brev = rev
5373 rev = scmutil.revsingle(repo, rev, rev).rev()
5374 rev = scmutil.revsingle(repo, rev, rev).rev()
5374
5375
5375 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
5376 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
5376
5377
5377 return hg.updatetotally(ui, repo, rev, brev, clean=clean,
5378 return hg.updatetotally(ui, repo, rev, brev, clean=clean,
5378 updatecheck=updatecheck)
5379 updatecheck=updatecheck)
5379
5380
5380 @command('verify', [])
5381 @command('verify', [])
5381 def verify(ui, repo):
5382 def verify(ui, repo):
5382 """verify the integrity of the repository
5383 """verify the integrity of the repository
5383
5384
5384 Verify the integrity of the current repository.
5385 Verify the integrity of the current repository.
5385
5386
5386 This will perform an extensive check of the repository's
5387 This will perform an extensive check of the repository's
5387 integrity, validating the hashes and checksums of each entry in
5388 integrity, validating the hashes and checksums of each entry in
5388 the changelog, manifest, and tracked files, as well as the
5389 the changelog, manifest, and tracked files, as well as the
5389 integrity of their crosslinks and indices.
5390 integrity of their crosslinks and indices.
5390
5391
5391 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
5392 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
5392 for more information about recovery from corruption of the
5393 for more information about recovery from corruption of the
5393 repository.
5394 repository.
5394
5395
5395 Returns 0 on success, 1 if errors are encountered.
5396 Returns 0 on success, 1 if errors are encountered.
5396 """
5397 """
5397 return hg.verify(repo)
5398 return hg.verify(repo)
5398
5399
5399 @command('version', [] + formatteropts, norepo=True)
5400 @command('version', [] + formatteropts, norepo=True)
5400 def version_(ui, **opts):
5401 def version_(ui, **opts):
5401 """output version and copyright information"""
5402 """output version and copyright information"""
5402 if ui.verbose:
5403 if ui.verbose:
5403 ui.pager('version')
5404 ui.pager('version')
5404 fm = ui.formatter("version", opts)
5405 fm = ui.formatter("version", opts)
5405 fm.startitem()
5406 fm.startitem()
5406 fm.write("ver", _("Mercurial Distributed SCM (version %s)\n"),
5407 fm.write("ver", _("Mercurial Distributed SCM (version %s)\n"),
5407 util.version())
5408 util.version())
5408 license = _(
5409 license = _(
5409 "(see https://mercurial-scm.org for more information)\n"
5410 "(see https://mercurial-scm.org for more information)\n"
5410 "\nCopyright (C) 2005-2017 Matt Mackall and others\n"
5411 "\nCopyright (C) 2005-2017 Matt Mackall and others\n"
5411 "This is free software; see the source for copying conditions. "
5412 "This is free software; see the source for copying conditions. "
5412 "There is NO\nwarranty; "
5413 "There is NO\nwarranty; "
5413 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5414 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5414 )
5415 )
5415 if not ui.quiet:
5416 if not ui.quiet:
5416 fm.plain(license)
5417 fm.plain(license)
5417
5418
5418 if ui.verbose:
5419 if ui.verbose:
5419 fm.plain(_("\nEnabled extensions:\n\n"))
5420 fm.plain(_("\nEnabled extensions:\n\n"))
5420 # format names and versions into columns
5421 # format names and versions into columns
5421 names = []
5422 names = []
5422 vers = []
5423 vers = []
5423 isinternals = []
5424 isinternals = []
5424 for name, module in extensions.extensions():
5425 for name, module in extensions.extensions():
5425 names.append(name)
5426 names.append(name)
5426 vers.append(extensions.moduleversion(module) or None)
5427 vers.append(extensions.moduleversion(module) or None)
5427 isinternals.append(extensions.ismoduleinternal(module))
5428 isinternals.append(extensions.ismoduleinternal(module))
5428 fn = fm.nested("extensions")
5429 fn = fm.nested("extensions")
5429 if names:
5430 if names:
5430 namefmt = " %%-%ds " % max(len(n) for n in names)
5431 namefmt = " %%-%ds " % max(len(n) for n in names)
5431 places = [_("external"), _("internal")]
5432 places = [_("external"), _("internal")]
5432 for n, v, p in zip(names, vers, isinternals):
5433 for n, v, p in zip(names, vers, isinternals):
5433 fn.startitem()
5434 fn.startitem()
5434 fn.condwrite(ui.verbose, "name", namefmt, n)
5435 fn.condwrite(ui.verbose, "name", namefmt, n)
5435 if ui.verbose:
5436 if ui.verbose:
5436 fn.plain("%s " % places[p])
5437 fn.plain("%s " % places[p])
5437 fn.data(bundled=p)
5438 fn.data(bundled=p)
5438 fn.condwrite(ui.verbose and v, "ver", "%s", v)
5439 fn.condwrite(ui.verbose and v, "ver", "%s", v)
5439 if ui.verbose:
5440 if ui.verbose:
5440 fn.plain("\n")
5441 fn.plain("\n")
5441 fn.end()
5442 fn.end()
5442 fm.end()
5443 fm.end()
5443
5444
5444 def loadcmdtable(ui, name, cmdtable):
5445 def loadcmdtable(ui, name, cmdtable):
5445 """Load command functions from specified cmdtable
5446 """Load command functions from specified cmdtable
5446 """
5447 """
5447 overrides = [cmd for cmd in cmdtable if cmd in table]
5448 overrides = [cmd for cmd in cmdtable if cmd in table]
5448 if overrides:
5449 if overrides:
5449 ui.warn(_("extension '%s' overrides commands: %s\n")
5450 ui.warn(_("extension '%s' overrides commands: %s\n")
5450 % (name, " ".join(overrides)))
5451 % (name, " ".join(overrides)))
5451 table.update(cmdtable)
5452 table.update(cmdtable)
General Comments 0
You need to be logged in to leave comments. Login now