##// END OF EJS Templates
bundle: handle compression earlier...
marmoute -
r32215:e17b8466 default
parent child Browse files
Show More
@@ -1,5517 +1,5517 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 rcutil,
46 rcutil,
47 revsetlang,
47 revsetlang,
48 scmutil,
48 scmutil,
49 server,
49 server,
50 sshserver,
50 sshserver,
51 streamclone,
51 streamclone,
52 tags as tagsmod,
52 tags as tagsmod,
53 templatekw,
53 templatekw,
54 ui as uimod,
54 ui as uimod,
55 util,
55 util,
56 )
56 )
57
57
58 release = lockmod.release
58 release = lockmod.release
59
59
60 table = {}
60 table = {}
61
61
62 command = cmdutil.command(table)
62 command = cmdutil.command(table)
63
63
64 # label constants
64 # label constants
65 # until 3.5, bookmarks.current was the advertised name, not
65 # until 3.5, bookmarks.current was the advertised name, not
66 # bookmarks.active, so we must use both to avoid breaking old
66 # bookmarks.active, so we must use both to avoid breaking old
67 # custom styles
67 # custom styles
68 activebookmarklabel = 'bookmarks.active bookmarks.current'
68 activebookmarklabel = 'bookmarks.active bookmarks.current'
69
69
70 # common command options
70 # common command options
71
71
72 globalopts = [
72 globalopts = [
73 ('R', 'repository', '',
73 ('R', 'repository', '',
74 _('repository root directory or name of overlay bundle file'),
74 _('repository root directory or name of overlay bundle file'),
75 _('REPO')),
75 _('REPO')),
76 ('', 'cwd', '',
76 ('', 'cwd', '',
77 _('change working directory'), _('DIR')),
77 _('change working directory'), _('DIR')),
78 ('y', 'noninteractive', None,
78 ('y', 'noninteractive', None,
79 _('do not prompt, automatically pick the first choice for all prompts')),
79 _('do not prompt, automatically pick the first choice for all prompts')),
80 ('q', 'quiet', None, _('suppress output')),
80 ('q', 'quiet', None, _('suppress output')),
81 ('v', 'verbose', None, _('enable additional output')),
81 ('v', 'verbose', None, _('enable additional output')),
82 ('', 'color', '',
82 ('', 'color', '',
83 # i18n: 'always', 'auto', 'never', and 'debug' are keywords
83 # i18n: 'always', 'auto', 'never', and 'debug' are keywords
84 # and should not be translated
84 # and should not be translated
85 _("when to colorize (boolean, always, auto, never, or debug)"),
85 _("when to colorize (boolean, always, auto, never, or debug)"),
86 _('TYPE')),
86 _('TYPE')),
87 ('', 'config', [],
87 ('', 'config', [],
88 _('set/override config option (use \'section.name=value\')'),
88 _('set/override config option (use \'section.name=value\')'),
89 _('CONFIG')),
89 _('CONFIG')),
90 ('', 'debug', None, _('enable debugging output')),
90 ('', 'debug', None, _('enable debugging output')),
91 ('', 'debugger', None, _('start debugger')),
91 ('', 'debugger', None, _('start debugger')),
92 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
92 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
93 _('ENCODE')),
93 _('ENCODE')),
94 ('', 'encodingmode', encoding.encodingmode,
94 ('', 'encodingmode', encoding.encodingmode,
95 _('set the charset encoding mode'), _('MODE')),
95 _('set the charset encoding mode'), _('MODE')),
96 ('', 'traceback', None, _('always print a traceback on exception')),
96 ('', 'traceback', None, _('always print a traceback on exception')),
97 ('', 'time', None, _('time how long the command takes')),
97 ('', 'time', None, _('time how long the command takes')),
98 ('', 'profile', None, _('print command execution profile')),
98 ('', 'profile', None, _('print command execution profile')),
99 ('', 'version', None, _('output version information and exit')),
99 ('', 'version', None, _('output version information and exit')),
100 ('h', 'help', None, _('display help and exit')),
100 ('h', 'help', None, _('display help and exit')),
101 ('', 'hidden', False, _('consider hidden changesets')),
101 ('', 'hidden', False, _('consider hidden changesets')),
102 ('', 'pager', 'auto',
102 ('', 'pager', 'auto',
103 _("when to paginate (boolean, always, auto, or never)"), _('TYPE')),
103 _("when to paginate (boolean, always, auto, or never)"), _('TYPE')),
104 ]
104 ]
105
105
106 dryrunopts = [('n', 'dry-run', None,
106 dryrunopts = [('n', 'dry-run', None,
107 _('do not perform actions, just print output'))]
107 _('do not perform actions, just print output'))]
108
108
109 remoteopts = [
109 remoteopts = [
110 ('e', 'ssh', '',
110 ('e', 'ssh', '',
111 _('specify ssh command to use'), _('CMD')),
111 _('specify ssh command to use'), _('CMD')),
112 ('', 'remotecmd', '',
112 ('', 'remotecmd', '',
113 _('specify hg command to run on the remote side'), _('CMD')),
113 _('specify hg command to run on the remote side'), _('CMD')),
114 ('', 'insecure', None,
114 ('', 'insecure', None,
115 _('do not verify server certificate (ignoring web.cacerts config)')),
115 _('do not verify server certificate (ignoring web.cacerts config)')),
116 ]
116 ]
117
117
118 walkopts = [
118 walkopts = [
119 ('I', 'include', [],
119 ('I', 'include', [],
120 _('include names matching the given patterns'), _('PATTERN')),
120 _('include names matching the given patterns'), _('PATTERN')),
121 ('X', 'exclude', [],
121 ('X', 'exclude', [],
122 _('exclude names matching the given patterns'), _('PATTERN')),
122 _('exclude names matching the given patterns'), _('PATTERN')),
123 ]
123 ]
124
124
125 commitopts = [
125 commitopts = [
126 ('m', 'message', '',
126 ('m', 'message', '',
127 _('use text as commit message'), _('TEXT')),
127 _('use text as commit message'), _('TEXT')),
128 ('l', 'logfile', '',
128 ('l', 'logfile', '',
129 _('read commit message from file'), _('FILE')),
129 _('read commit message from file'), _('FILE')),
130 ]
130 ]
131
131
132 commitopts2 = [
132 commitopts2 = [
133 ('d', 'date', '',
133 ('d', 'date', '',
134 _('record the specified date as commit date'), _('DATE')),
134 _('record the specified date as commit date'), _('DATE')),
135 ('u', 'user', '',
135 ('u', 'user', '',
136 _('record the specified user as committer'), _('USER')),
136 _('record the specified user as committer'), _('USER')),
137 ]
137 ]
138
138
139 # hidden for now
139 # hidden for now
140 formatteropts = [
140 formatteropts = [
141 ('T', 'template', '',
141 ('T', 'template', '',
142 _('display with template (EXPERIMENTAL)'), _('TEMPLATE')),
142 _('display with template (EXPERIMENTAL)'), _('TEMPLATE')),
143 ]
143 ]
144
144
145 templateopts = [
145 templateopts = [
146 ('', 'style', '',
146 ('', 'style', '',
147 _('display using template map file (DEPRECATED)'), _('STYLE')),
147 _('display using template map file (DEPRECATED)'), _('STYLE')),
148 ('T', 'template', '',
148 ('T', 'template', '',
149 _('display with template'), _('TEMPLATE')),
149 _('display with template'), _('TEMPLATE')),
150 ]
150 ]
151
151
152 logopts = [
152 logopts = [
153 ('p', 'patch', None, _('show patch')),
153 ('p', 'patch', None, _('show patch')),
154 ('g', 'git', None, _('use git extended diff format')),
154 ('g', 'git', None, _('use git extended diff format')),
155 ('l', 'limit', '',
155 ('l', 'limit', '',
156 _('limit number of changes displayed'), _('NUM')),
156 _('limit number of changes displayed'), _('NUM')),
157 ('M', 'no-merges', None, _('do not show merges')),
157 ('M', 'no-merges', None, _('do not show merges')),
158 ('', 'stat', None, _('output diffstat-style summary of changes')),
158 ('', 'stat', None, _('output diffstat-style summary of changes')),
159 ('G', 'graph', None, _("show the revision DAG")),
159 ('G', 'graph', None, _("show the revision DAG")),
160 ] + templateopts
160 ] + templateopts
161
161
162 diffopts = [
162 diffopts = [
163 ('a', 'text', None, _('treat all files as text')),
163 ('a', 'text', None, _('treat all files as text')),
164 ('g', 'git', None, _('use git extended diff format')),
164 ('g', 'git', None, _('use git extended diff format')),
165 ('', 'binary', None, _('generate binary diffs in git mode (default)')),
165 ('', 'binary', None, _('generate binary diffs in git mode (default)')),
166 ('', 'nodates', None, _('omit dates from diff headers'))
166 ('', 'nodates', None, _('omit dates from diff headers'))
167 ]
167 ]
168
168
169 diffwsopts = [
169 diffwsopts = [
170 ('w', 'ignore-all-space', None,
170 ('w', 'ignore-all-space', None,
171 _('ignore white space when comparing lines')),
171 _('ignore white space when comparing lines')),
172 ('b', 'ignore-space-change', None,
172 ('b', 'ignore-space-change', None,
173 _('ignore changes in the amount of white space')),
173 _('ignore changes in the amount of white space')),
174 ('B', 'ignore-blank-lines', None,
174 ('B', 'ignore-blank-lines', None,
175 _('ignore changes whose lines are all blank')),
175 _('ignore changes whose lines are all blank')),
176 ]
176 ]
177
177
178 diffopts2 = [
178 diffopts2 = [
179 ('', 'noprefix', None, _('omit a/ and b/ prefixes from filenames')),
179 ('', 'noprefix', None, _('omit a/ and b/ prefixes from filenames')),
180 ('p', 'show-function', None, _('show which function each change is in')),
180 ('p', 'show-function', None, _('show which function each change is in')),
181 ('', 'reverse', None, _('produce a diff that undoes the changes')),
181 ('', 'reverse', None, _('produce a diff that undoes the changes')),
182 ] + diffwsopts + [
182 ] + diffwsopts + [
183 ('U', 'unified', '',
183 ('U', 'unified', '',
184 _('number of lines of context to show'), _('NUM')),
184 _('number of lines of context to show'), _('NUM')),
185 ('', 'stat', None, _('output diffstat-style summary of changes')),
185 ('', 'stat', None, _('output diffstat-style summary of changes')),
186 ('', 'root', '', _('produce diffs relative to subdirectory'), _('DIR')),
186 ('', 'root', '', _('produce diffs relative to subdirectory'), _('DIR')),
187 ]
187 ]
188
188
189 mergetoolopts = [
189 mergetoolopts = [
190 ('t', 'tool', '', _('specify merge tool')),
190 ('t', 'tool', '', _('specify merge tool')),
191 ]
191 ]
192
192
193 similarityopts = [
193 similarityopts = [
194 ('s', 'similarity', '',
194 ('s', 'similarity', '',
195 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
195 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
196 ]
196 ]
197
197
198 subrepoopts = [
198 subrepoopts = [
199 ('S', 'subrepos', None,
199 ('S', 'subrepos', None,
200 _('recurse into subrepositories'))
200 _('recurse into subrepositories'))
201 ]
201 ]
202
202
203 debugrevlogopts = [
203 debugrevlogopts = [
204 ('c', 'changelog', False, _('open changelog')),
204 ('c', 'changelog', False, _('open changelog')),
205 ('m', 'manifest', False, _('open manifest')),
205 ('m', 'manifest', False, _('open manifest')),
206 ('', 'dir', '', _('open directory manifest')),
206 ('', 'dir', '', _('open directory manifest')),
207 ]
207 ]
208
208
209 # Commands start here, listed alphabetically
209 # Commands start here, listed alphabetically
210
210
211 @command('^add',
211 @command('^add',
212 walkopts + subrepoopts + dryrunopts,
212 walkopts + subrepoopts + dryrunopts,
213 _('[OPTION]... [FILE]...'),
213 _('[OPTION]... [FILE]...'),
214 inferrepo=True)
214 inferrepo=True)
215 def add(ui, repo, *pats, **opts):
215 def add(ui, repo, *pats, **opts):
216 """add the specified files on the next commit
216 """add the specified files on the next commit
217
217
218 Schedule files to be version controlled and added to the
218 Schedule files to be version controlled and added to the
219 repository.
219 repository.
220
220
221 The files will be added to the repository at the next commit. To
221 The files will be added to the repository at the next commit. To
222 undo an add before that, see :hg:`forget`.
222 undo an add before that, see :hg:`forget`.
223
223
224 If no names are given, add all files to the repository (except
224 If no names are given, add all files to the repository (except
225 files matching ``.hgignore``).
225 files matching ``.hgignore``).
226
226
227 .. container:: verbose
227 .. container:: verbose
228
228
229 Examples:
229 Examples:
230
230
231 - New (unknown) files are added
231 - New (unknown) files are added
232 automatically by :hg:`add`::
232 automatically by :hg:`add`::
233
233
234 $ ls
234 $ ls
235 foo.c
235 foo.c
236 $ hg status
236 $ hg status
237 ? foo.c
237 ? foo.c
238 $ hg add
238 $ hg add
239 adding foo.c
239 adding foo.c
240 $ hg status
240 $ hg status
241 A foo.c
241 A foo.c
242
242
243 - Specific files to be added can be specified::
243 - Specific files to be added can be specified::
244
244
245 $ ls
245 $ ls
246 bar.c foo.c
246 bar.c foo.c
247 $ hg status
247 $ hg status
248 ? bar.c
248 ? bar.c
249 ? foo.c
249 ? foo.c
250 $ hg add bar.c
250 $ hg add bar.c
251 $ hg status
251 $ hg status
252 A bar.c
252 A bar.c
253 ? foo.c
253 ? foo.c
254
254
255 Returns 0 if all files are successfully added.
255 Returns 0 if all files are successfully added.
256 """
256 """
257
257
258 m = scmutil.match(repo[None], pats, pycompat.byteskwargs(opts))
258 m = scmutil.match(repo[None], pats, pycompat.byteskwargs(opts))
259 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
259 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
260 return rejected and 1 or 0
260 return rejected and 1 or 0
261
261
262 @command('addremove',
262 @command('addremove',
263 similarityopts + subrepoopts + walkopts + dryrunopts,
263 similarityopts + subrepoopts + walkopts + dryrunopts,
264 _('[OPTION]... [FILE]...'),
264 _('[OPTION]... [FILE]...'),
265 inferrepo=True)
265 inferrepo=True)
266 def addremove(ui, repo, *pats, **opts):
266 def addremove(ui, repo, *pats, **opts):
267 """add all new files, delete all missing files
267 """add all new files, delete all missing files
268
268
269 Add all new files and remove all missing files from the
269 Add all new files and remove all missing files from the
270 repository.
270 repository.
271
271
272 Unless names are given, new files are ignored if they match any of
272 Unless names are given, new files are ignored if they match any of
273 the patterns in ``.hgignore``. As with add, these changes take
273 the patterns in ``.hgignore``. As with add, these changes take
274 effect at the next commit.
274 effect at the next commit.
275
275
276 Use the -s/--similarity option to detect renamed files. This
276 Use the -s/--similarity option to detect renamed files. This
277 option takes a percentage between 0 (disabled) and 100 (files must
277 option takes a percentage between 0 (disabled) and 100 (files must
278 be identical) as its parameter. With a parameter greater than 0,
278 be identical) as its parameter. With a parameter greater than 0,
279 this compares every removed file with every added file and records
279 this compares every removed file with every added file and records
280 those similar enough as renames. Detecting renamed files this way
280 those similar enough as renames. Detecting renamed files this way
281 can be expensive. After using this option, :hg:`status -C` can be
281 can be expensive. After using this option, :hg:`status -C` can be
282 used to check which files were identified as moved or renamed. If
282 used to check which files were identified as moved or renamed. If
283 not specified, -s/--similarity defaults to 100 and only renames of
283 not specified, -s/--similarity defaults to 100 and only renames of
284 identical files are detected.
284 identical files are detected.
285
285
286 .. container:: verbose
286 .. container:: verbose
287
287
288 Examples:
288 Examples:
289
289
290 - A number of files (bar.c and foo.c) are new,
290 - A number of files (bar.c and foo.c) are new,
291 while foobar.c has been removed (without using :hg:`remove`)
291 while foobar.c has been removed (without using :hg:`remove`)
292 from the repository::
292 from the repository::
293
293
294 $ ls
294 $ ls
295 bar.c foo.c
295 bar.c foo.c
296 $ hg status
296 $ hg status
297 ! foobar.c
297 ! foobar.c
298 ? bar.c
298 ? bar.c
299 ? foo.c
299 ? foo.c
300 $ hg addremove
300 $ hg addremove
301 adding bar.c
301 adding bar.c
302 adding foo.c
302 adding foo.c
303 removing foobar.c
303 removing foobar.c
304 $ hg status
304 $ hg status
305 A bar.c
305 A bar.c
306 A foo.c
306 A foo.c
307 R foobar.c
307 R foobar.c
308
308
309 - A file foobar.c was moved to foo.c without using :hg:`rename`.
309 - A file foobar.c was moved to foo.c without using :hg:`rename`.
310 Afterwards, it was edited slightly::
310 Afterwards, it was edited slightly::
311
311
312 $ ls
312 $ ls
313 foo.c
313 foo.c
314 $ hg status
314 $ hg status
315 ! foobar.c
315 ! foobar.c
316 ? foo.c
316 ? foo.c
317 $ hg addremove --similarity 90
317 $ hg addremove --similarity 90
318 removing foobar.c
318 removing foobar.c
319 adding foo.c
319 adding foo.c
320 recording removal of foobar.c as rename to foo.c (94% similar)
320 recording removal of foobar.c as rename to foo.c (94% similar)
321 $ hg status -C
321 $ hg status -C
322 A foo.c
322 A foo.c
323 foobar.c
323 foobar.c
324 R foobar.c
324 R foobar.c
325
325
326 Returns 0 if all files are successfully added.
326 Returns 0 if all files are successfully added.
327 """
327 """
328 opts = pycompat.byteskwargs(opts)
328 opts = pycompat.byteskwargs(opts)
329 try:
329 try:
330 sim = float(opts.get('similarity') or 100)
330 sim = float(opts.get('similarity') or 100)
331 except ValueError:
331 except ValueError:
332 raise error.Abort(_('similarity must be a number'))
332 raise error.Abort(_('similarity must be a number'))
333 if sim < 0 or sim > 100:
333 if sim < 0 or sim > 100:
334 raise error.Abort(_('similarity must be between 0 and 100'))
334 raise error.Abort(_('similarity must be between 0 and 100'))
335 matcher = scmutil.match(repo[None], pats, opts)
335 matcher = scmutil.match(repo[None], pats, opts)
336 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
336 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
337
337
338 @command('^annotate|blame',
338 @command('^annotate|blame',
339 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
339 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
340 ('', 'follow', None,
340 ('', 'follow', None,
341 _('follow copies/renames and list the filename (DEPRECATED)')),
341 _('follow copies/renames and list the filename (DEPRECATED)')),
342 ('', 'no-follow', None, _("don't follow copies and renames")),
342 ('', 'no-follow', None, _("don't follow copies and renames")),
343 ('a', 'text', None, _('treat all files as text')),
343 ('a', 'text', None, _('treat all files as text')),
344 ('u', 'user', None, _('list the author (long with -v)')),
344 ('u', 'user', None, _('list the author (long with -v)')),
345 ('f', 'file', None, _('list the filename')),
345 ('f', 'file', None, _('list the filename')),
346 ('d', 'date', None, _('list the date (short with -q)')),
346 ('d', 'date', None, _('list the date (short with -q)')),
347 ('n', 'number', None, _('list the revision number (default)')),
347 ('n', 'number', None, _('list the revision number (default)')),
348 ('c', 'changeset', None, _('list the changeset')),
348 ('c', 'changeset', None, _('list the changeset')),
349 ('l', 'line-number', None, _('show line number at the first appearance'))
349 ('l', 'line-number', None, _('show line number at the first appearance'))
350 ] + diffwsopts + walkopts + formatteropts,
350 ] + diffwsopts + walkopts + formatteropts,
351 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
351 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
352 inferrepo=True)
352 inferrepo=True)
353 def annotate(ui, repo, *pats, **opts):
353 def annotate(ui, repo, *pats, **opts):
354 """show changeset information by line for each file
354 """show changeset information by line for each file
355
355
356 List changes in files, showing the revision id responsible for
356 List changes in files, showing the revision id responsible for
357 each line.
357 each line.
358
358
359 This command is useful for discovering when a change was made and
359 This command is useful for discovering when a change was made and
360 by whom.
360 by whom.
361
361
362 If you include --file, --user, or --date, the revision number is
362 If you include --file, --user, or --date, the revision number is
363 suppressed unless you also include --number.
363 suppressed unless you also include --number.
364
364
365 Without the -a/--text option, annotate will avoid processing files
365 Without the -a/--text option, annotate will avoid processing files
366 it detects as binary. With -a, annotate will annotate the file
366 it detects as binary. With -a, annotate will annotate the file
367 anyway, although the results will probably be neither useful
367 anyway, although the results will probably be neither useful
368 nor desirable.
368 nor desirable.
369
369
370 Returns 0 on success.
370 Returns 0 on success.
371 """
371 """
372 opts = pycompat.byteskwargs(opts)
372 opts = pycompat.byteskwargs(opts)
373 if not pats:
373 if not pats:
374 raise error.Abort(_('at least one filename or pattern is required'))
374 raise error.Abort(_('at least one filename or pattern is required'))
375
375
376 if opts.get('follow'):
376 if opts.get('follow'):
377 # --follow is deprecated and now just an alias for -f/--file
377 # --follow is deprecated and now just an alias for -f/--file
378 # to mimic the behavior of Mercurial before version 1.5
378 # to mimic the behavior of Mercurial before version 1.5
379 opts['file'] = True
379 opts['file'] = True
380
380
381 ctx = scmutil.revsingle(repo, opts.get('rev'))
381 ctx = scmutil.revsingle(repo, opts.get('rev'))
382
382
383 fm = ui.formatter('annotate', opts)
383 fm = ui.formatter('annotate', opts)
384 if ui.quiet:
384 if ui.quiet:
385 datefunc = util.shortdate
385 datefunc = util.shortdate
386 else:
386 else:
387 datefunc = util.datestr
387 datefunc = util.datestr
388 if ctx.rev() is None:
388 if ctx.rev() is None:
389 def hexfn(node):
389 def hexfn(node):
390 if node is None:
390 if node is None:
391 return None
391 return None
392 else:
392 else:
393 return fm.hexfunc(node)
393 return fm.hexfunc(node)
394 if opts.get('changeset'):
394 if opts.get('changeset'):
395 # omit "+" suffix which is appended to node hex
395 # omit "+" suffix which is appended to node hex
396 def formatrev(rev):
396 def formatrev(rev):
397 if rev is None:
397 if rev is None:
398 return '%d' % ctx.p1().rev()
398 return '%d' % ctx.p1().rev()
399 else:
399 else:
400 return '%d' % rev
400 return '%d' % rev
401 else:
401 else:
402 def formatrev(rev):
402 def formatrev(rev):
403 if rev is None:
403 if rev is None:
404 return '%d+' % ctx.p1().rev()
404 return '%d+' % ctx.p1().rev()
405 else:
405 else:
406 return '%d ' % rev
406 return '%d ' % rev
407 def formathex(hex):
407 def formathex(hex):
408 if hex is None:
408 if hex is None:
409 return '%s+' % fm.hexfunc(ctx.p1().node())
409 return '%s+' % fm.hexfunc(ctx.p1().node())
410 else:
410 else:
411 return '%s ' % hex
411 return '%s ' % hex
412 else:
412 else:
413 hexfn = fm.hexfunc
413 hexfn = fm.hexfunc
414 formatrev = formathex = str
414 formatrev = formathex = str
415
415
416 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
416 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
417 ('number', ' ', lambda x: x[0].rev(), formatrev),
417 ('number', ' ', lambda x: x[0].rev(), formatrev),
418 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
418 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
419 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
419 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
420 ('file', ' ', lambda x: x[0].path(), str),
420 ('file', ' ', lambda x: x[0].path(), str),
421 ('line_number', ':', lambda x: x[1], str),
421 ('line_number', ':', lambda x: x[1], str),
422 ]
422 ]
423 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
423 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
424
424
425 if (not opts.get('user') and not opts.get('changeset')
425 if (not opts.get('user') and not opts.get('changeset')
426 and not opts.get('date') and not opts.get('file')):
426 and not opts.get('date') and not opts.get('file')):
427 opts['number'] = True
427 opts['number'] = True
428
428
429 linenumber = opts.get('line_number') is not None
429 linenumber = opts.get('line_number') is not None
430 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
430 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
431 raise error.Abort(_('at least one of -n/-c is required for -l'))
431 raise error.Abort(_('at least one of -n/-c is required for -l'))
432
432
433 ui.pager('annotate')
433 ui.pager('annotate')
434
434
435 if fm.isplain():
435 if fm.isplain():
436 def makefunc(get, fmt):
436 def makefunc(get, fmt):
437 return lambda x: fmt(get(x))
437 return lambda x: fmt(get(x))
438 else:
438 else:
439 def makefunc(get, fmt):
439 def makefunc(get, fmt):
440 return get
440 return get
441 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
441 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
442 if opts.get(op)]
442 if opts.get(op)]
443 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
443 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
444 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
444 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
445 if opts.get(op))
445 if opts.get(op))
446
446
447 def bad(x, y):
447 def bad(x, y):
448 raise error.Abort("%s: %s" % (x, y))
448 raise error.Abort("%s: %s" % (x, y))
449
449
450 m = scmutil.match(ctx, pats, opts, badfn=bad)
450 m = scmutil.match(ctx, pats, opts, badfn=bad)
451
451
452 follow = not opts.get('no_follow')
452 follow = not opts.get('no_follow')
453 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
453 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
454 whitespace=True)
454 whitespace=True)
455 for abs in ctx.walk(m):
455 for abs in ctx.walk(m):
456 fctx = ctx[abs]
456 fctx = ctx[abs]
457 if not opts.get('text') and fctx.isbinary():
457 if not opts.get('text') and fctx.isbinary():
458 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
458 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
459 continue
459 continue
460
460
461 lines = fctx.annotate(follow=follow, linenumber=linenumber,
461 lines = fctx.annotate(follow=follow, linenumber=linenumber,
462 diffopts=diffopts)
462 diffopts=diffopts)
463 if not lines:
463 if not lines:
464 continue
464 continue
465 formats = []
465 formats = []
466 pieces = []
466 pieces = []
467
467
468 for f, sep in funcmap:
468 for f, sep in funcmap:
469 l = [f(n) for n, dummy in lines]
469 l = [f(n) for n, dummy in lines]
470 if fm.isplain():
470 if fm.isplain():
471 sizes = [encoding.colwidth(x) for x in l]
471 sizes = [encoding.colwidth(x) for x in l]
472 ml = max(sizes)
472 ml = max(sizes)
473 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
473 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
474 else:
474 else:
475 formats.append(['%s' for x in l])
475 formats.append(['%s' for x in l])
476 pieces.append(l)
476 pieces.append(l)
477
477
478 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
478 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
479 fm.startitem()
479 fm.startitem()
480 fm.write(fields, "".join(f), *p)
480 fm.write(fields, "".join(f), *p)
481 fm.write('line', ": %s", l[1])
481 fm.write('line', ": %s", l[1])
482
482
483 if not lines[-1][1].endswith('\n'):
483 if not lines[-1][1].endswith('\n'):
484 fm.plain('\n')
484 fm.plain('\n')
485
485
486 fm.end()
486 fm.end()
487
487
488 @command('archive',
488 @command('archive',
489 [('', 'no-decode', None, _('do not pass files through decoders')),
489 [('', 'no-decode', None, _('do not pass files through decoders')),
490 ('p', 'prefix', '', _('directory prefix for files in archive'),
490 ('p', 'prefix', '', _('directory prefix for files in archive'),
491 _('PREFIX')),
491 _('PREFIX')),
492 ('r', 'rev', '', _('revision to distribute'), _('REV')),
492 ('r', 'rev', '', _('revision to distribute'), _('REV')),
493 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
493 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
494 ] + subrepoopts + walkopts,
494 ] + subrepoopts + walkopts,
495 _('[OPTION]... DEST'))
495 _('[OPTION]... DEST'))
496 def archive(ui, repo, dest, **opts):
496 def archive(ui, repo, dest, **opts):
497 '''create an unversioned archive of a repository revision
497 '''create an unversioned archive of a repository revision
498
498
499 By default, the revision used is the parent of the working
499 By default, the revision used is the parent of the working
500 directory; use -r/--rev to specify a different revision.
500 directory; use -r/--rev to specify a different revision.
501
501
502 The archive type is automatically detected based on file
502 The archive type is automatically detected based on file
503 extension (to override, use -t/--type).
503 extension (to override, use -t/--type).
504
504
505 .. container:: verbose
505 .. container:: verbose
506
506
507 Examples:
507 Examples:
508
508
509 - create a zip file containing the 1.0 release::
509 - create a zip file containing the 1.0 release::
510
510
511 hg archive -r 1.0 project-1.0.zip
511 hg archive -r 1.0 project-1.0.zip
512
512
513 - create a tarball excluding .hg files::
513 - create a tarball excluding .hg files::
514
514
515 hg archive project.tar.gz -X ".hg*"
515 hg archive project.tar.gz -X ".hg*"
516
516
517 Valid types are:
517 Valid types are:
518
518
519 :``files``: a directory full of files (default)
519 :``files``: a directory full of files (default)
520 :``tar``: tar archive, uncompressed
520 :``tar``: tar archive, uncompressed
521 :``tbz2``: tar archive, compressed using bzip2
521 :``tbz2``: tar archive, compressed using bzip2
522 :``tgz``: tar archive, compressed using gzip
522 :``tgz``: tar archive, compressed using gzip
523 :``uzip``: zip archive, uncompressed
523 :``uzip``: zip archive, uncompressed
524 :``zip``: zip archive, compressed using deflate
524 :``zip``: zip archive, compressed using deflate
525
525
526 The exact name of the destination archive or directory is given
526 The exact name of the destination archive or directory is given
527 using a format string; see :hg:`help export` for details.
527 using a format string; see :hg:`help export` for details.
528
528
529 Each member added to an archive file has a directory prefix
529 Each member added to an archive file has a directory prefix
530 prepended. Use -p/--prefix to specify a format string for the
530 prepended. Use -p/--prefix to specify a format string for the
531 prefix. The default is the basename of the archive, with suffixes
531 prefix. The default is the basename of the archive, with suffixes
532 removed.
532 removed.
533
533
534 Returns 0 on success.
534 Returns 0 on success.
535 '''
535 '''
536
536
537 opts = pycompat.byteskwargs(opts)
537 opts = pycompat.byteskwargs(opts)
538 ctx = scmutil.revsingle(repo, opts.get('rev'))
538 ctx = scmutil.revsingle(repo, opts.get('rev'))
539 if not ctx:
539 if not ctx:
540 raise error.Abort(_('no working directory: please specify a revision'))
540 raise error.Abort(_('no working directory: please specify a revision'))
541 node = ctx.node()
541 node = ctx.node()
542 dest = cmdutil.makefilename(repo, dest, node)
542 dest = cmdutil.makefilename(repo, dest, node)
543 if os.path.realpath(dest) == repo.root:
543 if os.path.realpath(dest) == repo.root:
544 raise error.Abort(_('repository root cannot be destination'))
544 raise error.Abort(_('repository root cannot be destination'))
545
545
546 kind = opts.get('type') or archival.guesskind(dest) or 'files'
546 kind = opts.get('type') or archival.guesskind(dest) or 'files'
547 prefix = opts.get('prefix')
547 prefix = opts.get('prefix')
548
548
549 if dest == '-':
549 if dest == '-':
550 if kind == 'files':
550 if kind == 'files':
551 raise error.Abort(_('cannot archive plain files to stdout'))
551 raise error.Abort(_('cannot archive plain files to stdout'))
552 dest = cmdutil.makefileobj(repo, dest)
552 dest = cmdutil.makefileobj(repo, dest)
553 if not prefix:
553 if not prefix:
554 prefix = os.path.basename(repo.root) + '-%h'
554 prefix = os.path.basename(repo.root) + '-%h'
555
555
556 prefix = cmdutil.makefilename(repo, prefix, node)
556 prefix = cmdutil.makefilename(repo, prefix, node)
557 matchfn = scmutil.match(ctx, [], opts)
557 matchfn = scmutil.match(ctx, [], opts)
558 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
558 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
559 matchfn, prefix, subrepos=opts.get('subrepos'))
559 matchfn, prefix, subrepos=opts.get('subrepos'))
560
560
561 @command('backout',
561 @command('backout',
562 [('', 'merge', None, _('merge with old dirstate parent after backout')),
562 [('', 'merge', None, _('merge with old dirstate parent after backout')),
563 ('', 'commit', None,
563 ('', 'commit', None,
564 _('commit if no conflicts were encountered (DEPRECATED)')),
564 _('commit if no conflicts were encountered (DEPRECATED)')),
565 ('', 'no-commit', None, _('do not commit')),
565 ('', 'no-commit', None, _('do not commit')),
566 ('', 'parent', '',
566 ('', 'parent', '',
567 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
567 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
568 ('r', 'rev', '', _('revision to backout'), _('REV')),
568 ('r', 'rev', '', _('revision to backout'), _('REV')),
569 ('e', 'edit', False, _('invoke editor on commit messages')),
569 ('e', 'edit', False, _('invoke editor on commit messages')),
570 ] + mergetoolopts + walkopts + commitopts + commitopts2,
570 ] + mergetoolopts + walkopts + commitopts + commitopts2,
571 _('[OPTION]... [-r] REV'))
571 _('[OPTION]... [-r] REV'))
572 def backout(ui, repo, node=None, rev=None, **opts):
572 def backout(ui, repo, node=None, rev=None, **opts):
573 '''reverse effect of earlier changeset
573 '''reverse effect of earlier changeset
574
574
575 Prepare a new changeset with the effect of REV undone in the
575 Prepare a new changeset with the effect of REV undone in the
576 current working directory. If no conflicts were encountered,
576 current working directory. If no conflicts were encountered,
577 it will be committed immediately.
577 it will be committed immediately.
578
578
579 If REV is the parent of the working directory, then this new changeset
579 If REV is the parent of the working directory, then this new changeset
580 is committed automatically (unless --no-commit is specified).
580 is committed automatically (unless --no-commit is specified).
581
581
582 .. note::
582 .. note::
583
583
584 :hg:`backout` cannot be used to fix either an unwanted or
584 :hg:`backout` cannot be used to fix either an unwanted or
585 incorrect merge.
585 incorrect merge.
586
586
587 .. container:: verbose
587 .. container:: verbose
588
588
589 Examples:
589 Examples:
590
590
591 - Reverse the effect of the parent of the working directory.
591 - Reverse the effect of the parent of the working directory.
592 This backout will be committed immediately::
592 This backout will be committed immediately::
593
593
594 hg backout -r .
594 hg backout -r .
595
595
596 - Reverse the effect of previous bad revision 23::
596 - Reverse the effect of previous bad revision 23::
597
597
598 hg backout -r 23
598 hg backout -r 23
599
599
600 - Reverse the effect of previous bad revision 23 and
600 - Reverse the effect of previous bad revision 23 and
601 leave changes uncommitted::
601 leave changes uncommitted::
602
602
603 hg backout -r 23 --no-commit
603 hg backout -r 23 --no-commit
604 hg commit -m "Backout revision 23"
604 hg commit -m "Backout revision 23"
605
605
606 By default, the pending changeset will have one parent,
606 By default, the pending changeset will have one parent,
607 maintaining a linear history. With --merge, the pending
607 maintaining a linear history. With --merge, the pending
608 changeset will instead have two parents: the old parent of the
608 changeset will instead have two parents: the old parent of the
609 working directory and a new child of REV that simply undoes REV.
609 working directory and a new child of REV that simply undoes REV.
610
610
611 Before version 1.7, the behavior without --merge was equivalent
611 Before version 1.7, the behavior without --merge was equivalent
612 to specifying --merge followed by :hg:`update --clean .` to
612 to specifying --merge followed by :hg:`update --clean .` to
613 cancel the merge and leave the child of REV as a head to be
613 cancel the merge and leave the child of REV as a head to be
614 merged separately.
614 merged separately.
615
615
616 See :hg:`help dates` for a list of formats valid for -d/--date.
616 See :hg:`help dates` for a list of formats valid for -d/--date.
617
617
618 See :hg:`help revert` for a way to restore files to the state
618 See :hg:`help revert` for a way to restore files to the state
619 of another revision.
619 of another revision.
620
620
621 Returns 0 on success, 1 if nothing to backout or there are unresolved
621 Returns 0 on success, 1 if nothing to backout or there are unresolved
622 files.
622 files.
623 '''
623 '''
624 wlock = lock = None
624 wlock = lock = None
625 try:
625 try:
626 wlock = repo.wlock()
626 wlock = repo.wlock()
627 lock = repo.lock()
627 lock = repo.lock()
628 return _dobackout(ui, repo, node, rev, **opts)
628 return _dobackout(ui, repo, node, rev, **opts)
629 finally:
629 finally:
630 release(lock, wlock)
630 release(lock, wlock)
631
631
632 def _dobackout(ui, repo, node=None, rev=None, **opts):
632 def _dobackout(ui, repo, node=None, rev=None, **opts):
633 opts = pycompat.byteskwargs(opts)
633 opts = pycompat.byteskwargs(opts)
634 if opts.get('commit') and opts.get('no_commit'):
634 if opts.get('commit') and opts.get('no_commit'):
635 raise error.Abort(_("cannot use --commit with --no-commit"))
635 raise error.Abort(_("cannot use --commit with --no-commit"))
636 if opts.get('merge') and opts.get('no_commit'):
636 if opts.get('merge') and opts.get('no_commit'):
637 raise error.Abort(_("cannot use --merge with --no-commit"))
637 raise error.Abort(_("cannot use --merge with --no-commit"))
638
638
639 if rev and node:
639 if rev and node:
640 raise error.Abort(_("please specify just one revision"))
640 raise error.Abort(_("please specify just one revision"))
641
641
642 if not rev:
642 if not rev:
643 rev = node
643 rev = node
644
644
645 if not rev:
645 if not rev:
646 raise error.Abort(_("please specify a revision to backout"))
646 raise error.Abort(_("please specify a revision to backout"))
647
647
648 date = opts.get('date')
648 date = opts.get('date')
649 if date:
649 if date:
650 opts['date'] = util.parsedate(date)
650 opts['date'] = util.parsedate(date)
651
651
652 cmdutil.checkunfinished(repo)
652 cmdutil.checkunfinished(repo)
653 cmdutil.bailifchanged(repo)
653 cmdutil.bailifchanged(repo)
654 node = scmutil.revsingle(repo, rev).node()
654 node = scmutil.revsingle(repo, rev).node()
655
655
656 op1, op2 = repo.dirstate.parents()
656 op1, op2 = repo.dirstate.parents()
657 if not repo.changelog.isancestor(node, op1):
657 if not repo.changelog.isancestor(node, op1):
658 raise error.Abort(_('cannot backout change that is not an ancestor'))
658 raise error.Abort(_('cannot backout change that is not an ancestor'))
659
659
660 p1, p2 = repo.changelog.parents(node)
660 p1, p2 = repo.changelog.parents(node)
661 if p1 == nullid:
661 if p1 == nullid:
662 raise error.Abort(_('cannot backout a change with no parents'))
662 raise error.Abort(_('cannot backout a change with no parents'))
663 if p2 != nullid:
663 if p2 != nullid:
664 if not opts.get('parent'):
664 if not opts.get('parent'):
665 raise error.Abort(_('cannot backout a merge changeset'))
665 raise error.Abort(_('cannot backout a merge changeset'))
666 p = repo.lookup(opts['parent'])
666 p = repo.lookup(opts['parent'])
667 if p not in (p1, p2):
667 if p not in (p1, p2):
668 raise error.Abort(_('%s is not a parent of %s') %
668 raise error.Abort(_('%s is not a parent of %s') %
669 (short(p), short(node)))
669 (short(p), short(node)))
670 parent = p
670 parent = p
671 else:
671 else:
672 if opts.get('parent'):
672 if opts.get('parent'):
673 raise error.Abort(_('cannot use --parent on non-merge changeset'))
673 raise error.Abort(_('cannot use --parent on non-merge changeset'))
674 parent = p1
674 parent = p1
675
675
676 # the backout should appear on the same branch
676 # the backout should appear on the same branch
677 branch = repo.dirstate.branch()
677 branch = repo.dirstate.branch()
678 bheads = repo.branchheads(branch)
678 bheads = repo.branchheads(branch)
679 rctx = scmutil.revsingle(repo, hex(parent))
679 rctx = scmutil.revsingle(repo, hex(parent))
680 if not opts.get('merge') and op1 != node:
680 if not opts.get('merge') and op1 != node:
681 dsguard = dirstateguard.dirstateguard(repo, 'backout')
681 dsguard = dirstateguard.dirstateguard(repo, 'backout')
682 try:
682 try:
683 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
683 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
684 'backout')
684 'backout')
685 stats = mergemod.update(repo, parent, True, True, node, False)
685 stats = mergemod.update(repo, parent, True, True, node, False)
686 repo.setparents(op1, op2)
686 repo.setparents(op1, op2)
687 dsguard.close()
687 dsguard.close()
688 hg._showstats(repo, stats)
688 hg._showstats(repo, stats)
689 if stats[3]:
689 if stats[3]:
690 repo.ui.status(_("use 'hg resolve' to retry unresolved "
690 repo.ui.status(_("use 'hg resolve' to retry unresolved "
691 "file merges\n"))
691 "file merges\n"))
692 return 1
692 return 1
693 finally:
693 finally:
694 ui.setconfig('ui', 'forcemerge', '', '')
694 ui.setconfig('ui', 'forcemerge', '', '')
695 lockmod.release(dsguard)
695 lockmod.release(dsguard)
696 else:
696 else:
697 hg.clean(repo, node, show_stats=False)
697 hg.clean(repo, node, show_stats=False)
698 repo.dirstate.setbranch(branch)
698 repo.dirstate.setbranch(branch)
699 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
699 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
700
700
701 if opts.get('no_commit'):
701 if opts.get('no_commit'):
702 msg = _("changeset %s backed out, "
702 msg = _("changeset %s backed out, "
703 "don't forget to commit.\n")
703 "don't forget to commit.\n")
704 ui.status(msg % short(node))
704 ui.status(msg % short(node))
705 return 0
705 return 0
706
706
707 def commitfunc(ui, repo, message, match, opts):
707 def commitfunc(ui, repo, message, match, opts):
708 editform = 'backout'
708 editform = 'backout'
709 e = cmdutil.getcommiteditor(editform=editform,
709 e = cmdutil.getcommiteditor(editform=editform,
710 **pycompat.strkwargs(opts))
710 **pycompat.strkwargs(opts))
711 if not message:
711 if not message:
712 # we don't translate commit messages
712 # we don't translate commit messages
713 message = "Backed out changeset %s" % short(node)
713 message = "Backed out changeset %s" % short(node)
714 e = cmdutil.getcommiteditor(edit=True, editform=editform)
714 e = cmdutil.getcommiteditor(edit=True, editform=editform)
715 return repo.commit(message, opts.get('user'), opts.get('date'),
715 return repo.commit(message, opts.get('user'), opts.get('date'),
716 match, editor=e)
716 match, editor=e)
717 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
717 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
718 if not newnode:
718 if not newnode:
719 ui.status(_("nothing changed\n"))
719 ui.status(_("nothing changed\n"))
720 return 1
720 return 1
721 cmdutil.commitstatus(repo, newnode, branch, bheads)
721 cmdutil.commitstatus(repo, newnode, branch, bheads)
722
722
723 def nice(node):
723 def nice(node):
724 return '%d:%s' % (repo.changelog.rev(node), short(node))
724 return '%d:%s' % (repo.changelog.rev(node), short(node))
725 ui.status(_('changeset %s backs out changeset %s\n') %
725 ui.status(_('changeset %s backs out changeset %s\n') %
726 (nice(repo.changelog.tip()), nice(node)))
726 (nice(repo.changelog.tip()), nice(node)))
727 if opts.get('merge') and op1 != node:
727 if opts.get('merge') and op1 != node:
728 hg.clean(repo, op1, show_stats=False)
728 hg.clean(repo, op1, show_stats=False)
729 ui.status(_('merging with changeset %s\n')
729 ui.status(_('merging with changeset %s\n')
730 % nice(repo.changelog.tip()))
730 % nice(repo.changelog.tip()))
731 try:
731 try:
732 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
732 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
733 'backout')
733 'backout')
734 return hg.merge(repo, hex(repo.changelog.tip()))
734 return hg.merge(repo, hex(repo.changelog.tip()))
735 finally:
735 finally:
736 ui.setconfig('ui', 'forcemerge', '', '')
736 ui.setconfig('ui', 'forcemerge', '', '')
737 return 0
737 return 0
738
738
739 @command('bisect',
739 @command('bisect',
740 [('r', 'reset', False, _('reset bisect state')),
740 [('r', 'reset', False, _('reset bisect state')),
741 ('g', 'good', False, _('mark changeset good')),
741 ('g', 'good', False, _('mark changeset good')),
742 ('b', 'bad', False, _('mark changeset bad')),
742 ('b', 'bad', False, _('mark changeset bad')),
743 ('s', 'skip', False, _('skip testing changeset')),
743 ('s', 'skip', False, _('skip testing changeset')),
744 ('e', 'extend', False, _('extend the bisect range')),
744 ('e', 'extend', False, _('extend the bisect range')),
745 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
745 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
746 ('U', 'noupdate', False, _('do not update to target'))],
746 ('U', 'noupdate', False, _('do not update to target'))],
747 _("[-gbsr] [-U] [-c CMD] [REV]"))
747 _("[-gbsr] [-U] [-c CMD] [REV]"))
748 def bisect(ui, repo, rev=None, extra=None, command=None,
748 def bisect(ui, repo, rev=None, extra=None, command=None,
749 reset=None, good=None, bad=None, skip=None, extend=None,
749 reset=None, good=None, bad=None, skip=None, extend=None,
750 noupdate=None):
750 noupdate=None):
751 """subdivision search of changesets
751 """subdivision search of changesets
752
752
753 This command helps to find changesets which introduce problems. To
753 This command helps to find changesets which introduce problems. To
754 use, mark the earliest changeset you know exhibits the problem as
754 use, mark the earliest changeset you know exhibits the problem as
755 bad, then mark the latest changeset which is free from the problem
755 bad, then mark the latest changeset which is free from the problem
756 as good. Bisect will update your working directory to a revision
756 as good. Bisect will update your working directory to a revision
757 for testing (unless the -U/--noupdate option is specified). Once
757 for testing (unless the -U/--noupdate option is specified). Once
758 you have performed tests, mark the working directory as good or
758 you have performed tests, mark the working directory as good or
759 bad, and bisect will either update to another candidate changeset
759 bad, and bisect will either update to another candidate changeset
760 or announce that it has found the bad revision.
760 or announce that it has found the bad revision.
761
761
762 As a shortcut, you can also use the revision argument to mark a
762 As a shortcut, you can also use the revision argument to mark a
763 revision as good or bad without checking it out first.
763 revision as good or bad without checking it out first.
764
764
765 If you supply a command, it will be used for automatic bisection.
765 If you supply a command, it will be used for automatic bisection.
766 The environment variable HG_NODE will contain the ID of the
766 The environment variable HG_NODE will contain the ID of the
767 changeset being tested. The exit status of the command will be
767 changeset being tested. The exit status of the command will be
768 used to mark revisions as good or bad: status 0 means good, 125
768 used to mark revisions as good or bad: status 0 means good, 125
769 means to skip the revision, 127 (command not found) will abort the
769 means to skip the revision, 127 (command not found) will abort the
770 bisection, and any other non-zero exit status means the revision
770 bisection, and any other non-zero exit status means the revision
771 is bad.
771 is bad.
772
772
773 .. container:: verbose
773 .. container:: verbose
774
774
775 Some examples:
775 Some examples:
776
776
777 - start a bisection with known bad revision 34, and good revision 12::
777 - start a bisection with known bad revision 34, and good revision 12::
778
778
779 hg bisect --bad 34
779 hg bisect --bad 34
780 hg bisect --good 12
780 hg bisect --good 12
781
781
782 - advance the current bisection by marking current revision as good or
782 - advance the current bisection by marking current revision as good or
783 bad::
783 bad::
784
784
785 hg bisect --good
785 hg bisect --good
786 hg bisect --bad
786 hg bisect --bad
787
787
788 - mark the current revision, or a known revision, to be skipped (e.g. if
788 - mark the current revision, or a known revision, to be skipped (e.g. if
789 that revision is not usable because of another issue)::
789 that revision is not usable because of another issue)::
790
790
791 hg bisect --skip
791 hg bisect --skip
792 hg bisect --skip 23
792 hg bisect --skip 23
793
793
794 - skip all revisions that do not touch directories ``foo`` or ``bar``::
794 - skip all revisions that do not touch directories ``foo`` or ``bar``::
795
795
796 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
796 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
797
797
798 - forget the current bisection::
798 - forget the current bisection::
799
799
800 hg bisect --reset
800 hg bisect --reset
801
801
802 - use 'make && make tests' to automatically find the first broken
802 - use 'make && make tests' to automatically find the first broken
803 revision::
803 revision::
804
804
805 hg bisect --reset
805 hg bisect --reset
806 hg bisect --bad 34
806 hg bisect --bad 34
807 hg bisect --good 12
807 hg bisect --good 12
808 hg bisect --command "make && make tests"
808 hg bisect --command "make && make tests"
809
809
810 - see all changesets whose states are already known in the current
810 - see all changesets whose states are already known in the current
811 bisection::
811 bisection::
812
812
813 hg log -r "bisect(pruned)"
813 hg log -r "bisect(pruned)"
814
814
815 - see the changeset currently being bisected (especially useful
815 - see the changeset currently being bisected (especially useful
816 if running with -U/--noupdate)::
816 if running with -U/--noupdate)::
817
817
818 hg log -r "bisect(current)"
818 hg log -r "bisect(current)"
819
819
820 - see all changesets that took part in the current bisection::
820 - see all changesets that took part in the current bisection::
821
821
822 hg log -r "bisect(range)"
822 hg log -r "bisect(range)"
823
823
824 - you can even get a nice graph::
824 - you can even get a nice graph::
825
825
826 hg log --graph -r "bisect(range)"
826 hg log --graph -r "bisect(range)"
827
827
828 See :hg:`help revisions.bisect` for more about the `bisect()` predicate.
828 See :hg:`help revisions.bisect` for more about the `bisect()` predicate.
829
829
830 Returns 0 on success.
830 Returns 0 on success.
831 """
831 """
832 # backward compatibility
832 # backward compatibility
833 if rev in "good bad reset init".split():
833 if rev in "good bad reset init".split():
834 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
834 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
835 cmd, rev, extra = rev, extra, None
835 cmd, rev, extra = rev, extra, None
836 if cmd == "good":
836 if cmd == "good":
837 good = True
837 good = True
838 elif cmd == "bad":
838 elif cmd == "bad":
839 bad = True
839 bad = True
840 else:
840 else:
841 reset = True
841 reset = True
842 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
842 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
843 raise error.Abort(_('incompatible arguments'))
843 raise error.Abort(_('incompatible arguments'))
844
844
845 if reset:
845 if reset:
846 hbisect.resetstate(repo)
846 hbisect.resetstate(repo)
847 return
847 return
848
848
849 state = hbisect.load_state(repo)
849 state = hbisect.load_state(repo)
850
850
851 # update state
851 # update state
852 if good or bad or skip:
852 if good or bad or skip:
853 if rev:
853 if rev:
854 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
854 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
855 else:
855 else:
856 nodes = [repo.lookup('.')]
856 nodes = [repo.lookup('.')]
857 if good:
857 if good:
858 state['good'] += nodes
858 state['good'] += nodes
859 elif bad:
859 elif bad:
860 state['bad'] += nodes
860 state['bad'] += nodes
861 elif skip:
861 elif skip:
862 state['skip'] += nodes
862 state['skip'] += nodes
863 hbisect.save_state(repo, state)
863 hbisect.save_state(repo, state)
864 if not (state['good'] and state['bad']):
864 if not (state['good'] and state['bad']):
865 return
865 return
866
866
867 def mayupdate(repo, node, show_stats=True):
867 def mayupdate(repo, node, show_stats=True):
868 """common used update sequence"""
868 """common used update sequence"""
869 if noupdate:
869 if noupdate:
870 return
870 return
871 cmdutil.checkunfinished(repo)
871 cmdutil.checkunfinished(repo)
872 cmdutil.bailifchanged(repo)
872 cmdutil.bailifchanged(repo)
873 return hg.clean(repo, node, show_stats=show_stats)
873 return hg.clean(repo, node, show_stats=show_stats)
874
874
875 displayer = cmdutil.show_changeset(ui, repo, {})
875 displayer = cmdutil.show_changeset(ui, repo, {})
876
876
877 if command:
877 if command:
878 changesets = 1
878 changesets = 1
879 if noupdate:
879 if noupdate:
880 try:
880 try:
881 node = state['current'][0]
881 node = state['current'][0]
882 except LookupError:
882 except LookupError:
883 raise error.Abort(_('current bisect revision is unknown - '
883 raise error.Abort(_('current bisect revision is unknown - '
884 'start a new bisect to fix'))
884 'start a new bisect to fix'))
885 else:
885 else:
886 node, p2 = repo.dirstate.parents()
886 node, p2 = repo.dirstate.parents()
887 if p2 != nullid:
887 if p2 != nullid:
888 raise error.Abort(_('current bisect revision is a merge'))
888 raise error.Abort(_('current bisect revision is a merge'))
889 if rev:
889 if rev:
890 node = repo[scmutil.revsingle(repo, rev, node)].node()
890 node = repo[scmutil.revsingle(repo, rev, node)].node()
891 try:
891 try:
892 while changesets:
892 while changesets:
893 # update state
893 # update state
894 state['current'] = [node]
894 state['current'] = [node]
895 hbisect.save_state(repo, state)
895 hbisect.save_state(repo, state)
896 status = ui.system(command, environ={'HG_NODE': hex(node)},
896 status = ui.system(command, environ={'HG_NODE': hex(node)},
897 blockedtag='bisect_check')
897 blockedtag='bisect_check')
898 if status == 125:
898 if status == 125:
899 transition = "skip"
899 transition = "skip"
900 elif status == 0:
900 elif status == 0:
901 transition = "good"
901 transition = "good"
902 # status < 0 means process was killed
902 # status < 0 means process was killed
903 elif status == 127:
903 elif status == 127:
904 raise error.Abort(_("failed to execute %s") % command)
904 raise error.Abort(_("failed to execute %s") % command)
905 elif status < 0:
905 elif status < 0:
906 raise error.Abort(_("%s killed") % command)
906 raise error.Abort(_("%s killed") % command)
907 else:
907 else:
908 transition = "bad"
908 transition = "bad"
909 state[transition].append(node)
909 state[transition].append(node)
910 ctx = repo[node]
910 ctx = repo[node]
911 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
911 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
912 hbisect.checkstate(state)
912 hbisect.checkstate(state)
913 # bisect
913 # bisect
914 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
914 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
915 # update to next check
915 # update to next check
916 node = nodes[0]
916 node = nodes[0]
917 mayupdate(repo, node, show_stats=False)
917 mayupdate(repo, node, show_stats=False)
918 finally:
918 finally:
919 state['current'] = [node]
919 state['current'] = [node]
920 hbisect.save_state(repo, state)
920 hbisect.save_state(repo, state)
921 hbisect.printresult(ui, repo, state, displayer, nodes, bgood)
921 hbisect.printresult(ui, repo, state, displayer, nodes, bgood)
922 return
922 return
923
923
924 hbisect.checkstate(state)
924 hbisect.checkstate(state)
925
925
926 # actually bisect
926 # actually bisect
927 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
927 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
928 if extend:
928 if extend:
929 if not changesets:
929 if not changesets:
930 extendnode = hbisect.extendrange(repo, state, nodes, good)
930 extendnode = hbisect.extendrange(repo, state, nodes, good)
931 if extendnode is not None:
931 if extendnode is not None:
932 ui.write(_("Extending search to changeset %d:%s\n")
932 ui.write(_("Extending search to changeset %d:%s\n")
933 % (extendnode.rev(), extendnode))
933 % (extendnode.rev(), extendnode))
934 state['current'] = [extendnode.node()]
934 state['current'] = [extendnode.node()]
935 hbisect.save_state(repo, state)
935 hbisect.save_state(repo, state)
936 return mayupdate(repo, extendnode.node())
936 return mayupdate(repo, extendnode.node())
937 raise error.Abort(_("nothing to extend"))
937 raise error.Abort(_("nothing to extend"))
938
938
939 if changesets == 0:
939 if changesets == 0:
940 hbisect.printresult(ui, repo, state, displayer, nodes, good)
940 hbisect.printresult(ui, repo, state, displayer, nodes, good)
941 else:
941 else:
942 assert len(nodes) == 1 # only a single node can be tested next
942 assert len(nodes) == 1 # only a single node can be tested next
943 node = nodes[0]
943 node = nodes[0]
944 # compute the approximate number of remaining tests
944 # compute the approximate number of remaining tests
945 tests, size = 0, 2
945 tests, size = 0, 2
946 while size <= changesets:
946 while size <= changesets:
947 tests, size = tests + 1, size * 2
947 tests, size = tests + 1, size * 2
948 rev = repo.changelog.rev(node)
948 rev = repo.changelog.rev(node)
949 ui.write(_("Testing changeset %d:%s "
949 ui.write(_("Testing changeset %d:%s "
950 "(%d changesets remaining, ~%d tests)\n")
950 "(%d changesets remaining, ~%d tests)\n")
951 % (rev, short(node), changesets, tests))
951 % (rev, short(node), changesets, tests))
952 state['current'] = [node]
952 state['current'] = [node]
953 hbisect.save_state(repo, state)
953 hbisect.save_state(repo, state)
954 return mayupdate(repo, node)
954 return mayupdate(repo, node)
955
955
956 @command('bookmarks|bookmark',
956 @command('bookmarks|bookmark',
957 [('f', 'force', False, _('force')),
957 [('f', 'force', False, _('force')),
958 ('r', 'rev', '', _('revision for bookmark action'), _('REV')),
958 ('r', 'rev', '', _('revision for bookmark action'), _('REV')),
959 ('d', 'delete', False, _('delete a given bookmark')),
959 ('d', 'delete', False, _('delete a given bookmark')),
960 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
960 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
961 ('i', 'inactive', False, _('mark a bookmark inactive')),
961 ('i', 'inactive', False, _('mark a bookmark inactive')),
962 ] + formatteropts,
962 ] + formatteropts,
963 _('hg bookmarks [OPTIONS]... [NAME]...'))
963 _('hg bookmarks [OPTIONS]... [NAME]...'))
964 def bookmark(ui, repo, *names, **opts):
964 def bookmark(ui, repo, *names, **opts):
965 '''create a new bookmark or list existing bookmarks
965 '''create a new bookmark or list existing bookmarks
966
966
967 Bookmarks are labels on changesets to help track lines of development.
967 Bookmarks are labels on changesets to help track lines of development.
968 Bookmarks are unversioned and can be moved, renamed and deleted.
968 Bookmarks are unversioned and can be moved, renamed and deleted.
969 Deleting or moving a bookmark has no effect on the associated changesets.
969 Deleting or moving a bookmark has no effect on the associated changesets.
970
970
971 Creating or updating to a bookmark causes it to be marked as 'active'.
971 Creating or updating to a bookmark causes it to be marked as 'active'.
972 The active bookmark is indicated with a '*'.
972 The active bookmark is indicated with a '*'.
973 When a commit is made, the active bookmark will advance to the new commit.
973 When a commit is made, the active bookmark will advance to the new commit.
974 A plain :hg:`update` will also advance an active bookmark, if possible.
974 A plain :hg:`update` will also advance an active bookmark, if possible.
975 Updating away from a bookmark will cause it to be deactivated.
975 Updating away from a bookmark will cause it to be deactivated.
976
976
977 Bookmarks can be pushed and pulled between repositories (see
977 Bookmarks can be pushed and pulled between repositories (see
978 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
978 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
979 diverged, a new 'divergent bookmark' of the form 'name@path' will
979 diverged, a new 'divergent bookmark' of the form 'name@path' will
980 be created. Using :hg:`merge` will resolve the divergence.
980 be created. Using :hg:`merge` will resolve the divergence.
981
981
982 A bookmark named '@' has the special property that :hg:`clone` will
982 A bookmark named '@' has the special property that :hg:`clone` will
983 check it out by default if it exists.
983 check it out by default if it exists.
984
984
985 .. container:: verbose
985 .. container:: verbose
986
986
987 Examples:
987 Examples:
988
988
989 - create an active bookmark for a new line of development::
989 - create an active bookmark for a new line of development::
990
990
991 hg book new-feature
991 hg book new-feature
992
992
993 - create an inactive bookmark as a place marker::
993 - create an inactive bookmark as a place marker::
994
994
995 hg book -i reviewed
995 hg book -i reviewed
996
996
997 - create an inactive bookmark on another changeset::
997 - create an inactive bookmark on another changeset::
998
998
999 hg book -r .^ tested
999 hg book -r .^ tested
1000
1000
1001 - rename bookmark turkey to dinner::
1001 - rename bookmark turkey to dinner::
1002
1002
1003 hg book -m turkey dinner
1003 hg book -m turkey dinner
1004
1004
1005 - move the '@' bookmark from another branch::
1005 - move the '@' bookmark from another branch::
1006
1006
1007 hg book -f @
1007 hg book -f @
1008 '''
1008 '''
1009 opts = pycompat.byteskwargs(opts)
1009 opts = pycompat.byteskwargs(opts)
1010 force = opts.get('force')
1010 force = opts.get('force')
1011 rev = opts.get('rev')
1011 rev = opts.get('rev')
1012 delete = opts.get('delete')
1012 delete = opts.get('delete')
1013 rename = opts.get('rename')
1013 rename = opts.get('rename')
1014 inactive = opts.get('inactive')
1014 inactive = opts.get('inactive')
1015
1015
1016 def checkformat(mark):
1016 def checkformat(mark):
1017 mark = mark.strip()
1017 mark = mark.strip()
1018 if not mark:
1018 if not mark:
1019 raise error.Abort(_("bookmark names cannot consist entirely of "
1019 raise error.Abort(_("bookmark names cannot consist entirely of "
1020 "whitespace"))
1020 "whitespace"))
1021 scmutil.checknewlabel(repo, mark, 'bookmark')
1021 scmutil.checknewlabel(repo, mark, 'bookmark')
1022 return mark
1022 return mark
1023
1023
1024 def checkconflict(repo, mark, cur, force=False, target=None):
1024 def checkconflict(repo, mark, cur, force=False, target=None):
1025 if mark in marks and not force:
1025 if mark in marks and not force:
1026 if target:
1026 if target:
1027 if marks[mark] == target and target == cur:
1027 if marks[mark] == target and target == cur:
1028 # re-activating a bookmark
1028 # re-activating a bookmark
1029 return
1029 return
1030 anc = repo.changelog.ancestors([repo[target].rev()])
1030 anc = repo.changelog.ancestors([repo[target].rev()])
1031 bmctx = repo[marks[mark]]
1031 bmctx = repo[marks[mark]]
1032 divs = [repo[b].node() for b in marks
1032 divs = [repo[b].node() for b in marks
1033 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
1033 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
1034
1034
1035 # allow resolving a single divergent bookmark even if moving
1035 # allow resolving a single divergent bookmark even if moving
1036 # the bookmark across branches when a revision is specified
1036 # the bookmark across branches when a revision is specified
1037 # that contains a divergent bookmark
1037 # that contains a divergent bookmark
1038 if bmctx.rev() not in anc and target in divs:
1038 if bmctx.rev() not in anc and target in divs:
1039 bookmarks.deletedivergent(repo, [target], mark)
1039 bookmarks.deletedivergent(repo, [target], mark)
1040 return
1040 return
1041
1041
1042 deletefrom = [b for b in divs
1042 deletefrom = [b for b in divs
1043 if repo[b].rev() in anc or b == target]
1043 if repo[b].rev() in anc or b == target]
1044 bookmarks.deletedivergent(repo, deletefrom, mark)
1044 bookmarks.deletedivergent(repo, deletefrom, mark)
1045 if bookmarks.validdest(repo, bmctx, repo[target]):
1045 if bookmarks.validdest(repo, bmctx, repo[target]):
1046 ui.status(_("moving bookmark '%s' forward from %s\n") %
1046 ui.status(_("moving bookmark '%s' forward from %s\n") %
1047 (mark, short(bmctx.node())))
1047 (mark, short(bmctx.node())))
1048 return
1048 return
1049 raise error.Abort(_("bookmark '%s' already exists "
1049 raise error.Abort(_("bookmark '%s' already exists "
1050 "(use -f to force)") % mark)
1050 "(use -f to force)") % mark)
1051 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
1051 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
1052 and not force):
1052 and not force):
1053 raise error.Abort(
1053 raise error.Abort(
1054 _("a bookmark cannot have the name of an existing branch"))
1054 _("a bookmark cannot have the name of an existing branch"))
1055
1055
1056 if delete and rename:
1056 if delete and rename:
1057 raise error.Abort(_("--delete and --rename are incompatible"))
1057 raise error.Abort(_("--delete and --rename are incompatible"))
1058 if delete and rev:
1058 if delete and rev:
1059 raise error.Abort(_("--rev is incompatible with --delete"))
1059 raise error.Abort(_("--rev is incompatible with --delete"))
1060 if rename and rev:
1060 if rename and rev:
1061 raise error.Abort(_("--rev is incompatible with --rename"))
1061 raise error.Abort(_("--rev is incompatible with --rename"))
1062 if not names and (delete or rev):
1062 if not names and (delete or rev):
1063 raise error.Abort(_("bookmark name required"))
1063 raise error.Abort(_("bookmark name required"))
1064
1064
1065 if delete or rename or names or inactive:
1065 if delete or rename or names or inactive:
1066 wlock = lock = tr = None
1066 wlock = lock = tr = None
1067 try:
1067 try:
1068 wlock = repo.wlock()
1068 wlock = repo.wlock()
1069 lock = repo.lock()
1069 lock = repo.lock()
1070 cur = repo.changectx('.').node()
1070 cur = repo.changectx('.').node()
1071 marks = repo._bookmarks
1071 marks = repo._bookmarks
1072 if delete:
1072 if delete:
1073 tr = repo.transaction('bookmark')
1073 tr = repo.transaction('bookmark')
1074 for mark in names:
1074 for mark in names:
1075 if mark not in marks:
1075 if mark not in marks:
1076 raise error.Abort(_("bookmark '%s' does not exist") %
1076 raise error.Abort(_("bookmark '%s' does not exist") %
1077 mark)
1077 mark)
1078 if mark == repo._activebookmark:
1078 if mark == repo._activebookmark:
1079 bookmarks.deactivate(repo)
1079 bookmarks.deactivate(repo)
1080 del marks[mark]
1080 del marks[mark]
1081
1081
1082 elif rename:
1082 elif rename:
1083 tr = repo.transaction('bookmark')
1083 tr = repo.transaction('bookmark')
1084 if not names:
1084 if not names:
1085 raise error.Abort(_("new bookmark name required"))
1085 raise error.Abort(_("new bookmark name required"))
1086 elif len(names) > 1:
1086 elif len(names) > 1:
1087 raise error.Abort(_("only one new bookmark name allowed"))
1087 raise error.Abort(_("only one new bookmark name allowed"))
1088 mark = checkformat(names[0])
1088 mark = checkformat(names[0])
1089 if rename not in marks:
1089 if rename not in marks:
1090 raise error.Abort(_("bookmark '%s' does not exist")
1090 raise error.Abort(_("bookmark '%s' does not exist")
1091 % rename)
1091 % rename)
1092 checkconflict(repo, mark, cur, force)
1092 checkconflict(repo, mark, cur, force)
1093 marks[mark] = marks[rename]
1093 marks[mark] = marks[rename]
1094 if repo._activebookmark == rename and not inactive:
1094 if repo._activebookmark == rename and not inactive:
1095 bookmarks.activate(repo, mark)
1095 bookmarks.activate(repo, mark)
1096 del marks[rename]
1096 del marks[rename]
1097 elif names:
1097 elif names:
1098 tr = repo.transaction('bookmark')
1098 tr = repo.transaction('bookmark')
1099 newact = None
1099 newact = None
1100 for mark in names:
1100 for mark in names:
1101 mark = checkformat(mark)
1101 mark = checkformat(mark)
1102 if newact is None:
1102 if newact is None:
1103 newact = mark
1103 newact = mark
1104 if inactive and mark == repo._activebookmark:
1104 if inactive and mark == repo._activebookmark:
1105 bookmarks.deactivate(repo)
1105 bookmarks.deactivate(repo)
1106 return
1106 return
1107 tgt = cur
1107 tgt = cur
1108 if rev:
1108 if rev:
1109 tgt = scmutil.revsingle(repo, rev).node()
1109 tgt = scmutil.revsingle(repo, rev).node()
1110 checkconflict(repo, mark, cur, force, tgt)
1110 checkconflict(repo, mark, cur, force, tgt)
1111 marks[mark] = tgt
1111 marks[mark] = tgt
1112 if not inactive and cur == marks[newact] and not rev:
1112 if not inactive and cur == marks[newact] and not rev:
1113 bookmarks.activate(repo, newact)
1113 bookmarks.activate(repo, newact)
1114 elif cur != tgt and newact == repo._activebookmark:
1114 elif cur != tgt and newact == repo._activebookmark:
1115 bookmarks.deactivate(repo)
1115 bookmarks.deactivate(repo)
1116 elif inactive:
1116 elif inactive:
1117 if len(marks) == 0:
1117 if len(marks) == 0:
1118 ui.status(_("no bookmarks set\n"))
1118 ui.status(_("no bookmarks set\n"))
1119 elif not repo._activebookmark:
1119 elif not repo._activebookmark:
1120 ui.status(_("no active bookmark\n"))
1120 ui.status(_("no active bookmark\n"))
1121 else:
1121 else:
1122 bookmarks.deactivate(repo)
1122 bookmarks.deactivate(repo)
1123 if tr is not None:
1123 if tr is not None:
1124 marks.recordchange(tr)
1124 marks.recordchange(tr)
1125 tr.close()
1125 tr.close()
1126 finally:
1126 finally:
1127 lockmod.release(tr, lock, wlock)
1127 lockmod.release(tr, lock, wlock)
1128 else: # show bookmarks
1128 else: # show bookmarks
1129 fm = ui.formatter('bookmarks', opts)
1129 fm = ui.formatter('bookmarks', opts)
1130 hexfn = fm.hexfunc
1130 hexfn = fm.hexfunc
1131 marks = repo._bookmarks
1131 marks = repo._bookmarks
1132 if len(marks) == 0 and fm.isplain():
1132 if len(marks) == 0 and fm.isplain():
1133 ui.status(_("no bookmarks set\n"))
1133 ui.status(_("no bookmarks set\n"))
1134 for bmark, n in sorted(marks.iteritems()):
1134 for bmark, n in sorted(marks.iteritems()):
1135 active = repo._activebookmark
1135 active = repo._activebookmark
1136 if bmark == active:
1136 if bmark == active:
1137 prefix, label = '*', activebookmarklabel
1137 prefix, label = '*', activebookmarklabel
1138 else:
1138 else:
1139 prefix, label = ' ', ''
1139 prefix, label = ' ', ''
1140
1140
1141 fm.startitem()
1141 fm.startitem()
1142 if not ui.quiet:
1142 if not ui.quiet:
1143 fm.plain(' %s ' % prefix, label=label)
1143 fm.plain(' %s ' % prefix, label=label)
1144 fm.write('bookmark', '%s', bmark, label=label)
1144 fm.write('bookmark', '%s', bmark, label=label)
1145 pad = " " * (25 - encoding.colwidth(bmark))
1145 pad = " " * (25 - encoding.colwidth(bmark))
1146 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1146 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1147 repo.changelog.rev(n), hexfn(n), label=label)
1147 repo.changelog.rev(n), hexfn(n), label=label)
1148 fm.data(active=(bmark == active))
1148 fm.data(active=(bmark == active))
1149 fm.plain('\n')
1149 fm.plain('\n')
1150 fm.end()
1150 fm.end()
1151
1151
1152 @command('branch',
1152 @command('branch',
1153 [('f', 'force', None,
1153 [('f', 'force', None,
1154 _('set branch name even if it shadows an existing branch')),
1154 _('set branch name even if it shadows an existing branch')),
1155 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1155 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1156 _('[-fC] [NAME]'))
1156 _('[-fC] [NAME]'))
1157 def branch(ui, repo, label=None, **opts):
1157 def branch(ui, repo, label=None, **opts):
1158 """set or show the current branch name
1158 """set or show the current branch name
1159
1159
1160 .. note::
1160 .. note::
1161
1161
1162 Branch names are permanent and global. Use :hg:`bookmark` to create a
1162 Branch names are permanent and global. Use :hg:`bookmark` to create a
1163 light-weight bookmark instead. See :hg:`help glossary` for more
1163 light-weight bookmark instead. See :hg:`help glossary` for more
1164 information about named branches and bookmarks.
1164 information about named branches and bookmarks.
1165
1165
1166 With no argument, show the current branch name. With one argument,
1166 With no argument, show the current branch name. With one argument,
1167 set the working directory branch name (the branch will not exist
1167 set the working directory branch name (the branch will not exist
1168 in the repository until the next commit). Standard practice
1168 in the repository until the next commit). Standard practice
1169 recommends that primary development take place on the 'default'
1169 recommends that primary development take place on the 'default'
1170 branch.
1170 branch.
1171
1171
1172 Unless -f/--force is specified, branch will not let you set a
1172 Unless -f/--force is specified, branch will not let you set a
1173 branch name that already exists.
1173 branch name that already exists.
1174
1174
1175 Use -C/--clean to reset the working directory branch to that of
1175 Use -C/--clean to reset the working directory branch to that of
1176 the parent of the working directory, negating a previous branch
1176 the parent of the working directory, negating a previous branch
1177 change.
1177 change.
1178
1178
1179 Use the command :hg:`update` to switch to an existing branch. Use
1179 Use the command :hg:`update` to switch to an existing branch. Use
1180 :hg:`commit --close-branch` to mark this branch head as closed.
1180 :hg:`commit --close-branch` to mark this branch head as closed.
1181 When all heads of a branch are closed, the branch will be
1181 When all heads of a branch are closed, the branch will be
1182 considered closed.
1182 considered closed.
1183
1183
1184 Returns 0 on success.
1184 Returns 0 on success.
1185 """
1185 """
1186 opts = pycompat.byteskwargs(opts)
1186 opts = pycompat.byteskwargs(opts)
1187 if label:
1187 if label:
1188 label = label.strip()
1188 label = label.strip()
1189
1189
1190 if not opts.get('clean') and not label:
1190 if not opts.get('clean') and not label:
1191 ui.write("%s\n" % repo.dirstate.branch())
1191 ui.write("%s\n" % repo.dirstate.branch())
1192 return
1192 return
1193
1193
1194 with repo.wlock():
1194 with repo.wlock():
1195 if opts.get('clean'):
1195 if opts.get('clean'):
1196 label = repo[None].p1().branch()
1196 label = repo[None].p1().branch()
1197 repo.dirstate.setbranch(label)
1197 repo.dirstate.setbranch(label)
1198 ui.status(_('reset working directory to branch %s\n') % label)
1198 ui.status(_('reset working directory to branch %s\n') % label)
1199 elif label:
1199 elif label:
1200 if not opts.get('force') and label in repo.branchmap():
1200 if not opts.get('force') and label in repo.branchmap():
1201 if label not in [p.branch() for p in repo[None].parents()]:
1201 if label not in [p.branch() for p in repo[None].parents()]:
1202 raise error.Abort(_('a branch of the same name already'
1202 raise error.Abort(_('a branch of the same name already'
1203 ' exists'),
1203 ' exists'),
1204 # i18n: "it" refers to an existing branch
1204 # i18n: "it" refers to an existing branch
1205 hint=_("use 'hg update' to switch to it"))
1205 hint=_("use 'hg update' to switch to it"))
1206 scmutil.checknewlabel(repo, label, 'branch')
1206 scmutil.checknewlabel(repo, label, 'branch')
1207 repo.dirstate.setbranch(label)
1207 repo.dirstate.setbranch(label)
1208 ui.status(_('marked working directory as branch %s\n') % label)
1208 ui.status(_('marked working directory as branch %s\n') % label)
1209
1209
1210 # find any open named branches aside from default
1210 # find any open named branches aside from default
1211 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1211 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1212 if n != "default" and not c]
1212 if n != "default" and not c]
1213 if not others:
1213 if not others:
1214 ui.status(_('(branches are permanent and global, '
1214 ui.status(_('(branches are permanent and global, '
1215 'did you want a bookmark?)\n'))
1215 'did you want a bookmark?)\n'))
1216
1216
1217 @command('branches',
1217 @command('branches',
1218 [('a', 'active', False,
1218 [('a', 'active', False,
1219 _('show only branches that have unmerged heads (DEPRECATED)')),
1219 _('show only branches that have unmerged heads (DEPRECATED)')),
1220 ('c', 'closed', False, _('show normal and closed branches')),
1220 ('c', 'closed', False, _('show normal and closed branches')),
1221 ] + formatteropts,
1221 ] + formatteropts,
1222 _('[-c]'))
1222 _('[-c]'))
1223 def branches(ui, repo, active=False, closed=False, **opts):
1223 def branches(ui, repo, active=False, closed=False, **opts):
1224 """list repository named branches
1224 """list repository named branches
1225
1225
1226 List the repository's named branches, indicating which ones are
1226 List the repository's named branches, indicating which ones are
1227 inactive. If -c/--closed is specified, also list branches which have
1227 inactive. If -c/--closed is specified, also list branches which have
1228 been marked closed (see :hg:`commit --close-branch`).
1228 been marked closed (see :hg:`commit --close-branch`).
1229
1229
1230 Use the command :hg:`update` to switch to an existing branch.
1230 Use the command :hg:`update` to switch to an existing branch.
1231
1231
1232 Returns 0.
1232 Returns 0.
1233 """
1233 """
1234
1234
1235 opts = pycompat.byteskwargs(opts)
1235 opts = pycompat.byteskwargs(opts)
1236 ui.pager('branches')
1236 ui.pager('branches')
1237 fm = ui.formatter('branches', opts)
1237 fm = ui.formatter('branches', opts)
1238 hexfunc = fm.hexfunc
1238 hexfunc = fm.hexfunc
1239
1239
1240 allheads = set(repo.heads())
1240 allheads = set(repo.heads())
1241 branches = []
1241 branches = []
1242 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1242 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1243 isactive = not isclosed and bool(set(heads) & allheads)
1243 isactive = not isclosed and bool(set(heads) & allheads)
1244 branches.append((tag, repo[tip], isactive, not isclosed))
1244 branches.append((tag, repo[tip], isactive, not isclosed))
1245 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1245 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1246 reverse=True)
1246 reverse=True)
1247
1247
1248 for tag, ctx, isactive, isopen in branches:
1248 for tag, ctx, isactive, isopen in branches:
1249 if active and not isactive:
1249 if active and not isactive:
1250 continue
1250 continue
1251 if isactive:
1251 if isactive:
1252 label = 'branches.active'
1252 label = 'branches.active'
1253 notice = ''
1253 notice = ''
1254 elif not isopen:
1254 elif not isopen:
1255 if not closed:
1255 if not closed:
1256 continue
1256 continue
1257 label = 'branches.closed'
1257 label = 'branches.closed'
1258 notice = _(' (closed)')
1258 notice = _(' (closed)')
1259 else:
1259 else:
1260 label = 'branches.inactive'
1260 label = 'branches.inactive'
1261 notice = _(' (inactive)')
1261 notice = _(' (inactive)')
1262 current = (tag == repo.dirstate.branch())
1262 current = (tag == repo.dirstate.branch())
1263 if current:
1263 if current:
1264 label = 'branches.current'
1264 label = 'branches.current'
1265
1265
1266 fm.startitem()
1266 fm.startitem()
1267 fm.write('branch', '%s', tag, label=label)
1267 fm.write('branch', '%s', tag, label=label)
1268 rev = ctx.rev()
1268 rev = ctx.rev()
1269 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1269 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1270 fmt = ' ' * padsize + ' %d:%s'
1270 fmt = ' ' * padsize + ' %d:%s'
1271 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1271 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1272 label='log.changeset changeset.%s' % ctx.phasestr())
1272 label='log.changeset changeset.%s' % ctx.phasestr())
1273 fm.context(ctx=ctx)
1273 fm.context(ctx=ctx)
1274 fm.data(active=isactive, closed=not isopen, current=current)
1274 fm.data(active=isactive, closed=not isopen, current=current)
1275 if not ui.quiet:
1275 if not ui.quiet:
1276 fm.plain(notice)
1276 fm.plain(notice)
1277 fm.plain('\n')
1277 fm.plain('\n')
1278 fm.end()
1278 fm.end()
1279
1279
1280 @command('bundle',
1280 @command('bundle',
1281 [('f', 'force', None, _('run even when the destination is unrelated')),
1281 [('f', 'force', None, _('run even when the destination is unrelated')),
1282 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1282 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1283 _('REV')),
1283 _('REV')),
1284 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1284 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1285 _('BRANCH')),
1285 _('BRANCH')),
1286 ('', 'base', [],
1286 ('', 'base', [],
1287 _('a base changeset assumed to be available at the destination'),
1287 _('a base changeset assumed to be available at the destination'),
1288 _('REV')),
1288 _('REV')),
1289 ('a', 'all', None, _('bundle all changesets in the repository')),
1289 ('a', 'all', None, _('bundle all changesets in the repository')),
1290 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1290 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1291 ] + remoteopts,
1291 ] + remoteopts,
1292 _('[-f] [-t BUNDLESPEC] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1292 _('[-f] [-t BUNDLESPEC] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1293 def bundle(ui, repo, fname, dest=None, **opts):
1293 def bundle(ui, repo, fname, dest=None, **opts):
1294 """create a bundle file
1294 """create a bundle file
1295
1295
1296 Generate a bundle file containing data to be added to a repository.
1296 Generate a bundle file containing data to be added to a repository.
1297
1297
1298 To create a bundle containing all changesets, use -a/--all
1298 To create a bundle containing all changesets, use -a/--all
1299 (or --base null). Otherwise, hg assumes the destination will have
1299 (or --base null). Otherwise, hg assumes the destination will have
1300 all the nodes you specify with --base parameters. Otherwise, hg
1300 all the nodes you specify with --base parameters. Otherwise, hg
1301 will assume the repository has all the nodes in destination, or
1301 will assume the repository has all the nodes in destination, or
1302 default-push/default if no destination is specified.
1302 default-push/default if no destination is specified.
1303
1303
1304 You can change bundle format with the -t/--type option. See
1304 You can change bundle format with the -t/--type option. See
1305 :hg:`help bundlespec` for documentation on this format. By default,
1305 :hg:`help bundlespec` for documentation on this format. By default,
1306 the most appropriate format is used and compression defaults to
1306 the most appropriate format is used and compression defaults to
1307 bzip2.
1307 bzip2.
1308
1308
1309 The bundle file can then be transferred using conventional means
1309 The bundle file can then be transferred using conventional means
1310 and applied to another repository with the unbundle or pull
1310 and applied to another repository with the unbundle or pull
1311 command. This is useful when direct push and pull are not
1311 command. This is useful when direct push and pull are not
1312 available or when exporting an entire repository is undesirable.
1312 available or when exporting an entire repository is undesirable.
1313
1313
1314 Applying bundles preserves all changeset contents including
1314 Applying bundles preserves all changeset contents including
1315 permissions, copy/rename information, and revision history.
1315 permissions, copy/rename information, and revision history.
1316
1316
1317 Returns 0 on success, 1 if no changes found.
1317 Returns 0 on success, 1 if no changes found.
1318 """
1318 """
1319 opts = pycompat.byteskwargs(opts)
1319 opts = pycompat.byteskwargs(opts)
1320 revs = None
1320 revs = None
1321 if 'rev' in opts:
1321 if 'rev' in opts:
1322 revstrings = opts['rev']
1322 revstrings = opts['rev']
1323 revs = scmutil.revrange(repo, revstrings)
1323 revs = scmutil.revrange(repo, revstrings)
1324 if revstrings and not revs:
1324 if revstrings and not revs:
1325 raise error.Abort(_('no commits to bundle'))
1325 raise error.Abort(_('no commits to bundle'))
1326
1326
1327 bundletype = opts.get('type', 'bzip2').lower()
1327 bundletype = opts.get('type', 'bzip2').lower()
1328 try:
1328 try:
1329 bcompression, cgversion, params = exchange.parsebundlespec(
1329 bcompression, cgversion, params = exchange.parsebundlespec(
1330 repo, bundletype, strict=False)
1330 repo, bundletype, strict=False)
1331 except error.UnsupportedBundleSpecification as e:
1331 except error.UnsupportedBundleSpecification as e:
1332 raise error.Abort(str(e),
1332 raise error.Abort(str(e),
1333 hint=_("see 'hg help bundlespec' for supported "
1333 hint=_("see 'hg help bundlespec' for supported "
1334 "values for --type"))
1334 "values for --type"))
1335
1335
1336 # Packed bundles are a pseudo bundle format for now.
1336 # Packed bundles are a pseudo bundle format for now.
1337 if cgversion == 's1':
1337 if cgversion == 's1':
1338 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1338 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1339 hint=_("use 'hg debugcreatestreamclonebundle'"))
1339 hint=_("use 'hg debugcreatestreamclonebundle'"))
1340
1340
1341 if opts.get('all'):
1341 if opts.get('all'):
1342 if dest:
1342 if dest:
1343 raise error.Abort(_("--all is incompatible with specifying "
1343 raise error.Abort(_("--all is incompatible with specifying "
1344 "a destination"))
1344 "a destination"))
1345 if opts.get('base'):
1345 if opts.get('base'):
1346 ui.warn(_("ignoring --base because --all was specified\n"))
1346 ui.warn(_("ignoring --base because --all was specified\n"))
1347 base = ['null']
1347 base = ['null']
1348 else:
1348 else:
1349 base = scmutil.revrange(repo, opts.get('base'))
1349 base = scmutil.revrange(repo, opts.get('base'))
1350 if cgversion not in changegroup.supportedoutgoingversions(repo):
1350 if cgversion not in changegroup.supportedoutgoingversions(repo):
1351 raise error.Abort(_("repository does not support bundle version %s") %
1351 raise error.Abort(_("repository does not support bundle version %s") %
1352 cgversion)
1352 cgversion)
1353
1353
1354 if base:
1354 if base:
1355 if dest:
1355 if dest:
1356 raise error.Abort(_("--base is incompatible with specifying "
1356 raise error.Abort(_("--base is incompatible with specifying "
1357 "a destination"))
1357 "a destination"))
1358 common = [repo.lookup(rev) for rev in base]
1358 common = [repo.lookup(rev) for rev in base]
1359 heads = revs and map(repo.lookup, revs) or None
1359 heads = revs and map(repo.lookup, revs) or None
1360 outgoing = discovery.outgoing(repo, common, heads)
1360 outgoing = discovery.outgoing(repo, common, heads)
1361 else:
1361 else:
1362 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1362 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1363 dest, branches = hg.parseurl(dest, opts.get('branch'))
1363 dest, branches = hg.parseurl(dest, opts.get('branch'))
1364 other = hg.peer(repo, opts, dest)
1364 other = hg.peer(repo, opts, dest)
1365 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1365 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1366 heads = revs and map(repo.lookup, revs) or revs
1366 heads = revs and map(repo.lookup, revs) or revs
1367 outgoing = discovery.findcommonoutgoing(repo, other,
1367 outgoing = discovery.findcommonoutgoing(repo, other,
1368 onlyheads=heads,
1368 onlyheads=heads,
1369 force=opts.get('force'),
1369 force=opts.get('force'),
1370 portable=True)
1370 portable=True)
1371
1371
1372 if not outgoing.missing:
1372 if not outgoing.missing:
1373 scmutil.nochangesfound(ui, repo, not base and outgoing.excluded)
1373 scmutil.nochangesfound(ui, repo, not base and outgoing.excluded)
1374 return 1
1374 return 1
1375
1375
1376 if cgversion == '01': #bundle1
1376 if cgversion == '01': #bundle1
1377 if bcompression is None:
1377 if bcompression is None:
1378 bcompression = 'UN'
1378 bcompression = 'UN'
1379 bversion = 'HG10' + bcompression
1379 bversion = 'HG10' + bcompression
1380 bcompression = None
1380 bcompression = None
1381 elif cgversion in ('02', '03'):
1381 elif cgversion in ('02', '03'):
1382 bversion = 'HG20'
1382 bversion = 'HG20'
1383 else:
1383 else:
1384 raise error.ProgrammingError(
1384 raise error.ProgrammingError(
1385 'bundle: unexpected changegroup version %s' % cgversion)
1385 'bundle: unexpected changegroup version %s' % cgversion)
1386
1386
1387 cg = changegroup.getchangegroup(repo, 'bundle', outgoing, version=cgversion)
1388
1389 # TODO compression options should be derived from bundlespec parsing.
1387 # TODO compression options should be derived from bundlespec parsing.
1390 # This is a temporary hack to allow adjusting bundle compression
1388 # This is a temporary hack to allow adjusting bundle compression
1391 # level without a) formalizing the bundlespec changes to declare it
1389 # level without a) formalizing the bundlespec changes to declare it
1392 # b) introducing a command flag.
1390 # b) introducing a command flag.
1393 compopts = {}
1391 compopts = {}
1394 complevel = ui.configint('experimental', 'bundlecomplevel')
1392 complevel = ui.configint('experimental', 'bundlecomplevel')
1395 if complevel is not None:
1393 if complevel is not None:
1396 compopts['level'] = complevel
1394 compopts['level'] = complevel
1397
1395
1396 cg = changegroup.getchangegroup(repo, 'bundle', outgoing, version=cgversion)
1397
1398 bundle2.writebundle(ui, cg, fname, bversion, compression=bcompression,
1398 bundle2.writebundle(ui, cg, fname, bversion, compression=bcompression,
1399 compopts=compopts)
1399 compopts=compopts)
1400
1400
1401 @command('cat',
1401 @command('cat',
1402 [('o', 'output', '',
1402 [('o', 'output', '',
1403 _('print output to file with formatted name'), _('FORMAT')),
1403 _('print output to file with formatted name'), _('FORMAT')),
1404 ('r', 'rev', '', _('print the given revision'), _('REV')),
1404 ('r', 'rev', '', _('print the given revision'), _('REV')),
1405 ('', 'decode', None, _('apply any matching decode filter')),
1405 ('', 'decode', None, _('apply any matching decode filter')),
1406 ] + walkopts,
1406 ] + walkopts,
1407 _('[OPTION]... FILE...'),
1407 _('[OPTION]... FILE...'),
1408 inferrepo=True)
1408 inferrepo=True)
1409 def cat(ui, repo, file1, *pats, **opts):
1409 def cat(ui, repo, file1, *pats, **opts):
1410 """output the current or given revision of files
1410 """output the current or given revision of files
1411
1411
1412 Print the specified files as they were at the given revision. If
1412 Print the specified files as they were at the given revision. If
1413 no revision is given, the parent of the working directory is used.
1413 no revision is given, the parent of the working directory is used.
1414
1414
1415 Output may be to a file, in which case the name of the file is
1415 Output may be to a file, in which case the name of the file is
1416 given using a format string. The formatting rules as follows:
1416 given using a format string. The formatting rules as follows:
1417
1417
1418 :``%%``: literal "%" character
1418 :``%%``: literal "%" character
1419 :``%s``: basename of file being printed
1419 :``%s``: basename of file being printed
1420 :``%d``: dirname of file being printed, or '.' if in repository root
1420 :``%d``: dirname of file being printed, or '.' if in repository root
1421 :``%p``: root-relative path name of file being printed
1421 :``%p``: root-relative path name of file being printed
1422 :``%H``: changeset hash (40 hexadecimal digits)
1422 :``%H``: changeset hash (40 hexadecimal digits)
1423 :``%R``: changeset revision number
1423 :``%R``: changeset revision number
1424 :``%h``: short-form changeset hash (12 hexadecimal digits)
1424 :``%h``: short-form changeset hash (12 hexadecimal digits)
1425 :``%r``: zero-padded changeset revision number
1425 :``%r``: zero-padded changeset revision number
1426 :``%b``: basename of the exporting repository
1426 :``%b``: basename of the exporting repository
1427
1427
1428 Returns 0 on success.
1428 Returns 0 on success.
1429 """
1429 """
1430 ctx = scmutil.revsingle(repo, opts.get('rev'))
1430 ctx = scmutil.revsingle(repo, opts.get('rev'))
1431 m = scmutil.match(ctx, (file1,) + pats, opts)
1431 m = scmutil.match(ctx, (file1,) + pats, opts)
1432
1432
1433 ui.pager('cat')
1433 ui.pager('cat')
1434 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1434 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1435
1435
1436 @command('^clone',
1436 @command('^clone',
1437 [('U', 'noupdate', None, _('the clone will include an empty working '
1437 [('U', 'noupdate', None, _('the clone will include an empty working '
1438 'directory (only a repository)')),
1438 'directory (only a repository)')),
1439 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1439 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1440 _('REV')),
1440 _('REV')),
1441 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1441 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1442 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1442 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1443 ('', 'pull', None, _('use pull protocol to copy metadata')),
1443 ('', 'pull', None, _('use pull protocol to copy metadata')),
1444 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1444 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1445 ] + remoteopts,
1445 ] + remoteopts,
1446 _('[OPTION]... SOURCE [DEST]'),
1446 _('[OPTION]... SOURCE [DEST]'),
1447 norepo=True)
1447 norepo=True)
1448 def clone(ui, source, dest=None, **opts):
1448 def clone(ui, source, dest=None, **opts):
1449 """make a copy of an existing repository
1449 """make a copy of an existing repository
1450
1450
1451 Create a copy of an existing repository in a new directory.
1451 Create a copy of an existing repository in a new directory.
1452
1452
1453 If no destination directory name is specified, it defaults to the
1453 If no destination directory name is specified, it defaults to the
1454 basename of the source.
1454 basename of the source.
1455
1455
1456 The location of the source is added to the new repository's
1456 The location of the source is added to the new repository's
1457 ``.hg/hgrc`` file, as the default to be used for future pulls.
1457 ``.hg/hgrc`` file, as the default to be used for future pulls.
1458
1458
1459 Only local paths and ``ssh://`` URLs are supported as
1459 Only local paths and ``ssh://`` URLs are supported as
1460 destinations. For ``ssh://`` destinations, no working directory or
1460 destinations. For ``ssh://`` destinations, no working directory or
1461 ``.hg/hgrc`` will be created on the remote side.
1461 ``.hg/hgrc`` will be created on the remote side.
1462
1462
1463 If the source repository has a bookmark called '@' set, that
1463 If the source repository has a bookmark called '@' set, that
1464 revision will be checked out in the new repository by default.
1464 revision will be checked out in the new repository by default.
1465
1465
1466 To check out a particular version, use -u/--update, or
1466 To check out a particular version, use -u/--update, or
1467 -U/--noupdate to create a clone with no working directory.
1467 -U/--noupdate to create a clone with no working directory.
1468
1468
1469 To pull only a subset of changesets, specify one or more revisions
1469 To pull only a subset of changesets, specify one or more revisions
1470 identifiers with -r/--rev or branches with -b/--branch. The
1470 identifiers with -r/--rev or branches with -b/--branch. The
1471 resulting clone will contain only the specified changesets and
1471 resulting clone will contain only the specified changesets and
1472 their ancestors. These options (or 'clone src#rev dest') imply
1472 their ancestors. These options (or 'clone src#rev dest') imply
1473 --pull, even for local source repositories.
1473 --pull, even for local source repositories.
1474
1474
1475 .. note::
1475 .. note::
1476
1476
1477 Specifying a tag will include the tagged changeset but not the
1477 Specifying a tag will include the tagged changeset but not the
1478 changeset containing the tag.
1478 changeset containing the tag.
1479
1479
1480 .. container:: verbose
1480 .. container:: verbose
1481
1481
1482 For efficiency, hardlinks are used for cloning whenever the
1482 For efficiency, hardlinks are used for cloning whenever the
1483 source and destination are on the same filesystem (note this
1483 source and destination are on the same filesystem (note this
1484 applies only to the repository data, not to the working
1484 applies only to the repository data, not to the working
1485 directory). Some filesystems, such as AFS, implement hardlinking
1485 directory). Some filesystems, such as AFS, implement hardlinking
1486 incorrectly, but do not report errors. In these cases, use the
1486 incorrectly, but do not report errors. In these cases, use the
1487 --pull option to avoid hardlinking.
1487 --pull option to avoid hardlinking.
1488
1488
1489 In some cases, you can clone repositories and the working
1489 In some cases, you can clone repositories and the working
1490 directory using full hardlinks with ::
1490 directory using full hardlinks with ::
1491
1491
1492 $ cp -al REPO REPOCLONE
1492 $ cp -al REPO REPOCLONE
1493
1493
1494 This is the fastest way to clone, but it is not always safe. The
1494 This is the fastest way to clone, but it is not always safe. The
1495 operation is not atomic (making sure REPO is not modified during
1495 operation is not atomic (making sure REPO is not modified during
1496 the operation is up to you) and you have to make sure your
1496 the operation is up to you) and you have to make sure your
1497 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1497 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1498 so). Also, this is not compatible with certain extensions that
1498 so). Also, this is not compatible with certain extensions that
1499 place their metadata under the .hg directory, such as mq.
1499 place their metadata under the .hg directory, such as mq.
1500
1500
1501 Mercurial will update the working directory to the first applicable
1501 Mercurial will update the working directory to the first applicable
1502 revision from this list:
1502 revision from this list:
1503
1503
1504 a) null if -U or the source repository has no changesets
1504 a) null if -U or the source repository has no changesets
1505 b) if -u . and the source repository is local, the first parent of
1505 b) if -u . and the source repository is local, the first parent of
1506 the source repository's working directory
1506 the source repository's working directory
1507 c) the changeset specified with -u (if a branch name, this means the
1507 c) the changeset specified with -u (if a branch name, this means the
1508 latest head of that branch)
1508 latest head of that branch)
1509 d) the changeset specified with -r
1509 d) the changeset specified with -r
1510 e) the tipmost head specified with -b
1510 e) the tipmost head specified with -b
1511 f) the tipmost head specified with the url#branch source syntax
1511 f) the tipmost head specified with the url#branch source syntax
1512 g) the revision marked with the '@' bookmark, if present
1512 g) the revision marked with the '@' bookmark, if present
1513 h) the tipmost head of the default branch
1513 h) the tipmost head of the default branch
1514 i) tip
1514 i) tip
1515
1515
1516 When cloning from servers that support it, Mercurial may fetch
1516 When cloning from servers that support it, Mercurial may fetch
1517 pre-generated data from a server-advertised URL. When this is done,
1517 pre-generated data from a server-advertised URL. When this is done,
1518 hooks operating on incoming changesets and changegroups may fire twice,
1518 hooks operating on incoming changesets and changegroups may fire twice,
1519 once for the bundle fetched from the URL and another for any additional
1519 once for the bundle fetched from the URL and another for any additional
1520 data not fetched from this URL. In addition, if an error occurs, the
1520 data not fetched from this URL. In addition, if an error occurs, the
1521 repository may be rolled back to a partial clone. This behavior may
1521 repository may be rolled back to a partial clone. This behavior may
1522 change in future releases. See :hg:`help -e clonebundles` for more.
1522 change in future releases. See :hg:`help -e clonebundles` for more.
1523
1523
1524 Examples:
1524 Examples:
1525
1525
1526 - clone a remote repository to a new directory named hg/::
1526 - clone a remote repository to a new directory named hg/::
1527
1527
1528 hg clone https://www.mercurial-scm.org/repo/hg/
1528 hg clone https://www.mercurial-scm.org/repo/hg/
1529
1529
1530 - create a lightweight local clone::
1530 - create a lightweight local clone::
1531
1531
1532 hg clone project/ project-feature/
1532 hg clone project/ project-feature/
1533
1533
1534 - clone from an absolute path on an ssh server (note double-slash)::
1534 - clone from an absolute path on an ssh server (note double-slash)::
1535
1535
1536 hg clone ssh://user@server//home/projects/alpha/
1536 hg clone ssh://user@server//home/projects/alpha/
1537
1537
1538 - do a high-speed clone over a LAN while checking out a
1538 - do a high-speed clone over a LAN while checking out a
1539 specified version::
1539 specified version::
1540
1540
1541 hg clone --uncompressed http://server/repo -u 1.5
1541 hg clone --uncompressed http://server/repo -u 1.5
1542
1542
1543 - create a repository without changesets after a particular revision::
1543 - create a repository without changesets after a particular revision::
1544
1544
1545 hg clone -r 04e544 experimental/ good/
1545 hg clone -r 04e544 experimental/ good/
1546
1546
1547 - clone (and track) a particular named branch::
1547 - clone (and track) a particular named branch::
1548
1548
1549 hg clone https://www.mercurial-scm.org/repo/hg/#stable
1549 hg clone https://www.mercurial-scm.org/repo/hg/#stable
1550
1550
1551 See :hg:`help urls` for details on specifying URLs.
1551 See :hg:`help urls` for details on specifying URLs.
1552
1552
1553 Returns 0 on success.
1553 Returns 0 on success.
1554 """
1554 """
1555 opts = pycompat.byteskwargs(opts)
1555 opts = pycompat.byteskwargs(opts)
1556 if opts.get('noupdate') and opts.get('updaterev'):
1556 if opts.get('noupdate') and opts.get('updaterev'):
1557 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1557 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1558
1558
1559 r = hg.clone(ui, opts, source, dest,
1559 r = hg.clone(ui, opts, source, dest,
1560 pull=opts.get('pull'),
1560 pull=opts.get('pull'),
1561 stream=opts.get('uncompressed'),
1561 stream=opts.get('uncompressed'),
1562 rev=opts.get('rev'),
1562 rev=opts.get('rev'),
1563 update=opts.get('updaterev') or not opts.get('noupdate'),
1563 update=opts.get('updaterev') or not opts.get('noupdate'),
1564 branch=opts.get('branch'),
1564 branch=opts.get('branch'),
1565 shareopts=opts.get('shareopts'))
1565 shareopts=opts.get('shareopts'))
1566
1566
1567 return r is None
1567 return r is None
1568
1568
1569 @command('^commit|ci',
1569 @command('^commit|ci',
1570 [('A', 'addremove', None,
1570 [('A', 'addremove', None,
1571 _('mark new/missing files as added/removed before committing')),
1571 _('mark new/missing files as added/removed before committing')),
1572 ('', 'close-branch', None,
1572 ('', 'close-branch', None,
1573 _('mark a branch head as closed')),
1573 _('mark a branch head as closed')),
1574 ('', 'amend', None, _('amend the parent of the working directory')),
1574 ('', 'amend', None, _('amend the parent of the working directory')),
1575 ('s', 'secret', None, _('use the secret phase for committing')),
1575 ('s', 'secret', None, _('use the secret phase for committing')),
1576 ('e', 'edit', None, _('invoke editor on commit messages')),
1576 ('e', 'edit', None, _('invoke editor on commit messages')),
1577 ('i', 'interactive', None, _('use interactive mode')),
1577 ('i', 'interactive', None, _('use interactive mode')),
1578 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1578 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1579 _('[OPTION]... [FILE]...'),
1579 _('[OPTION]... [FILE]...'),
1580 inferrepo=True)
1580 inferrepo=True)
1581 def commit(ui, repo, *pats, **opts):
1581 def commit(ui, repo, *pats, **opts):
1582 """commit the specified files or all outstanding changes
1582 """commit the specified files or all outstanding changes
1583
1583
1584 Commit changes to the given files into the repository. Unlike a
1584 Commit changes to the given files into the repository. Unlike a
1585 centralized SCM, this operation is a local operation. See
1585 centralized SCM, this operation is a local operation. See
1586 :hg:`push` for a way to actively distribute your changes.
1586 :hg:`push` for a way to actively distribute your changes.
1587
1587
1588 If a list of files is omitted, all changes reported by :hg:`status`
1588 If a list of files is omitted, all changes reported by :hg:`status`
1589 will be committed.
1589 will be committed.
1590
1590
1591 If you are committing the result of a merge, do not provide any
1591 If you are committing the result of a merge, do not provide any
1592 filenames or -I/-X filters.
1592 filenames or -I/-X filters.
1593
1593
1594 If no commit message is specified, Mercurial starts your
1594 If no commit message is specified, Mercurial starts your
1595 configured editor where you can enter a message. In case your
1595 configured editor where you can enter a message. In case your
1596 commit fails, you will find a backup of your message in
1596 commit fails, you will find a backup of your message in
1597 ``.hg/last-message.txt``.
1597 ``.hg/last-message.txt``.
1598
1598
1599 The --close-branch flag can be used to mark the current branch
1599 The --close-branch flag can be used to mark the current branch
1600 head closed. When all heads of a branch are closed, the branch
1600 head closed. When all heads of a branch are closed, the branch
1601 will be considered closed and no longer listed.
1601 will be considered closed and no longer listed.
1602
1602
1603 The --amend flag can be used to amend the parent of the
1603 The --amend flag can be used to amend the parent of the
1604 working directory with a new commit that contains the changes
1604 working directory with a new commit that contains the changes
1605 in the parent in addition to those currently reported by :hg:`status`,
1605 in the parent in addition to those currently reported by :hg:`status`,
1606 if there are any. The old commit is stored in a backup bundle in
1606 if there are any. The old commit is stored in a backup bundle in
1607 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1607 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1608 on how to restore it).
1608 on how to restore it).
1609
1609
1610 Message, user and date are taken from the amended commit unless
1610 Message, user and date are taken from the amended commit unless
1611 specified. When a message isn't specified on the command line,
1611 specified. When a message isn't specified on the command line,
1612 the editor will open with the message of the amended commit.
1612 the editor will open with the message of the amended commit.
1613
1613
1614 It is not possible to amend public changesets (see :hg:`help phases`)
1614 It is not possible to amend public changesets (see :hg:`help phases`)
1615 or changesets that have children.
1615 or changesets that have children.
1616
1616
1617 See :hg:`help dates` for a list of formats valid for -d/--date.
1617 See :hg:`help dates` for a list of formats valid for -d/--date.
1618
1618
1619 Returns 0 on success, 1 if nothing changed.
1619 Returns 0 on success, 1 if nothing changed.
1620
1620
1621 .. container:: verbose
1621 .. container:: verbose
1622
1622
1623 Examples:
1623 Examples:
1624
1624
1625 - commit all files ending in .py::
1625 - commit all files ending in .py::
1626
1626
1627 hg commit --include "set:**.py"
1627 hg commit --include "set:**.py"
1628
1628
1629 - commit all non-binary files::
1629 - commit all non-binary files::
1630
1630
1631 hg commit --exclude "set:binary()"
1631 hg commit --exclude "set:binary()"
1632
1632
1633 - amend the current commit and set the date to now::
1633 - amend the current commit and set the date to now::
1634
1634
1635 hg commit --amend --date now
1635 hg commit --amend --date now
1636 """
1636 """
1637 wlock = lock = None
1637 wlock = lock = None
1638 try:
1638 try:
1639 wlock = repo.wlock()
1639 wlock = repo.wlock()
1640 lock = repo.lock()
1640 lock = repo.lock()
1641 return _docommit(ui, repo, *pats, **opts)
1641 return _docommit(ui, repo, *pats, **opts)
1642 finally:
1642 finally:
1643 release(lock, wlock)
1643 release(lock, wlock)
1644
1644
1645 def _docommit(ui, repo, *pats, **opts):
1645 def _docommit(ui, repo, *pats, **opts):
1646 if opts.get(r'interactive'):
1646 if opts.get(r'interactive'):
1647 opts.pop(r'interactive')
1647 opts.pop(r'interactive')
1648 ret = cmdutil.dorecord(ui, repo, commit, None, False,
1648 ret = cmdutil.dorecord(ui, repo, commit, None, False,
1649 cmdutil.recordfilter, *pats,
1649 cmdutil.recordfilter, *pats,
1650 **opts)
1650 **opts)
1651 # ret can be 0 (no changes to record) or the value returned by
1651 # ret can be 0 (no changes to record) or the value returned by
1652 # commit(), 1 if nothing changed or None on success.
1652 # commit(), 1 if nothing changed or None on success.
1653 return 1 if ret == 0 else ret
1653 return 1 if ret == 0 else ret
1654
1654
1655 opts = pycompat.byteskwargs(opts)
1655 opts = pycompat.byteskwargs(opts)
1656 if opts.get('subrepos'):
1656 if opts.get('subrepos'):
1657 if opts.get('amend'):
1657 if opts.get('amend'):
1658 raise error.Abort(_('cannot amend with --subrepos'))
1658 raise error.Abort(_('cannot amend with --subrepos'))
1659 # Let --subrepos on the command line override config setting.
1659 # Let --subrepos on the command line override config setting.
1660 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1660 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1661
1661
1662 cmdutil.checkunfinished(repo, commit=True)
1662 cmdutil.checkunfinished(repo, commit=True)
1663
1663
1664 branch = repo[None].branch()
1664 branch = repo[None].branch()
1665 bheads = repo.branchheads(branch)
1665 bheads = repo.branchheads(branch)
1666
1666
1667 extra = {}
1667 extra = {}
1668 if opts.get('close_branch'):
1668 if opts.get('close_branch'):
1669 extra['close'] = 1
1669 extra['close'] = 1
1670
1670
1671 if not bheads:
1671 if not bheads:
1672 raise error.Abort(_('can only close branch heads'))
1672 raise error.Abort(_('can only close branch heads'))
1673 elif opts.get('amend'):
1673 elif opts.get('amend'):
1674 if repo[None].parents()[0].p1().branch() != branch and \
1674 if repo[None].parents()[0].p1().branch() != branch and \
1675 repo[None].parents()[0].p2().branch() != branch:
1675 repo[None].parents()[0].p2().branch() != branch:
1676 raise error.Abort(_('can only close branch heads'))
1676 raise error.Abort(_('can only close branch heads'))
1677
1677
1678 if opts.get('amend'):
1678 if opts.get('amend'):
1679 if ui.configbool('ui', 'commitsubrepos'):
1679 if ui.configbool('ui', 'commitsubrepos'):
1680 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1680 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1681
1681
1682 old = repo['.']
1682 old = repo['.']
1683 if not old.mutable():
1683 if not old.mutable():
1684 raise error.Abort(_('cannot amend public changesets'))
1684 raise error.Abort(_('cannot amend public changesets'))
1685 if len(repo[None].parents()) > 1:
1685 if len(repo[None].parents()) > 1:
1686 raise error.Abort(_('cannot amend while merging'))
1686 raise error.Abort(_('cannot amend while merging'))
1687 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1687 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1688 if not allowunstable and old.children():
1688 if not allowunstable and old.children():
1689 raise error.Abort(_('cannot amend changeset with children'))
1689 raise error.Abort(_('cannot amend changeset with children'))
1690
1690
1691 # Currently histedit gets confused if an amend happens while histedit
1691 # Currently histedit gets confused if an amend happens while histedit
1692 # is in progress. Since we have a checkunfinished command, we are
1692 # is in progress. Since we have a checkunfinished command, we are
1693 # temporarily honoring it.
1693 # temporarily honoring it.
1694 #
1694 #
1695 # Note: eventually this guard will be removed. Please do not expect
1695 # Note: eventually this guard will be removed. Please do not expect
1696 # this behavior to remain.
1696 # this behavior to remain.
1697 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
1697 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
1698 cmdutil.checkunfinished(repo)
1698 cmdutil.checkunfinished(repo)
1699
1699
1700 # commitfunc is used only for temporary amend commit by cmdutil.amend
1700 # commitfunc is used only for temporary amend commit by cmdutil.amend
1701 def commitfunc(ui, repo, message, match, opts):
1701 def commitfunc(ui, repo, message, match, opts):
1702 return repo.commit(message,
1702 return repo.commit(message,
1703 opts.get('user') or old.user(),
1703 opts.get('user') or old.user(),
1704 opts.get('date') or old.date(),
1704 opts.get('date') or old.date(),
1705 match,
1705 match,
1706 extra=extra)
1706 extra=extra)
1707
1707
1708 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1708 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1709 if node == old.node():
1709 if node == old.node():
1710 ui.status(_("nothing changed\n"))
1710 ui.status(_("nothing changed\n"))
1711 return 1
1711 return 1
1712 else:
1712 else:
1713 def commitfunc(ui, repo, message, match, opts):
1713 def commitfunc(ui, repo, message, match, opts):
1714 overrides = {}
1714 overrides = {}
1715 if opts.get('secret'):
1715 if opts.get('secret'):
1716 overrides[('phases', 'new-commit')] = 'secret'
1716 overrides[('phases', 'new-commit')] = 'secret'
1717
1717
1718 baseui = repo.baseui
1718 baseui = repo.baseui
1719 with baseui.configoverride(overrides, 'commit'):
1719 with baseui.configoverride(overrides, 'commit'):
1720 with ui.configoverride(overrides, 'commit'):
1720 with ui.configoverride(overrides, 'commit'):
1721 editform = cmdutil.mergeeditform(repo[None],
1721 editform = cmdutil.mergeeditform(repo[None],
1722 'commit.normal')
1722 'commit.normal')
1723 editor = cmdutil.getcommiteditor(
1723 editor = cmdutil.getcommiteditor(
1724 editform=editform, **pycompat.strkwargs(opts))
1724 editform=editform, **pycompat.strkwargs(opts))
1725 return repo.commit(message,
1725 return repo.commit(message,
1726 opts.get('user'),
1726 opts.get('user'),
1727 opts.get('date'),
1727 opts.get('date'),
1728 match,
1728 match,
1729 editor=editor,
1729 editor=editor,
1730 extra=extra)
1730 extra=extra)
1731
1731
1732 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1732 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1733
1733
1734 if not node:
1734 if not node:
1735 stat = cmdutil.postcommitstatus(repo, pats, opts)
1735 stat = cmdutil.postcommitstatus(repo, pats, opts)
1736 if stat[3]:
1736 if stat[3]:
1737 ui.status(_("nothing changed (%d missing files, see "
1737 ui.status(_("nothing changed (%d missing files, see "
1738 "'hg status')\n") % len(stat[3]))
1738 "'hg status')\n") % len(stat[3]))
1739 else:
1739 else:
1740 ui.status(_("nothing changed\n"))
1740 ui.status(_("nothing changed\n"))
1741 return 1
1741 return 1
1742
1742
1743 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1743 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1744
1744
1745 @command('config|showconfig|debugconfig',
1745 @command('config|showconfig|debugconfig',
1746 [('u', 'untrusted', None, _('show untrusted configuration options')),
1746 [('u', 'untrusted', None, _('show untrusted configuration options')),
1747 ('e', 'edit', None, _('edit user config')),
1747 ('e', 'edit', None, _('edit user config')),
1748 ('l', 'local', None, _('edit repository config')),
1748 ('l', 'local', None, _('edit repository config')),
1749 ('g', 'global', None, _('edit global config'))] + formatteropts,
1749 ('g', 'global', None, _('edit global config'))] + formatteropts,
1750 _('[-u] [NAME]...'),
1750 _('[-u] [NAME]...'),
1751 optionalrepo=True)
1751 optionalrepo=True)
1752 def config(ui, repo, *values, **opts):
1752 def config(ui, repo, *values, **opts):
1753 """show combined config settings from all hgrc files
1753 """show combined config settings from all hgrc files
1754
1754
1755 With no arguments, print names and values of all config items.
1755 With no arguments, print names and values of all config items.
1756
1756
1757 With one argument of the form section.name, print just the value
1757 With one argument of the form section.name, print just the value
1758 of that config item.
1758 of that config item.
1759
1759
1760 With multiple arguments, print names and values of all config
1760 With multiple arguments, print names and values of all config
1761 items with matching section names.
1761 items with matching section names.
1762
1762
1763 With --edit, start an editor on the user-level config file. With
1763 With --edit, start an editor on the user-level config file. With
1764 --global, edit the system-wide config file. With --local, edit the
1764 --global, edit the system-wide config file. With --local, edit the
1765 repository-level config file.
1765 repository-level config file.
1766
1766
1767 With --debug, the source (filename and line number) is printed
1767 With --debug, the source (filename and line number) is printed
1768 for each config item.
1768 for each config item.
1769
1769
1770 See :hg:`help config` for more information about config files.
1770 See :hg:`help config` for more information about config files.
1771
1771
1772 Returns 0 on success, 1 if NAME does not exist.
1772 Returns 0 on success, 1 if NAME does not exist.
1773
1773
1774 """
1774 """
1775
1775
1776 opts = pycompat.byteskwargs(opts)
1776 opts = pycompat.byteskwargs(opts)
1777 if opts.get('edit') or opts.get('local') or opts.get('global'):
1777 if opts.get('edit') or opts.get('local') or opts.get('global'):
1778 if opts.get('local') and opts.get('global'):
1778 if opts.get('local') and opts.get('global'):
1779 raise error.Abort(_("can't use --local and --global together"))
1779 raise error.Abort(_("can't use --local and --global together"))
1780
1780
1781 if opts.get('local'):
1781 if opts.get('local'):
1782 if not repo:
1782 if not repo:
1783 raise error.Abort(_("can't use --local outside a repository"))
1783 raise error.Abort(_("can't use --local outside a repository"))
1784 paths = [repo.vfs.join('hgrc')]
1784 paths = [repo.vfs.join('hgrc')]
1785 elif opts.get('global'):
1785 elif opts.get('global'):
1786 paths = rcutil.systemrcpath()
1786 paths = rcutil.systemrcpath()
1787 else:
1787 else:
1788 paths = rcutil.userrcpath()
1788 paths = rcutil.userrcpath()
1789
1789
1790 for f in paths:
1790 for f in paths:
1791 if os.path.exists(f):
1791 if os.path.exists(f):
1792 break
1792 break
1793 else:
1793 else:
1794 if opts.get('global'):
1794 if opts.get('global'):
1795 samplehgrc = uimod.samplehgrcs['global']
1795 samplehgrc = uimod.samplehgrcs['global']
1796 elif opts.get('local'):
1796 elif opts.get('local'):
1797 samplehgrc = uimod.samplehgrcs['local']
1797 samplehgrc = uimod.samplehgrcs['local']
1798 else:
1798 else:
1799 samplehgrc = uimod.samplehgrcs['user']
1799 samplehgrc = uimod.samplehgrcs['user']
1800
1800
1801 f = paths[0]
1801 f = paths[0]
1802 fp = open(f, "w")
1802 fp = open(f, "w")
1803 fp.write(samplehgrc)
1803 fp.write(samplehgrc)
1804 fp.close()
1804 fp.close()
1805
1805
1806 editor = ui.geteditor()
1806 editor = ui.geteditor()
1807 ui.system("%s \"%s\"" % (editor, f),
1807 ui.system("%s \"%s\"" % (editor, f),
1808 onerr=error.Abort, errprefix=_("edit failed"),
1808 onerr=error.Abort, errprefix=_("edit failed"),
1809 blockedtag='config_edit')
1809 blockedtag='config_edit')
1810 return
1810 return
1811 ui.pager('config')
1811 ui.pager('config')
1812 fm = ui.formatter('config', opts)
1812 fm = ui.formatter('config', opts)
1813 for t, f in rcutil.rccomponents():
1813 for t, f in rcutil.rccomponents():
1814 if t == 'path':
1814 if t == 'path':
1815 ui.debug('read config from: %s\n' % f)
1815 ui.debug('read config from: %s\n' % f)
1816 elif t == 'items':
1816 elif t == 'items':
1817 for section, name, value, source in f:
1817 for section, name, value, source in f:
1818 ui.debug('set config by: %s\n' % source)
1818 ui.debug('set config by: %s\n' % source)
1819 else:
1819 else:
1820 raise error.ProgrammingError('unknown rctype: %s' % t)
1820 raise error.ProgrammingError('unknown rctype: %s' % t)
1821 untrusted = bool(opts.get('untrusted'))
1821 untrusted = bool(opts.get('untrusted'))
1822 if values:
1822 if values:
1823 sections = [v for v in values if '.' not in v]
1823 sections = [v for v in values if '.' not in v]
1824 items = [v for v in values if '.' in v]
1824 items = [v for v in values if '.' in v]
1825 if len(items) > 1 or items and sections:
1825 if len(items) > 1 or items and sections:
1826 raise error.Abort(_('only one config item permitted'))
1826 raise error.Abort(_('only one config item permitted'))
1827 matched = False
1827 matched = False
1828 for section, name, value in ui.walkconfig(untrusted=untrusted):
1828 for section, name, value in ui.walkconfig(untrusted=untrusted):
1829 source = ui.configsource(section, name, untrusted)
1829 source = ui.configsource(section, name, untrusted)
1830 value = pycompat.bytestr(value)
1830 value = pycompat.bytestr(value)
1831 if fm.isplain():
1831 if fm.isplain():
1832 source = source or 'none'
1832 source = source or 'none'
1833 value = value.replace('\n', '\\n')
1833 value = value.replace('\n', '\\n')
1834 entryname = section + '.' + name
1834 entryname = section + '.' + name
1835 if values:
1835 if values:
1836 for v in values:
1836 for v in values:
1837 if v == section:
1837 if v == section:
1838 fm.startitem()
1838 fm.startitem()
1839 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1839 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1840 fm.write('name value', '%s=%s\n', entryname, value)
1840 fm.write('name value', '%s=%s\n', entryname, value)
1841 matched = True
1841 matched = True
1842 elif v == entryname:
1842 elif v == entryname:
1843 fm.startitem()
1843 fm.startitem()
1844 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1844 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1845 fm.write('value', '%s\n', value)
1845 fm.write('value', '%s\n', value)
1846 fm.data(name=entryname)
1846 fm.data(name=entryname)
1847 matched = True
1847 matched = True
1848 else:
1848 else:
1849 fm.startitem()
1849 fm.startitem()
1850 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1850 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1851 fm.write('name value', '%s=%s\n', entryname, value)
1851 fm.write('name value', '%s=%s\n', entryname, value)
1852 matched = True
1852 matched = True
1853 fm.end()
1853 fm.end()
1854 if matched:
1854 if matched:
1855 return 0
1855 return 0
1856 return 1
1856 return 1
1857
1857
1858 @command('copy|cp',
1858 @command('copy|cp',
1859 [('A', 'after', None, _('record a copy that has already occurred')),
1859 [('A', 'after', None, _('record a copy that has already occurred')),
1860 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1860 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1861 ] + walkopts + dryrunopts,
1861 ] + walkopts + dryrunopts,
1862 _('[OPTION]... [SOURCE]... DEST'))
1862 _('[OPTION]... [SOURCE]... DEST'))
1863 def copy(ui, repo, *pats, **opts):
1863 def copy(ui, repo, *pats, **opts):
1864 """mark files as copied for the next commit
1864 """mark files as copied for the next commit
1865
1865
1866 Mark dest as having copies of source files. If dest is a
1866 Mark dest as having copies of source files. If dest is a
1867 directory, copies are put in that directory. If dest is a file,
1867 directory, copies are put in that directory. If dest is a file,
1868 the source must be a single file.
1868 the source must be a single file.
1869
1869
1870 By default, this command copies the contents of files as they
1870 By default, this command copies the contents of files as they
1871 exist in the working directory. If invoked with -A/--after, the
1871 exist in the working directory. If invoked with -A/--after, the
1872 operation is recorded, but no copying is performed.
1872 operation is recorded, but no copying is performed.
1873
1873
1874 This command takes effect with the next commit. To undo a copy
1874 This command takes effect with the next commit. To undo a copy
1875 before that, see :hg:`revert`.
1875 before that, see :hg:`revert`.
1876
1876
1877 Returns 0 on success, 1 if errors are encountered.
1877 Returns 0 on success, 1 if errors are encountered.
1878 """
1878 """
1879 opts = pycompat.byteskwargs(opts)
1879 opts = pycompat.byteskwargs(opts)
1880 with repo.wlock(False):
1880 with repo.wlock(False):
1881 return cmdutil.copy(ui, repo, pats, opts)
1881 return cmdutil.copy(ui, repo, pats, opts)
1882
1882
1883 @command('^diff',
1883 @command('^diff',
1884 [('r', 'rev', [], _('revision'), _('REV')),
1884 [('r', 'rev', [], _('revision'), _('REV')),
1885 ('c', 'change', '', _('change made by revision'), _('REV'))
1885 ('c', 'change', '', _('change made by revision'), _('REV'))
1886 ] + diffopts + diffopts2 + walkopts + subrepoopts,
1886 ] + diffopts + diffopts2 + walkopts + subrepoopts,
1887 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
1887 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
1888 inferrepo=True)
1888 inferrepo=True)
1889 def diff(ui, repo, *pats, **opts):
1889 def diff(ui, repo, *pats, **opts):
1890 """diff repository (or selected files)
1890 """diff repository (or selected files)
1891
1891
1892 Show differences between revisions for the specified files.
1892 Show differences between revisions for the specified files.
1893
1893
1894 Differences between files are shown using the unified diff format.
1894 Differences between files are shown using the unified diff format.
1895
1895
1896 .. note::
1896 .. note::
1897
1897
1898 :hg:`diff` may generate unexpected results for merges, as it will
1898 :hg:`diff` may generate unexpected results for merges, as it will
1899 default to comparing against the working directory's first
1899 default to comparing against the working directory's first
1900 parent changeset if no revisions are specified.
1900 parent changeset if no revisions are specified.
1901
1901
1902 When two revision arguments are given, then changes are shown
1902 When two revision arguments are given, then changes are shown
1903 between those revisions. If only one revision is specified then
1903 between those revisions. If only one revision is specified then
1904 that revision is compared to the working directory, and, when no
1904 that revision is compared to the working directory, and, when no
1905 revisions are specified, the working directory files are compared
1905 revisions are specified, the working directory files are compared
1906 to its first parent.
1906 to its first parent.
1907
1907
1908 Alternatively you can specify -c/--change with a revision to see
1908 Alternatively you can specify -c/--change with a revision to see
1909 the changes in that changeset relative to its first parent.
1909 the changes in that changeset relative to its first parent.
1910
1910
1911 Without the -a/--text option, diff will avoid generating diffs of
1911 Without the -a/--text option, diff will avoid generating diffs of
1912 files it detects as binary. With -a, diff will generate a diff
1912 files it detects as binary. With -a, diff will generate a diff
1913 anyway, probably with undesirable results.
1913 anyway, probably with undesirable results.
1914
1914
1915 Use the -g/--git option to generate diffs in the git extended diff
1915 Use the -g/--git option to generate diffs in the git extended diff
1916 format. For more information, read :hg:`help diffs`.
1916 format. For more information, read :hg:`help diffs`.
1917
1917
1918 .. container:: verbose
1918 .. container:: verbose
1919
1919
1920 Examples:
1920 Examples:
1921
1921
1922 - compare a file in the current working directory to its parent::
1922 - compare a file in the current working directory to its parent::
1923
1923
1924 hg diff foo.c
1924 hg diff foo.c
1925
1925
1926 - compare two historical versions of a directory, with rename info::
1926 - compare two historical versions of a directory, with rename info::
1927
1927
1928 hg diff --git -r 1.0:1.2 lib/
1928 hg diff --git -r 1.0:1.2 lib/
1929
1929
1930 - get change stats relative to the last change on some date::
1930 - get change stats relative to the last change on some date::
1931
1931
1932 hg diff --stat -r "date('may 2')"
1932 hg diff --stat -r "date('may 2')"
1933
1933
1934 - diff all newly-added files that contain a keyword::
1934 - diff all newly-added files that contain a keyword::
1935
1935
1936 hg diff "set:added() and grep(GNU)"
1936 hg diff "set:added() and grep(GNU)"
1937
1937
1938 - compare a revision and its parents::
1938 - compare a revision and its parents::
1939
1939
1940 hg diff -c 9353 # compare against first parent
1940 hg diff -c 9353 # compare against first parent
1941 hg diff -r 9353^:9353 # same using revset syntax
1941 hg diff -r 9353^:9353 # same using revset syntax
1942 hg diff -r 9353^2:9353 # compare against the second parent
1942 hg diff -r 9353^2:9353 # compare against the second parent
1943
1943
1944 Returns 0 on success.
1944 Returns 0 on success.
1945 """
1945 """
1946
1946
1947 opts = pycompat.byteskwargs(opts)
1947 opts = pycompat.byteskwargs(opts)
1948 revs = opts.get('rev')
1948 revs = opts.get('rev')
1949 change = opts.get('change')
1949 change = opts.get('change')
1950 stat = opts.get('stat')
1950 stat = opts.get('stat')
1951 reverse = opts.get('reverse')
1951 reverse = opts.get('reverse')
1952
1952
1953 if revs and change:
1953 if revs and change:
1954 msg = _('cannot specify --rev and --change at the same time')
1954 msg = _('cannot specify --rev and --change at the same time')
1955 raise error.Abort(msg)
1955 raise error.Abort(msg)
1956 elif change:
1956 elif change:
1957 node2 = scmutil.revsingle(repo, change, None).node()
1957 node2 = scmutil.revsingle(repo, change, None).node()
1958 node1 = repo[node2].p1().node()
1958 node1 = repo[node2].p1().node()
1959 else:
1959 else:
1960 node1, node2 = scmutil.revpair(repo, revs)
1960 node1, node2 = scmutil.revpair(repo, revs)
1961
1961
1962 if reverse:
1962 if reverse:
1963 node1, node2 = node2, node1
1963 node1, node2 = node2, node1
1964
1964
1965 diffopts = patch.diffallopts(ui, opts)
1965 diffopts = patch.diffallopts(ui, opts)
1966 m = scmutil.match(repo[node2], pats, opts)
1966 m = scmutil.match(repo[node2], pats, opts)
1967 ui.pager('diff')
1967 ui.pager('diff')
1968 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
1968 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
1969 listsubrepos=opts.get('subrepos'),
1969 listsubrepos=opts.get('subrepos'),
1970 root=opts.get('root'))
1970 root=opts.get('root'))
1971
1971
1972 @command('^export',
1972 @command('^export',
1973 [('o', 'output', '',
1973 [('o', 'output', '',
1974 _('print output to file with formatted name'), _('FORMAT')),
1974 _('print output to file with formatted name'), _('FORMAT')),
1975 ('', 'switch-parent', None, _('diff against the second parent')),
1975 ('', 'switch-parent', None, _('diff against the second parent')),
1976 ('r', 'rev', [], _('revisions to export'), _('REV')),
1976 ('r', 'rev', [], _('revisions to export'), _('REV')),
1977 ] + diffopts,
1977 ] + diffopts,
1978 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
1978 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
1979 def export(ui, repo, *changesets, **opts):
1979 def export(ui, repo, *changesets, **opts):
1980 """dump the header and diffs for one or more changesets
1980 """dump the header and diffs for one or more changesets
1981
1981
1982 Print the changeset header and diffs for one or more revisions.
1982 Print the changeset header and diffs for one or more revisions.
1983 If no revision is given, the parent of the working directory is used.
1983 If no revision is given, the parent of the working directory is used.
1984
1984
1985 The information shown in the changeset header is: author, date,
1985 The information shown in the changeset header is: author, date,
1986 branch name (if non-default), changeset hash, parent(s) and commit
1986 branch name (if non-default), changeset hash, parent(s) and commit
1987 comment.
1987 comment.
1988
1988
1989 .. note::
1989 .. note::
1990
1990
1991 :hg:`export` may generate unexpected diff output for merge
1991 :hg:`export` may generate unexpected diff output for merge
1992 changesets, as it will compare the merge changeset against its
1992 changesets, as it will compare the merge changeset against its
1993 first parent only.
1993 first parent only.
1994
1994
1995 Output may be to a file, in which case the name of the file is
1995 Output may be to a file, in which case the name of the file is
1996 given using a format string. The formatting rules are as follows:
1996 given using a format string. The formatting rules are as follows:
1997
1997
1998 :``%%``: literal "%" character
1998 :``%%``: literal "%" character
1999 :``%H``: changeset hash (40 hexadecimal digits)
1999 :``%H``: changeset hash (40 hexadecimal digits)
2000 :``%N``: number of patches being generated
2000 :``%N``: number of patches being generated
2001 :``%R``: changeset revision number
2001 :``%R``: changeset revision number
2002 :``%b``: basename of the exporting repository
2002 :``%b``: basename of the exporting repository
2003 :``%h``: short-form changeset hash (12 hexadecimal digits)
2003 :``%h``: short-form changeset hash (12 hexadecimal digits)
2004 :``%m``: first line of the commit message (only alphanumeric characters)
2004 :``%m``: first line of the commit message (only alphanumeric characters)
2005 :``%n``: zero-padded sequence number, starting at 1
2005 :``%n``: zero-padded sequence number, starting at 1
2006 :``%r``: zero-padded changeset revision number
2006 :``%r``: zero-padded changeset revision number
2007
2007
2008 Without the -a/--text option, export will avoid generating diffs
2008 Without the -a/--text option, export will avoid generating diffs
2009 of files it detects as binary. With -a, export will generate a
2009 of files it detects as binary. With -a, export will generate a
2010 diff anyway, probably with undesirable results.
2010 diff anyway, probably with undesirable results.
2011
2011
2012 Use the -g/--git option to generate diffs in the git extended diff
2012 Use the -g/--git option to generate diffs in the git extended diff
2013 format. See :hg:`help diffs` for more information.
2013 format. See :hg:`help diffs` for more information.
2014
2014
2015 With the --switch-parent option, the diff will be against the
2015 With the --switch-parent option, the diff will be against the
2016 second parent. It can be useful to review a merge.
2016 second parent. It can be useful to review a merge.
2017
2017
2018 .. container:: verbose
2018 .. container:: verbose
2019
2019
2020 Examples:
2020 Examples:
2021
2021
2022 - use export and import to transplant a bugfix to the current
2022 - use export and import to transplant a bugfix to the current
2023 branch::
2023 branch::
2024
2024
2025 hg export -r 9353 | hg import -
2025 hg export -r 9353 | hg import -
2026
2026
2027 - export all the changesets between two revisions to a file with
2027 - export all the changesets between two revisions to a file with
2028 rename information::
2028 rename information::
2029
2029
2030 hg export --git -r 123:150 > changes.txt
2030 hg export --git -r 123:150 > changes.txt
2031
2031
2032 - split outgoing changes into a series of patches with
2032 - split outgoing changes into a series of patches with
2033 descriptive names::
2033 descriptive names::
2034
2034
2035 hg export -r "outgoing()" -o "%n-%m.patch"
2035 hg export -r "outgoing()" -o "%n-%m.patch"
2036
2036
2037 Returns 0 on success.
2037 Returns 0 on success.
2038 """
2038 """
2039 opts = pycompat.byteskwargs(opts)
2039 opts = pycompat.byteskwargs(opts)
2040 changesets += tuple(opts.get('rev', []))
2040 changesets += tuple(opts.get('rev', []))
2041 if not changesets:
2041 if not changesets:
2042 changesets = ['.']
2042 changesets = ['.']
2043 revs = scmutil.revrange(repo, changesets)
2043 revs = scmutil.revrange(repo, changesets)
2044 if not revs:
2044 if not revs:
2045 raise error.Abort(_("export requires at least one changeset"))
2045 raise error.Abort(_("export requires at least one changeset"))
2046 if len(revs) > 1:
2046 if len(revs) > 1:
2047 ui.note(_('exporting patches:\n'))
2047 ui.note(_('exporting patches:\n'))
2048 else:
2048 else:
2049 ui.note(_('exporting patch:\n'))
2049 ui.note(_('exporting patch:\n'))
2050 ui.pager('export')
2050 ui.pager('export')
2051 cmdutil.export(repo, revs, template=opts.get('output'),
2051 cmdutil.export(repo, revs, template=opts.get('output'),
2052 switch_parent=opts.get('switch_parent'),
2052 switch_parent=opts.get('switch_parent'),
2053 opts=patch.diffallopts(ui, opts))
2053 opts=patch.diffallopts(ui, opts))
2054
2054
2055 @command('files',
2055 @command('files',
2056 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
2056 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
2057 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
2057 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
2058 ] + walkopts + formatteropts + subrepoopts,
2058 ] + walkopts + formatteropts + subrepoopts,
2059 _('[OPTION]... [FILE]...'))
2059 _('[OPTION]... [FILE]...'))
2060 def files(ui, repo, *pats, **opts):
2060 def files(ui, repo, *pats, **opts):
2061 """list tracked files
2061 """list tracked files
2062
2062
2063 Print files under Mercurial control in the working directory or
2063 Print files under Mercurial control in the working directory or
2064 specified revision for given files (excluding removed files).
2064 specified revision for given files (excluding removed files).
2065 Files can be specified as filenames or filesets.
2065 Files can be specified as filenames or filesets.
2066
2066
2067 If no files are given to match, this command prints the names
2067 If no files are given to match, this command prints the names
2068 of all files under Mercurial control.
2068 of all files under Mercurial control.
2069
2069
2070 .. container:: verbose
2070 .. container:: verbose
2071
2071
2072 Examples:
2072 Examples:
2073
2073
2074 - list all files under the current directory::
2074 - list all files under the current directory::
2075
2075
2076 hg files .
2076 hg files .
2077
2077
2078 - shows sizes and flags for current revision::
2078 - shows sizes and flags for current revision::
2079
2079
2080 hg files -vr .
2080 hg files -vr .
2081
2081
2082 - list all files named README::
2082 - list all files named README::
2083
2083
2084 hg files -I "**/README"
2084 hg files -I "**/README"
2085
2085
2086 - list all binary files::
2086 - list all binary files::
2087
2087
2088 hg files "set:binary()"
2088 hg files "set:binary()"
2089
2089
2090 - find files containing a regular expression::
2090 - find files containing a regular expression::
2091
2091
2092 hg files "set:grep('bob')"
2092 hg files "set:grep('bob')"
2093
2093
2094 - search tracked file contents with xargs and grep::
2094 - search tracked file contents with xargs and grep::
2095
2095
2096 hg files -0 | xargs -0 grep foo
2096 hg files -0 | xargs -0 grep foo
2097
2097
2098 See :hg:`help patterns` and :hg:`help filesets` for more information
2098 See :hg:`help patterns` and :hg:`help filesets` for more information
2099 on specifying file patterns.
2099 on specifying file patterns.
2100
2100
2101 Returns 0 if a match is found, 1 otherwise.
2101 Returns 0 if a match is found, 1 otherwise.
2102
2102
2103 """
2103 """
2104
2104
2105 opts = pycompat.byteskwargs(opts)
2105 opts = pycompat.byteskwargs(opts)
2106 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2106 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2107
2107
2108 end = '\n'
2108 end = '\n'
2109 if opts.get('print0'):
2109 if opts.get('print0'):
2110 end = '\0'
2110 end = '\0'
2111 fmt = '%s' + end
2111 fmt = '%s' + end
2112
2112
2113 m = scmutil.match(ctx, pats, opts)
2113 m = scmutil.match(ctx, pats, opts)
2114 ui.pager('files')
2114 ui.pager('files')
2115 with ui.formatter('files', opts) as fm:
2115 with ui.formatter('files', opts) as fm:
2116 return cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
2116 return cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
2117
2117
2118 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
2118 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
2119 def forget(ui, repo, *pats, **opts):
2119 def forget(ui, repo, *pats, **opts):
2120 """forget the specified files on the next commit
2120 """forget the specified files on the next commit
2121
2121
2122 Mark the specified files so they will no longer be tracked
2122 Mark the specified files so they will no longer be tracked
2123 after the next commit.
2123 after the next commit.
2124
2124
2125 This only removes files from the current branch, not from the
2125 This only removes files from the current branch, not from the
2126 entire project history, and it does not delete them from the
2126 entire project history, and it does not delete them from the
2127 working directory.
2127 working directory.
2128
2128
2129 To delete the file from the working directory, see :hg:`remove`.
2129 To delete the file from the working directory, see :hg:`remove`.
2130
2130
2131 To undo a forget before the next commit, see :hg:`add`.
2131 To undo a forget before the next commit, see :hg:`add`.
2132
2132
2133 .. container:: verbose
2133 .. container:: verbose
2134
2134
2135 Examples:
2135 Examples:
2136
2136
2137 - forget newly-added binary files::
2137 - forget newly-added binary files::
2138
2138
2139 hg forget "set:added() and binary()"
2139 hg forget "set:added() and binary()"
2140
2140
2141 - forget files that would be excluded by .hgignore::
2141 - forget files that would be excluded by .hgignore::
2142
2142
2143 hg forget "set:hgignore()"
2143 hg forget "set:hgignore()"
2144
2144
2145 Returns 0 on success.
2145 Returns 0 on success.
2146 """
2146 """
2147
2147
2148 opts = pycompat.byteskwargs(opts)
2148 opts = pycompat.byteskwargs(opts)
2149 if not pats:
2149 if not pats:
2150 raise error.Abort(_('no files specified'))
2150 raise error.Abort(_('no files specified'))
2151
2151
2152 m = scmutil.match(repo[None], pats, opts)
2152 m = scmutil.match(repo[None], pats, opts)
2153 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2153 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2154 return rejected and 1 or 0
2154 return rejected and 1 or 0
2155
2155
2156 @command(
2156 @command(
2157 'graft',
2157 'graft',
2158 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2158 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2159 ('c', 'continue', False, _('resume interrupted graft')),
2159 ('c', 'continue', False, _('resume interrupted graft')),
2160 ('e', 'edit', False, _('invoke editor on commit messages')),
2160 ('e', 'edit', False, _('invoke editor on commit messages')),
2161 ('', 'log', None, _('append graft info to log message')),
2161 ('', 'log', None, _('append graft info to log message')),
2162 ('f', 'force', False, _('force graft')),
2162 ('f', 'force', False, _('force graft')),
2163 ('D', 'currentdate', False,
2163 ('D', 'currentdate', False,
2164 _('record the current date as commit date')),
2164 _('record the current date as commit date')),
2165 ('U', 'currentuser', False,
2165 ('U', 'currentuser', False,
2166 _('record the current user as committer'), _('DATE'))]
2166 _('record the current user as committer'), _('DATE'))]
2167 + commitopts2 + mergetoolopts + dryrunopts,
2167 + commitopts2 + mergetoolopts + dryrunopts,
2168 _('[OPTION]... [-r REV]... REV...'))
2168 _('[OPTION]... [-r REV]... REV...'))
2169 def graft(ui, repo, *revs, **opts):
2169 def graft(ui, repo, *revs, **opts):
2170 '''copy changes from other branches onto the current branch
2170 '''copy changes from other branches onto the current branch
2171
2171
2172 This command uses Mercurial's merge logic to copy individual
2172 This command uses Mercurial's merge logic to copy individual
2173 changes from other branches without merging branches in the
2173 changes from other branches without merging branches in the
2174 history graph. This is sometimes known as 'backporting' or
2174 history graph. This is sometimes known as 'backporting' or
2175 'cherry-picking'. By default, graft will copy user, date, and
2175 'cherry-picking'. By default, graft will copy user, date, and
2176 description from the source changesets.
2176 description from the source changesets.
2177
2177
2178 Changesets that are ancestors of the current revision, that have
2178 Changesets that are ancestors of the current revision, that have
2179 already been grafted, or that are merges will be skipped.
2179 already been grafted, or that are merges will be skipped.
2180
2180
2181 If --log is specified, log messages will have a comment appended
2181 If --log is specified, log messages will have a comment appended
2182 of the form::
2182 of the form::
2183
2183
2184 (grafted from CHANGESETHASH)
2184 (grafted from CHANGESETHASH)
2185
2185
2186 If --force is specified, revisions will be grafted even if they
2186 If --force is specified, revisions will be grafted even if they
2187 are already ancestors of or have been grafted to the destination.
2187 are already ancestors of or have been grafted to the destination.
2188 This is useful when the revisions have since been backed out.
2188 This is useful when the revisions have since been backed out.
2189
2189
2190 If a graft merge results in conflicts, the graft process is
2190 If a graft merge results in conflicts, the graft process is
2191 interrupted so that the current merge can be manually resolved.
2191 interrupted so that the current merge can be manually resolved.
2192 Once all conflicts are addressed, the graft process can be
2192 Once all conflicts are addressed, the graft process can be
2193 continued with the -c/--continue option.
2193 continued with the -c/--continue option.
2194
2194
2195 .. note::
2195 .. note::
2196
2196
2197 The -c/--continue option does not reapply earlier options, except
2197 The -c/--continue option does not reapply earlier options, except
2198 for --force.
2198 for --force.
2199
2199
2200 .. container:: verbose
2200 .. container:: verbose
2201
2201
2202 Examples:
2202 Examples:
2203
2203
2204 - copy a single change to the stable branch and edit its description::
2204 - copy a single change to the stable branch and edit its description::
2205
2205
2206 hg update stable
2206 hg update stable
2207 hg graft --edit 9393
2207 hg graft --edit 9393
2208
2208
2209 - graft a range of changesets with one exception, updating dates::
2209 - graft a range of changesets with one exception, updating dates::
2210
2210
2211 hg graft -D "2085::2093 and not 2091"
2211 hg graft -D "2085::2093 and not 2091"
2212
2212
2213 - continue a graft after resolving conflicts::
2213 - continue a graft after resolving conflicts::
2214
2214
2215 hg graft -c
2215 hg graft -c
2216
2216
2217 - show the source of a grafted changeset::
2217 - show the source of a grafted changeset::
2218
2218
2219 hg log --debug -r .
2219 hg log --debug -r .
2220
2220
2221 - show revisions sorted by date::
2221 - show revisions sorted by date::
2222
2222
2223 hg log -r "sort(all(), date)"
2223 hg log -r "sort(all(), date)"
2224
2224
2225 See :hg:`help revisions` for more about specifying revisions.
2225 See :hg:`help revisions` for more about specifying revisions.
2226
2226
2227 Returns 0 on successful completion.
2227 Returns 0 on successful completion.
2228 '''
2228 '''
2229 with repo.wlock():
2229 with repo.wlock():
2230 return _dograft(ui, repo, *revs, **opts)
2230 return _dograft(ui, repo, *revs, **opts)
2231
2231
2232 def _dograft(ui, repo, *revs, **opts):
2232 def _dograft(ui, repo, *revs, **opts):
2233 opts = pycompat.byteskwargs(opts)
2233 opts = pycompat.byteskwargs(opts)
2234 if revs and opts.get('rev'):
2234 if revs and opts.get('rev'):
2235 ui.warn(_('warning: inconsistent use of --rev might give unexpected '
2235 ui.warn(_('warning: inconsistent use of --rev might give unexpected '
2236 'revision ordering!\n'))
2236 'revision ordering!\n'))
2237
2237
2238 revs = list(revs)
2238 revs = list(revs)
2239 revs.extend(opts.get('rev'))
2239 revs.extend(opts.get('rev'))
2240
2240
2241 if not opts.get('user') and opts.get('currentuser'):
2241 if not opts.get('user') and opts.get('currentuser'):
2242 opts['user'] = ui.username()
2242 opts['user'] = ui.username()
2243 if not opts.get('date') and opts.get('currentdate'):
2243 if not opts.get('date') and opts.get('currentdate'):
2244 opts['date'] = "%d %d" % util.makedate()
2244 opts['date'] = "%d %d" % util.makedate()
2245
2245
2246 editor = cmdutil.getcommiteditor(editform='graft',
2246 editor = cmdutil.getcommiteditor(editform='graft',
2247 **pycompat.strkwargs(opts))
2247 **pycompat.strkwargs(opts))
2248
2248
2249 cont = False
2249 cont = False
2250 if opts.get('continue'):
2250 if opts.get('continue'):
2251 cont = True
2251 cont = True
2252 if revs:
2252 if revs:
2253 raise error.Abort(_("can't specify --continue and revisions"))
2253 raise error.Abort(_("can't specify --continue and revisions"))
2254 # read in unfinished revisions
2254 # read in unfinished revisions
2255 try:
2255 try:
2256 nodes = repo.vfs.read('graftstate').splitlines()
2256 nodes = repo.vfs.read('graftstate').splitlines()
2257 revs = [repo[node].rev() for node in nodes]
2257 revs = [repo[node].rev() for node in nodes]
2258 except IOError as inst:
2258 except IOError as inst:
2259 if inst.errno != errno.ENOENT:
2259 if inst.errno != errno.ENOENT:
2260 raise
2260 raise
2261 cmdutil.wrongtooltocontinue(repo, _('graft'))
2261 cmdutil.wrongtooltocontinue(repo, _('graft'))
2262 else:
2262 else:
2263 cmdutil.checkunfinished(repo)
2263 cmdutil.checkunfinished(repo)
2264 cmdutil.bailifchanged(repo)
2264 cmdutil.bailifchanged(repo)
2265 if not revs:
2265 if not revs:
2266 raise error.Abort(_('no revisions specified'))
2266 raise error.Abort(_('no revisions specified'))
2267 revs = scmutil.revrange(repo, revs)
2267 revs = scmutil.revrange(repo, revs)
2268
2268
2269 skipped = set()
2269 skipped = set()
2270 # check for merges
2270 # check for merges
2271 for rev in repo.revs('%ld and merge()', revs):
2271 for rev in repo.revs('%ld and merge()', revs):
2272 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2272 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2273 skipped.add(rev)
2273 skipped.add(rev)
2274 revs = [r for r in revs if r not in skipped]
2274 revs = [r for r in revs if r not in skipped]
2275 if not revs:
2275 if not revs:
2276 return -1
2276 return -1
2277
2277
2278 # Don't check in the --continue case, in effect retaining --force across
2278 # Don't check in the --continue case, in effect retaining --force across
2279 # --continues. That's because without --force, any revisions we decided to
2279 # --continues. That's because without --force, any revisions we decided to
2280 # skip would have been filtered out here, so they wouldn't have made their
2280 # skip would have been filtered out here, so they wouldn't have made their
2281 # way to the graftstate. With --force, any revisions we would have otherwise
2281 # way to the graftstate. With --force, any revisions we would have otherwise
2282 # skipped would not have been filtered out, and if they hadn't been applied
2282 # skipped would not have been filtered out, and if they hadn't been applied
2283 # already, they'd have been in the graftstate.
2283 # already, they'd have been in the graftstate.
2284 if not (cont or opts.get('force')):
2284 if not (cont or opts.get('force')):
2285 # check for ancestors of dest branch
2285 # check for ancestors of dest branch
2286 crev = repo['.'].rev()
2286 crev = repo['.'].rev()
2287 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2287 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2288 # XXX make this lazy in the future
2288 # XXX make this lazy in the future
2289 # don't mutate while iterating, create a copy
2289 # don't mutate while iterating, create a copy
2290 for rev in list(revs):
2290 for rev in list(revs):
2291 if rev in ancestors:
2291 if rev in ancestors:
2292 ui.warn(_('skipping ancestor revision %d:%s\n') %
2292 ui.warn(_('skipping ancestor revision %d:%s\n') %
2293 (rev, repo[rev]))
2293 (rev, repo[rev]))
2294 # XXX remove on list is slow
2294 # XXX remove on list is slow
2295 revs.remove(rev)
2295 revs.remove(rev)
2296 if not revs:
2296 if not revs:
2297 return -1
2297 return -1
2298
2298
2299 # analyze revs for earlier grafts
2299 # analyze revs for earlier grafts
2300 ids = {}
2300 ids = {}
2301 for ctx in repo.set("%ld", revs):
2301 for ctx in repo.set("%ld", revs):
2302 ids[ctx.hex()] = ctx.rev()
2302 ids[ctx.hex()] = ctx.rev()
2303 n = ctx.extra().get('source')
2303 n = ctx.extra().get('source')
2304 if n:
2304 if n:
2305 ids[n] = ctx.rev()
2305 ids[n] = ctx.rev()
2306
2306
2307 # check ancestors for earlier grafts
2307 # check ancestors for earlier grafts
2308 ui.debug('scanning for duplicate grafts\n')
2308 ui.debug('scanning for duplicate grafts\n')
2309
2309
2310 for rev in repo.changelog.findmissingrevs(revs, [crev]):
2310 for rev in repo.changelog.findmissingrevs(revs, [crev]):
2311 ctx = repo[rev]
2311 ctx = repo[rev]
2312 n = ctx.extra().get('source')
2312 n = ctx.extra().get('source')
2313 if n in ids:
2313 if n in ids:
2314 try:
2314 try:
2315 r = repo[n].rev()
2315 r = repo[n].rev()
2316 except error.RepoLookupError:
2316 except error.RepoLookupError:
2317 r = None
2317 r = None
2318 if r in revs:
2318 if r in revs:
2319 ui.warn(_('skipping revision %d:%s '
2319 ui.warn(_('skipping revision %d:%s '
2320 '(already grafted to %d:%s)\n')
2320 '(already grafted to %d:%s)\n')
2321 % (r, repo[r], rev, ctx))
2321 % (r, repo[r], rev, ctx))
2322 revs.remove(r)
2322 revs.remove(r)
2323 elif ids[n] in revs:
2323 elif ids[n] in revs:
2324 if r is None:
2324 if r is None:
2325 ui.warn(_('skipping already grafted revision %d:%s '
2325 ui.warn(_('skipping already grafted revision %d:%s '
2326 '(%d:%s also has unknown origin %s)\n')
2326 '(%d:%s also has unknown origin %s)\n')
2327 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
2327 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
2328 else:
2328 else:
2329 ui.warn(_('skipping already grafted revision %d:%s '
2329 ui.warn(_('skipping already grafted revision %d:%s '
2330 '(%d:%s also has origin %d:%s)\n')
2330 '(%d:%s also has origin %d:%s)\n')
2331 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
2331 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
2332 revs.remove(ids[n])
2332 revs.remove(ids[n])
2333 elif ctx.hex() in ids:
2333 elif ctx.hex() in ids:
2334 r = ids[ctx.hex()]
2334 r = ids[ctx.hex()]
2335 ui.warn(_('skipping already grafted revision %d:%s '
2335 ui.warn(_('skipping already grafted revision %d:%s '
2336 '(was grafted from %d:%s)\n') %
2336 '(was grafted from %d:%s)\n') %
2337 (r, repo[r], rev, ctx))
2337 (r, repo[r], rev, ctx))
2338 revs.remove(r)
2338 revs.remove(r)
2339 if not revs:
2339 if not revs:
2340 return -1
2340 return -1
2341
2341
2342 for pos, ctx in enumerate(repo.set("%ld", revs)):
2342 for pos, ctx in enumerate(repo.set("%ld", revs)):
2343 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
2343 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
2344 ctx.description().split('\n', 1)[0])
2344 ctx.description().split('\n', 1)[0])
2345 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
2345 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
2346 if names:
2346 if names:
2347 desc += ' (%s)' % ' '.join(names)
2347 desc += ' (%s)' % ' '.join(names)
2348 ui.status(_('grafting %s\n') % desc)
2348 ui.status(_('grafting %s\n') % desc)
2349 if opts.get('dry_run'):
2349 if opts.get('dry_run'):
2350 continue
2350 continue
2351
2351
2352 source = ctx.extra().get('source')
2352 source = ctx.extra().get('source')
2353 extra = {}
2353 extra = {}
2354 if source:
2354 if source:
2355 extra['source'] = source
2355 extra['source'] = source
2356 extra['intermediate-source'] = ctx.hex()
2356 extra['intermediate-source'] = ctx.hex()
2357 else:
2357 else:
2358 extra['source'] = ctx.hex()
2358 extra['source'] = ctx.hex()
2359 user = ctx.user()
2359 user = ctx.user()
2360 if opts.get('user'):
2360 if opts.get('user'):
2361 user = opts['user']
2361 user = opts['user']
2362 date = ctx.date()
2362 date = ctx.date()
2363 if opts.get('date'):
2363 if opts.get('date'):
2364 date = opts['date']
2364 date = opts['date']
2365 message = ctx.description()
2365 message = ctx.description()
2366 if opts.get('log'):
2366 if opts.get('log'):
2367 message += '\n(grafted from %s)' % ctx.hex()
2367 message += '\n(grafted from %s)' % ctx.hex()
2368
2368
2369 # we don't merge the first commit when continuing
2369 # we don't merge the first commit when continuing
2370 if not cont:
2370 if not cont:
2371 # perform the graft merge with p1(rev) as 'ancestor'
2371 # perform the graft merge with p1(rev) as 'ancestor'
2372 try:
2372 try:
2373 # ui.forcemerge is an internal variable, do not document
2373 # ui.forcemerge is an internal variable, do not document
2374 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
2374 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
2375 'graft')
2375 'graft')
2376 stats = mergemod.graft(repo, ctx, ctx.p1(),
2376 stats = mergemod.graft(repo, ctx, ctx.p1(),
2377 ['local', 'graft'])
2377 ['local', 'graft'])
2378 finally:
2378 finally:
2379 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
2379 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
2380 # report any conflicts
2380 # report any conflicts
2381 if stats and stats[3] > 0:
2381 if stats and stats[3] > 0:
2382 # write out state for --continue
2382 # write out state for --continue
2383 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2383 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2384 repo.vfs.write('graftstate', ''.join(nodelines))
2384 repo.vfs.write('graftstate', ''.join(nodelines))
2385 extra = ''
2385 extra = ''
2386 if opts.get('user'):
2386 if opts.get('user'):
2387 extra += ' --user %s' % util.shellquote(opts['user'])
2387 extra += ' --user %s' % util.shellquote(opts['user'])
2388 if opts.get('date'):
2388 if opts.get('date'):
2389 extra += ' --date %s' % util.shellquote(opts['date'])
2389 extra += ' --date %s' % util.shellquote(opts['date'])
2390 if opts.get('log'):
2390 if opts.get('log'):
2391 extra += ' --log'
2391 extra += ' --log'
2392 hint=_("use 'hg resolve' and 'hg graft --continue%s'") % extra
2392 hint=_("use 'hg resolve' and 'hg graft --continue%s'") % extra
2393 raise error.Abort(
2393 raise error.Abort(
2394 _("unresolved conflicts, can't continue"),
2394 _("unresolved conflicts, can't continue"),
2395 hint=hint)
2395 hint=hint)
2396 else:
2396 else:
2397 cont = False
2397 cont = False
2398
2398
2399 # commit
2399 # commit
2400 node = repo.commit(text=message, user=user,
2400 node = repo.commit(text=message, user=user,
2401 date=date, extra=extra, editor=editor)
2401 date=date, extra=extra, editor=editor)
2402 if node is None:
2402 if node is None:
2403 ui.warn(
2403 ui.warn(
2404 _('note: graft of %d:%s created no changes to commit\n') %
2404 _('note: graft of %d:%s created no changes to commit\n') %
2405 (ctx.rev(), ctx))
2405 (ctx.rev(), ctx))
2406
2406
2407 # remove state when we complete successfully
2407 # remove state when we complete successfully
2408 if not opts.get('dry_run'):
2408 if not opts.get('dry_run'):
2409 repo.vfs.unlinkpath('graftstate', ignoremissing=True)
2409 repo.vfs.unlinkpath('graftstate', ignoremissing=True)
2410
2410
2411 return 0
2411 return 0
2412
2412
2413 @command('grep',
2413 @command('grep',
2414 [('0', 'print0', None, _('end fields with NUL')),
2414 [('0', 'print0', None, _('end fields with NUL')),
2415 ('', 'all', None, _('print all revisions that match')),
2415 ('', 'all', None, _('print all revisions that match')),
2416 ('a', 'text', None, _('treat all files as text')),
2416 ('a', 'text', None, _('treat all files as text')),
2417 ('f', 'follow', None,
2417 ('f', 'follow', None,
2418 _('follow changeset history,'
2418 _('follow changeset history,'
2419 ' or file history across copies and renames')),
2419 ' or file history across copies and renames')),
2420 ('i', 'ignore-case', None, _('ignore case when matching')),
2420 ('i', 'ignore-case', None, _('ignore case when matching')),
2421 ('l', 'files-with-matches', None,
2421 ('l', 'files-with-matches', None,
2422 _('print only filenames and revisions that match')),
2422 _('print only filenames and revisions that match')),
2423 ('n', 'line-number', None, _('print matching line numbers')),
2423 ('n', 'line-number', None, _('print matching line numbers')),
2424 ('r', 'rev', [],
2424 ('r', 'rev', [],
2425 _('only search files changed within revision range'), _('REV')),
2425 _('only search files changed within revision range'), _('REV')),
2426 ('u', 'user', None, _('list the author (long with -v)')),
2426 ('u', 'user', None, _('list the author (long with -v)')),
2427 ('d', 'date', None, _('list the date (short with -q)')),
2427 ('d', 'date', None, _('list the date (short with -q)')),
2428 ] + formatteropts + walkopts,
2428 ] + formatteropts + walkopts,
2429 _('[OPTION]... PATTERN [FILE]...'),
2429 _('[OPTION]... PATTERN [FILE]...'),
2430 inferrepo=True)
2430 inferrepo=True)
2431 def grep(ui, repo, pattern, *pats, **opts):
2431 def grep(ui, repo, pattern, *pats, **opts):
2432 """search revision history for a pattern in specified files
2432 """search revision history for a pattern in specified files
2433
2433
2434 Search revision history for a regular expression in the specified
2434 Search revision history for a regular expression in the specified
2435 files or the entire project.
2435 files or the entire project.
2436
2436
2437 By default, grep prints the most recent revision number for each
2437 By default, grep prints the most recent revision number for each
2438 file in which it finds a match. To get it to print every revision
2438 file in which it finds a match. To get it to print every revision
2439 that contains a change in match status ("-" for a match that becomes
2439 that contains a change in match status ("-" for a match that becomes
2440 a non-match, or "+" for a non-match that becomes a match), use the
2440 a non-match, or "+" for a non-match that becomes a match), use the
2441 --all flag.
2441 --all flag.
2442
2442
2443 PATTERN can be any Python (roughly Perl-compatible) regular
2443 PATTERN can be any Python (roughly Perl-compatible) regular
2444 expression.
2444 expression.
2445
2445
2446 If no FILEs are specified (and -f/--follow isn't set), all files in
2446 If no FILEs are specified (and -f/--follow isn't set), all files in
2447 the repository are searched, including those that don't exist in the
2447 the repository are searched, including those that don't exist in the
2448 current branch or have been deleted in a prior changeset.
2448 current branch or have been deleted in a prior changeset.
2449
2449
2450 Returns 0 if a match is found, 1 otherwise.
2450 Returns 0 if a match is found, 1 otherwise.
2451 """
2451 """
2452 opts = pycompat.byteskwargs(opts)
2452 opts = pycompat.byteskwargs(opts)
2453 reflags = re.M
2453 reflags = re.M
2454 if opts.get('ignore_case'):
2454 if opts.get('ignore_case'):
2455 reflags |= re.I
2455 reflags |= re.I
2456 try:
2456 try:
2457 regexp = util.re.compile(pattern, reflags)
2457 regexp = util.re.compile(pattern, reflags)
2458 except re.error as inst:
2458 except re.error as inst:
2459 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2459 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2460 return 1
2460 return 1
2461 sep, eol = ':', '\n'
2461 sep, eol = ':', '\n'
2462 if opts.get('print0'):
2462 if opts.get('print0'):
2463 sep = eol = '\0'
2463 sep = eol = '\0'
2464
2464
2465 getfile = util.lrucachefunc(repo.file)
2465 getfile = util.lrucachefunc(repo.file)
2466
2466
2467 def matchlines(body):
2467 def matchlines(body):
2468 begin = 0
2468 begin = 0
2469 linenum = 0
2469 linenum = 0
2470 while begin < len(body):
2470 while begin < len(body):
2471 match = regexp.search(body, begin)
2471 match = regexp.search(body, begin)
2472 if not match:
2472 if not match:
2473 break
2473 break
2474 mstart, mend = match.span()
2474 mstart, mend = match.span()
2475 linenum += body.count('\n', begin, mstart) + 1
2475 linenum += body.count('\n', begin, mstart) + 1
2476 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2476 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2477 begin = body.find('\n', mend) + 1 or len(body) + 1
2477 begin = body.find('\n', mend) + 1 or len(body) + 1
2478 lend = begin - 1
2478 lend = begin - 1
2479 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2479 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2480
2480
2481 class linestate(object):
2481 class linestate(object):
2482 def __init__(self, line, linenum, colstart, colend):
2482 def __init__(self, line, linenum, colstart, colend):
2483 self.line = line
2483 self.line = line
2484 self.linenum = linenum
2484 self.linenum = linenum
2485 self.colstart = colstart
2485 self.colstart = colstart
2486 self.colend = colend
2486 self.colend = colend
2487
2487
2488 def __hash__(self):
2488 def __hash__(self):
2489 return hash((self.linenum, self.line))
2489 return hash((self.linenum, self.line))
2490
2490
2491 def __eq__(self, other):
2491 def __eq__(self, other):
2492 return self.line == other.line
2492 return self.line == other.line
2493
2493
2494 def findpos(self):
2494 def findpos(self):
2495 """Iterate all (start, end) indices of matches"""
2495 """Iterate all (start, end) indices of matches"""
2496 yield self.colstart, self.colend
2496 yield self.colstart, self.colend
2497 p = self.colend
2497 p = self.colend
2498 while p < len(self.line):
2498 while p < len(self.line):
2499 m = regexp.search(self.line, p)
2499 m = regexp.search(self.line, p)
2500 if not m:
2500 if not m:
2501 break
2501 break
2502 yield m.span()
2502 yield m.span()
2503 p = m.end()
2503 p = m.end()
2504
2504
2505 matches = {}
2505 matches = {}
2506 copies = {}
2506 copies = {}
2507 def grepbody(fn, rev, body):
2507 def grepbody(fn, rev, body):
2508 matches[rev].setdefault(fn, [])
2508 matches[rev].setdefault(fn, [])
2509 m = matches[rev][fn]
2509 m = matches[rev][fn]
2510 for lnum, cstart, cend, line in matchlines(body):
2510 for lnum, cstart, cend, line in matchlines(body):
2511 s = linestate(line, lnum, cstart, cend)
2511 s = linestate(line, lnum, cstart, cend)
2512 m.append(s)
2512 m.append(s)
2513
2513
2514 def difflinestates(a, b):
2514 def difflinestates(a, b):
2515 sm = difflib.SequenceMatcher(None, a, b)
2515 sm = difflib.SequenceMatcher(None, a, b)
2516 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2516 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2517 if tag == 'insert':
2517 if tag == 'insert':
2518 for i in xrange(blo, bhi):
2518 for i in xrange(blo, bhi):
2519 yield ('+', b[i])
2519 yield ('+', b[i])
2520 elif tag == 'delete':
2520 elif tag == 'delete':
2521 for i in xrange(alo, ahi):
2521 for i in xrange(alo, ahi):
2522 yield ('-', a[i])
2522 yield ('-', a[i])
2523 elif tag == 'replace':
2523 elif tag == 'replace':
2524 for i in xrange(alo, ahi):
2524 for i in xrange(alo, ahi):
2525 yield ('-', a[i])
2525 yield ('-', a[i])
2526 for i in xrange(blo, bhi):
2526 for i in xrange(blo, bhi):
2527 yield ('+', b[i])
2527 yield ('+', b[i])
2528
2528
2529 def display(fm, fn, ctx, pstates, states):
2529 def display(fm, fn, ctx, pstates, states):
2530 rev = ctx.rev()
2530 rev = ctx.rev()
2531 if fm.isplain():
2531 if fm.isplain():
2532 formatuser = ui.shortuser
2532 formatuser = ui.shortuser
2533 else:
2533 else:
2534 formatuser = str
2534 formatuser = str
2535 if ui.quiet:
2535 if ui.quiet:
2536 datefmt = '%Y-%m-%d'
2536 datefmt = '%Y-%m-%d'
2537 else:
2537 else:
2538 datefmt = '%a %b %d %H:%M:%S %Y %1%2'
2538 datefmt = '%a %b %d %H:%M:%S %Y %1%2'
2539 found = False
2539 found = False
2540 @util.cachefunc
2540 @util.cachefunc
2541 def binary():
2541 def binary():
2542 flog = getfile(fn)
2542 flog = getfile(fn)
2543 return util.binary(flog.read(ctx.filenode(fn)))
2543 return util.binary(flog.read(ctx.filenode(fn)))
2544
2544
2545 fieldnamemap = {'filename': 'file', 'linenumber': 'line_number'}
2545 fieldnamemap = {'filename': 'file', 'linenumber': 'line_number'}
2546 if opts.get('all'):
2546 if opts.get('all'):
2547 iter = difflinestates(pstates, states)
2547 iter = difflinestates(pstates, states)
2548 else:
2548 else:
2549 iter = [('', l) for l in states]
2549 iter = [('', l) for l in states]
2550 for change, l in iter:
2550 for change, l in iter:
2551 fm.startitem()
2551 fm.startitem()
2552 fm.data(node=fm.hexfunc(ctx.node()))
2552 fm.data(node=fm.hexfunc(ctx.node()))
2553 cols = [
2553 cols = [
2554 ('filename', fn, True),
2554 ('filename', fn, True),
2555 ('rev', rev, True),
2555 ('rev', rev, True),
2556 ('linenumber', l.linenum, opts.get('line_number')),
2556 ('linenumber', l.linenum, opts.get('line_number')),
2557 ]
2557 ]
2558 if opts.get('all'):
2558 if opts.get('all'):
2559 cols.append(('change', change, True))
2559 cols.append(('change', change, True))
2560 cols.extend([
2560 cols.extend([
2561 ('user', formatuser(ctx.user()), opts.get('user')),
2561 ('user', formatuser(ctx.user()), opts.get('user')),
2562 ('date', fm.formatdate(ctx.date(), datefmt), opts.get('date')),
2562 ('date', fm.formatdate(ctx.date(), datefmt), opts.get('date')),
2563 ])
2563 ])
2564 lastcol = next(name for name, data, cond in reversed(cols) if cond)
2564 lastcol = next(name for name, data, cond in reversed(cols) if cond)
2565 for name, data, cond in cols:
2565 for name, data, cond in cols:
2566 field = fieldnamemap.get(name, name)
2566 field = fieldnamemap.get(name, name)
2567 fm.condwrite(cond, field, '%s', data, label='grep.%s' % name)
2567 fm.condwrite(cond, field, '%s', data, label='grep.%s' % name)
2568 if cond and name != lastcol:
2568 if cond and name != lastcol:
2569 fm.plain(sep, label='grep.sep')
2569 fm.plain(sep, label='grep.sep')
2570 if not opts.get('files_with_matches'):
2570 if not opts.get('files_with_matches'):
2571 fm.plain(sep, label='grep.sep')
2571 fm.plain(sep, label='grep.sep')
2572 if not opts.get('text') and binary():
2572 if not opts.get('text') and binary():
2573 fm.plain(_(" Binary file matches"))
2573 fm.plain(_(" Binary file matches"))
2574 else:
2574 else:
2575 displaymatches(fm.nested('texts'), l)
2575 displaymatches(fm.nested('texts'), l)
2576 fm.plain(eol)
2576 fm.plain(eol)
2577 found = True
2577 found = True
2578 if opts.get('files_with_matches'):
2578 if opts.get('files_with_matches'):
2579 break
2579 break
2580 return found
2580 return found
2581
2581
2582 def displaymatches(fm, l):
2582 def displaymatches(fm, l):
2583 p = 0
2583 p = 0
2584 for s, e in l.findpos():
2584 for s, e in l.findpos():
2585 if p < s:
2585 if p < s:
2586 fm.startitem()
2586 fm.startitem()
2587 fm.write('text', '%s', l.line[p:s])
2587 fm.write('text', '%s', l.line[p:s])
2588 fm.data(matched=False)
2588 fm.data(matched=False)
2589 fm.startitem()
2589 fm.startitem()
2590 fm.write('text', '%s', l.line[s:e], label='grep.match')
2590 fm.write('text', '%s', l.line[s:e], label='grep.match')
2591 fm.data(matched=True)
2591 fm.data(matched=True)
2592 p = e
2592 p = e
2593 if p < len(l.line):
2593 if p < len(l.line):
2594 fm.startitem()
2594 fm.startitem()
2595 fm.write('text', '%s', l.line[p:])
2595 fm.write('text', '%s', l.line[p:])
2596 fm.data(matched=False)
2596 fm.data(matched=False)
2597 fm.end()
2597 fm.end()
2598
2598
2599 skip = {}
2599 skip = {}
2600 revfiles = {}
2600 revfiles = {}
2601 matchfn = scmutil.match(repo[None], pats, opts)
2601 matchfn = scmutil.match(repo[None], pats, opts)
2602 found = False
2602 found = False
2603 follow = opts.get('follow')
2603 follow = opts.get('follow')
2604
2604
2605 def prep(ctx, fns):
2605 def prep(ctx, fns):
2606 rev = ctx.rev()
2606 rev = ctx.rev()
2607 pctx = ctx.p1()
2607 pctx = ctx.p1()
2608 parent = pctx.rev()
2608 parent = pctx.rev()
2609 matches.setdefault(rev, {})
2609 matches.setdefault(rev, {})
2610 matches.setdefault(parent, {})
2610 matches.setdefault(parent, {})
2611 files = revfiles.setdefault(rev, [])
2611 files = revfiles.setdefault(rev, [])
2612 for fn in fns:
2612 for fn in fns:
2613 flog = getfile(fn)
2613 flog = getfile(fn)
2614 try:
2614 try:
2615 fnode = ctx.filenode(fn)
2615 fnode = ctx.filenode(fn)
2616 except error.LookupError:
2616 except error.LookupError:
2617 continue
2617 continue
2618
2618
2619 copied = flog.renamed(fnode)
2619 copied = flog.renamed(fnode)
2620 copy = follow and copied and copied[0]
2620 copy = follow and copied and copied[0]
2621 if copy:
2621 if copy:
2622 copies.setdefault(rev, {})[fn] = copy
2622 copies.setdefault(rev, {})[fn] = copy
2623 if fn in skip:
2623 if fn in skip:
2624 if copy:
2624 if copy:
2625 skip[copy] = True
2625 skip[copy] = True
2626 continue
2626 continue
2627 files.append(fn)
2627 files.append(fn)
2628
2628
2629 if fn not in matches[rev]:
2629 if fn not in matches[rev]:
2630 grepbody(fn, rev, flog.read(fnode))
2630 grepbody(fn, rev, flog.read(fnode))
2631
2631
2632 pfn = copy or fn
2632 pfn = copy or fn
2633 if pfn not in matches[parent]:
2633 if pfn not in matches[parent]:
2634 try:
2634 try:
2635 fnode = pctx.filenode(pfn)
2635 fnode = pctx.filenode(pfn)
2636 grepbody(pfn, parent, flog.read(fnode))
2636 grepbody(pfn, parent, flog.read(fnode))
2637 except error.LookupError:
2637 except error.LookupError:
2638 pass
2638 pass
2639
2639
2640 ui.pager('grep')
2640 ui.pager('grep')
2641 fm = ui.formatter('grep', opts)
2641 fm = ui.formatter('grep', opts)
2642 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2642 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2643 rev = ctx.rev()
2643 rev = ctx.rev()
2644 parent = ctx.p1().rev()
2644 parent = ctx.p1().rev()
2645 for fn in sorted(revfiles.get(rev, [])):
2645 for fn in sorted(revfiles.get(rev, [])):
2646 states = matches[rev][fn]
2646 states = matches[rev][fn]
2647 copy = copies.get(rev, {}).get(fn)
2647 copy = copies.get(rev, {}).get(fn)
2648 if fn in skip:
2648 if fn in skip:
2649 if copy:
2649 if copy:
2650 skip[copy] = True
2650 skip[copy] = True
2651 continue
2651 continue
2652 pstates = matches.get(parent, {}).get(copy or fn, [])
2652 pstates = matches.get(parent, {}).get(copy or fn, [])
2653 if pstates or states:
2653 if pstates or states:
2654 r = display(fm, fn, ctx, pstates, states)
2654 r = display(fm, fn, ctx, pstates, states)
2655 found = found or r
2655 found = found or r
2656 if r and not opts.get('all'):
2656 if r and not opts.get('all'):
2657 skip[fn] = True
2657 skip[fn] = True
2658 if copy:
2658 if copy:
2659 skip[copy] = True
2659 skip[copy] = True
2660 del matches[rev]
2660 del matches[rev]
2661 del revfiles[rev]
2661 del revfiles[rev]
2662 fm.end()
2662 fm.end()
2663
2663
2664 return not found
2664 return not found
2665
2665
2666 @command('heads',
2666 @command('heads',
2667 [('r', 'rev', '',
2667 [('r', 'rev', '',
2668 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2668 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2669 ('t', 'topo', False, _('show topological heads only')),
2669 ('t', 'topo', False, _('show topological heads only')),
2670 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2670 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2671 ('c', 'closed', False, _('show normal and closed branch heads')),
2671 ('c', 'closed', False, _('show normal and closed branch heads')),
2672 ] + templateopts,
2672 ] + templateopts,
2673 _('[-ct] [-r STARTREV] [REV]...'))
2673 _('[-ct] [-r STARTREV] [REV]...'))
2674 def heads(ui, repo, *branchrevs, **opts):
2674 def heads(ui, repo, *branchrevs, **opts):
2675 """show branch heads
2675 """show branch heads
2676
2676
2677 With no arguments, show all open branch heads in the repository.
2677 With no arguments, show all open branch heads in the repository.
2678 Branch heads are changesets that have no descendants on the
2678 Branch heads are changesets that have no descendants on the
2679 same branch. They are where development generally takes place and
2679 same branch. They are where development generally takes place and
2680 are the usual targets for update and merge operations.
2680 are the usual targets for update and merge operations.
2681
2681
2682 If one or more REVs are given, only open branch heads on the
2682 If one or more REVs are given, only open branch heads on the
2683 branches associated with the specified changesets are shown. This
2683 branches associated with the specified changesets are shown. This
2684 means that you can use :hg:`heads .` to see the heads on the
2684 means that you can use :hg:`heads .` to see the heads on the
2685 currently checked-out branch.
2685 currently checked-out branch.
2686
2686
2687 If -c/--closed is specified, also show branch heads marked closed
2687 If -c/--closed is specified, also show branch heads marked closed
2688 (see :hg:`commit --close-branch`).
2688 (see :hg:`commit --close-branch`).
2689
2689
2690 If STARTREV is specified, only those heads that are descendants of
2690 If STARTREV is specified, only those heads that are descendants of
2691 STARTREV will be displayed.
2691 STARTREV will be displayed.
2692
2692
2693 If -t/--topo is specified, named branch mechanics will be ignored and only
2693 If -t/--topo is specified, named branch mechanics will be ignored and only
2694 topological heads (changesets with no children) will be shown.
2694 topological heads (changesets with no children) will be shown.
2695
2695
2696 Returns 0 if matching heads are found, 1 if not.
2696 Returns 0 if matching heads are found, 1 if not.
2697 """
2697 """
2698
2698
2699 opts = pycompat.byteskwargs(opts)
2699 opts = pycompat.byteskwargs(opts)
2700 start = None
2700 start = None
2701 if 'rev' in opts:
2701 if 'rev' in opts:
2702 start = scmutil.revsingle(repo, opts['rev'], None).node()
2702 start = scmutil.revsingle(repo, opts['rev'], None).node()
2703
2703
2704 if opts.get('topo'):
2704 if opts.get('topo'):
2705 heads = [repo[h] for h in repo.heads(start)]
2705 heads = [repo[h] for h in repo.heads(start)]
2706 else:
2706 else:
2707 heads = []
2707 heads = []
2708 for branch in repo.branchmap():
2708 for branch in repo.branchmap():
2709 heads += repo.branchheads(branch, start, opts.get('closed'))
2709 heads += repo.branchheads(branch, start, opts.get('closed'))
2710 heads = [repo[h] for h in heads]
2710 heads = [repo[h] for h in heads]
2711
2711
2712 if branchrevs:
2712 if branchrevs:
2713 branches = set(repo[br].branch() for br in branchrevs)
2713 branches = set(repo[br].branch() for br in branchrevs)
2714 heads = [h for h in heads if h.branch() in branches]
2714 heads = [h for h in heads if h.branch() in branches]
2715
2715
2716 if opts.get('active') and branchrevs:
2716 if opts.get('active') and branchrevs:
2717 dagheads = repo.heads(start)
2717 dagheads = repo.heads(start)
2718 heads = [h for h in heads if h.node() in dagheads]
2718 heads = [h for h in heads if h.node() in dagheads]
2719
2719
2720 if branchrevs:
2720 if branchrevs:
2721 haveheads = set(h.branch() for h in heads)
2721 haveheads = set(h.branch() for h in heads)
2722 if branches - haveheads:
2722 if branches - haveheads:
2723 headless = ', '.join(b for b in branches - haveheads)
2723 headless = ', '.join(b for b in branches - haveheads)
2724 msg = _('no open branch heads found on branches %s')
2724 msg = _('no open branch heads found on branches %s')
2725 if opts.get('rev'):
2725 if opts.get('rev'):
2726 msg += _(' (started at %s)') % opts['rev']
2726 msg += _(' (started at %s)') % opts['rev']
2727 ui.warn((msg + '\n') % headless)
2727 ui.warn((msg + '\n') % headless)
2728
2728
2729 if not heads:
2729 if not heads:
2730 return 1
2730 return 1
2731
2731
2732 ui.pager('heads')
2732 ui.pager('heads')
2733 heads = sorted(heads, key=lambda x: -x.rev())
2733 heads = sorted(heads, key=lambda x: -x.rev())
2734 displayer = cmdutil.show_changeset(ui, repo, opts)
2734 displayer = cmdutil.show_changeset(ui, repo, opts)
2735 for ctx in heads:
2735 for ctx in heads:
2736 displayer.show(ctx)
2736 displayer.show(ctx)
2737 displayer.close()
2737 displayer.close()
2738
2738
2739 @command('help',
2739 @command('help',
2740 [('e', 'extension', None, _('show only help for extensions')),
2740 [('e', 'extension', None, _('show only help for extensions')),
2741 ('c', 'command', None, _('show only help for commands')),
2741 ('c', 'command', None, _('show only help for commands')),
2742 ('k', 'keyword', None, _('show topics matching keyword')),
2742 ('k', 'keyword', None, _('show topics matching keyword')),
2743 ('s', 'system', [], _('show help for specific platform(s)')),
2743 ('s', 'system', [], _('show help for specific platform(s)')),
2744 ],
2744 ],
2745 _('[-ecks] [TOPIC]'),
2745 _('[-ecks] [TOPIC]'),
2746 norepo=True)
2746 norepo=True)
2747 def help_(ui, name=None, **opts):
2747 def help_(ui, name=None, **opts):
2748 """show help for a given topic or a help overview
2748 """show help for a given topic or a help overview
2749
2749
2750 With no arguments, print a list of commands with short help messages.
2750 With no arguments, print a list of commands with short help messages.
2751
2751
2752 Given a topic, extension, or command name, print help for that
2752 Given a topic, extension, or command name, print help for that
2753 topic.
2753 topic.
2754
2754
2755 Returns 0 if successful.
2755 Returns 0 if successful.
2756 """
2756 """
2757
2757
2758 keep = opts.get(r'system') or []
2758 keep = opts.get(r'system') or []
2759 if len(keep) == 0:
2759 if len(keep) == 0:
2760 if pycompat.sysplatform.startswith('win'):
2760 if pycompat.sysplatform.startswith('win'):
2761 keep.append('windows')
2761 keep.append('windows')
2762 elif pycompat.sysplatform == 'OpenVMS':
2762 elif pycompat.sysplatform == 'OpenVMS':
2763 keep.append('vms')
2763 keep.append('vms')
2764 elif pycompat.sysplatform == 'plan9':
2764 elif pycompat.sysplatform == 'plan9':
2765 keep.append('plan9')
2765 keep.append('plan9')
2766 else:
2766 else:
2767 keep.append('unix')
2767 keep.append('unix')
2768 keep.append(pycompat.sysplatform.lower())
2768 keep.append(pycompat.sysplatform.lower())
2769 if ui.verbose:
2769 if ui.verbose:
2770 keep.append('verbose')
2770 keep.append('verbose')
2771
2771
2772 formatted = help.formattedhelp(ui, name, keep=keep, **opts)
2772 formatted = help.formattedhelp(ui, name, keep=keep, **opts)
2773 ui.pager('help')
2773 ui.pager('help')
2774 ui.write(formatted)
2774 ui.write(formatted)
2775
2775
2776
2776
2777 @command('identify|id',
2777 @command('identify|id',
2778 [('r', 'rev', '',
2778 [('r', 'rev', '',
2779 _('identify the specified revision'), _('REV')),
2779 _('identify the specified revision'), _('REV')),
2780 ('n', 'num', None, _('show local revision number')),
2780 ('n', 'num', None, _('show local revision number')),
2781 ('i', 'id', None, _('show global revision id')),
2781 ('i', 'id', None, _('show global revision id')),
2782 ('b', 'branch', None, _('show branch')),
2782 ('b', 'branch', None, _('show branch')),
2783 ('t', 'tags', None, _('show tags')),
2783 ('t', 'tags', None, _('show tags')),
2784 ('B', 'bookmarks', None, _('show bookmarks')),
2784 ('B', 'bookmarks', None, _('show bookmarks')),
2785 ] + remoteopts,
2785 ] + remoteopts,
2786 _('[-nibtB] [-r REV] [SOURCE]'),
2786 _('[-nibtB] [-r REV] [SOURCE]'),
2787 optionalrepo=True)
2787 optionalrepo=True)
2788 def identify(ui, repo, source=None, rev=None,
2788 def identify(ui, repo, source=None, rev=None,
2789 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
2789 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
2790 """identify the working directory or specified revision
2790 """identify the working directory or specified revision
2791
2791
2792 Print a summary identifying the repository state at REV using one or
2792 Print a summary identifying the repository state at REV using one or
2793 two parent hash identifiers, followed by a "+" if the working
2793 two parent hash identifiers, followed by a "+" if the working
2794 directory has uncommitted changes, the branch name (if not default),
2794 directory has uncommitted changes, the branch name (if not default),
2795 a list of tags, and a list of bookmarks.
2795 a list of tags, and a list of bookmarks.
2796
2796
2797 When REV is not given, print a summary of the current state of the
2797 When REV is not given, print a summary of the current state of the
2798 repository.
2798 repository.
2799
2799
2800 Specifying a path to a repository root or Mercurial bundle will
2800 Specifying a path to a repository root or Mercurial bundle will
2801 cause lookup to operate on that repository/bundle.
2801 cause lookup to operate on that repository/bundle.
2802
2802
2803 .. container:: verbose
2803 .. container:: verbose
2804
2804
2805 Examples:
2805 Examples:
2806
2806
2807 - generate a build identifier for the working directory::
2807 - generate a build identifier for the working directory::
2808
2808
2809 hg id --id > build-id.dat
2809 hg id --id > build-id.dat
2810
2810
2811 - find the revision corresponding to a tag::
2811 - find the revision corresponding to a tag::
2812
2812
2813 hg id -n -r 1.3
2813 hg id -n -r 1.3
2814
2814
2815 - check the most recent revision of a remote repository::
2815 - check the most recent revision of a remote repository::
2816
2816
2817 hg id -r tip https://www.mercurial-scm.org/repo/hg/
2817 hg id -r tip https://www.mercurial-scm.org/repo/hg/
2818
2818
2819 See :hg:`log` for generating more information about specific revisions,
2819 See :hg:`log` for generating more information about specific revisions,
2820 including full hash identifiers.
2820 including full hash identifiers.
2821
2821
2822 Returns 0 if successful.
2822 Returns 0 if successful.
2823 """
2823 """
2824
2824
2825 opts = pycompat.byteskwargs(opts)
2825 opts = pycompat.byteskwargs(opts)
2826 if not repo and not source:
2826 if not repo and not source:
2827 raise error.Abort(_("there is no Mercurial repository here "
2827 raise error.Abort(_("there is no Mercurial repository here "
2828 "(.hg not found)"))
2828 "(.hg not found)"))
2829
2829
2830 if ui.debugflag:
2830 if ui.debugflag:
2831 hexfunc = hex
2831 hexfunc = hex
2832 else:
2832 else:
2833 hexfunc = short
2833 hexfunc = short
2834 default = not (num or id or branch or tags or bookmarks)
2834 default = not (num or id or branch or tags or bookmarks)
2835 output = []
2835 output = []
2836 revs = []
2836 revs = []
2837
2837
2838 if source:
2838 if source:
2839 source, branches = hg.parseurl(ui.expandpath(source))
2839 source, branches = hg.parseurl(ui.expandpath(source))
2840 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
2840 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
2841 repo = peer.local()
2841 repo = peer.local()
2842 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
2842 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
2843
2843
2844 if not repo:
2844 if not repo:
2845 if num or branch or tags:
2845 if num or branch or tags:
2846 raise error.Abort(
2846 raise error.Abort(
2847 _("can't query remote revision number, branch, or tags"))
2847 _("can't query remote revision number, branch, or tags"))
2848 if not rev and revs:
2848 if not rev and revs:
2849 rev = revs[0]
2849 rev = revs[0]
2850 if not rev:
2850 if not rev:
2851 rev = "tip"
2851 rev = "tip"
2852
2852
2853 remoterev = peer.lookup(rev)
2853 remoterev = peer.lookup(rev)
2854 if default or id:
2854 if default or id:
2855 output = [hexfunc(remoterev)]
2855 output = [hexfunc(remoterev)]
2856
2856
2857 def getbms():
2857 def getbms():
2858 bms = []
2858 bms = []
2859
2859
2860 if 'bookmarks' in peer.listkeys('namespaces'):
2860 if 'bookmarks' in peer.listkeys('namespaces'):
2861 hexremoterev = hex(remoterev)
2861 hexremoterev = hex(remoterev)
2862 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
2862 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
2863 if bmr == hexremoterev]
2863 if bmr == hexremoterev]
2864
2864
2865 return sorted(bms)
2865 return sorted(bms)
2866
2866
2867 if bookmarks:
2867 if bookmarks:
2868 output.extend(getbms())
2868 output.extend(getbms())
2869 elif default and not ui.quiet:
2869 elif default and not ui.quiet:
2870 # multiple bookmarks for a single parent separated by '/'
2870 # multiple bookmarks for a single parent separated by '/'
2871 bm = '/'.join(getbms())
2871 bm = '/'.join(getbms())
2872 if bm:
2872 if bm:
2873 output.append(bm)
2873 output.append(bm)
2874 else:
2874 else:
2875 ctx = scmutil.revsingle(repo, rev, None)
2875 ctx = scmutil.revsingle(repo, rev, None)
2876
2876
2877 if ctx.rev() is None:
2877 if ctx.rev() is None:
2878 ctx = repo[None]
2878 ctx = repo[None]
2879 parents = ctx.parents()
2879 parents = ctx.parents()
2880 taglist = []
2880 taglist = []
2881 for p in parents:
2881 for p in parents:
2882 taglist.extend(p.tags())
2882 taglist.extend(p.tags())
2883
2883
2884 changed = ""
2884 changed = ""
2885 if default or id or num:
2885 if default or id or num:
2886 if (any(repo.status())
2886 if (any(repo.status())
2887 or any(ctx.sub(s).dirty() for s in ctx.substate)):
2887 or any(ctx.sub(s).dirty() for s in ctx.substate)):
2888 changed = '+'
2888 changed = '+'
2889 if default or id:
2889 if default or id:
2890 output = ["%s%s" %
2890 output = ["%s%s" %
2891 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
2891 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
2892 if num:
2892 if num:
2893 output.append("%s%s" %
2893 output.append("%s%s" %
2894 ('+'.join([str(p.rev()) for p in parents]), changed))
2894 ('+'.join([str(p.rev()) for p in parents]), changed))
2895 else:
2895 else:
2896 if default or id:
2896 if default or id:
2897 output = [hexfunc(ctx.node())]
2897 output = [hexfunc(ctx.node())]
2898 if num:
2898 if num:
2899 output.append(str(ctx.rev()))
2899 output.append(str(ctx.rev()))
2900 taglist = ctx.tags()
2900 taglist = ctx.tags()
2901
2901
2902 if default and not ui.quiet:
2902 if default and not ui.quiet:
2903 b = ctx.branch()
2903 b = ctx.branch()
2904 if b != 'default':
2904 if b != 'default':
2905 output.append("(%s)" % b)
2905 output.append("(%s)" % b)
2906
2906
2907 # multiple tags for a single parent separated by '/'
2907 # multiple tags for a single parent separated by '/'
2908 t = '/'.join(taglist)
2908 t = '/'.join(taglist)
2909 if t:
2909 if t:
2910 output.append(t)
2910 output.append(t)
2911
2911
2912 # multiple bookmarks for a single parent separated by '/'
2912 # multiple bookmarks for a single parent separated by '/'
2913 bm = '/'.join(ctx.bookmarks())
2913 bm = '/'.join(ctx.bookmarks())
2914 if bm:
2914 if bm:
2915 output.append(bm)
2915 output.append(bm)
2916 else:
2916 else:
2917 if branch:
2917 if branch:
2918 output.append(ctx.branch())
2918 output.append(ctx.branch())
2919
2919
2920 if tags:
2920 if tags:
2921 output.extend(taglist)
2921 output.extend(taglist)
2922
2922
2923 if bookmarks:
2923 if bookmarks:
2924 output.extend(ctx.bookmarks())
2924 output.extend(ctx.bookmarks())
2925
2925
2926 ui.write("%s\n" % ' '.join(output))
2926 ui.write("%s\n" % ' '.join(output))
2927
2927
2928 @command('import|patch',
2928 @command('import|patch',
2929 [('p', 'strip', 1,
2929 [('p', 'strip', 1,
2930 _('directory strip option for patch. This has the same '
2930 _('directory strip option for patch. This has the same '
2931 'meaning as the corresponding patch option'), _('NUM')),
2931 'meaning as the corresponding patch option'), _('NUM')),
2932 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
2932 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
2933 ('e', 'edit', False, _('invoke editor on commit messages')),
2933 ('e', 'edit', False, _('invoke editor on commit messages')),
2934 ('f', 'force', None,
2934 ('f', 'force', None,
2935 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
2935 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
2936 ('', 'no-commit', None,
2936 ('', 'no-commit', None,
2937 _("don't commit, just update the working directory")),
2937 _("don't commit, just update the working directory")),
2938 ('', 'bypass', None,
2938 ('', 'bypass', None,
2939 _("apply patch without touching the working directory")),
2939 _("apply patch without touching the working directory")),
2940 ('', 'partial', None,
2940 ('', 'partial', None,
2941 _('commit even if some hunks fail')),
2941 _('commit even if some hunks fail')),
2942 ('', 'exact', None,
2942 ('', 'exact', None,
2943 _('abort if patch would apply lossily')),
2943 _('abort if patch would apply lossily')),
2944 ('', 'prefix', '',
2944 ('', 'prefix', '',
2945 _('apply patch to subdirectory'), _('DIR')),
2945 _('apply patch to subdirectory'), _('DIR')),
2946 ('', 'import-branch', None,
2946 ('', 'import-branch', None,
2947 _('use any branch information in patch (implied by --exact)'))] +
2947 _('use any branch information in patch (implied by --exact)'))] +
2948 commitopts + commitopts2 + similarityopts,
2948 commitopts + commitopts2 + similarityopts,
2949 _('[OPTION]... PATCH...'))
2949 _('[OPTION]... PATCH...'))
2950 def import_(ui, repo, patch1=None, *patches, **opts):
2950 def import_(ui, repo, patch1=None, *patches, **opts):
2951 """import an ordered set of patches
2951 """import an ordered set of patches
2952
2952
2953 Import a list of patches and commit them individually (unless
2953 Import a list of patches and commit them individually (unless
2954 --no-commit is specified).
2954 --no-commit is specified).
2955
2955
2956 To read a patch from standard input (stdin), use "-" as the patch
2956 To read a patch from standard input (stdin), use "-" as the patch
2957 name. If a URL is specified, the patch will be downloaded from
2957 name. If a URL is specified, the patch will be downloaded from
2958 there.
2958 there.
2959
2959
2960 Import first applies changes to the working directory (unless
2960 Import first applies changes to the working directory (unless
2961 --bypass is specified), import will abort if there are outstanding
2961 --bypass is specified), import will abort if there are outstanding
2962 changes.
2962 changes.
2963
2963
2964 Use --bypass to apply and commit patches directly to the
2964 Use --bypass to apply and commit patches directly to the
2965 repository, without affecting the working directory. Without
2965 repository, without affecting the working directory. Without
2966 --exact, patches will be applied on top of the working directory
2966 --exact, patches will be applied on top of the working directory
2967 parent revision.
2967 parent revision.
2968
2968
2969 You can import a patch straight from a mail message. Even patches
2969 You can import a patch straight from a mail message. Even patches
2970 as attachments work (to use the body part, it must have type
2970 as attachments work (to use the body part, it must have type
2971 text/plain or text/x-patch). From and Subject headers of email
2971 text/plain or text/x-patch). From and Subject headers of email
2972 message are used as default committer and commit message. All
2972 message are used as default committer and commit message. All
2973 text/plain body parts before first diff are added to the commit
2973 text/plain body parts before first diff are added to the commit
2974 message.
2974 message.
2975
2975
2976 If the imported patch was generated by :hg:`export`, user and
2976 If the imported patch was generated by :hg:`export`, user and
2977 description from patch override values from message headers and
2977 description from patch override values from message headers and
2978 body. Values given on command line with -m/--message and -u/--user
2978 body. Values given on command line with -m/--message and -u/--user
2979 override these.
2979 override these.
2980
2980
2981 If --exact is specified, import will set the working directory to
2981 If --exact is specified, import will set the working directory to
2982 the parent of each patch before applying it, and will abort if the
2982 the parent of each patch before applying it, and will abort if the
2983 resulting changeset has a different ID than the one recorded in
2983 resulting changeset has a different ID than the one recorded in
2984 the patch. This will guard against various ways that portable
2984 the patch. This will guard against various ways that portable
2985 patch formats and mail systems might fail to transfer Mercurial
2985 patch formats and mail systems might fail to transfer Mercurial
2986 data or metadata. See :hg:`bundle` for lossless transmission.
2986 data or metadata. See :hg:`bundle` for lossless transmission.
2987
2987
2988 Use --partial to ensure a changeset will be created from the patch
2988 Use --partial to ensure a changeset will be created from the patch
2989 even if some hunks fail to apply. Hunks that fail to apply will be
2989 even if some hunks fail to apply. Hunks that fail to apply will be
2990 written to a <target-file>.rej file. Conflicts can then be resolved
2990 written to a <target-file>.rej file. Conflicts can then be resolved
2991 by hand before :hg:`commit --amend` is run to update the created
2991 by hand before :hg:`commit --amend` is run to update the created
2992 changeset. This flag exists to let people import patches that
2992 changeset. This flag exists to let people import patches that
2993 partially apply without losing the associated metadata (author,
2993 partially apply without losing the associated metadata (author,
2994 date, description, ...).
2994 date, description, ...).
2995
2995
2996 .. note::
2996 .. note::
2997
2997
2998 When no hunks apply cleanly, :hg:`import --partial` will create
2998 When no hunks apply cleanly, :hg:`import --partial` will create
2999 an empty changeset, importing only the patch metadata.
2999 an empty changeset, importing only the patch metadata.
3000
3000
3001 With -s/--similarity, hg will attempt to discover renames and
3001 With -s/--similarity, hg will attempt to discover renames and
3002 copies in the patch in the same way as :hg:`addremove`.
3002 copies in the patch in the same way as :hg:`addremove`.
3003
3003
3004 It is possible to use external patch programs to perform the patch
3004 It is possible to use external patch programs to perform the patch
3005 by setting the ``ui.patch`` configuration option. For the default
3005 by setting the ``ui.patch`` configuration option. For the default
3006 internal tool, the fuzz can also be configured via ``patch.fuzz``.
3006 internal tool, the fuzz can also be configured via ``patch.fuzz``.
3007 See :hg:`help config` for more information about configuration
3007 See :hg:`help config` for more information about configuration
3008 files and how to use these options.
3008 files and how to use these options.
3009
3009
3010 See :hg:`help dates` for a list of formats valid for -d/--date.
3010 See :hg:`help dates` for a list of formats valid for -d/--date.
3011
3011
3012 .. container:: verbose
3012 .. container:: verbose
3013
3013
3014 Examples:
3014 Examples:
3015
3015
3016 - import a traditional patch from a website and detect renames::
3016 - import a traditional patch from a website and detect renames::
3017
3017
3018 hg import -s 80 http://example.com/bugfix.patch
3018 hg import -s 80 http://example.com/bugfix.patch
3019
3019
3020 - import a changeset from an hgweb server::
3020 - import a changeset from an hgweb server::
3021
3021
3022 hg import https://www.mercurial-scm.org/repo/hg/rev/5ca8c111e9aa
3022 hg import https://www.mercurial-scm.org/repo/hg/rev/5ca8c111e9aa
3023
3023
3024 - import all the patches in an Unix-style mbox::
3024 - import all the patches in an Unix-style mbox::
3025
3025
3026 hg import incoming-patches.mbox
3026 hg import incoming-patches.mbox
3027
3027
3028 - import patches from stdin::
3028 - import patches from stdin::
3029
3029
3030 hg import -
3030 hg import -
3031
3031
3032 - attempt to exactly restore an exported changeset (not always
3032 - attempt to exactly restore an exported changeset (not always
3033 possible)::
3033 possible)::
3034
3034
3035 hg import --exact proposed-fix.patch
3035 hg import --exact proposed-fix.patch
3036
3036
3037 - use an external tool to apply a patch which is too fuzzy for
3037 - use an external tool to apply a patch which is too fuzzy for
3038 the default internal tool.
3038 the default internal tool.
3039
3039
3040 hg import --config ui.patch="patch --merge" fuzzy.patch
3040 hg import --config ui.patch="patch --merge" fuzzy.patch
3041
3041
3042 - change the default fuzzing from 2 to a less strict 7
3042 - change the default fuzzing from 2 to a less strict 7
3043
3043
3044 hg import --config ui.fuzz=7 fuzz.patch
3044 hg import --config ui.fuzz=7 fuzz.patch
3045
3045
3046 Returns 0 on success, 1 on partial success (see --partial).
3046 Returns 0 on success, 1 on partial success (see --partial).
3047 """
3047 """
3048
3048
3049 opts = pycompat.byteskwargs(opts)
3049 opts = pycompat.byteskwargs(opts)
3050 if not patch1:
3050 if not patch1:
3051 raise error.Abort(_('need at least one patch to import'))
3051 raise error.Abort(_('need at least one patch to import'))
3052
3052
3053 patches = (patch1,) + patches
3053 patches = (patch1,) + patches
3054
3054
3055 date = opts.get('date')
3055 date = opts.get('date')
3056 if date:
3056 if date:
3057 opts['date'] = util.parsedate(date)
3057 opts['date'] = util.parsedate(date)
3058
3058
3059 exact = opts.get('exact')
3059 exact = opts.get('exact')
3060 update = not opts.get('bypass')
3060 update = not opts.get('bypass')
3061 if not update and opts.get('no_commit'):
3061 if not update and opts.get('no_commit'):
3062 raise error.Abort(_('cannot use --no-commit with --bypass'))
3062 raise error.Abort(_('cannot use --no-commit with --bypass'))
3063 try:
3063 try:
3064 sim = float(opts.get('similarity') or 0)
3064 sim = float(opts.get('similarity') or 0)
3065 except ValueError:
3065 except ValueError:
3066 raise error.Abort(_('similarity must be a number'))
3066 raise error.Abort(_('similarity must be a number'))
3067 if sim < 0 or sim > 100:
3067 if sim < 0 or sim > 100:
3068 raise error.Abort(_('similarity must be between 0 and 100'))
3068 raise error.Abort(_('similarity must be between 0 and 100'))
3069 if sim and not update:
3069 if sim and not update:
3070 raise error.Abort(_('cannot use --similarity with --bypass'))
3070 raise error.Abort(_('cannot use --similarity with --bypass'))
3071 if exact:
3071 if exact:
3072 if opts.get('edit'):
3072 if opts.get('edit'):
3073 raise error.Abort(_('cannot use --exact with --edit'))
3073 raise error.Abort(_('cannot use --exact with --edit'))
3074 if opts.get('prefix'):
3074 if opts.get('prefix'):
3075 raise error.Abort(_('cannot use --exact with --prefix'))
3075 raise error.Abort(_('cannot use --exact with --prefix'))
3076
3076
3077 base = opts["base"]
3077 base = opts["base"]
3078 wlock = dsguard = lock = tr = None
3078 wlock = dsguard = lock = tr = None
3079 msgs = []
3079 msgs = []
3080 ret = 0
3080 ret = 0
3081
3081
3082
3082
3083 try:
3083 try:
3084 wlock = repo.wlock()
3084 wlock = repo.wlock()
3085
3085
3086 if update:
3086 if update:
3087 cmdutil.checkunfinished(repo)
3087 cmdutil.checkunfinished(repo)
3088 if (exact or not opts.get('force')):
3088 if (exact or not opts.get('force')):
3089 cmdutil.bailifchanged(repo)
3089 cmdutil.bailifchanged(repo)
3090
3090
3091 if not opts.get('no_commit'):
3091 if not opts.get('no_commit'):
3092 lock = repo.lock()
3092 lock = repo.lock()
3093 tr = repo.transaction('import')
3093 tr = repo.transaction('import')
3094 else:
3094 else:
3095 dsguard = dirstateguard.dirstateguard(repo, 'import')
3095 dsguard = dirstateguard.dirstateguard(repo, 'import')
3096 parents = repo[None].parents()
3096 parents = repo[None].parents()
3097 for patchurl in patches:
3097 for patchurl in patches:
3098 if patchurl == '-':
3098 if patchurl == '-':
3099 ui.status(_('applying patch from stdin\n'))
3099 ui.status(_('applying patch from stdin\n'))
3100 patchfile = ui.fin
3100 patchfile = ui.fin
3101 patchurl = 'stdin' # for error message
3101 patchurl = 'stdin' # for error message
3102 else:
3102 else:
3103 patchurl = os.path.join(base, patchurl)
3103 patchurl = os.path.join(base, patchurl)
3104 ui.status(_('applying %s\n') % patchurl)
3104 ui.status(_('applying %s\n') % patchurl)
3105 patchfile = hg.openpath(ui, patchurl)
3105 patchfile = hg.openpath(ui, patchurl)
3106
3106
3107 haspatch = False
3107 haspatch = False
3108 for hunk in patch.split(patchfile):
3108 for hunk in patch.split(patchfile):
3109 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
3109 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
3110 parents, opts,
3110 parents, opts,
3111 msgs, hg.clean)
3111 msgs, hg.clean)
3112 if msg:
3112 if msg:
3113 haspatch = True
3113 haspatch = True
3114 ui.note(msg + '\n')
3114 ui.note(msg + '\n')
3115 if update or exact:
3115 if update or exact:
3116 parents = repo[None].parents()
3116 parents = repo[None].parents()
3117 else:
3117 else:
3118 parents = [repo[node]]
3118 parents = [repo[node]]
3119 if rej:
3119 if rej:
3120 ui.write_err(_("patch applied partially\n"))
3120 ui.write_err(_("patch applied partially\n"))
3121 ui.write_err(_("(fix the .rej files and run "
3121 ui.write_err(_("(fix the .rej files and run "
3122 "`hg commit --amend`)\n"))
3122 "`hg commit --amend`)\n"))
3123 ret = 1
3123 ret = 1
3124 break
3124 break
3125
3125
3126 if not haspatch:
3126 if not haspatch:
3127 raise error.Abort(_('%s: no diffs found') % patchurl)
3127 raise error.Abort(_('%s: no diffs found') % patchurl)
3128
3128
3129 if tr:
3129 if tr:
3130 tr.close()
3130 tr.close()
3131 if msgs:
3131 if msgs:
3132 repo.savecommitmessage('\n* * *\n'.join(msgs))
3132 repo.savecommitmessage('\n* * *\n'.join(msgs))
3133 if dsguard:
3133 if dsguard:
3134 dsguard.close()
3134 dsguard.close()
3135 return ret
3135 return ret
3136 finally:
3136 finally:
3137 if tr:
3137 if tr:
3138 tr.release()
3138 tr.release()
3139 release(lock, dsguard, wlock)
3139 release(lock, dsguard, wlock)
3140
3140
3141 @command('incoming|in',
3141 @command('incoming|in',
3142 [('f', 'force', None,
3142 [('f', 'force', None,
3143 _('run even if remote repository is unrelated')),
3143 _('run even if remote repository is unrelated')),
3144 ('n', 'newest-first', None, _('show newest record first')),
3144 ('n', 'newest-first', None, _('show newest record first')),
3145 ('', 'bundle', '',
3145 ('', 'bundle', '',
3146 _('file to store the bundles into'), _('FILE')),
3146 _('file to store the bundles into'), _('FILE')),
3147 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3147 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3148 ('B', 'bookmarks', False, _("compare bookmarks")),
3148 ('B', 'bookmarks', False, _("compare bookmarks")),
3149 ('b', 'branch', [],
3149 ('b', 'branch', [],
3150 _('a specific branch you would like to pull'), _('BRANCH')),
3150 _('a specific branch you would like to pull'), _('BRANCH')),
3151 ] + logopts + remoteopts + subrepoopts,
3151 ] + logopts + remoteopts + subrepoopts,
3152 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3152 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3153 def incoming(ui, repo, source="default", **opts):
3153 def incoming(ui, repo, source="default", **opts):
3154 """show new changesets found in source
3154 """show new changesets found in source
3155
3155
3156 Show new changesets found in the specified path/URL or the default
3156 Show new changesets found in the specified path/URL or the default
3157 pull location. These are the changesets that would have been pulled
3157 pull location. These are the changesets that would have been pulled
3158 if a pull at the time you issued this command.
3158 if a pull at the time you issued this command.
3159
3159
3160 See pull for valid source format details.
3160 See pull for valid source format details.
3161
3161
3162 .. container:: verbose
3162 .. container:: verbose
3163
3163
3164 With -B/--bookmarks, the result of bookmark comparison between
3164 With -B/--bookmarks, the result of bookmark comparison between
3165 local and remote repositories is displayed. With -v/--verbose,
3165 local and remote repositories is displayed. With -v/--verbose,
3166 status is also displayed for each bookmark like below::
3166 status is also displayed for each bookmark like below::
3167
3167
3168 BM1 01234567890a added
3168 BM1 01234567890a added
3169 BM2 1234567890ab advanced
3169 BM2 1234567890ab advanced
3170 BM3 234567890abc diverged
3170 BM3 234567890abc diverged
3171 BM4 34567890abcd changed
3171 BM4 34567890abcd changed
3172
3172
3173 The action taken locally when pulling depends on the
3173 The action taken locally when pulling depends on the
3174 status of each bookmark:
3174 status of each bookmark:
3175
3175
3176 :``added``: pull will create it
3176 :``added``: pull will create it
3177 :``advanced``: pull will update it
3177 :``advanced``: pull will update it
3178 :``diverged``: pull will create a divergent bookmark
3178 :``diverged``: pull will create a divergent bookmark
3179 :``changed``: result depends on remote changesets
3179 :``changed``: result depends on remote changesets
3180
3180
3181 From the point of view of pulling behavior, bookmark
3181 From the point of view of pulling behavior, bookmark
3182 existing only in the remote repository are treated as ``added``,
3182 existing only in the remote repository are treated as ``added``,
3183 even if it is in fact locally deleted.
3183 even if it is in fact locally deleted.
3184
3184
3185 .. container:: verbose
3185 .. container:: verbose
3186
3186
3187 For remote repository, using --bundle avoids downloading the
3187 For remote repository, using --bundle avoids downloading the
3188 changesets twice if the incoming is followed by a pull.
3188 changesets twice if the incoming is followed by a pull.
3189
3189
3190 Examples:
3190 Examples:
3191
3191
3192 - show incoming changes with patches and full description::
3192 - show incoming changes with patches and full description::
3193
3193
3194 hg incoming -vp
3194 hg incoming -vp
3195
3195
3196 - show incoming changes excluding merges, store a bundle::
3196 - show incoming changes excluding merges, store a bundle::
3197
3197
3198 hg in -vpM --bundle incoming.hg
3198 hg in -vpM --bundle incoming.hg
3199 hg pull incoming.hg
3199 hg pull incoming.hg
3200
3200
3201 - briefly list changes inside a bundle::
3201 - briefly list changes inside a bundle::
3202
3202
3203 hg in changes.hg -T "{desc|firstline}\\n"
3203 hg in changes.hg -T "{desc|firstline}\\n"
3204
3204
3205 Returns 0 if there are incoming changes, 1 otherwise.
3205 Returns 0 if there are incoming changes, 1 otherwise.
3206 """
3206 """
3207 opts = pycompat.byteskwargs(opts)
3207 opts = pycompat.byteskwargs(opts)
3208 if opts.get('graph'):
3208 if opts.get('graph'):
3209 cmdutil.checkunsupportedgraphflags([], opts)
3209 cmdutil.checkunsupportedgraphflags([], opts)
3210 def display(other, chlist, displayer):
3210 def display(other, chlist, displayer):
3211 revdag = cmdutil.graphrevs(other, chlist, opts)
3211 revdag = cmdutil.graphrevs(other, chlist, opts)
3212 cmdutil.displaygraph(ui, repo, revdag, displayer,
3212 cmdutil.displaygraph(ui, repo, revdag, displayer,
3213 graphmod.asciiedges)
3213 graphmod.asciiedges)
3214
3214
3215 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3215 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3216 return 0
3216 return 0
3217
3217
3218 if opts.get('bundle') and opts.get('subrepos'):
3218 if opts.get('bundle') and opts.get('subrepos'):
3219 raise error.Abort(_('cannot combine --bundle and --subrepos'))
3219 raise error.Abort(_('cannot combine --bundle and --subrepos'))
3220
3220
3221 if opts.get('bookmarks'):
3221 if opts.get('bookmarks'):
3222 source, branches = hg.parseurl(ui.expandpath(source),
3222 source, branches = hg.parseurl(ui.expandpath(source),
3223 opts.get('branch'))
3223 opts.get('branch'))
3224 other = hg.peer(repo, opts, source)
3224 other = hg.peer(repo, opts, source)
3225 if 'bookmarks' not in other.listkeys('namespaces'):
3225 if 'bookmarks' not in other.listkeys('namespaces'):
3226 ui.warn(_("remote doesn't support bookmarks\n"))
3226 ui.warn(_("remote doesn't support bookmarks\n"))
3227 return 0
3227 return 0
3228 ui.pager('incoming')
3228 ui.pager('incoming')
3229 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3229 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3230 return bookmarks.incoming(ui, repo, other)
3230 return bookmarks.incoming(ui, repo, other)
3231
3231
3232 repo._subtoppath = ui.expandpath(source)
3232 repo._subtoppath = ui.expandpath(source)
3233 try:
3233 try:
3234 return hg.incoming(ui, repo, source, opts)
3234 return hg.incoming(ui, repo, source, opts)
3235 finally:
3235 finally:
3236 del repo._subtoppath
3236 del repo._subtoppath
3237
3237
3238
3238
3239 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
3239 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
3240 norepo=True)
3240 norepo=True)
3241 def init(ui, dest=".", **opts):
3241 def init(ui, dest=".", **opts):
3242 """create a new repository in the given directory
3242 """create a new repository in the given directory
3243
3243
3244 Initialize a new repository in the given directory. If the given
3244 Initialize a new repository in the given directory. If the given
3245 directory does not exist, it will be created.
3245 directory does not exist, it will be created.
3246
3246
3247 If no directory is given, the current directory is used.
3247 If no directory is given, the current directory is used.
3248
3248
3249 It is possible to specify an ``ssh://`` URL as the destination.
3249 It is possible to specify an ``ssh://`` URL as the destination.
3250 See :hg:`help urls` for more information.
3250 See :hg:`help urls` for more information.
3251
3251
3252 Returns 0 on success.
3252 Returns 0 on success.
3253 """
3253 """
3254 opts = pycompat.byteskwargs(opts)
3254 opts = pycompat.byteskwargs(opts)
3255 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3255 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3256
3256
3257 @command('locate',
3257 @command('locate',
3258 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3258 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3259 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3259 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3260 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3260 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3261 ] + walkopts,
3261 ] + walkopts,
3262 _('[OPTION]... [PATTERN]...'))
3262 _('[OPTION]... [PATTERN]...'))
3263 def locate(ui, repo, *pats, **opts):
3263 def locate(ui, repo, *pats, **opts):
3264 """locate files matching specific patterns (DEPRECATED)
3264 """locate files matching specific patterns (DEPRECATED)
3265
3265
3266 Print files under Mercurial control in the working directory whose
3266 Print files under Mercurial control in the working directory whose
3267 names match the given patterns.
3267 names match the given patterns.
3268
3268
3269 By default, this command searches all directories in the working
3269 By default, this command searches all directories in the working
3270 directory. To search just the current directory and its
3270 directory. To search just the current directory and its
3271 subdirectories, use "--include .".
3271 subdirectories, use "--include .".
3272
3272
3273 If no patterns are given to match, this command prints the names
3273 If no patterns are given to match, this command prints the names
3274 of all files under Mercurial control in the working directory.
3274 of all files under Mercurial control in the working directory.
3275
3275
3276 If you want to feed the output of this command into the "xargs"
3276 If you want to feed the output of this command into the "xargs"
3277 command, use the -0 option to both this command and "xargs". This
3277 command, use the -0 option to both this command and "xargs". This
3278 will avoid the problem of "xargs" treating single filenames that
3278 will avoid the problem of "xargs" treating single filenames that
3279 contain whitespace as multiple filenames.
3279 contain whitespace as multiple filenames.
3280
3280
3281 See :hg:`help files` for a more versatile command.
3281 See :hg:`help files` for a more versatile command.
3282
3282
3283 Returns 0 if a match is found, 1 otherwise.
3283 Returns 0 if a match is found, 1 otherwise.
3284 """
3284 """
3285 opts = pycompat.byteskwargs(opts)
3285 opts = pycompat.byteskwargs(opts)
3286 if opts.get('print0'):
3286 if opts.get('print0'):
3287 end = '\0'
3287 end = '\0'
3288 else:
3288 else:
3289 end = '\n'
3289 end = '\n'
3290 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3290 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3291
3291
3292 ret = 1
3292 ret = 1
3293 ctx = repo[rev]
3293 ctx = repo[rev]
3294 m = scmutil.match(ctx, pats, opts, default='relglob',
3294 m = scmutil.match(ctx, pats, opts, default='relglob',
3295 badfn=lambda x, y: False)
3295 badfn=lambda x, y: False)
3296
3296
3297 ui.pager('locate')
3297 ui.pager('locate')
3298 for abs in ctx.matches(m):
3298 for abs in ctx.matches(m):
3299 if opts.get('fullpath'):
3299 if opts.get('fullpath'):
3300 ui.write(repo.wjoin(abs), end)
3300 ui.write(repo.wjoin(abs), end)
3301 else:
3301 else:
3302 ui.write(((pats and m.rel(abs)) or abs), end)
3302 ui.write(((pats and m.rel(abs)) or abs), end)
3303 ret = 0
3303 ret = 0
3304
3304
3305 return ret
3305 return ret
3306
3306
3307 @command('^log|history',
3307 @command('^log|history',
3308 [('f', 'follow', None,
3308 [('f', 'follow', None,
3309 _('follow changeset history, or file history across copies and renames')),
3309 _('follow changeset history, or file history across copies and renames')),
3310 ('', 'follow-first', None,
3310 ('', 'follow-first', None,
3311 _('only follow the first parent of merge changesets (DEPRECATED)')),
3311 _('only follow the first parent of merge changesets (DEPRECATED)')),
3312 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3312 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3313 ('C', 'copies', None, _('show copied files')),
3313 ('C', 'copies', None, _('show copied files')),
3314 ('k', 'keyword', [],
3314 ('k', 'keyword', [],
3315 _('do case-insensitive search for a given text'), _('TEXT')),
3315 _('do case-insensitive search for a given text'), _('TEXT')),
3316 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
3316 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
3317 ('', 'removed', None, _('include revisions where files were removed')),
3317 ('', 'removed', None, _('include revisions where files were removed')),
3318 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3318 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3319 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3319 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3320 ('', 'only-branch', [],
3320 ('', 'only-branch', [],
3321 _('show only changesets within the given named branch (DEPRECATED)'),
3321 _('show only changesets within the given named branch (DEPRECATED)'),
3322 _('BRANCH')),
3322 _('BRANCH')),
3323 ('b', 'branch', [],
3323 ('b', 'branch', [],
3324 _('show changesets within the given named branch'), _('BRANCH')),
3324 _('show changesets within the given named branch'), _('BRANCH')),
3325 ('P', 'prune', [],
3325 ('P', 'prune', [],
3326 _('do not display revision or any of its ancestors'), _('REV')),
3326 _('do not display revision or any of its ancestors'), _('REV')),
3327 ] + logopts + walkopts,
3327 ] + logopts + walkopts,
3328 _('[OPTION]... [FILE]'),
3328 _('[OPTION]... [FILE]'),
3329 inferrepo=True)
3329 inferrepo=True)
3330 def log(ui, repo, *pats, **opts):
3330 def log(ui, repo, *pats, **opts):
3331 """show revision history of entire repository or files
3331 """show revision history of entire repository or files
3332
3332
3333 Print the revision history of the specified files or the entire
3333 Print the revision history of the specified files or the entire
3334 project.
3334 project.
3335
3335
3336 If no revision range is specified, the default is ``tip:0`` unless
3336 If no revision range is specified, the default is ``tip:0`` unless
3337 --follow is set, in which case the working directory parent is
3337 --follow is set, in which case the working directory parent is
3338 used as the starting revision.
3338 used as the starting revision.
3339
3339
3340 File history is shown without following rename or copy history of
3340 File history is shown without following rename or copy history of
3341 files. Use -f/--follow with a filename to follow history across
3341 files. Use -f/--follow with a filename to follow history across
3342 renames and copies. --follow without a filename will only show
3342 renames and copies. --follow without a filename will only show
3343 ancestors or descendants of the starting revision.
3343 ancestors or descendants of the starting revision.
3344
3344
3345 By default this command prints revision number and changeset id,
3345 By default this command prints revision number and changeset id,
3346 tags, non-trivial parents, user, date and time, and a summary for
3346 tags, non-trivial parents, user, date and time, and a summary for
3347 each commit. When the -v/--verbose switch is used, the list of
3347 each commit. When the -v/--verbose switch is used, the list of
3348 changed files and full commit message are shown.
3348 changed files and full commit message are shown.
3349
3349
3350 With --graph the revisions are shown as an ASCII art DAG with the most
3350 With --graph the revisions are shown as an ASCII art DAG with the most
3351 recent changeset at the top.
3351 recent changeset at the top.
3352 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
3352 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
3353 and '+' represents a fork where the changeset from the lines below is a
3353 and '+' represents a fork where the changeset from the lines below is a
3354 parent of the 'o' merge on the same line.
3354 parent of the 'o' merge on the same line.
3355 Paths in the DAG are represented with '|', '/' and so forth. ':' in place
3355 Paths in the DAG are represented with '|', '/' and so forth. ':' in place
3356 of a '|' indicates one or more revisions in a path are omitted.
3356 of a '|' indicates one or more revisions in a path are omitted.
3357
3357
3358 .. note::
3358 .. note::
3359
3359
3360 :hg:`log --patch` may generate unexpected diff output for merge
3360 :hg:`log --patch` may generate unexpected diff output for merge
3361 changesets, as it will only compare the merge changeset against
3361 changesets, as it will only compare the merge changeset against
3362 its first parent. Also, only files different from BOTH parents
3362 its first parent. Also, only files different from BOTH parents
3363 will appear in files:.
3363 will appear in files:.
3364
3364
3365 .. note::
3365 .. note::
3366
3366
3367 For performance reasons, :hg:`log FILE` may omit duplicate changes
3367 For performance reasons, :hg:`log FILE` may omit duplicate changes
3368 made on branches and will not show removals or mode changes. To
3368 made on branches and will not show removals or mode changes. To
3369 see all such changes, use the --removed switch.
3369 see all such changes, use the --removed switch.
3370
3370
3371 .. container:: verbose
3371 .. container:: verbose
3372
3372
3373 Some examples:
3373 Some examples:
3374
3374
3375 - changesets with full descriptions and file lists::
3375 - changesets with full descriptions and file lists::
3376
3376
3377 hg log -v
3377 hg log -v
3378
3378
3379 - changesets ancestral to the working directory::
3379 - changesets ancestral to the working directory::
3380
3380
3381 hg log -f
3381 hg log -f
3382
3382
3383 - last 10 commits on the current branch::
3383 - last 10 commits on the current branch::
3384
3384
3385 hg log -l 10 -b .
3385 hg log -l 10 -b .
3386
3386
3387 - changesets showing all modifications of a file, including removals::
3387 - changesets showing all modifications of a file, including removals::
3388
3388
3389 hg log --removed file.c
3389 hg log --removed file.c
3390
3390
3391 - all changesets that touch a directory, with diffs, excluding merges::
3391 - all changesets that touch a directory, with diffs, excluding merges::
3392
3392
3393 hg log -Mp lib/
3393 hg log -Mp lib/
3394
3394
3395 - all revision numbers that match a keyword::
3395 - all revision numbers that match a keyword::
3396
3396
3397 hg log -k bug --template "{rev}\\n"
3397 hg log -k bug --template "{rev}\\n"
3398
3398
3399 - the full hash identifier of the working directory parent::
3399 - the full hash identifier of the working directory parent::
3400
3400
3401 hg log -r . --template "{node}\\n"
3401 hg log -r . --template "{node}\\n"
3402
3402
3403 - list available log templates::
3403 - list available log templates::
3404
3404
3405 hg log -T list
3405 hg log -T list
3406
3406
3407 - check if a given changeset is included in a tagged release::
3407 - check if a given changeset is included in a tagged release::
3408
3408
3409 hg log -r "a21ccf and ancestor(1.9)"
3409 hg log -r "a21ccf and ancestor(1.9)"
3410
3410
3411 - find all changesets by some user in a date range::
3411 - find all changesets by some user in a date range::
3412
3412
3413 hg log -k alice -d "may 2008 to jul 2008"
3413 hg log -k alice -d "may 2008 to jul 2008"
3414
3414
3415 - summary of all changesets after the last tag::
3415 - summary of all changesets after the last tag::
3416
3416
3417 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3417 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3418
3418
3419 See :hg:`help dates` for a list of formats valid for -d/--date.
3419 See :hg:`help dates` for a list of formats valid for -d/--date.
3420
3420
3421 See :hg:`help revisions` for more about specifying and ordering
3421 See :hg:`help revisions` for more about specifying and ordering
3422 revisions.
3422 revisions.
3423
3423
3424 See :hg:`help templates` for more about pre-packaged styles and
3424 See :hg:`help templates` for more about pre-packaged styles and
3425 specifying custom templates.
3425 specifying custom templates.
3426
3426
3427 Returns 0 on success.
3427 Returns 0 on success.
3428
3428
3429 """
3429 """
3430 opts = pycompat.byteskwargs(opts)
3430 opts = pycompat.byteskwargs(opts)
3431 if opts.get('follow') and opts.get('rev'):
3431 if opts.get('follow') and opts.get('rev'):
3432 opts['rev'] = [revsetlang.formatspec('reverse(::%lr)', opts.get('rev'))]
3432 opts['rev'] = [revsetlang.formatspec('reverse(::%lr)', opts.get('rev'))]
3433 del opts['follow']
3433 del opts['follow']
3434
3434
3435 if opts.get('graph'):
3435 if opts.get('graph'):
3436 return cmdutil.graphlog(ui, repo, pats, opts)
3436 return cmdutil.graphlog(ui, repo, pats, opts)
3437
3437
3438 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
3438 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
3439 limit = cmdutil.loglimit(opts)
3439 limit = cmdutil.loglimit(opts)
3440 count = 0
3440 count = 0
3441
3441
3442 getrenamed = None
3442 getrenamed = None
3443 if opts.get('copies'):
3443 if opts.get('copies'):
3444 endrev = None
3444 endrev = None
3445 if opts.get('rev'):
3445 if opts.get('rev'):
3446 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
3446 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
3447 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3447 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3448
3448
3449 ui.pager('log')
3449 ui.pager('log')
3450 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
3450 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
3451 for rev in revs:
3451 for rev in revs:
3452 if count == limit:
3452 if count == limit:
3453 break
3453 break
3454 ctx = repo[rev]
3454 ctx = repo[rev]
3455 copies = None
3455 copies = None
3456 if getrenamed is not None and rev:
3456 if getrenamed is not None and rev:
3457 copies = []
3457 copies = []
3458 for fn in ctx.files():
3458 for fn in ctx.files():
3459 rename = getrenamed(fn, rev)
3459 rename = getrenamed(fn, rev)
3460 if rename:
3460 if rename:
3461 copies.append((fn, rename[0]))
3461 copies.append((fn, rename[0]))
3462 if filematcher:
3462 if filematcher:
3463 revmatchfn = filematcher(ctx.rev())
3463 revmatchfn = filematcher(ctx.rev())
3464 else:
3464 else:
3465 revmatchfn = None
3465 revmatchfn = None
3466 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
3466 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
3467 if displayer.flush(ctx):
3467 if displayer.flush(ctx):
3468 count += 1
3468 count += 1
3469
3469
3470 displayer.close()
3470 displayer.close()
3471
3471
3472 @command('manifest',
3472 @command('manifest',
3473 [('r', 'rev', '', _('revision to display'), _('REV')),
3473 [('r', 'rev', '', _('revision to display'), _('REV')),
3474 ('', 'all', False, _("list files from all revisions"))]
3474 ('', 'all', False, _("list files from all revisions"))]
3475 + formatteropts,
3475 + formatteropts,
3476 _('[-r REV]'))
3476 _('[-r REV]'))
3477 def manifest(ui, repo, node=None, rev=None, **opts):
3477 def manifest(ui, repo, node=None, rev=None, **opts):
3478 """output the current or given revision of the project manifest
3478 """output the current or given revision of the project manifest
3479
3479
3480 Print a list of version controlled files for the given revision.
3480 Print a list of version controlled files for the given revision.
3481 If no revision is given, the first parent of the working directory
3481 If no revision is given, the first parent of the working directory
3482 is used, or the null revision if no revision is checked out.
3482 is used, or the null revision if no revision is checked out.
3483
3483
3484 With -v, print file permissions, symlink and executable bits.
3484 With -v, print file permissions, symlink and executable bits.
3485 With --debug, print file revision hashes.
3485 With --debug, print file revision hashes.
3486
3486
3487 If option --all is specified, the list of all files from all revisions
3487 If option --all is specified, the list of all files from all revisions
3488 is printed. This includes deleted and renamed files.
3488 is printed. This includes deleted and renamed files.
3489
3489
3490 Returns 0 on success.
3490 Returns 0 on success.
3491 """
3491 """
3492 opts = pycompat.byteskwargs(opts)
3492 opts = pycompat.byteskwargs(opts)
3493 fm = ui.formatter('manifest', opts)
3493 fm = ui.formatter('manifest', opts)
3494
3494
3495 if opts.get('all'):
3495 if opts.get('all'):
3496 if rev or node:
3496 if rev or node:
3497 raise error.Abort(_("can't specify a revision with --all"))
3497 raise error.Abort(_("can't specify a revision with --all"))
3498
3498
3499 res = []
3499 res = []
3500 prefix = "data/"
3500 prefix = "data/"
3501 suffix = ".i"
3501 suffix = ".i"
3502 plen = len(prefix)
3502 plen = len(prefix)
3503 slen = len(suffix)
3503 slen = len(suffix)
3504 with repo.lock():
3504 with repo.lock():
3505 for fn, b, size in repo.store.datafiles():
3505 for fn, b, size in repo.store.datafiles():
3506 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
3506 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
3507 res.append(fn[plen:-slen])
3507 res.append(fn[plen:-slen])
3508 ui.pager('manifest')
3508 ui.pager('manifest')
3509 for f in res:
3509 for f in res:
3510 fm.startitem()
3510 fm.startitem()
3511 fm.write("path", '%s\n', f)
3511 fm.write("path", '%s\n', f)
3512 fm.end()
3512 fm.end()
3513 return
3513 return
3514
3514
3515 if rev and node:
3515 if rev and node:
3516 raise error.Abort(_("please specify just one revision"))
3516 raise error.Abort(_("please specify just one revision"))
3517
3517
3518 if not node:
3518 if not node:
3519 node = rev
3519 node = rev
3520
3520
3521 char = {'l': '@', 'x': '*', '': ''}
3521 char = {'l': '@', 'x': '*', '': ''}
3522 mode = {'l': '644', 'x': '755', '': '644'}
3522 mode = {'l': '644', 'x': '755', '': '644'}
3523 ctx = scmutil.revsingle(repo, node)
3523 ctx = scmutil.revsingle(repo, node)
3524 mf = ctx.manifest()
3524 mf = ctx.manifest()
3525 ui.pager('manifest')
3525 ui.pager('manifest')
3526 for f in ctx:
3526 for f in ctx:
3527 fm.startitem()
3527 fm.startitem()
3528 fl = ctx[f].flags()
3528 fl = ctx[f].flags()
3529 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
3529 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
3530 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
3530 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
3531 fm.write('path', '%s\n', f)
3531 fm.write('path', '%s\n', f)
3532 fm.end()
3532 fm.end()
3533
3533
3534 @command('^merge',
3534 @command('^merge',
3535 [('f', 'force', None,
3535 [('f', 'force', None,
3536 _('force a merge including outstanding changes (DEPRECATED)')),
3536 _('force a merge including outstanding changes (DEPRECATED)')),
3537 ('r', 'rev', '', _('revision to merge'), _('REV')),
3537 ('r', 'rev', '', _('revision to merge'), _('REV')),
3538 ('P', 'preview', None,
3538 ('P', 'preview', None,
3539 _('review revisions to merge (no merge is performed)'))
3539 _('review revisions to merge (no merge is performed)'))
3540 ] + mergetoolopts,
3540 ] + mergetoolopts,
3541 _('[-P] [[-r] REV]'))
3541 _('[-P] [[-r] REV]'))
3542 def merge(ui, repo, node=None, **opts):
3542 def merge(ui, repo, node=None, **opts):
3543 """merge another revision into working directory
3543 """merge another revision into working directory
3544
3544
3545 The current working directory is updated with all changes made in
3545 The current working directory is updated with all changes made in
3546 the requested revision since the last common predecessor revision.
3546 the requested revision since the last common predecessor revision.
3547
3547
3548 Files that changed between either parent are marked as changed for
3548 Files that changed between either parent are marked as changed for
3549 the next commit and a commit must be performed before any further
3549 the next commit and a commit must be performed before any further
3550 updates to the repository are allowed. The next commit will have
3550 updates to the repository are allowed. The next commit will have
3551 two parents.
3551 two parents.
3552
3552
3553 ``--tool`` can be used to specify the merge tool used for file
3553 ``--tool`` can be used to specify the merge tool used for file
3554 merges. It overrides the HGMERGE environment variable and your
3554 merges. It overrides the HGMERGE environment variable and your
3555 configuration files. See :hg:`help merge-tools` for options.
3555 configuration files. See :hg:`help merge-tools` for options.
3556
3556
3557 If no revision is specified, the working directory's parent is a
3557 If no revision is specified, the working directory's parent is a
3558 head revision, and the current branch contains exactly one other
3558 head revision, and the current branch contains exactly one other
3559 head, the other head is merged with by default. Otherwise, an
3559 head, the other head is merged with by default. Otherwise, an
3560 explicit revision with which to merge with must be provided.
3560 explicit revision with which to merge with must be provided.
3561
3561
3562 See :hg:`help resolve` for information on handling file conflicts.
3562 See :hg:`help resolve` for information on handling file conflicts.
3563
3563
3564 To undo an uncommitted merge, use :hg:`update --clean .` which
3564 To undo an uncommitted merge, use :hg:`update --clean .` which
3565 will check out a clean copy of the original merge parent, losing
3565 will check out a clean copy of the original merge parent, losing
3566 all changes.
3566 all changes.
3567
3567
3568 Returns 0 on success, 1 if there are unresolved files.
3568 Returns 0 on success, 1 if there are unresolved files.
3569 """
3569 """
3570
3570
3571 opts = pycompat.byteskwargs(opts)
3571 opts = pycompat.byteskwargs(opts)
3572 if opts.get('rev') and node:
3572 if opts.get('rev') and node:
3573 raise error.Abort(_("please specify just one revision"))
3573 raise error.Abort(_("please specify just one revision"))
3574 if not node:
3574 if not node:
3575 node = opts.get('rev')
3575 node = opts.get('rev')
3576
3576
3577 if node:
3577 if node:
3578 node = scmutil.revsingle(repo, node).node()
3578 node = scmutil.revsingle(repo, node).node()
3579
3579
3580 if not node:
3580 if not node:
3581 node = repo[destutil.destmerge(repo)].node()
3581 node = repo[destutil.destmerge(repo)].node()
3582
3582
3583 if opts.get('preview'):
3583 if opts.get('preview'):
3584 # find nodes that are ancestors of p2 but not of p1
3584 # find nodes that are ancestors of p2 but not of p1
3585 p1 = repo.lookup('.')
3585 p1 = repo.lookup('.')
3586 p2 = repo.lookup(node)
3586 p2 = repo.lookup(node)
3587 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
3587 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
3588
3588
3589 displayer = cmdutil.show_changeset(ui, repo, opts)
3589 displayer = cmdutil.show_changeset(ui, repo, opts)
3590 for node in nodes:
3590 for node in nodes:
3591 displayer.show(repo[node])
3591 displayer.show(repo[node])
3592 displayer.close()
3592 displayer.close()
3593 return 0
3593 return 0
3594
3594
3595 try:
3595 try:
3596 # ui.forcemerge is an internal variable, do not document
3596 # ui.forcemerge is an internal variable, do not document
3597 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
3597 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
3598 force = opts.get('force')
3598 force = opts.get('force')
3599 labels = ['working copy', 'merge rev']
3599 labels = ['working copy', 'merge rev']
3600 return hg.merge(repo, node, force=force, mergeforce=force,
3600 return hg.merge(repo, node, force=force, mergeforce=force,
3601 labels=labels)
3601 labels=labels)
3602 finally:
3602 finally:
3603 ui.setconfig('ui', 'forcemerge', '', 'merge')
3603 ui.setconfig('ui', 'forcemerge', '', 'merge')
3604
3604
3605 @command('outgoing|out',
3605 @command('outgoing|out',
3606 [('f', 'force', None, _('run even when the destination is unrelated')),
3606 [('f', 'force', None, _('run even when the destination is unrelated')),
3607 ('r', 'rev', [],
3607 ('r', 'rev', [],
3608 _('a changeset intended to be included in the destination'), _('REV')),
3608 _('a changeset intended to be included in the destination'), _('REV')),
3609 ('n', 'newest-first', None, _('show newest record first')),
3609 ('n', 'newest-first', None, _('show newest record first')),
3610 ('B', 'bookmarks', False, _('compare bookmarks')),
3610 ('B', 'bookmarks', False, _('compare bookmarks')),
3611 ('b', 'branch', [], _('a specific branch you would like to push'),
3611 ('b', 'branch', [], _('a specific branch you would like to push'),
3612 _('BRANCH')),
3612 _('BRANCH')),
3613 ] + logopts + remoteopts + subrepoopts,
3613 ] + logopts + remoteopts + subrepoopts,
3614 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
3614 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
3615 def outgoing(ui, repo, dest=None, **opts):
3615 def outgoing(ui, repo, dest=None, **opts):
3616 """show changesets not found in the destination
3616 """show changesets not found in the destination
3617
3617
3618 Show changesets not found in the specified destination repository
3618 Show changesets not found in the specified destination repository
3619 or the default push location. These are the changesets that would
3619 or the default push location. These are the changesets that would
3620 be pushed if a push was requested.
3620 be pushed if a push was requested.
3621
3621
3622 See pull for details of valid destination formats.
3622 See pull for details of valid destination formats.
3623
3623
3624 .. container:: verbose
3624 .. container:: verbose
3625
3625
3626 With -B/--bookmarks, the result of bookmark comparison between
3626 With -B/--bookmarks, the result of bookmark comparison between
3627 local and remote repositories is displayed. With -v/--verbose,
3627 local and remote repositories is displayed. With -v/--verbose,
3628 status is also displayed for each bookmark like below::
3628 status is also displayed for each bookmark like below::
3629
3629
3630 BM1 01234567890a added
3630 BM1 01234567890a added
3631 BM2 deleted
3631 BM2 deleted
3632 BM3 234567890abc advanced
3632 BM3 234567890abc advanced
3633 BM4 34567890abcd diverged
3633 BM4 34567890abcd diverged
3634 BM5 4567890abcde changed
3634 BM5 4567890abcde changed
3635
3635
3636 The action taken when pushing depends on the
3636 The action taken when pushing depends on the
3637 status of each bookmark:
3637 status of each bookmark:
3638
3638
3639 :``added``: push with ``-B`` will create it
3639 :``added``: push with ``-B`` will create it
3640 :``deleted``: push with ``-B`` will delete it
3640 :``deleted``: push with ``-B`` will delete it
3641 :``advanced``: push will update it
3641 :``advanced``: push will update it
3642 :``diverged``: push with ``-B`` will update it
3642 :``diverged``: push with ``-B`` will update it
3643 :``changed``: push with ``-B`` will update it
3643 :``changed``: push with ``-B`` will update it
3644
3644
3645 From the point of view of pushing behavior, bookmarks
3645 From the point of view of pushing behavior, bookmarks
3646 existing only in the remote repository are treated as
3646 existing only in the remote repository are treated as
3647 ``deleted``, even if it is in fact added remotely.
3647 ``deleted``, even if it is in fact added remotely.
3648
3648
3649 Returns 0 if there are outgoing changes, 1 otherwise.
3649 Returns 0 if there are outgoing changes, 1 otherwise.
3650 """
3650 """
3651 opts = pycompat.byteskwargs(opts)
3651 opts = pycompat.byteskwargs(opts)
3652 if opts.get('graph'):
3652 if opts.get('graph'):
3653 cmdutil.checkunsupportedgraphflags([], opts)
3653 cmdutil.checkunsupportedgraphflags([], opts)
3654 o, other = hg._outgoing(ui, repo, dest, opts)
3654 o, other = hg._outgoing(ui, repo, dest, opts)
3655 if not o:
3655 if not o:
3656 cmdutil.outgoinghooks(ui, repo, other, opts, o)
3656 cmdutil.outgoinghooks(ui, repo, other, opts, o)
3657 return
3657 return
3658
3658
3659 revdag = cmdutil.graphrevs(repo, o, opts)
3659 revdag = cmdutil.graphrevs(repo, o, opts)
3660 ui.pager('outgoing')
3660 ui.pager('outgoing')
3661 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
3661 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
3662 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
3662 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
3663 cmdutil.outgoinghooks(ui, repo, other, opts, o)
3663 cmdutil.outgoinghooks(ui, repo, other, opts, o)
3664 return 0
3664 return 0
3665
3665
3666 if opts.get('bookmarks'):
3666 if opts.get('bookmarks'):
3667 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3667 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3668 dest, branches = hg.parseurl(dest, opts.get('branch'))
3668 dest, branches = hg.parseurl(dest, opts.get('branch'))
3669 other = hg.peer(repo, opts, dest)
3669 other = hg.peer(repo, opts, dest)
3670 if 'bookmarks' not in other.listkeys('namespaces'):
3670 if 'bookmarks' not in other.listkeys('namespaces'):
3671 ui.warn(_("remote doesn't support bookmarks\n"))
3671 ui.warn(_("remote doesn't support bookmarks\n"))
3672 return 0
3672 return 0
3673 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
3673 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
3674 ui.pager('outgoing')
3674 ui.pager('outgoing')
3675 return bookmarks.outgoing(ui, repo, other)
3675 return bookmarks.outgoing(ui, repo, other)
3676
3676
3677 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
3677 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
3678 try:
3678 try:
3679 return hg.outgoing(ui, repo, dest, opts)
3679 return hg.outgoing(ui, repo, dest, opts)
3680 finally:
3680 finally:
3681 del repo._subtoppath
3681 del repo._subtoppath
3682
3682
3683 @command('parents',
3683 @command('parents',
3684 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
3684 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
3685 ] + templateopts,
3685 ] + templateopts,
3686 _('[-r REV] [FILE]'),
3686 _('[-r REV] [FILE]'),
3687 inferrepo=True)
3687 inferrepo=True)
3688 def parents(ui, repo, file_=None, **opts):
3688 def parents(ui, repo, file_=None, **opts):
3689 """show the parents of the working directory or revision (DEPRECATED)
3689 """show the parents of the working directory or revision (DEPRECATED)
3690
3690
3691 Print the working directory's parent revisions. If a revision is
3691 Print the working directory's parent revisions. If a revision is
3692 given via -r/--rev, the parent of that revision will be printed.
3692 given via -r/--rev, the parent of that revision will be printed.
3693 If a file argument is given, the revision in which the file was
3693 If a file argument is given, the revision in which the file was
3694 last changed (before the working directory revision or the
3694 last changed (before the working directory revision or the
3695 argument to --rev if given) is printed.
3695 argument to --rev if given) is printed.
3696
3696
3697 This command is equivalent to::
3697 This command is equivalent to::
3698
3698
3699 hg log -r "p1()+p2()" or
3699 hg log -r "p1()+p2()" or
3700 hg log -r "p1(REV)+p2(REV)" or
3700 hg log -r "p1(REV)+p2(REV)" or
3701 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
3701 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
3702 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
3702 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
3703
3703
3704 See :hg:`summary` and :hg:`help revsets` for related information.
3704 See :hg:`summary` and :hg:`help revsets` for related information.
3705
3705
3706 Returns 0 on success.
3706 Returns 0 on success.
3707 """
3707 """
3708
3708
3709 opts = pycompat.byteskwargs(opts)
3709 opts = pycompat.byteskwargs(opts)
3710 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3710 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3711
3711
3712 if file_:
3712 if file_:
3713 m = scmutil.match(ctx, (file_,), opts)
3713 m = scmutil.match(ctx, (file_,), opts)
3714 if m.anypats() or len(m.files()) != 1:
3714 if m.anypats() or len(m.files()) != 1:
3715 raise error.Abort(_('can only specify an explicit filename'))
3715 raise error.Abort(_('can only specify an explicit filename'))
3716 file_ = m.files()[0]
3716 file_ = m.files()[0]
3717 filenodes = []
3717 filenodes = []
3718 for cp in ctx.parents():
3718 for cp in ctx.parents():
3719 if not cp:
3719 if not cp:
3720 continue
3720 continue
3721 try:
3721 try:
3722 filenodes.append(cp.filenode(file_))
3722 filenodes.append(cp.filenode(file_))
3723 except error.LookupError:
3723 except error.LookupError:
3724 pass
3724 pass
3725 if not filenodes:
3725 if not filenodes:
3726 raise error.Abort(_("'%s' not found in manifest!") % file_)
3726 raise error.Abort(_("'%s' not found in manifest!") % file_)
3727 p = []
3727 p = []
3728 for fn in filenodes:
3728 for fn in filenodes:
3729 fctx = repo.filectx(file_, fileid=fn)
3729 fctx = repo.filectx(file_, fileid=fn)
3730 p.append(fctx.node())
3730 p.append(fctx.node())
3731 else:
3731 else:
3732 p = [cp.node() for cp in ctx.parents()]
3732 p = [cp.node() for cp in ctx.parents()]
3733
3733
3734 displayer = cmdutil.show_changeset(ui, repo, opts)
3734 displayer = cmdutil.show_changeset(ui, repo, opts)
3735 for n in p:
3735 for n in p:
3736 if n != nullid:
3736 if n != nullid:
3737 displayer.show(repo[n])
3737 displayer.show(repo[n])
3738 displayer.close()
3738 displayer.close()
3739
3739
3740 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True)
3740 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True)
3741 def paths(ui, repo, search=None, **opts):
3741 def paths(ui, repo, search=None, **opts):
3742 """show aliases for remote repositories
3742 """show aliases for remote repositories
3743
3743
3744 Show definition of symbolic path name NAME. If no name is given,
3744 Show definition of symbolic path name NAME. If no name is given,
3745 show definition of all available names.
3745 show definition of all available names.
3746
3746
3747 Option -q/--quiet suppresses all output when searching for NAME
3747 Option -q/--quiet suppresses all output when searching for NAME
3748 and shows only the path names when listing all definitions.
3748 and shows only the path names when listing all definitions.
3749
3749
3750 Path names are defined in the [paths] section of your
3750 Path names are defined in the [paths] section of your
3751 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
3751 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
3752 repository, ``.hg/hgrc`` is used, too.
3752 repository, ``.hg/hgrc`` is used, too.
3753
3753
3754 The path names ``default`` and ``default-push`` have a special
3754 The path names ``default`` and ``default-push`` have a special
3755 meaning. When performing a push or pull operation, they are used
3755 meaning. When performing a push or pull operation, they are used
3756 as fallbacks if no location is specified on the command-line.
3756 as fallbacks if no location is specified on the command-line.
3757 When ``default-push`` is set, it will be used for push and
3757 When ``default-push`` is set, it will be used for push and
3758 ``default`` will be used for pull; otherwise ``default`` is used
3758 ``default`` will be used for pull; otherwise ``default`` is used
3759 as the fallback for both. When cloning a repository, the clone
3759 as the fallback for both. When cloning a repository, the clone
3760 source is written as ``default`` in ``.hg/hgrc``.
3760 source is written as ``default`` in ``.hg/hgrc``.
3761
3761
3762 .. note::
3762 .. note::
3763
3763
3764 ``default`` and ``default-push`` apply to all inbound (e.g.
3764 ``default`` and ``default-push`` apply to all inbound (e.g.
3765 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
3765 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
3766 and :hg:`bundle`) operations.
3766 and :hg:`bundle`) operations.
3767
3767
3768 See :hg:`help urls` for more information.
3768 See :hg:`help urls` for more information.
3769
3769
3770 Returns 0 on success.
3770 Returns 0 on success.
3771 """
3771 """
3772
3772
3773 opts = pycompat.byteskwargs(opts)
3773 opts = pycompat.byteskwargs(opts)
3774 ui.pager('paths')
3774 ui.pager('paths')
3775 if search:
3775 if search:
3776 pathitems = [(name, path) for name, path in ui.paths.iteritems()
3776 pathitems = [(name, path) for name, path in ui.paths.iteritems()
3777 if name == search]
3777 if name == search]
3778 else:
3778 else:
3779 pathitems = sorted(ui.paths.iteritems())
3779 pathitems = sorted(ui.paths.iteritems())
3780
3780
3781 fm = ui.formatter('paths', opts)
3781 fm = ui.formatter('paths', opts)
3782 if fm.isplain():
3782 if fm.isplain():
3783 hidepassword = util.hidepassword
3783 hidepassword = util.hidepassword
3784 else:
3784 else:
3785 hidepassword = str
3785 hidepassword = str
3786 if ui.quiet:
3786 if ui.quiet:
3787 namefmt = '%s\n'
3787 namefmt = '%s\n'
3788 else:
3788 else:
3789 namefmt = '%s = '
3789 namefmt = '%s = '
3790 showsubopts = not search and not ui.quiet
3790 showsubopts = not search and not ui.quiet
3791
3791
3792 for name, path in pathitems:
3792 for name, path in pathitems:
3793 fm.startitem()
3793 fm.startitem()
3794 fm.condwrite(not search, 'name', namefmt, name)
3794 fm.condwrite(not search, 'name', namefmt, name)
3795 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
3795 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
3796 for subopt, value in sorted(path.suboptions.items()):
3796 for subopt, value in sorted(path.suboptions.items()):
3797 assert subopt not in ('name', 'url')
3797 assert subopt not in ('name', 'url')
3798 if showsubopts:
3798 if showsubopts:
3799 fm.plain('%s:%s = ' % (name, subopt))
3799 fm.plain('%s:%s = ' % (name, subopt))
3800 fm.condwrite(showsubopts, subopt, '%s\n', value)
3800 fm.condwrite(showsubopts, subopt, '%s\n', value)
3801
3801
3802 fm.end()
3802 fm.end()
3803
3803
3804 if search and not pathitems:
3804 if search and not pathitems:
3805 if not ui.quiet:
3805 if not ui.quiet:
3806 ui.warn(_("not found!\n"))
3806 ui.warn(_("not found!\n"))
3807 return 1
3807 return 1
3808 else:
3808 else:
3809 return 0
3809 return 0
3810
3810
3811 @command('phase',
3811 @command('phase',
3812 [('p', 'public', False, _('set changeset phase to public')),
3812 [('p', 'public', False, _('set changeset phase to public')),
3813 ('d', 'draft', False, _('set changeset phase to draft')),
3813 ('d', 'draft', False, _('set changeset phase to draft')),
3814 ('s', 'secret', False, _('set changeset phase to secret')),
3814 ('s', 'secret', False, _('set changeset phase to secret')),
3815 ('f', 'force', False, _('allow to move boundary backward')),
3815 ('f', 'force', False, _('allow to move boundary backward')),
3816 ('r', 'rev', [], _('target revision'), _('REV')),
3816 ('r', 'rev', [], _('target revision'), _('REV')),
3817 ],
3817 ],
3818 _('[-p|-d|-s] [-f] [-r] [REV...]'))
3818 _('[-p|-d|-s] [-f] [-r] [REV...]'))
3819 def phase(ui, repo, *revs, **opts):
3819 def phase(ui, repo, *revs, **opts):
3820 """set or show the current phase name
3820 """set or show the current phase name
3821
3821
3822 With no argument, show the phase name of the current revision(s).
3822 With no argument, show the phase name of the current revision(s).
3823
3823
3824 With one of -p/--public, -d/--draft or -s/--secret, change the
3824 With one of -p/--public, -d/--draft or -s/--secret, change the
3825 phase value of the specified revisions.
3825 phase value of the specified revisions.
3826
3826
3827 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
3827 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
3828 lower phase to an higher phase. Phases are ordered as follows::
3828 lower phase to an higher phase. Phases are ordered as follows::
3829
3829
3830 public < draft < secret
3830 public < draft < secret
3831
3831
3832 Returns 0 on success, 1 if some phases could not be changed.
3832 Returns 0 on success, 1 if some phases could not be changed.
3833
3833
3834 (For more information about the phases concept, see :hg:`help phases`.)
3834 (For more information about the phases concept, see :hg:`help phases`.)
3835 """
3835 """
3836 opts = pycompat.byteskwargs(opts)
3836 opts = pycompat.byteskwargs(opts)
3837 # search for a unique phase argument
3837 # search for a unique phase argument
3838 targetphase = None
3838 targetphase = None
3839 for idx, name in enumerate(phases.phasenames):
3839 for idx, name in enumerate(phases.phasenames):
3840 if opts[name]:
3840 if opts[name]:
3841 if targetphase is not None:
3841 if targetphase is not None:
3842 raise error.Abort(_('only one phase can be specified'))
3842 raise error.Abort(_('only one phase can be specified'))
3843 targetphase = idx
3843 targetphase = idx
3844
3844
3845 # look for specified revision
3845 # look for specified revision
3846 revs = list(revs)
3846 revs = list(revs)
3847 revs.extend(opts['rev'])
3847 revs.extend(opts['rev'])
3848 if not revs:
3848 if not revs:
3849 # display both parents as the second parent phase can influence
3849 # display both parents as the second parent phase can influence
3850 # the phase of a merge commit
3850 # the phase of a merge commit
3851 revs = [c.rev() for c in repo[None].parents()]
3851 revs = [c.rev() for c in repo[None].parents()]
3852
3852
3853 revs = scmutil.revrange(repo, revs)
3853 revs = scmutil.revrange(repo, revs)
3854
3854
3855 lock = None
3855 lock = None
3856 ret = 0
3856 ret = 0
3857 if targetphase is None:
3857 if targetphase is None:
3858 # display
3858 # display
3859 for r in revs:
3859 for r in revs:
3860 ctx = repo[r]
3860 ctx = repo[r]
3861 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
3861 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
3862 else:
3862 else:
3863 tr = None
3863 tr = None
3864 lock = repo.lock()
3864 lock = repo.lock()
3865 try:
3865 try:
3866 tr = repo.transaction("phase")
3866 tr = repo.transaction("phase")
3867 # set phase
3867 # set phase
3868 if not revs:
3868 if not revs:
3869 raise error.Abort(_('empty revision set'))
3869 raise error.Abort(_('empty revision set'))
3870 nodes = [repo[r].node() for r in revs]
3870 nodes = [repo[r].node() for r in revs]
3871 # moving revision from public to draft may hide them
3871 # moving revision from public to draft may hide them
3872 # We have to check result on an unfiltered repository
3872 # We have to check result on an unfiltered repository
3873 unfi = repo.unfiltered()
3873 unfi = repo.unfiltered()
3874 getphase = unfi._phasecache.phase
3874 getphase = unfi._phasecache.phase
3875 olddata = [getphase(unfi, r) for r in unfi]
3875 olddata = [getphase(unfi, r) for r in unfi]
3876 phases.advanceboundary(repo, tr, targetphase, nodes)
3876 phases.advanceboundary(repo, tr, targetphase, nodes)
3877 if opts['force']:
3877 if opts['force']:
3878 phases.retractboundary(repo, tr, targetphase, nodes)
3878 phases.retractboundary(repo, tr, targetphase, nodes)
3879 tr.close()
3879 tr.close()
3880 finally:
3880 finally:
3881 if tr is not None:
3881 if tr is not None:
3882 tr.release()
3882 tr.release()
3883 lock.release()
3883 lock.release()
3884 getphase = unfi._phasecache.phase
3884 getphase = unfi._phasecache.phase
3885 newdata = [getphase(unfi, r) for r in unfi]
3885 newdata = [getphase(unfi, r) for r in unfi]
3886 changes = sum(newdata[r] != olddata[r] for r in unfi)
3886 changes = sum(newdata[r] != olddata[r] for r in unfi)
3887 cl = unfi.changelog
3887 cl = unfi.changelog
3888 rejected = [n for n in nodes
3888 rejected = [n for n in nodes
3889 if newdata[cl.rev(n)] < targetphase]
3889 if newdata[cl.rev(n)] < targetphase]
3890 if rejected:
3890 if rejected:
3891 ui.warn(_('cannot move %i changesets to a higher '
3891 ui.warn(_('cannot move %i changesets to a higher '
3892 'phase, use --force\n') % len(rejected))
3892 'phase, use --force\n') % len(rejected))
3893 ret = 1
3893 ret = 1
3894 if changes:
3894 if changes:
3895 msg = _('phase changed for %i changesets\n') % changes
3895 msg = _('phase changed for %i changesets\n') % changes
3896 if ret:
3896 if ret:
3897 ui.status(msg)
3897 ui.status(msg)
3898 else:
3898 else:
3899 ui.note(msg)
3899 ui.note(msg)
3900 else:
3900 else:
3901 ui.warn(_('no phases changed\n'))
3901 ui.warn(_('no phases changed\n'))
3902 return ret
3902 return ret
3903
3903
3904 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
3904 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
3905 """Run after a changegroup has been added via pull/unbundle
3905 """Run after a changegroup has been added via pull/unbundle
3906
3906
3907 This takes arguments below:
3907 This takes arguments below:
3908
3908
3909 :modheads: change of heads by pull/unbundle
3909 :modheads: change of heads by pull/unbundle
3910 :optupdate: updating working directory is needed or not
3910 :optupdate: updating working directory is needed or not
3911 :checkout: update destination revision (or None to default destination)
3911 :checkout: update destination revision (or None to default destination)
3912 :brev: a name, which might be a bookmark to be activated after updating
3912 :brev: a name, which might be a bookmark to be activated after updating
3913 """
3913 """
3914 if modheads == 0:
3914 if modheads == 0:
3915 return
3915 return
3916 if optupdate:
3916 if optupdate:
3917 try:
3917 try:
3918 return hg.updatetotally(ui, repo, checkout, brev)
3918 return hg.updatetotally(ui, repo, checkout, brev)
3919 except error.UpdateAbort as inst:
3919 except error.UpdateAbort as inst:
3920 msg = _("not updating: %s") % str(inst)
3920 msg = _("not updating: %s") % str(inst)
3921 hint = inst.hint
3921 hint = inst.hint
3922 raise error.UpdateAbort(msg, hint=hint)
3922 raise error.UpdateAbort(msg, hint=hint)
3923 if modheads > 1:
3923 if modheads > 1:
3924 currentbranchheads = len(repo.branchheads())
3924 currentbranchheads = len(repo.branchheads())
3925 if currentbranchheads == modheads:
3925 if currentbranchheads == modheads:
3926 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
3926 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
3927 elif currentbranchheads > 1:
3927 elif currentbranchheads > 1:
3928 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
3928 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
3929 "merge)\n"))
3929 "merge)\n"))
3930 else:
3930 else:
3931 ui.status(_("(run 'hg heads' to see heads)\n"))
3931 ui.status(_("(run 'hg heads' to see heads)\n"))
3932 else:
3932 else:
3933 ui.status(_("(run 'hg update' to get a working copy)\n"))
3933 ui.status(_("(run 'hg update' to get a working copy)\n"))
3934
3934
3935 @command('^pull',
3935 @command('^pull',
3936 [('u', 'update', None,
3936 [('u', 'update', None,
3937 _('update to new branch head if changesets were pulled')),
3937 _('update to new branch head if changesets were pulled')),
3938 ('f', 'force', None, _('run even when remote repository is unrelated')),
3938 ('f', 'force', None, _('run even when remote repository is unrelated')),
3939 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3939 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3940 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
3940 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
3941 ('b', 'branch', [], _('a specific branch you would like to pull'),
3941 ('b', 'branch', [], _('a specific branch you would like to pull'),
3942 _('BRANCH')),
3942 _('BRANCH')),
3943 ] + remoteopts,
3943 ] + remoteopts,
3944 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
3944 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
3945 def pull(ui, repo, source="default", **opts):
3945 def pull(ui, repo, source="default", **opts):
3946 """pull changes from the specified source
3946 """pull changes from the specified source
3947
3947
3948 Pull changes from a remote repository to a local one.
3948 Pull changes from a remote repository to a local one.
3949
3949
3950 This finds all changes from the repository at the specified path
3950 This finds all changes from the repository at the specified path
3951 or URL and adds them to a local repository (the current one unless
3951 or URL and adds them to a local repository (the current one unless
3952 -R is specified). By default, this does not update the copy of the
3952 -R is specified). By default, this does not update the copy of the
3953 project in the working directory.
3953 project in the working directory.
3954
3954
3955 Use :hg:`incoming` if you want to see what would have been added
3955 Use :hg:`incoming` if you want to see what would have been added
3956 by a pull at the time you issued this command. If you then decide
3956 by a pull at the time you issued this command. If you then decide
3957 to add those changes to the repository, you should use :hg:`pull
3957 to add those changes to the repository, you should use :hg:`pull
3958 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
3958 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
3959
3959
3960 If SOURCE is omitted, the 'default' path will be used.
3960 If SOURCE is omitted, the 'default' path will be used.
3961 See :hg:`help urls` for more information.
3961 See :hg:`help urls` for more information.
3962
3962
3963 Specifying bookmark as ``.`` is equivalent to specifying the active
3963 Specifying bookmark as ``.`` is equivalent to specifying the active
3964 bookmark's name.
3964 bookmark's name.
3965
3965
3966 Returns 0 on success, 1 if an update had unresolved files.
3966 Returns 0 on success, 1 if an update had unresolved files.
3967 """
3967 """
3968
3968
3969 opts = pycompat.byteskwargs(opts)
3969 opts = pycompat.byteskwargs(opts)
3970 if ui.configbool('commands', 'update.requiredest') and opts.get('update'):
3970 if ui.configbool('commands', 'update.requiredest') and opts.get('update'):
3971 msg = _('update destination required by configuration')
3971 msg = _('update destination required by configuration')
3972 hint = _('use hg pull followed by hg update DEST')
3972 hint = _('use hg pull followed by hg update DEST')
3973 raise error.Abort(msg, hint=hint)
3973 raise error.Abort(msg, hint=hint)
3974
3974
3975 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
3975 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
3976 ui.status(_('pulling from %s\n') % util.hidepassword(source))
3976 ui.status(_('pulling from %s\n') % util.hidepassword(source))
3977 other = hg.peer(repo, opts, source)
3977 other = hg.peer(repo, opts, source)
3978 try:
3978 try:
3979 revs, checkout = hg.addbranchrevs(repo, other, branches,
3979 revs, checkout = hg.addbranchrevs(repo, other, branches,
3980 opts.get('rev'))
3980 opts.get('rev'))
3981
3981
3982
3982
3983 pullopargs = {}
3983 pullopargs = {}
3984 if opts.get('bookmark'):
3984 if opts.get('bookmark'):
3985 if not revs:
3985 if not revs:
3986 revs = []
3986 revs = []
3987 # The list of bookmark used here is not the one used to actually
3987 # The list of bookmark used here is not the one used to actually
3988 # update the bookmark name. This can result in the revision pulled
3988 # update the bookmark name. This can result in the revision pulled
3989 # not ending up with the name of the bookmark because of a race
3989 # not ending up with the name of the bookmark because of a race
3990 # condition on the server. (See issue 4689 for details)
3990 # condition on the server. (See issue 4689 for details)
3991 remotebookmarks = other.listkeys('bookmarks')
3991 remotebookmarks = other.listkeys('bookmarks')
3992 pullopargs['remotebookmarks'] = remotebookmarks
3992 pullopargs['remotebookmarks'] = remotebookmarks
3993 for b in opts['bookmark']:
3993 for b in opts['bookmark']:
3994 b = repo._bookmarks.expandname(b)
3994 b = repo._bookmarks.expandname(b)
3995 if b not in remotebookmarks:
3995 if b not in remotebookmarks:
3996 raise error.Abort(_('remote bookmark %s not found!') % b)
3996 raise error.Abort(_('remote bookmark %s not found!') % b)
3997 revs.append(remotebookmarks[b])
3997 revs.append(remotebookmarks[b])
3998
3998
3999 if revs:
3999 if revs:
4000 try:
4000 try:
4001 # When 'rev' is a bookmark name, we cannot guarantee that it
4001 # When 'rev' is a bookmark name, we cannot guarantee that it
4002 # will be updated with that name because of a race condition
4002 # will be updated with that name because of a race condition
4003 # server side. (See issue 4689 for details)
4003 # server side. (See issue 4689 for details)
4004 oldrevs = revs
4004 oldrevs = revs
4005 revs = [] # actually, nodes
4005 revs = [] # actually, nodes
4006 for r in oldrevs:
4006 for r in oldrevs:
4007 node = other.lookup(r)
4007 node = other.lookup(r)
4008 revs.append(node)
4008 revs.append(node)
4009 if r == checkout:
4009 if r == checkout:
4010 checkout = node
4010 checkout = node
4011 except error.CapabilityError:
4011 except error.CapabilityError:
4012 err = _("other repository doesn't support revision lookup, "
4012 err = _("other repository doesn't support revision lookup, "
4013 "so a rev cannot be specified.")
4013 "so a rev cannot be specified.")
4014 raise error.Abort(err)
4014 raise error.Abort(err)
4015
4015
4016 pullopargs.update(opts.get('opargs', {}))
4016 pullopargs.update(opts.get('opargs', {}))
4017 modheads = exchange.pull(repo, other, heads=revs,
4017 modheads = exchange.pull(repo, other, heads=revs,
4018 force=opts.get('force'),
4018 force=opts.get('force'),
4019 bookmarks=opts.get('bookmark', ()),
4019 bookmarks=opts.get('bookmark', ()),
4020 opargs=pullopargs).cgresult
4020 opargs=pullopargs).cgresult
4021
4021
4022 # brev is a name, which might be a bookmark to be activated at
4022 # brev is a name, which might be a bookmark to be activated at
4023 # the end of the update. In other words, it is an explicit
4023 # the end of the update. In other words, it is an explicit
4024 # destination of the update
4024 # destination of the update
4025 brev = None
4025 brev = None
4026
4026
4027 if checkout:
4027 if checkout:
4028 checkout = str(repo.changelog.rev(checkout))
4028 checkout = str(repo.changelog.rev(checkout))
4029
4029
4030 # order below depends on implementation of
4030 # order below depends on implementation of
4031 # hg.addbranchrevs(). opts['bookmark'] is ignored,
4031 # hg.addbranchrevs(). opts['bookmark'] is ignored,
4032 # because 'checkout' is determined without it.
4032 # because 'checkout' is determined without it.
4033 if opts.get('rev'):
4033 if opts.get('rev'):
4034 brev = opts['rev'][0]
4034 brev = opts['rev'][0]
4035 elif opts.get('branch'):
4035 elif opts.get('branch'):
4036 brev = opts['branch'][0]
4036 brev = opts['branch'][0]
4037 else:
4037 else:
4038 brev = branches[0]
4038 brev = branches[0]
4039 repo._subtoppath = source
4039 repo._subtoppath = source
4040 try:
4040 try:
4041 ret = postincoming(ui, repo, modheads, opts.get('update'),
4041 ret = postincoming(ui, repo, modheads, opts.get('update'),
4042 checkout, brev)
4042 checkout, brev)
4043
4043
4044 finally:
4044 finally:
4045 del repo._subtoppath
4045 del repo._subtoppath
4046
4046
4047 finally:
4047 finally:
4048 other.close()
4048 other.close()
4049 return ret
4049 return ret
4050
4050
4051 @command('^push',
4051 @command('^push',
4052 [('f', 'force', None, _('force push')),
4052 [('f', 'force', None, _('force push')),
4053 ('r', 'rev', [],
4053 ('r', 'rev', [],
4054 _('a changeset intended to be included in the destination'),
4054 _('a changeset intended to be included in the destination'),
4055 _('REV')),
4055 _('REV')),
4056 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4056 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4057 ('b', 'branch', [],
4057 ('b', 'branch', [],
4058 _('a specific branch you would like to push'), _('BRANCH')),
4058 _('a specific branch you would like to push'), _('BRANCH')),
4059 ('', 'new-branch', False, _('allow pushing a new branch')),
4059 ('', 'new-branch', False, _('allow pushing a new branch')),
4060 ] + remoteopts,
4060 ] + remoteopts,
4061 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4061 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4062 def push(ui, repo, dest=None, **opts):
4062 def push(ui, repo, dest=None, **opts):
4063 """push changes to the specified destination
4063 """push changes to the specified destination
4064
4064
4065 Push changesets from the local repository to the specified
4065 Push changesets from the local repository to the specified
4066 destination.
4066 destination.
4067
4067
4068 This operation is symmetrical to pull: it is identical to a pull
4068 This operation is symmetrical to pull: it is identical to a pull
4069 in the destination repository from the current one.
4069 in the destination repository from the current one.
4070
4070
4071 By default, push will not allow creation of new heads at the
4071 By default, push will not allow creation of new heads at the
4072 destination, since multiple heads would make it unclear which head
4072 destination, since multiple heads would make it unclear which head
4073 to use. In this situation, it is recommended to pull and merge
4073 to use. In this situation, it is recommended to pull and merge
4074 before pushing.
4074 before pushing.
4075
4075
4076 Use --new-branch if you want to allow push to create a new named
4076 Use --new-branch if you want to allow push to create a new named
4077 branch that is not present at the destination. This allows you to
4077 branch that is not present at the destination. This allows you to
4078 only create a new branch without forcing other changes.
4078 only create a new branch without forcing other changes.
4079
4079
4080 .. note::
4080 .. note::
4081
4081
4082 Extra care should be taken with the -f/--force option,
4082 Extra care should be taken with the -f/--force option,
4083 which will push all new heads on all branches, an action which will
4083 which will push all new heads on all branches, an action which will
4084 almost always cause confusion for collaborators.
4084 almost always cause confusion for collaborators.
4085
4085
4086 If -r/--rev is used, the specified revision and all its ancestors
4086 If -r/--rev is used, the specified revision and all its ancestors
4087 will be pushed to the remote repository.
4087 will be pushed to the remote repository.
4088
4088
4089 If -B/--bookmark is used, the specified bookmarked revision, its
4089 If -B/--bookmark is used, the specified bookmarked revision, its
4090 ancestors, and the bookmark will be pushed to the remote
4090 ancestors, and the bookmark will be pushed to the remote
4091 repository. Specifying ``.`` is equivalent to specifying the active
4091 repository. Specifying ``.`` is equivalent to specifying the active
4092 bookmark's name.
4092 bookmark's name.
4093
4093
4094 Please see :hg:`help urls` for important details about ``ssh://``
4094 Please see :hg:`help urls` for important details about ``ssh://``
4095 URLs. If DESTINATION is omitted, a default path will be used.
4095 URLs. If DESTINATION is omitted, a default path will be used.
4096
4096
4097 Returns 0 if push was successful, 1 if nothing to push.
4097 Returns 0 if push was successful, 1 if nothing to push.
4098 """
4098 """
4099
4099
4100 opts = pycompat.byteskwargs(opts)
4100 opts = pycompat.byteskwargs(opts)
4101 if opts.get('bookmark'):
4101 if opts.get('bookmark'):
4102 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
4102 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
4103 for b in opts['bookmark']:
4103 for b in opts['bookmark']:
4104 # translate -B options to -r so changesets get pushed
4104 # translate -B options to -r so changesets get pushed
4105 b = repo._bookmarks.expandname(b)
4105 b = repo._bookmarks.expandname(b)
4106 if b in repo._bookmarks:
4106 if b in repo._bookmarks:
4107 opts.setdefault('rev', []).append(b)
4107 opts.setdefault('rev', []).append(b)
4108 else:
4108 else:
4109 # if we try to push a deleted bookmark, translate it to null
4109 # if we try to push a deleted bookmark, translate it to null
4110 # this lets simultaneous -r, -b options continue working
4110 # this lets simultaneous -r, -b options continue working
4111 opts.setdefault('rev', []).append("null")
4111 opts.setdefault('rev', []).append("null")
4112
4112
4113 path = ui.paths.getpath(dest, default=('default-push', 'default'))
4113 path = ui.paths.getpath(dest, default=('default-push', 'default'))
4114 if not path:
4114 if not path:
4115 raise error.Abort(_('default repository not configured!'),
4115 raise error.Abort(_('default repository not configured!'),
4116 hint=_("see 'hg help config.paths'"))
4116 hint=_("see 'hg help config.paths'"))
4117 dest = path.pushloc or path.loc
4117 dest = path.pushloc or path.loc
4118 branches = (path.branch, opts.get('branch') or [])
4118 branches = (path.branch, opts.get('branch') or [])
4119 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4119 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4120 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4120 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4121 other = hg.peer(repo, opts, dest)
4121 other = hg.peer(repo, opts, dest)
4122
4122
4123 if revs:
4123 if revs:
4124 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4124 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4125 if not revs:
4125 if not revs:
4126 raise error.Abort(_("specified revisions evaluate to an empty set"),
4126 raise error.Abort(_("specified revisions evaluate to an empty set"),
4127 hint=_("use different revision arguments"))
4127 hint=_("use different revision arguments"))
4128 elif path.pushrev:
4128 elif path.pushrev:
4129 # It doesn't make any sense to specify ancestor revisions. So limit
4129 # It doesn't make any sense to specify ancestor revisions. So limit
4130 # to DAG heads to make discovery simpler.
4130 # to DAG heads to make discovery simpler.
4131 expr = revsetlang.formatspec('heads(%r)', path.pushrev)
4131 expr = revsetlang.formatspec('heads(%r)', path.pushrev)
4132 revs = scmutil.revrange(repo, [expr])
4132 revs = scmutil.revrange(repo, [expr])
4133 revs = [repo[rev].node() for rev in revs]
4133 revs = [repo[rev].node() for rev in revs]
4134 if not revs:
4134 if not revs:
4135 raise error.Abort(_('default push revset for path evaluates to an '
4135 raise error.Abort(_('default push revset for path evaluates to an '
4136 'empty set'))
4136 'empty set'))
4137
4137
4138 repo._subtoppath = dest
4138 repo._subtoppath = dest
4139 try:
4139 try:
4140 # push subrepos depth-first for coherent ordering
4140 # push subrepos depth-first for coherent ordering
4141 c = repo['']
4141 c = repo['']
4142 subs = c.substate # only repos that are committed
4142 subs = c.substate # only repos that are committed
4143 for s in sorted(subs):
4143 for s in sorted(subs):
4144 result = c.sub(s).push(opts)
4144 result = c.sub(s).push(opts)
4145 if result == 0:
4145 if result == 0:
4146 return not result
4146 return not result
4147 finally:
4147 finally:
4148 del repo._subtoppath
4148 del repo._subtoppath
4149 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
4149 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
4150 newbranch=opts.get('new_branch'),
4150 newbranch=opts.get('new_branch'),
4151 bookmarks=opts.get('bookmark', ()),
4151 bookmarks=opts.get('bookmark', ()),
4152 opargs=opts.get('opargs'))
4152 opargs=opts.get('opargs'))
4153
4153
4154 result = not pushop.cgresult
4154 result = not pushop.cgresult
4155
4155
4156 if pushop.bkresult is not None:
4156 if pushop.bkresult is not None:
4157 if pushop.bkresult == 2:
4157 if pushop.bkresult == 2:
4158 result = 2
4158 result = 2
4159 elif not result and pushop.bkresult:
4159 elif not result and pushop.bkresult:
4160 result = 2
4160 result = 2
4161
4161
4162 return result
4162 return result
4163
4163
4164 @command('recover', [])
4164 @command('recover', [])
4165 def recover(ui, repo):
4165 def recover(ui, repo):
4166 """roll back an interrupted transaction
4166 """roll back an interrupted transaction
4167
4167
4168 Recover from an interrupted commit or pull.
4168 Recover from an interrupted commit or pull.
4169
4169
4170 This command tries to fix the repository status after an
4170 This command tries to fix the repository status after an
4171 interrupted operation. It should only be necessary when Mercurial
4171 interrupted operation. It should only be necessary when Mercurial
4172 suggests it.
4172 suggests it.
4173
4173
4174 Returns 0 if successful, 1 if nothing to recover or verify fails.
4174 Returns 0 if successful, 1 if nothing to recover or verify fails.
4175 """
4175 """
4176 if repo.recover():
4176 if repo.recover():
4177 return hg.verify(repo)
4177 return hg.verify(repo)
4178 return 1
4178 return 1
4179
4179
4180 @command('^remove|rm',
4180 @command('^remove|rm',
4181 [('A', 'after', None, _('record delete for missing files')),
4181 [('A', 'after', None, _('record delete for missing files')),
4182 ('f', 'force', None,
4182 ('f', 'force', None,
4183 _('forget added files, delete modified files')),
4183 _('forget added files, delete modified files')),
4184 ] + subrepoopts + walkopts,
4184 ] + subrepoopts + walkopts,
4185 _('[OPTION]... FILE...'),
4185 _('[OPTION]... FILE...'),
4186 inferrepo=True)
4186 inferrepo=True)
4187 def remove(ui, repo, *pats, **opts):
4187 def remove(ui, repo, *pats, **opts):
4188 """remove the specified files on the next commit
4188 """remove the specified files on the next commit
4189
4189
4190 Schedule the indicated files for removal from the current branch.
4190 Schedule the indicated files for removal from the current branch.
4191
4191
4192 This command schedules the files to be removed at the next commit.
4192 This command schedules the files to be removed at the next commit.
4193 To undo a remove before that, see :hg:`revert`. To undo added
4193 To undo a remove before that, see :hg:`revert`. To undo added
4194 files, see :hg:`forget`.
4194 files, see :hg:`forget`.
4195
4195
4196 .. container:: verbose
4196 .. container:: verbose
4197
4197
4198 -A/--after can be used to remove only files that have already
4198 -A/--after can be used to remove only files that have already
4199 been deleted, -f/--force can be used to force deletion, and -Af
4199 been deleted, -f/--force can be used to force deletion, and -Af
4200 can be used to remove files from the next revision without
4200 can be used to remove files from the next revision without
4201 deleting them from the working directory.
4201 deleting them from the working directory.
4202
4202
4203 The following table details the behavior of remove for different
4203 The following table details the behavior of remove for different
4204 file states (columns) and option combinations (rows). The file
4204 file states (columns) and option combinations (rows). The file
4205 states are Added [A], Clean [C], Modified [M] and Missing [!]
4205 states are Added [A], Clean [C], Modified [M] and Missing [!]
4206 (as reported by :hg:`status`). The actions are Warn, Remove
4206 (as reported by :hg:`status`). The actions are Warn, Remove
4207 (from branch) and Delete (from disk):
4207 (from branch) and Delete (from disk):
4208
4208
4209 ========= == == == ==
4209 ========= == == == ==
4210 opt/state A C M !
4210 opt/state A C M !
4211 ========= == == == ==
4211 ========= == == == ==
4212 none W RD W R
4212 none W RD W R
4213 -f R RD RD R
4213 -f R RD RD R
4214 -A W W W R
4214 -A W W W R
4215 -Af R R R R
4215 -Af R R R R
4216 ========= == == == ==
4216 ========= == == == ==
4217
4217
4218 .. note::
4218 .. note::
4219
4219
4220 :hg:`remove` never deletes files in Added [A] state from the
4220 :hg:`remove` never deletes files in Added [A] state from the
4221 working directory, not even if ``--force`` is specified.
4221 working directory, not even if ``--force`` is specified.
4222
4222
4223 Returns 0 on success, 1 if any warnings encountered.
4223 Returns 0 on success, 1 if any warnings encountered.
4224 """
4224 """
4225
4225
4226 opts = pycompat.byteskwargs(opts)
4226 opts = pycompat.byteskwargs(opts)
4227 after, force = opts.get('after'), opts.get('force')
4227 after, force = opts.get('after'), opts.get('force')
4228 if not pats and not after:
4228 if not pats and not after:
4229 raise error.Abort(_('no files specified'))
4229 raise error.Abort(_('no files specified'))
4230
4230
4231 m = scmutil.match(repo[None], pats, opts)
4231 m = scmutil.match(repo[None], pats, opts)
4232 subrepos = opts.get('subrepos')
4232 subrepos = opts.get('subrepos')
4233 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
4233 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
4234
4234
4235 @command('rename|move|mv',
4235 @command('rename|move|mv',
4236 [('A', 'after', None, _('record a rename that has already occurred')),
4236 [('A', 'after', None, _('record a rename that has already occurred')),
4237 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4237 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4238 ] + walkopts + dryrunopts,
4238 ] + walkopts + dryrunopts,
4239 _('[OPTION]... SOURCE... DEST'))
4239 _('[OPTION]... SOURCE... DEST'))
4240 def rename(ui, repo, *pats, **opts):
4240 def rename(ui, repo, *pats, **opts):
4241 """rename files; equivalent of copy + remove
4241 """rename files; equivalent of copy + remove
4242
4242
4243 Mark dest as copies of sources; mark sources for deletion. If dest
4243 Mark dest as copies of sources; mark sources for deletion. If dest
4244 is a directory, copies are put in that directory. If dest is a
4244 is a directory, copies are put in that directory. If dest is a
4245 file, there can only be one source.
4245 file, there can only be one source.
4246
4246
4247 By default, this command copies the contents of files as they
4247 By default, this command copies the contents of files as they
4248 exist in the working directory. If invoked with -A/--after, the
4248 exist in the working directory. If invoked with -A/--after, the
4249 operation is recorded, but no copying is performed.
4249 operation is recorded, but no copying is performed.
4250
4250
4251 This command takes effect at the next commit. To undo a rename
4251 This command takes effect at the next commit. To undo a rename
4252 before that, see :hg:`revert`.
4252 before that, see :hg:`revert`.
4253
4253
4254 Returns 0 on success, 1 if errors are encountered.
4254 Returns 0 on success, 1 if errors are encountered.
4255 """
4255 """
4256 opts = pycompat.byteskwargs(opts)
4256 opts = pycompat.byteskwargs(opts)
4257 with repo.wlock(False):
4257 with repo.wlock(False):
4258 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4258 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4259
4259
4260 @command('resolve',
4260 @command('resolve',
4261 [('a', 'all', None, _('select all unresolved files')),
4261 [('a', 'all', None, _('select all unresolved files')),
4262 ('l', 'list', None, _('list state of files needing merge')),
4262 ('l', 'list', None, _('list state of files needing merge')),
4263 ('m', 'mark', None, _('mark files as resolved')),
4263 ('m', 'mark', None, _('mark files as resolved')),
4264 ('u', 'unmark', None, _('mark files as unresolved')),
4264 ('u', 'unmark', None, _('mark files as unresolved')),
4265 ('n', 'no-status', None, _('hide status prefix'))]
4265 ('n', 'no-status', None, _('hide status prefix'))]
4266 + mergetoolopts + walkopts + formatteropts,
4266 + mergetoolopts + walkopts + formatteropts,
4267 _('[OPTION]... [FILE]...'),
4267 _('[OPTION]... [FILE]...'),
4268 inferrepo=True)
4268 inferrepo=True)
4269 def resolve(ui, repo, *pats, **opts):
4269 def resolve(ui, repo, *pats, **opts):
4270 """redo merges or set/view the merge status of files
4270 """redo merges or set/view the merge status of files
4271
4271
4272 Merges with unresolved conflicts are often the result of
4272 Merges with unresolved conflicts are often the result of
4273 non-interactive merging using the ``internal:merge`` configuration
4273 non-interactive merging using the ``internal:merge`` configuration
4274 setting, or a command-line merge tool like ``diff3``. The resolve
4274 setting, or a command-line merge tool like ``diff3``. The resolve
4275 command is used to manage the files involved in a merge, after
4275 command is used to manage the files involved in a merge, after
4276 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4276 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4277 working directory must have two parents). See :hg:`help
4277 working directory must have two parents). See :hg:`help
4278 merge-tools` for information on configuring merge tools.
4278 merge-tools` for information on configuring merge tools.
4279
4279
4280 The resolve command can be used in the following ways:
4280 The resolve command can be used in the following ways:
4281
4281
4282 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4282 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4283 files, discarding any previous merge attempts. Re-merging is not
4283 files, discarding any previous merge attempts. Re-merging is not
4284 performed for files already marked as resolved. Use ``--all/-a``
4284 performed for files already marked as resolved. Use ``--all/-a``
4285 to select all unresolved files. ``--tool`` can be used to specify
4285 to select all unresolved files. ``--tool`` can be used to specify
4286 the merge tool used for the given files. It overrides the HGMERGE
4286 the merge tool used for the given files. It overrides the HGMERGE
4287 environment variable and your configuration files. Previous file
4287 environment variable and your configuration files. Previous file
4288 contents are saved with a ``.orig`` suffix.
4288 contents are saved with a ``.orig`` suffix.
4289
4289
4290 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4290 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4291 (e.g. after having manually fixed-up the files). The default is
4291 (e.g. after having manually fixed-up the files). The default is
4292 to mark all unresolved files.
4292 to mark all unresolved files.
4293
4293
4294 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4294 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4295 default is to mark all resolved files.
4295 default is to mark all resolved files.
4296
4296
4297 - :hg:`resolve -l`: list files which had or still have conflicts.
4297 - :hg:`resolve -l`: list files which had or still have conflicts.
4298 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4298 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4299 You can use ``set:unresolved()`` or ``set:resolved()`` to filter
4299 You can use ``set:unresolved()`` or ``set:resolved()`` to filter
4300 the list. See :hg:`help filesets` for details.
4300 the list. See :hg:`help filesets` for details.
4301
4301
4302 .. note::
4302 .. note::
4303
4303
4304 Mercurial will not let you commit files with unresolved merge
4304 Mercurial will not let you commit files with unresolved merge
4305 conflicts. You must use :hg:`resolve -m ...` before you can
4305 conflicts. You must use :hg:`resolve -m ...` before you can
4306 commit after a conflicting merge.
4306 commit after a conflicting merge.
4307
4307
4308 Returns 0 on success, 1 if any files fail a resolve attempt.
4308 Returns 0 on success, 1 if any files fail a resolve attempt.
4309 """
4309 """
4310
4310
4311 opts = pycompat.byteskwargs(opts)
4311 opts = pycompat.byteskwargs(opts)
4312 flaglist = 'all mark unmark list no_status'.split()
4312 flaglist = 'all mark unmark list no_status'.split()
4313 all, mark, unmark, show, nostatus = \
4313 all, mark, unmark, show, nostatus = \
4314 [opts.get(o) for o in flaglist]
4314 [opts.get(o) for o in flaglist]
4315
4315
4316 if (show and (mark or unmark)) or (mark and unmark):
4316 if (show and (mark or unmark)) or (mark and unmark):
4317 raise error.Abort(_("too many options specified"))
4317 raise error.Abort(_("too many options specified"))
4318 if pats and all:
4318 if pats and all:
4319 raise error.Abort(_("can't specify --all and patterns"))
4319 raise error.Abort(_("can't specify --all and patterns"))
4320 if not (all or pats or show or mark or unmark):
4320 if not (all or pats or show or mark or unmark):
4321 raise error.Abort(_('no files or directories specified'),
4321 raise error.Abort(_('no files or directories specified'),
4322 hint=('use --all to re-merge all unresolved files'))
4322 hint=('use --all to re-merge all unresolved files'))
4323
4323
4324 if show:
4324 if show:
4325 ui.pager('resolve')
4325 ui.pager('resolve')
4326 fm = ui.formatter('resolve', opts)
4326 fm = ui.formatter('resolve', opts)
4327 ms = mergemod.mergestate.read(repo)
4327 ms = mergemod.mergestate.read(repo)
4328 m = scmutil.match(repo[None], pats, opts)
4328 m = scmutil.match(repo[None], pats, opts)
4329 for f in ms:
4329 for f in ms:
4330 if not m(f):
4330 if not m(f):
4331 continue
4331 continue
4332 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
4332 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
4333 'd': 'driverresolved'}[ms[f]]
4333 'd': 'driverresolved'}[ms[f]]
4334 fm.startitem()
4334 fm.startitem()
4335 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
4335 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
4336 fm.write('path', '%s\n', f, label=l)
4336 fm.write('path', '%s\n', f, label=l)
4337 fm.end()
4337 fm.end()
4338 return 0
4338 return 0
4339
4339
4340 with repo.wlock():
4340 with repo.wlock():
4341 ms = mergemod.mergestate.read(repo)
4341 ms = mergemod.mergestate.read(repo)
4342
4342
4343 if not (ms.active() or repo.dirstate.p2() != nullid):
4343 if not (ms.active() or repo.dirstate.p2() != nullid):
4344 raise error.Abort(
4344 raise error.Abort(
4345 _('resolve command not applicable when not merging'))
4345 _('resolve command not applicable when not merging'))
4346
4346
4347 wctx = repo[None]
4347 wctx = repo[None]
4348
4348
4349 if ms.mergedriver and ms.mdstate() == 'u':
4349 if ms.mergedriver and ms.mdstate() == 'u':
4350 proceed = mergemod.driverpreprocess(repo, ms, wctx)
4350 proceed = mergemod.driverpreprocess(repo, ms, wctx)
4351 ms.commit()
4351 ms.commit()
4352 # allow mark and unmark to go through
4352 # allow mark and unmark to go through
4353 if not mark and not unmark and not proceed:
4353 if not mark and not unmark and not proceed:
4354 return 1
4354 return 1
4355
4355
4356 m = scmutil.match(wctx, pats, opts)
4356 m = scmutil.match(wctx, pats, opts)
4357 ret = 0
4357 ret = 0
4358 didwork = False
4358 didwork = False
4359 runconclude = False
4359 runconclude = False
4360
4360
4361 tocomplete = []
4361 tocomplete = []
4362 for f in ms:
4362 for f in ms:
4363 if not m(f):
4363 if not m(f):
4364 continue
4364 continue
4365
4365
4366 didwork = True
4366 didwork = True
4367
4367
4368 # don't let driver-resolved files be marked, and run the conclude
4368 # don't let driver-resolved files be marked, and run the conclude
4369 # step if asked to resolve
4369 # step if asked to resolve
4370 if ms[f] == "d":
4370 if ms[f] == "d":
4371 exact = m.exact(f)
4371 exact = m.exact(f)
4372 if mark:
4372 if mark:
4373 if exact:
4373 if exact:
4374 ui.warn(_('not marking %s as it is driver-resolved\n')
4374 ui.warn(_('not marking %s as it is driver-resolved\n')
4375 % f)
4375 % f)
4376 elif unmark:
4376 elif unmark:
4377 if exact:
4377 if exact:
4378 ui.warn(_('not unmarking %s as it is driver-resolved\n')
4378 ui.warn(_('not unmarking %s as it is driver-resolved\n')
4379 % f)
4379 % f)
4380 else:
4380 else:
4381 runconclude = True
4381 runconclude = True
4382 continue
4382 continue
4383
4383
4384 if mark:
4384 if mark:
4385 ms.mark(f, "r")
4385 ms.mark(f, "r")
4386 elif unmark:
4386 elif unmark:
4387 ms.mark(f, "u")
4387 ms.mark(f, "u")
4388 else:
4388 else:
4389 # backup pre-resolve (merge uses .orig for its own purposes)
4389 # backup pre-resolve (merge uses .orig for its own purposes)
4390 a = repo.wjoin(f)
4390 a = repo.wjoin(f)
4391 try:
4391 try:
4392 util.copyfile(a, a + ".resolve")
4392 util.copyfile(a, a + ".resolve")
4393 except (IOError, OSError) as inst:
4393 except (IOError, OSError) as inst:
4394 if inst.errno != errno.ENOENT:
4394 if inst.errno != errno.ENOENT:
4395 raise
4395 raise
4396
4396
4397 try:
4397 try:
4398 # preresolve file
4398 # preresolve file
4399 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4399 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4400 'resolve')
4400 'resolve')
4401 complete, r = ms.preresolve(f, wctx)
4401 complete, r = ms.preresolve(f, wctx)
4402 if not complete:
4402 if not complete:
4403 tocomplete.append(f)
4403 tocomplete.append(f)
4404 elif r:
4404 elif r:
4405 ret = 1
4405 ret = 1
4406 finally:
4406 finally:
4407 ui.setconfig('ui', 'forcemerge', '', 'resolve')
4407 ui.setconfig('ui', 'forcemerge', '', 'resolve')
4408 ms.commit()
4408 ms.commit()
4409
4409
4410 # replace filemerge's .orig file with our resolve file, but only
4410 # replace filemerge's .orig file with our resolve file, but only
4411 # for merges that are complete
4411 # for merges that are complete
4412 if complete:
4412 if complete:
4413 try:
4413 try:
4414 util.rename(a + ".resolve",
4414 util.rename(a + ".resolve",
4415 scmutil.origpath(ui, repo, a))
4415 scmutil.origpath(ui, repo, a))
4416 except OSError as inst:
4416 except OSError as inst:
4417 if inst.errno != errno.ENOENT:
4417 if inst.errno != errno.ENOENT:
4418 raise
4418 raise
4419
4419
4420 for f in tocomplete:
4420 for f in tocomplete:
4421 try:
4421 try:
4422 # resolve file
4422 # resolve file
4423 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4423 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4424 'resolve')
4424 'resolve')
4425 r = ms.resolve(f, wctx)
4425 r = ms.resolve(f, wctx)
4426 if r:
4426 if r:
4427 ret = 1
4427 ret = 1
4428 finally:
4428 finally:
4429 ui.setconfig('ui', 'forcemerge', '', 'resolve')
4429 ui.setconfig('ui', 'forcemerge', '', 'resolve')
4430 ms.commit()
4430 ms.commit()
4431
4431
4432 # replace filemerge's .orig file with our resolve file
4432 # replace filemerge's .orig file with our resolve file
4433 a = repo.wjoin(f)
4433 a = repo.wjoin(f)
4434 try:
4434 try:
4435 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
4435 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
4436 except OSError as inst:
4436 except OSError as inst:
4437 if inst.errno != errno.ENOENT:
4437 if inst.errno != errno.ENOENT:
4438 raise
4438 raise
4439
4439
4440 ms.commit()
4440 ms.commit()
4441 ms.recordactions()
4441 ms.recordactions()
4442
4442
4443 if not didwork and pats:
4443 if not didwork and pats:
4444 hint = None
4444 hint = None
4445 if not any([p for p in pats if p.find(':') >= 0]):
4445 if not any([p for p in pats if p.find(':') >= 0]):
4446 pats = ['path:%s' % p for p in pats]
4446 pats = ['path:%s' % p for p in pats]
4447 m = scmutil.match(wctx, pats, opts)
4447 m = scmutil.match(wctx, pats, opts)
4448 for f in ms:
4448 for f in ms:
4449 if not m(f):
4449 if not m(f):
4450 continue
4450 continue
4451 flags = ''.join(['-%s ' % o[0] for o in flaglist
4451 flags = ''.join(['-%s ' % o[0] for o in flaglist
4452 if opts.get(o)])
4452 if opts.get(o)])
4453 hint = _("(try: hg resolve %s%s)\n") % (
4453 hint = _("(try: hg resolve %s%s)\n") % (
4454 flags,
4454 flags,
4455 ' '.join(pats))
4455 ' '.join(pats))
4456 break
4456 break
4457 ui.warn(_("arguments do not match paths that need resolving\n"))
4457 ui.warn(_("arguments do not match paths that need resolving\n"))
4458 if hint:
4458 if hint:
4459 ui.warn(hint)
4459 ui.warn(hint)
4460 elif ms.mergedriver and ms.mdstate() != 's':
4460 elif ms.mergedriver and ms.mdstate() != 's':
4461 # run conclude step when either a driver-resolved file is requested
4461 # run conclude step when either a driver-resolved file is requested
4462 # or there are no driver-resolved files
4462 # or there are no driver-resolved files
4463 # we can't use 'ret' to determine whether any files are unresolved
4463 # we can't use 'ret' to determine whether any files are unresolved
4464 # because we might not have tried to resolve some
4464 # because we might not have tried to resolve some
4465 if ((runconclude or not list(ms.driverresolved()))
4465 if ((runconclude or not list(ms.driverresolved()))
4466 and not list(ms.unresolved())):
4466 and not list(ms.unresolved())):
4467 proceed = mergemod.driverconclude(repo, ms, wctx)
4467 proceed = mergemod.driverconclude(repo, ms, wctx)
4468 ms.commit()
4468 ms.commit()
4469 if not proceed:
4469 if not proceed:
4470 return 1
4470 return 1
4471
4471
4472 # Nudge users into finishing an unfinished operation
4472 # Nudge users into finishing an unfinished operation
4473 unresolvedf = list(ms.unresolved())
4473 unresolvedf = list(ms.unresolved())
4474 driverresolvedf = list(ms.driverresolved())
4474 driverresolvedf = list(ms.driverresolved())
4475 if not unresolvedf and not driverresolvedf:
4475 if not unresolvedf and not driverresolvedf:
4476 ui.status(_('(no more unresolved files)\n'))
4476 ui.status(_('(no more unresolved files)\n'))
4477 cmdutil.checkafterresolved(repo)
4477 cmdutil.checkafterresolved(repo)
4478 elif not unresolvedf:
4478 elif not unresolvedf:
4479 ui.status(_('(no more unresolved files -- '
4479 ui.status(_('(no more unresolved files -- '
4480 'run "hg resolve --all" to conclude)\n'))
4480 'run "hg resolve --all" to conclude)\n'))
4481
4481
4482 return ret
4482 return ret
4483
4483
4484 @command('revert',
4484 @command('revert',
4485 [('a', 'all', None, _('revert all changes when no arguments given')),
4485 [('a', 'all', None, _('revert all changes when no arguments given')),
4486 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4486 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4487 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4487 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4488 ('C', 'no-backup', None, _('do not save backup copies of files')),
4488 ('C', 'no-backup', None, _('do not save backup copies of files')),
4489 ('i', 'interactive', None,
4489 ('i', 'interactive', None,
4490 _('interactively select the changes (EXPERIMENTAL)')),
4490 _('interactively select the changes (EXPERIMENTAL)')),
4491 ] + walkopts + dryrunopts,
4491 ] + walkopts + dryrunopts,
4492 _('[OPTION]... [-r REV] [NAME]...'))
4492 _('[OPTION]... [-r REV] [NAME]...'))
4493 def revert(ui, repo, *pats, **opts):
4493 def revert(ui, repo, *pats, **opts):
4494 """restore files to their checkout state
4494 """restore files to their checkout state
4495
4495
4496 .. note::
4496 .. note::
4497
4497
4498 To check out earlier revisions, you should use :hg:`update REV`.
4498 To check out earlier revisions, you should use :hg:`update REV`.
4499 To cancel an uncommitted merge (and lose your changes),
4499 To cancel an uncommitted merge (and lose your changes),
4500 use :hg:`update --clean .`.
4500 use :hg:`update --clean .`.
4501
4501
4502 With no revision specified, revert the specified files or directories
4502 With no revision specified, revert the specified files or directories
4503 to the contents they had in the parent of the working directory.
4503 to the contents they had in the parent of the working directory.
4504 This restores the contents of files to an unmodified
4504 This restores the contents of files to an unmodified
4505 state and unschedules adds, removes, copies, and renames. If the
4505 state and unschedules adds, removes, copies, and renames. If the
4506 working directory has two parents, you must explicitly specify a
4506 working directory has two parents, you must explicitly specify a
4507 revision.
4507 revision.
4508
4508
4509 Using the -r/--rev or -d/--date options, revert the given files or
4509 Using the -r/--rev or -d/--date options, revert the given files or
4510 directories to their states as of a specific revision. Because
4510 directories to their states as of a specific revision. Because
4511 revert does not change the working directory parents, this will
4511 revert does not change the working directory parents, this will
4512 cause these files to appear modified. This can be helpful to "back
4512 cause these files to appear modified. This can be helpful to "back
4513 out" some or all of an earlier change. See :hg:`backout` for a
4513 out" some or all of an earlier change. See :hg:`backout` for a
4514 related method.
4514 related method.
4515
4515
4516 Modified files are saved with a .orig suffix before reverting.
4516 Modified files are saved with a .orig suffix before reverting.
4517 To disable these backups, use --no-backup. It is possible to store
4517 To disable these backups, use --no-backup. It is possible to store
4518 the backup files in a custom directory relative to the root of the
4518 the backup files in a custom directory relative to the root of the
4519 repository by setting the ``ui.origbackuppath`` configuration
4519 repository by setting the ``ui.origbackuppath`` configuration
4520 option.
4520 option.
4521
4521
4522 See :hg:`help dates` for a list of formats valid for -d/--date.
4522 See :hg:`help dates` for a list of formats valid for -d/--date.
4523
4523
4524 See :hg:`help backout` for a way to reverse the effect of an
4524 See :hg:`help backout` for a way to reverse the effect of an
4525 earlier changeset.
4525 earlier changeset.
4526
4526
4527 Returns 0 on success.
4527 Returns 0 on success.
4528 """
4528 """
4529
4529
4530 if opts.get("date"):
4530 if opts.get("date"):
4531 if opts.get("rev"):
4531 if opts.get("rev"):
4532 raise error.Abort(_("you can't specify a revision and a date"))
4532 raise error.Abort(_("you can't specify a revision and a date"))
4533 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4533 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4534
4534
4535 parent, p2 = repo.dirstate.parents()
4535 parent, p2 = repo.dirstate.parents()
4536 if not opts.get('rev') and p2 != nullid:
4536 if not opts.get('rev') and p2 != nullid:
4537 # revert after merge is a trap for new users (issue2915)
4537 # revert after merge is a trap for new users (issue2915)
4538 raise error.Abort(_('uncommitted merge with no revision specified'),
4538 raise error.Abort(_('uncommitted merge with no revision specified'),
4539 hint=_("use 'hg update' or see 'hg help revert'"))
4539 hint=_("use 'hg update' or see 'hg help revert'"))
4540
4540
4541 ctx = scmutil.revsingle(repo, opts.get('rev'))
4541 ctx = scmutil.revsingle(repo, opts.get('rev'))
4542
4542
4543 if (not (pats or opts.get('include') or opts.get('exclude') or
4543 if (not (pats or opts.get('include') or opts.get('exclude') or
4544 opts.get('all') or opts.get('interactive'))):
4544 opts.get('all') or opts.get('interactive'))):
4545 msg = _("no files or directories specified")
4545 msg = _("no files or directories specified")
4546 if p2 != nullid:
4546 if p2 != nullid:
4547 hint = _("uncommitted merge, use --all to discard all changes,"
4547 hint = _("uncommitted merge, use --all to discard all changes,"
4548 " or 'hg update -C .' to abort the merge")
4548 " or 'hg update -C .' to abort the merge")
4549 raise error.Abort(msg, hint=hint)
4549 raise error.Abort(msg, hint=hint)
4550 dirty = any(repo.status())
4550 dirty = any(repo.status())
4551 node = ctx.node()
4551 node = ctx.node()
4552 if node != parent:
4552 if node != parent:
4553 if dirty:
4553 if dirty:
4554 hint = _("uncommitted changes, use --all to discard all"
4554 hint = _("uncommitted changes, use --all to discard all"
4555 " changes, or 'hg update %s' to update") % ctx.rev()
4555 " changes, or 'hg update %s' to update") % ctx.rev()
4556 else:
4556 else:
4557 hint = _("use --all to revert all files,"
4557 hint = _("use --all to revert all files,"
4558 " or 'hg update %s' to update") % ctx.rev()
4558 " or 'hg update %s' to update") % ctx.rev()
4559 elif dirty:
4559 elif dirty:
4560 hint = _("uncommitted changes, use --all to discard all changes")
4560 hint = _("uncommitted changes, use --all to discard all changes")
4561 else:
4561 else:
4562 hint = _("use --all to revert all files")
4562 hint = _("use --all to revert all files")
4563 raise error.Abort(msg, hint=hint)
4563 raise error.Abort(msg, hint=hint)
4564
4564
4565 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
4565 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
4566
4566
4567 @command('rollback', dryrunopts +
4567 @command('rollback', dryrunopts +
4568 [('f', 'force', False, _('ignore safety measures'))])
4568 [('f', 'force', False, _('ignore safety measures'))])
4569 def rollback(ui, repo, **opts):
4569 def rollback(ui, repo, **opts):
4570 """roll back the last transaction (DANGEROUS) (DEPRECATED)
4570 """roll back the last transaction (DANGEROUS) (DEPRECATED)
4571
4571
4572 Please use :hg:`commit --amend` instead of rollback to correct
4572 Please use :hg:`commit --amend` instead of rollback to correct
4573 mistakes in the last commit.
4573 mistakes in the last commit.
4574
4574
4575 This command should be used with care. There is only one level of
4575 This command should be used with care. There is only one level of
4576 rollback, and there is no way to undo a rollback. It will also
4576 rollback, and there is no way to undo a rollback. It will also
4577 restore the dirstate at the time of the last transaction, losing
4577 restore the dirstate at the time of the last transaction, losing
4578 any dirstate changes since that time. This command does not alter
4578 any dirstate changes since that time. This command does not alter
4579 the working directory.
4579 the working directory.
4580
4580
4581 Transactions are used to encapsulate the effects of all commands
4581 Transactions are used to encapsulate the effects of all commands
4582 that create new changesets or propagate existing changesets into a
4582 that create new changesets or propagate existing changesets into a
4583 repository.
4583 repository.
4584
4584
4585 .. container:: verbose
4585 .. container:: verbose
4586
4586
4587 For example, the following commands are transactional, and their
4587 For example, the following commands are transactional, and their
4588 effects can be rolled back:
4588 effects can be rolled back:
4589
4589
4590 - commit
4590 - commit
4591 - import
4591 - import
4592 - pull
4592 - pull
4593 - push (with this repository as the destination)
4593 - push (with this repository as the destination)
4594 - unbundle
4594 - unbundle
4595
4595
4596 To avoid permanent data loss, rollback will refuse to rollback a
4596 To avoid permanent data loss, rollback will refuse to rollback a
4597 commit transaction if it isn't checked out. Use --force to
4597 commit transaction if it isn't checked out. Use --force to
4598 override this protection.
4598 override this protection.
4599
4599
4600 The rollback command can be entirely disabled by setting the
4600 The rollback command can be entirely disabled by setting the
4601 ``ui.rollback`` configuration setting to false. If you're here
4601 ``ui.rollback`` configuration setting to false. If you're here
4602 because you want to use rollback and it's disabled, you can
4602 because you want to use rollback and it's disabled, you can
4603 re-enable the command by setting ``ui.rollback`` to true.
4603 re-enable the command by setting ``ui.rollback`` to true.
4604
4604
4605 This command is not intended for use on public repositories. Once
4605 This command is not intended for use on public repositories. Once
4606 changes are visible for pull by other users, rolling a transaction
4606 changes are visible for pull by other users, rolling a transaction
4607 back locally is ineffective (someone else may already have pulled
4607 back locally is ineffective (someone else may already have pulled
4608 the changes). Furthermore, a race is possible with readers of the
4608 the changes). Furthermore, a race is possible with readers of the
4609 repository; for example an in-progress pull from the repository
4609 repository; for example an in-progress pull from the repository
4610 may fail if a rollback is performed.
4610 may fail if a rollback is performed.
4611
4611
4612 Returns 0 on success, 1 if no rollback data is available.
4612 Returns 0 on success, 1 if no rollback data is available.
4613 """
4613 """
4614 if not ui.configbool('ui', 'rollback', True):
4614 if not ui.configbool('ui', 'rollback', True):
4615 raise error.Abort(_('rollback is disabled because it is unsafe'),
4615 raise error.Abort(_('rollback is disabled because it is unsafe'),
4616 hint=('see `hg help -v rollback` for information'))
4616 hint=('see `hg help -v rollback` for information'))
4617 return repo.rollback(dryrun=opts.get(r'dry_run'),
4617 return repo.rollback(dryrun=opts.get(r'dry_run'),
4618 force=opts.get(r'force'))
4618 force=opts.get(r'force'))
4619
4619
4620 @command('root', [])
4620 @command('root', [])
4621 def root(ui, repo):
4621 def root(ui, repo):
4622 """print the root (top) of the current working directory
4622 """print the root (top) of the current working directory
4623
4623
4624 Print the root directory of the current repository.
4624 Print the root directory of the current repository.
4625
4625
4626 Returns 0 on success.
4626 Returns 0 on success.
4627 """
4627 """
4628 ui.write(repo.root + "\n")
4628 ui.write(repo.root + "\n")
4629
4629
4630 @command('^serve',
4630 @command('^serve',
4631 [('A', 'accesslog', '', _('name of access log file to write to'),
4631 [('A', 'accesslog', '', _('name of access log file to write to'),
4632 _('FILE')),
4632 _('FILE')),
4633 ('d', 'daemon', None, _('run server in background')),
4633 ('d', 'daemon', None, _('run server in background')),
4634 ('', 'daemon-postexec', [], _('used internally by daemon mode')),
4634 ('', 'daemon-postexec', [], _('used internally by daemon mode')),
4635 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4635 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4636 # use string type, then we can check if something was passed
4636 # use string type, then we can check if something was passed
4637 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4637 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4638 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4638 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4639 _('ADDR')),
4639 _('ADDR')),
4640 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4640 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4641 _('PREFIX')),
4641 _('PREFIX')),
4642 ('n', 'name', '',
4642 ('n', 'name', '',
4643 _('name to show in web pages (default: working directory)'), _('NAME')),
4643 _('name to show in web pages (default: working directory)'), _('NAME')),
4644 ('', 'web-conf', '',
4644 ('', 'web-conf', '',
4645 _("name of the hgweb config file (see 'hg help hgweb')"), _('FILE')),
4645 _("name of the hgweb config file (see 'hg help hgweb')"), _('FILE')),
4646 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4646 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4647 _('FILE')),
4647 _('FILE')),
4648 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4648 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4649 ('', 'stdio', None, _('for remote clients (ADVANCED)')),
4649 ('', 'stdio', None, _('for remote clients (ADVANCED)')),
4650 ('', 'cmdserver', '', _('for remote clients (ADVANCED)'), _('MODE')),
4650 ('', 'cmdserver', '', _('for remote clients (ADVANCED)'), _('MODE')),
4651 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4651 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4652 ('', 'style', '', _('template style to use'), _('STYLE')),
4652 ('', 'style', '', _('template style to use'), _('STYLE')),
4653 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4653 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4654 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))]
4654 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))]
4655 + subrepoopts,
4655 + subrepoopts,
4656 _('[OPTION]...'),
4656 _('[OPTION]...'),
4657 optionalrepo=True)
4657 optionalrepo=True)
4658 def serve(ui, repo, **opts):
4658 def serve(ui, repo, **opts):
4659 """start stand-alone webserver
4659 """start stand-alone webserver
4660
4660
4661 Start a local HTTP repository browser and pull server. You can use
4661 Start a local HTTP repository browser and pull server. You can use
4662 this for ad-hoc sharing and browsing of repositories. It is
4662 this for ad-hoc sharing and browsing of repositories. It is
4663 recommended to use a real web server to serve a repository for
4663 recommended to use a real web server to serve a repository for
4664 longer periods of time.
4664 longer periods of time.
4665
4665
4666 Please note that the server does not implement access control.
4666 Please note that the server does not implement access control.
4667 This means that, by default, anybody can read from the server and
4667 This means that, by default, anybody can read from the server and
4668 nobody can write to it by default. Set the ``web.allow_push``
4668 nobody can write to it by default. Set the ``web.allow_push``
4669 option to ``*`` to allow everybody to push to the server. You
4669 option to ``*`` to allow everybody to push to the server. You
4670 should use a real web server if you need to authenticate users.
4670 should use a real web server if you need to authenticate users.
4671
4671
4672 By default, the server logs accesses to stdout and errors to
4672 By default, the server logs accesses to stdout and errors to
4673 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
4673 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
4674 files.
4674 files.
4675
4675
4676 To have the server choose a free port number to listen on, specify
4676 To have the server choose a free port number to listen on, specify
4677 a port number of 0; in this case, the server will print the port
4677 a port number of 0; in this case, the server will print the port
4678 number it uses.
4678 number it uses.
4679
4679
4680 Returns 0 on success.
4680 Returns 0 on success.
4681 """
4681 """
4682
4682
4683 opts = pycompat.byteskwargs(opts)
4683 opts = pycompat.byteskwargs(opts)
4684 if opts["stdio"] and opts["cmdserver"]:
4684 if opts["stdio"] and opts["cmdserver"]:
4685 raise error.Abort(_("cannot use --stdio with --cmdserver"))
4685 raise error.Abort(_("cannot use --stdio with --cmdserver"))
4686
4686
4687 if opts["stdio"]:
4687 if opts["stdio"]:
4688 if repo is None:
4688 if repo is None:
4689 raise error.RepoError(_("there is no Mercurial repository here"
4689 raise error.RepoError(_("there is no Mercurial repository here"
4690 " (.hg not found)"))
4690 " (.hg not found)"))
4691 s = sshserver.sshserver(ui, repo)
4691 s = sshserver.sshserver(ui, repo)
4692 s.serve_forever()
4692 s.serve_forever()
4693
4693
4694 service = server.createservice(ui, repo, opts)
4694 service = server.createservice(ui, repo, opts)
4695 return server.runservice(opts, initfn=service.init, runfn=service.run)
4695 return server.runservice(opts, initfn=service.init, runfn=service.run)
4696
4696
4697 @command('^status|st',
4697 @command('^status|st',
4698 [('A', 'all', None, _('show status of all files')),
4698 [('A', 'all', None, _('show status of all files')),
4699 ('m', 'modified', None, _('show only modified files')),
4699 ('m', 'modified', None, _('show only modified files')),
4700 ('a', 'added', None, _('show only added files')),
4700 ('a', 'added', None, _('show only added files')),
4701 ('r', 'removed', None, _('show only removed files')),
4701 ('r', 'removed', None, _('show only removed files')),
4702 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4702 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4703 ('c', 'clean', None, _('show only files without changes')),
4703 ('c', 'clean', None, _('show only files without changes')),
4704 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4704 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4705 ('i', 'ignored', None, _('show only ignored files')),
4705 ('i', 'ignored', None, _('show only ignored files')),
4706 ('n', 'no-status', None, _('hide status prefix')),
4706 ('n', 'no-status', None, _('hide status prefix')),
4707 ('C', 'copies', None, _('show source of copied files')),
4707 ('C', 'copies', None, _('show source of copied files')),
4708 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4708 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4709 ('', 'rev', [], _('show difference from revision'), _('REV')),
4709 ('', 'rev', [], _('show difference from revision'), _('REV')),
4710 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
4710 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
4711 ] + walkopts + subrepoopts + formatteropts,
4711 ] + walkopts + subrepoopts + formatteropts,
4712 _('[OPTION]... [FILE]...'),
4712 _('[OPTION]... [FILE]...'),
4713 inferrepo=True)
4713 inferrepo=True)
4714 def status(ui, repo, *pats, **opts):
4714 def status(ui, repo, *pats, **opts):
4715 """show changed files in the working directory
4715 """show changed files in the working directory
4716
4716
4717 Show status of files in the repository. If names are given, only
4717 Show status of files in the repository. If names are given, only
4718 files that match are shown. Files that are clean or ignored or
4718 files that match are shown. Files that are clean or ignored or
4719 the source of a copy/move operation, are not listed unless
4719 the source of a copy/move operation, are not listed unless
4720 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
4720 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
4721 Unless options described with "show only ..." are given, the
4721 Unless options described with "show only ..." are given, the
4722 options -mardu are used.
4722 options -mardu are used.
4723
4723
4724 Option -q/--quiet hides untracked (unknown and ignored) files
4724 Option -q/--quiet hides untracked (unknown and ignored) files
4725 unless explicitly requested with -u/--unknown or -i/--ignored.
4725 unless explicitly requested with -u/--unknown or -i/--ignored.
4726
4726
4727 .. note::
4727 .. note::
4728
4728
4729 :hg:`status` may appear to disagree with diff if permissions have
4729 :hg:`status` may appear to disagree with diff if permissions have
4730 changed or a merge has occurred. The standard diff format does
4730 changed or a merge has occurred. The standard diff format does
4731 not report permission changes and diff only reports changes
4731 not report permission changes and diff only reports changes
4732 relative to one merge parent.
4732 relative to one merge parent.
4733
4733
4734 If one revision is given, it is used as the base revision.
4734 If one revision is given, it is used as the base revision.
4735 If two revisions are given, the differences between them are
4735 If two revisions are given, the differences between them are
4736 shown. The --change option can also be used as a shortcut to list
4736 shown. The --change option can also be used as a shortcut to list
4737 the changed files of a revision from its first parent.
4737 the changed files of a revision from its first parent.
4738
4738
4739 The codes used to show the status of files are::
4739 The codes used to show the status of files are::
4740
4740
4741 M = modified
4741 M = modified
4742 A = added
4742 A = added
4743 R = removed
4743 R = removed
4744 C = clean
4744 C = clean
4745 ! = missing (deleted by non-hg command, but still tracked)
4745 ! = missing (deleted by non-hg command, but still tracked)
4746 ? = not tracked
4746 ? = not tracked
4747 I = ignored
4747 I = ignored
4748 = origin of the previous file (with --copies)
4748 = origin of the previous file (with --copies)
4749
4749
4750 .. container:: verbose
4750 .. container:: verbose
4751
4751
4752 Examples:
4752 Examples:
4753
4753
4754 - show changes in the working directory relative to a
4754 - show changes in the working directory relative to a
4755 changeset::
4755 changeset::
4756
4756
4757 hg status --rev 9353
4757 hg status --rev 9353
4758
4758
4759 - show changes in the working directory relative to the
4759 - show changes in the working directory relative to the
4760 current directory (see :hg:`help patterns` for more information)::
4760 current directory (see :hg:`help patterns` for more information)::
4761
4761
4762 hg status re:
4762 hg status re:
4763
4763
4764 - show all changes including copies in an existing changeset::
4764 - show all changes including copies in an existing changeset::
4765
4765
4766 hg status --copies --change 9353
4766 hg status --copies --change 9353
4767
4767
4768 - get a NUL separated list of added files, suitable for xargs::
4768 - get a NUL separated list of added files, suitable for xargs::
4769
4769
4770 hg status -an0
4770 hg status -an0
4771
4771
4772 Returns 0 on success.
4772 Returns 0 on success.
4773 """
4773 """
4774
4774
4775 opts = pycompat.byteskwargs(opts)
4775 opts = pycompat.byteskwargs(opts)
4776 revs = opts.get('rev')
4776 revs = opts.get('rev')
4777 change = opts.get('change')
4777 change = opts.get('change')
4778
4778
4779 if revs and change:
4779 if revs and change:
4780 msg = _('cannot specify --rev and --change at the same time')
4780 msg = _('cannot specify --rev and --change at the same time')
4781 raise error.Abort(msg)
4781 raise error.Abort(msg)
4782 elif change:
4782 elif change:
4783 node2 = scmutil.revsingle(repo, change, None).node()
4783 node2 = scmutil.revsingle(repo, change, None).node()
4784 node1 = repo[node2].p1().node()
4784 node1 = repo[node2].p1().node()
4785 else:
4785 else:
4786 node1, node2 = scmutil.revpair(repo, revs)
4786 node1, node2 = scmutil.revpair(repo, revs)
4787
4787
4788 if pats or ui.configbool('commands', 'status.relative'):
4788 if pats or ui.configbool('commands', 'status.relative'):
4789 cwd = repo.getcwd()
4789 cwd = repo.getcwd()
4790 else:
4790 else:
4791 cwd = ''
4791 cwd = ''
4792
4792
4793 if opts.get('print0'):
4793 if opts.get('print0'):
4794 end = '\0'
4794 end = '\0'
4795 else:
4795 else:
4796 end = '\n'
4796 end = '\n'
4797 copy = {}
4797 copy = {}
4798 states = 'modified added removed deleted unknown ignored clean'.split()
4798 states = 'modified added removed deleted unknown ignored clean'.split()
4799 show = [k for k in states if opts.get(k)]
4799 show = [k for k in states if opts.get(k)]
4800 if opts.get('all'):
4800 if opts.get('all'):
4801 show += ui.quiet and (states[:4] + ['clean']) or states
4801 show += ui.quiet and (states[:4] + ['clean']) or states
4802 if not show:
4802 if not show:
4803 if ui.quiet:
4803 if ui.quiet:
4804 show = states[:4]
4804 show = states[:4]
4805 else:
4805 else:
4806 show = states[:5]
4806 show = states[:5]
4807
4807
4808 m = scmutil.match(repo[node2], pats, opts)
4808 m = scmutil.match(repo[node2], pats, opts)
4809 stat = repo.status(node1, node2, m,
4809 stat = repo.status(node1, node2, m,
4810 'ignored' in show, 'clean' in show, 'unknown' in show,
4810 'ignored' in show, 'clean' in show, 'unknown' in show,
4811 opts.get('subrepos'))
4811 opts.get('subrepos'))
4812 changestates = zip(states, pycompat.iterbytestr('MAR!?IC'), stat)
4812 changestates = zip(states, pycompat.iterbytestr('MAR!?IC'), stat)
4813
4813
4814 if (opts.get('all') or opts.get('copies')
4814 if (opts.get('all') or opts.get('copies')
4815 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
4815 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
4816 copy = copies.pathcopies(repo[node1], repo[node2], m)
4816 copy = copies.pathcopies(repo[node1], repo[node2], m)
4817
4817
4818 ui.pager('status')
4818 ui.pager('status')
4819 fm = ui.formatter('status', opts)
4819 fm = ui.formatter('status', opts)
4820 fmt = '%s' + end
4820 fmt = '%s' + end
4821 showchar = not opts.get('no_status')
4821 showchar = not opts.get('no_status')
4822
4822
4823 for state, char, files in changestates:
4823 for state, char, files in changestates:
4824 if state in show:
4824 if state in show:
4825 label = 'status.' + state
4825 label = 'status.' + state
4826 for f in files:
4826 for f in files:
4827 fm.startitem()
4827 fm.startitem()
4828 fm.condwrite(showchar, 'status', '%s ', char, label=label)
4828 fm.condwrite(showchar, 'status', '%s ', char, label=label)
4829 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
4829 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
4830 if f in copy:
4830 if f in copy:
4831 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
4831 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
4832 label='status.copied')
4832 label='status.copied')
4833 fm.end()
4833 fm.end()
4834
4834
4835 @command('^summary|sum',
4835 @command('^summary|sum',
4836 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
4836 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
4837 def summary(ui, repo, **opts):
4837 def summary(ui, repo, **opts):
4838 """summarize working directory state
4838 """summarize working directory state
4839
4839
4840 This generates a brief summary of the working directory state,
4840 This generates a brief summary of the working directory state,
4841 including parents, branch, commit status, phase and available updates.
4841 including parents, branch, commit status, phase and available updates.
4842
4842
4843 With the --remote option, this will check the default paths for
4843 With the --remote option, this will check the default paths for
4844 incoming and outgoing changes. This can be time-consuming.
4844 incoming and outgoing changes. This can be time-consuming.
4845
4845
4846 Returns 0 on success.
4846 Returns 0 on success.
4847 """
4847 """
4848
4848
4849 opts = pycompat.byteskwargs(opts)
4849 opts = pycompat.byteskwargs(opts)
4850 ui.pager('summary')
4850 ui.pager('summary')
4851 ctx = repo[None]
4851 ctx = repo[None]
4852 parents = ctx.parents()
4852 parents = ctx.parents()
4853 pnode = parents[0].node()
4853 pnode = parents[0].node()
4854 marks = []
4854 marks = []
4855
4855
4856 ms = None
4856 ms = None
4857 try:
4857 try:
4858 ms = mergemod.mergestate.read(repo)
4858 ms = mergemod.mergestate.read(repo)
4859 except error.UnsupportedMergeRecords as e:
4859 except error.UnsupportedMergeRecords as e:
4860 s = ' '.join(e.recordtypes)
4860 s = ' '.join(e.recordtypes)
4861 ui.warn(
4861 ui.warn(
4862 _('warning: merge state has unsupported record types: %s\n') % s)
4862 _('warning: merge state has unsupported record types: %s\n') % s)
4863 unresolved = 0
4863 unresolved = 0
4864 else:
4864 else:
4865 unresolved = [f for f in ms if ms[f] == 'u']
4865 unresolved = [f for f in ms if ms[f] == 'u']
4866
4866
4867 for p in parents:
4867 for p in parents:
4868 # label with log.changeset (instead of log.parent) since this
4868 # label with log.changeset (instead of log.parent) since this
4869 # shows a working directory parent *changeset*:
4869 # shows a working directory parent *changeset*:
4870 # i18n: column positioning for "hg summary"
4870 # i18n: column positioning for "hg summary"
4871 ui.write(_('parent: %d:%s ') % (p.rev(), p),
4871 ui.write(_('parent: %d:%s ') % (p.rev(), p),
4872 label=cmdutil._changesetlabels(p))
4872 label=cmdutil._changesetlabels(p))
4873 ui.write(' '.join(p.tags()), label='log.tag')
4873 ui.write(' '.join(p.tags()), label='log.tag')
4874 if p.bookmarks():
4874 if p.bookmarks():
4875 marks.extend(p.bookmarks())
4875 marks.extend(p.bookmarks())
4876 if p.rev() == -1:
4876 if p.rev() == -1:
4877 if not len(repo):
4877 if not len(repo):
4878 ui.write(_(' (empty repository)'))
4878 ui.write(_(' (empty repository)'))
4879 else:
4879 else:
4880 ui.write(_(' (no revision checked out)'))
4880 ui.write(_(' (no revision checked out)'))
4881 if p.obsolete():
4881 if p.obsolete():
4882 ui.write(_(' (obsolete)'))
4882 ui.write(_(' (obsolete)'))
4883 if p.troubled():
4883 if p.troubled():
4884 ui.write(' ('
4884 ui.write(' ('
4885 + ', '.join(ui.label(trouble, 'trouble.%s' % trouble)
4885 + ', '.join(ui.label(trouble, 'trouble.%s' % trouble)
4886 for trouble in p.troubles())
4886 for trouble in p.troubles())
4887 + ')')
4887 + ')')
4888 ui.write('\n')
4888 ui.write('\n')
4889 if p.description():
4889 if p.description():
4890 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
4890 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
4891 label='log.summary')
4891 label='log.summary')
4892
4892
4893 branch = ctx.branch()
4893 branch = ctx.branch()
4894 bheads = repo.branchheads(branch)
4894 bheads = repo.branchheads(branch)
4895 # i18n: column positioning for "hg summary"
4895 # i18n: column positioning for "hg summary"
4896 m = _('branch: %s\n') % branch
4896 m = _('branch: %s\n') % branch
4897 if branch != 'default':
4897 if branch != 'default':
4898 ui.write(m, label='log.branch')
4898 ui.write(m, label='log.branch')
4899 else:
4899 else:
4900 ui.status(m, label='log.branch')
4900 ui.status(m, label='log.branch')
4901
4901
4902 if marks:
4902 if marks:
4903 active = repo._activebookmark
4903 active = repo._activebookmark
4904 # i18n: column positioning for "hg summary"
4904 # i18n: column positioning for "hg summary"
4905 ui.write(_('bookmarks:'), label='log.bookmark')
4905 ui.write(_('bookmarks:'), label='log.bookmark')
4906 if active is not None:
4906 if active is not None:
4907 if active in marks:
4907 if active in marks:
4908 ui.write(' *' + active, label=activebookmarklabel)
4908 ui.write(' *' + active, label=activebookmarklabel)
4909 marks.remove(active)
4909 marks.remove(active)
4910 else:
4910 else:
4911 ui.write(' [%s]' % active, label=activebookmarklabel)
4911 ui.write(' [%s]' % active, label=activebookmarklabel)
4912 for m in marks:
4912 for m in marks:
4913 ui.write(' ' + m, label='log.bookmark')
4913 ui.write(' ' + m, label='log.bookmark')
4914 ui.write('\n', label='log.bookmark')
4914 ui.write('\n', label='log.bookmark')
4915
4915
4916 status = repo.status(unknown=True)
4916 status = repo.status(unknown=True)
4917
4917
4918 c = repo.dirstate.copies()
4918 c = repo.dirstate.copies()
4919 copied, renamed = [], []
4919 copied, renamed = [], []
4920 for d, s in c.iteritems():
4920 for d, s in c.iteritems():
4921 if s in status.removed:
4921 if s in status.removed:
4922 status.removed.remove(s)
4922 status.removed.remove(s)
4923 renamed.append(d)
4923 renamed.append(d)
4924 else:
4924 else:
4925 copied.append(d)
4925 copied.append(d)
4926 if d in status.added:
4926 if d in status.added:
4927 status.added.remove(d)
4927 status.added.remove(d)
4928
4928
4929 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
4929 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
4930
4930
4931 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
4931 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
4932 (ui.label(_('%d added'), 'status.added'), status.added),
4932 (ui.label(_('%d added'), 'status.added'), status.added),
4933 (ui.label(_('%d removed'), 'status.removed'), status.removed),
4933 (ui.label(_('%d removed'), 'status.removed'), status.removed),
4934 (ui.label(_('%d renamed'), 'status.copied'), renamed),
4934 (ui.label(_('%d renamed'), 'status.copied'), renamed),
4935 (ui.label(_('%d copied'), 'status.copied'), copied),
4935 (ui.label(_('%d copied'), 'status.copied'), copied),
4936 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
4936 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
4937 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
4937 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
4938 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
4938 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
4939 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
4939 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
4940 t = []
4940 t = []
4941 for l, s in labels:
4941 for l, s in labels:
4942 if s:
4942 if s:
4943 t.append(l % len(s))
4943 t.append(l % len(s))
4944
4944
4945 t = ', '.join(t)
4945 t = ', '.join(t)
4946 cleanworkdir = False
4946 cleanworkdir = False
4947
4947
4948 if repo.vfs.exists('graftstate'):
4948 if repo.vfs.exists('graftstate'):
4949 t += _(' (graft in progress)')
4949 t += _(' (graft in progress)')
4950 if repo.vfs.exists('updatestate'):
4950 if repo.vfs.exists('updatestate'):
4951 t += _(' (interrupted update)')
4951 t += _(' (interrupted update)')
4952 elif len(parents) > 1:
4952 elif len(parents) > 1:
4953 t += _(' (merge)')
4953 t += _(' (merge)')
4954 elif branch != parents[0].branch():
4954 elif branch != parents[0].branch():
4955 t += _(' (new branch)')
4955 t += _(' (new branch)')
4956 elif (parents[0].closesbranch() and
4956 elif (parents[0].closesbranch() and
4957 pnode in repo.branchheads(branch, closed=True)):
4957 pnode in repo.branchheads(branch, closed=True)):
4958 t += _(' (head closed)')
4958 t += _(' (head closed)')
4959 elif not (status.modified or status.added or status.removed or renamed or
4959 elif not (status.modified or status.added or status.removed or renamed or
4960 copied or subs):
4960 copied or subs):
4961 t += _(' (clean)')
4961 t += _(' (clean)')
4962 cleanworkdir = True
4962 cleanworkdir = True
4963 elif pnode not in bheads:
4963 elif pnode not in bheads:
4964 t += _(' (new branch head)')
4964 t += _(' (new branch head)')
4965
4965
4966 if parents:
4966 if parents:
4967 pendingphase = max(p.phase() for p in parents)
4967 pendingphase = max(p.phase() for p in parents)
4968 else:
4968 else:
4969 pendingphase = phases.public
4969 pendingphase = phases.public
4970
4970
4971 if pendingphase > phases.newcommitphase(ui):
4971 if pendingphase > phases.newcommitphase(ui):
4972 t += ' (%s)' % phases.phasenames[pendingphase]
4972 t += ' (%s)' % phases.phasenames[pendingphase]
4973
4973
4974 if cleanworkdir:
4974 if cleanworkdir:
4975 # i18n: column positioning for "hg summary"
4975 # i18n: column positioning for "hg summary"
4976 ui.status(_('commit: %s\n') % t.strip())
4976 ui.status(_('commit: %s\n') % t.strip())
4977 else:
4977 else:
4978 # i18n: column positioning for "hg summary"
4978 # i18n: column positioning for "hg summary"
4979 ui.write(_('commit: %s\n') % t.strip())
4979 ui.write(_('commit: %s\n') % t.strip())
4980
4980
4981 # all ancestors of branch heads - all ancestors of parent = new csets
4981 # all ancestors of branch heads - all ancestors of parent = new csets
4982 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
4982 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
4983 bheads))
4983 bheads))
4984
4984
4985 if new == 0:
4985 if new == 0:
4986 # i18n: column positioning for "hg summary"
4986 # i18n: column positioning for "hg summary"
4987 ui.status(_('update: (current)\n'))
4987 ui.status(_('update: (current)\n'))
4988 elif pnode not in bheads:
4988 elif pnode not in bheads:
4989 # i18n: column positioning for "hg summary"
4989 # i18n: column positioning for "hg summary"
4990 ui.write(_('update: %d new changesets (update)\n') % new)
4990 ui.write(_('update: %d new changesets (update)\n') % new)
4991 else:
4991 else:
4992 # i18n: column positioning for "hg summary"
4992 # i18n: column positioning for "hg summary"
4993 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
4993 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
4994 (new, len(bheads)))
4994 (new, len(bheads)))
4995
4995
4996 t = []
4996 t = []
4997 draft = len(repo.revs('draft()'))
4997 draft = len(repo.revs('draft()'))
4998 if draft:
4998 if draft:
4999 t.append(_('%d draft') % draft)
4999 t.append(_('%d draft') % draft)
5000 secret = len(repo.revs('secret()'))
5000 secret = len(repo.revs('secret()'))
5001 if secret:
5001 if secret:
5002 t.append(_('%d secret') % secret)
5002 t.append(_('%d secret') % secret)
5003
5003
5004 if draft or secret:
5004 if draft or secret:
5005 ui.status(_('phases: %s\n') % ', '.join(t))
5005 ui.status(_('phases: %s\n') % ', '.join(t))
5006
5006
5007 if obsolete.isenabled(repo, obsolete.createmarkersopt):
5007 if obsolete.isenabled(repo, obsolete.createmarkersopt):
5008 for trouble in ("unstable", "divergent", "bumped"):
5008 for trouble in ("unstable", "divergent", "bumped"):
5009 numtrouble = len(repo.revs(trouble + "()"))
5009 numtrouble = len(repo.revs(trouble + "()"))
5010 # We write all the possibilities to ease translation
5010 # We write all the possibilities to ease translation
5011 troublemsg = {
5011 troublemsg = {
5012 "unstable": _("unstable: %d changesets"),
5012 "unstable": _("unstable: %d changesets"),
5013 "divergent": _("divergent: %d changesets"),
5013 "divergent": _("divergent: %d changesets"),
5014 "bumped": _("bumped: %d changesets"),
5014 "bumped": _("bumped: %d changesets"),
5015 }
5015 }
5016 if numtrouble > 0:
5016 if numtrouble > 0:
5017 ui.status(troublemsg[trouble] % numtrouble + "\n")
5017 ui.status(troublemsg[trouble] % numtrouble + "\n")
5018
5018
5019 cmdutil.summaryhooks(ui, repo)
5019 cmdutil.summaryhooks(ui, repo)
5020
5020
5021 if opts.get('remote'):
5021 if opts.get('remote'):
5022 needsincoming, needsoutgoing = True, True
5022 needsincoming, needsoutgoing = True, True
5023 else:
5023 else:
5024 needsincoming, needsoutgoing = False, False
5024 needsincoming, needsoutgoing = False, False
5025 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5025 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5026 if i:
5026 if i:
5027 needsincoming = True
5027 needsincoming = True
5028 if o:
5028 if o:
5029 needsoutgoing = True
5029 needsoutgoing = True
5030 if not needsincoming and not needsoutgoing:
5030 if not needsincoming and not needsoutgoing:
5031 return
5031 return
5032
5032
5033 def getincoming():
5033 def getincoming():
5034 source, branches = hg.parseurl(ui.expandpath('default'))
5034 source, branches = hg.parseurl(ui.expandpath('default'))
5035 sbranch = branches[0]
5035 sbranch = branches[0]
5036 try:
5036 try:
5037 other = hg.peer(repo, {}, source)
5037 other = hg.peer(repo, {}, source)
5038 except error.RepoError:
5038 except error.RepoError:
5039 if opts.get('remote'):
5039 if opts.get('remote'):
5040 raise
5040 raise
5041 return source, sbranch, None, None, None
5041 return source, sbranch, None, None, None
5042 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5042 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5043 if revs:
5043 if revs:
5044 revs = [other.lookup(rev) for rev in revs]
5044 revs = [other.lookup(rev) for rev in revs]
5045 ui.debug('comparing with %s\n' % util.hidepassword(source))
5045 ui.debug('comparing with %s\n' % util.hidepassword(source))
5046 repo.ui.pushbuffer()
5046 repo.ui.pushbuffer()
5047 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5047 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5048 repo.ui.popbuffer()
5048 repo.ui.popbuffer()
5049 return source, sbranch, other, commoninc, commoninc[1]
5049 return source, sbranch, other, commoninc, commoninc[1]
5050
5050
5051 if needsincoming:
5051 if needsincoming:
5052 source, sbranch, sother, commoninc, incoming = getincoming()
5052 source, sbranch, sother, commoninc, incoming = getincoming()
5053 else:
5053 else:
5054 source = sbranch = sother = commoninc = incoming = None
5054 source = sbranch = sother = commoninc = incoming = None
5055
5055
5056 def getoutgoing():
5056 def getoutgoing():
5057 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5057 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5058 dbranch = branches[0]
5058 dbranch = branches[0]
5059 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5059 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5060 if source != dest:
5060 if source != dest:
5061 try:
5061 try:
5062 dother = hg.peer(repo, {}, dest)
5062 dother = hg.peer(repo, {}, dest)
5063 except error.RepoError:
5063 except error.RepoError:
5064 if opts.get('remote'):
5064 if opts.get('remote'):
5065 raise
5065 raise
5066 return dest, dbranch, None, None
5066 return dest, dbranch, None, None
5067 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5067 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5068 elif sother is None:
5068 elif sother is None:
5069 # there is no explicit destination peer, but source one is invalid
5069 # there is no explicit destination peer, but source one is invalid
5070 return dest, dbranch, None, None
5070 return dest, dbranch, None, None
5071 else:
5071 else:
5072 dother = sother
5072 dother = sother
5073 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5073 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5074 common = None
5074 common = None
5075 else:
5075 else:
5076 common = commoninc
5076 common = commoninc
5077 if revs:
5077 if revs:
5078 revs = [repo.lookup(rev) for rev in revs]
5078 revs = [repo.lookup(rev) for rev in revs]
5079 repo.ui.pushbuffer()
5079 repo.ui.pushbuffer()
5080 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5080 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5081 commoninc=common)
5081 commoninc=common)
5082 repo.ui.popbuffer()
5082 repo.ui.popbuffer()
5083 return dest, dbranch, dother, outgoing
5083 return dest, dbranch, dother, outgoing
5084
5084
5085 if needsoutgoing:
5085 if needsoutgoing:
5086 dest, dbranch, dother, outgoing = getoutgoing()
5086 dest, dbranch, dother, outgoing = getoutgoing()
5087 else:
5087 else:
5088 dest = dbranch = dother = outgoing = None
5088 dest = dbranch = dother = outgoing = None
5089
5089
5090 if opts.get('remote'):
5090 if opts.get('remote'):
5091 t = []
5091 t = []
5092 if incoming:
5092 if incoming:
5093 t.append(_('1 or more incoming'))
5093 t.append(_('1 or more incoming'))
5094 o = outgoing.missing
5094 o = outgoing.missing
5095 if o:
5095 if o:
5096 t.append(_('%d outgoing') % len(o))
5096 t.append(_('%d outgoing') % len(o))
5097 other = dother or sother
5097 other = dother or sother
5098 if 'bookmarks' in other.listkeys('namespaces'):
5098 if 'bookmarks' in other.listkeys('namespaces'):
5099 counts = bookmarks.summary(repo, other)
5099 counts = bookmarks.summary(repo, other)
5100 if counts[0] > 0:
5100 if counts[0] > 0:
5101 t.append(_('%d incoming bookmarks') % counts[0])
5101 t.append(_('%d incoming bookmarks') % counts[0])
5102 if counts[1] > 0:
5102 if counts[1] > 0:
5103 t.append(_('%d outgoing bookmarks') % counts[1])
5103 t.append(_('%d outgoing bookmarks') % counts[1])
5104
5104
5105 if t:
5105 if t:
5106 # i18n: column positioning for "hg summary"
5106 # i18n: column positioning for "hg summary"
5107 ui.write(_('remote: %s\n') % (', '.join(t)))
5107 ui.write(_('remote: %s\n') % (', '.join(t)))
5108 else:
5108 else:
5109 # i18n: column positioning for "hg summary"
5109 # i18n: column positioning for "hg summary"
5110 ui.status(_('remote: (synced)\n'))
5110 ui.status(_('remote: (synced)\n'))
5111
5111
5112 cmdutil.summaryremotehooks(ui, repo, opts,
5112 cmdutil.summaryremotehooks(ui, repo, opts,
5113 ((source, sbranch, sother, commoninc),
5113 ((source, sbranch, sother, commoninc),
5114 (dest, dbranch, dother, outgoing)))
5114 (dest, dbranch, dother, outgoing)))
5115
5115
5116 @command('tag',
5116 @command('tag',
5117 [('f', 'force', None, _('force tag')),
5117 [('f', 'force', None, _('force tag')),
5118 ('l', 'local', None, _('make the tag local')),
5118 ('l', 'local', None, _('make the tag local')),
5119 ('r', 'rev', '', _('revision to tag'), _('REV')),
5119 ('r', 'rev', '', _('revision to tag'), _('REV')),
5120 ('', 'remove', None, _('remove a tag')),
5120 ('', 'remove', None, _('remove a tag')),
5121 # -l/--local is already there, commitopts cannot be used
5121 # -l/--local is already there, commitopts cannot be used
5122 ('e', 'edit', None, _('invoke editor on commit messages')),
5122 ('e', 'edit', None, _('invoke editor on commit messages')),
5123 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5123 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5124 ] + commitopts2,
5124 ] + commitopts2,
5125 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5125 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5126 def tag(ui, repo, name1, *names, **opts):
5126 def tag(ui, repo, name1, *names, **opts):
5127 """add one or more tags for the current or given revision
5127 """add one or more tags for the current or given revision
5128
5128
5129 Name a particular revision using <name>.
5129 Name a particular revision using <name>.
5130
5130
5131 Tags are used to name particular revisions of the repository and are
5131 Tags are used to name particular revisions of the repository and are
5132 very useful to compare different revisions, to go back to significant
5132 very useful to compare different revisions, to go back to significant
5133 earlier versions or to mark branch points as releases, etc. Changing
5133 earlier versions or to mark branch points as releases, etc. Changing
5134 an existing tag is normally disallowed; use -f/--force to override.
5134 an existing tag is normally disallowed; use -f/--force to override.
5135
5135
5136 If no revision is given, the parent of the working directory is
5136 If no revision is given, the parent of the working directory is
5137 used.
5137 used.
5138
5138
5139 To facilitate version control, distribution, and merging of tags,
5139 To facilitate version control, distribution, and merging of tags,
5140 they are stored as a file named ".hgtags" which is managed similarly
5140 they are stored as a file named ".hgtags" which is managed similarly
5141 to other project files and can be hand-edited if necessary. This
5141 to other project files and can be hand-edited if necessary. This
5142 also means that tagging creates a new commit. The file
5142 also means that tagging creates a new commit. The file
5143 ".hg/localtags" is used for local tags (not shared among
5143 ".hg/localtags" is used for local tags (not shared among
5144 repositories).
5144 repositories).
5145
5145
5146 Tag commits are usually made at the head of a branch. If the parent
5146 Tag commits are usually made at the head of a branch. If the parent
5147 of the working directory is not a branch head, :hg:`tag` aborts; use
5147 of the working directory is not a branch head, :hg:`tag` aborts; use
5148 -f/--force to force the tag commit to be based on a non-head
5148 -f/--force to force the tag commit to be based on a non-head
5149 changeset.
5149 changeset.
5150
5150
5151 See :hg:`help dates` for a list of formats valid for -d/--date.
5151 See :hg:`help dates` for a list of formats valid for -d/--date.
5152
5152
5153 Since tag names have priority over branch names during revision
5153 Since tag names have priority over branch names during revision
5154 lookup, using an existing branch name as a tag name is discouraged.
5154 lookup, using an existing branch name as a tag name is discouraged.
5155
5155
5156 Returns 0 on success.
5156 Returns 0 on success.
5157 """
5157 """
5158 opts = pycompat.byteskwargs(opts)
5158 opts = pycompat.byteskwargs(opts)
5159 wlock = lock = None
5159 wlock = lock = None
5160 try:
5160 try:
5161 wlock = repo.wlock()
5161 wlock = repo.wlock()
5162 lock = repo.lock()
5162 lock = repo.lock()
5163 rev_ = "."
5163 rev_ = "."
5164 names = [t.strip() for t in (name1,) + names]
5164 names = [t.strip() for t in (name1,) + names]
5165 if len(names) != len(set(names)):
5165 if len(names) != len(set(names)):
5166 raise error.Abort(_('tag names must be unique'))
5166 raise error.Abort(_('tag names must be unique'))
5167 for n in names:
5167 for n in names:
5168 scmutil.checknewlabel(repo, n, 'tag')
5168 scmutil.checknewlabel(repo, n, 'tag')
5169 if not n:
5169 if not n:
5170 raise error.Abort(_('tag names cannot consist entirely of '
5170 raise error.Abort(_('tag names cannot consist entirely of '
5171 'whitespace'))
5171 'whitespace'))
5172 if opts.get('rev') and opts.get('remove'):
5172 if opts.get('rev') and opts.get('remove'):
5173 raise error.Abort(_("--rev and --remove are incompatible"))
5173 raise error.Abort(_("--rev and --remove are incompatible"))
5174 if opts.get('rev'):
5174 if opts.get('rev'):
5175 rev_ = opts['rev']
5175 rev_ = opts['rev']
5176 message = opts.get('message')
5176 message = opts.get('message')
5177 if opts.get('remove'):
5177 if opts.get('remove'):
5178 if opts.get('local'):
5178 if opts.get('local'):
5179 expectedtype = 'local'
5179 expectedtype = 'local'
5180 else:
5180 else:
5181 expectedtype = 'global'
5181 expectedtype = 'global'
5182
5182
5183 for n in names:
5183 for n in names:
5184 if not repo.tagtype(n):
5184 if not repo.tagtype(n):
5185 raise error.Abort(_("tag '%s' does not exist") % n)
5185 raise error.Abort(_("tag '%s' does not exist") % n)
5186 if repo.tagtype(n) != expectedtype:
5186 if repo.tagtype(n) != expectedtype:
5187 if expectedtype == 'global':
5187 if expectedtype == 'global':
5188 raise error.Abort(_("tag '%s' is not a global tag") % n)
5188 raise error.Abort(_("tag '%s' is not a global tag") % n)
5189 else:
5189 else:
5190 raise error.Abort(_("tag '%s' is not a local tag") % n)
5190 raise error.Abort(_("tag '%s' is not a local tag") % n)
5191 rev_ = 'null'
5191 rev_ = 'null'
5192 if not message:
5192 if not message:
5193 # we don't translate commit messages
5193 # we don't translate commit messages
5194 message = 'Removed tag %s' % ', '.join(names)
5194 message = 'Removed tag %s' % ', '.join(names)
5195 elif not opts.get('force'):
5195 elif not opts.get('force'):
5196 for n in names:
5196 for n in names:
5197 if n in repo.tags():
5197 if n in repo.tags():
5198 raise error.Abort(_("tag '%s' already exists "
5198 raise error.Abort(_("tag '%s' already exists "
5199 "(use -f to force)") % n)
5199 "(use -f to force)") % n)
5200 if not opts.get('local'):
5200 if not opts.get('local'):
5201 p1, p2 = repo.dirstate.parents()
5201 p1, p2 = repo.dirstate.parents()
5202 if p2 != nullid:
5202 if p2 != nullid:
5203 raise error.Abort(_('uncommitted merge'))
5203 raise error.Abort(_('uncommitted merge'))
5204 bheads = repo.branchheads()
5204 bheads = repo.branchheads()
5205 if not opts.get('force') and bheads and p1 not in bheads:
5205 if not opts.get('force') and bheads and p1 not in bheads:
5206 raise error.Abort(_('working directory is not at a branch head '
5206 raise error.Abort(_('working directory is not at a branch head '
5207 '(use -f to force)'))
5207 '(use -f to force)'))
5208 r = scmutil.revsingle(repo, rev_).node()
5208 r = scmutil.revsingle(repo, rev_).node()
5209
5209
5210 if not message:
5210 if not message:
5211 # we don't translate commit messages
5211 # we don't translate commit messages
5212 message = ('Added tag %s for changeset %s' %
5212 message = ('Added tag %s for changeset %s' %
5213 (', '.join(names), short(r)))
5213 (', '.join(names), short(r)))
5214
5214
5215 date = opts.get('date')
5215 date = opts.get('date')
5216 if date:
5216 if date:
5217 date = util.parsedate(date)
5217 date = util.parsedate(date)
5218
5218
5219 if opts.get('remove'):
5219 if opts.get('remove'):
5220 editform = 'tag.remove'
5220 editform = 'tag.remove'
5221 else:
5221 else:
5222 editform = 'tag.add'
5222 editform = 'tag.add'
5223 editor = cmdutil.getcommiteditor(editform=editform,
5223 editor = cmdutil.getcommiteditor(editform=editform,
5224 **pycompat.strkwargs(opts))
5224 **pycompat.strkwargs(opts))
5225
5225
5226 # don't allow tagging the null rev
5226 # don't allow tagging the null rev
5227 if (not opts.get('remove') and
5227 if (not opts.get('remove') and
5228 scmutil.revsingle(repo, rev_).rev() == nullrev):
5228 scmutil.revsingle(repo, rev_).rev() == nullrev):
5229 raise error.Abort(_("cannot tag null revision"))
5229 raise error.Abort(_("cannot tag null revision"))
5230
5230
5231 tagsmod.tag(repo, names, r, message, opts.get('local'),
5231 tagsmod.tag(repo, names, r, message, opts.get('local'),
5232 opts.get('user'), date, editor=editor)
5232 opts.get('user'), date, editor=editor)
5233 finally:
5233 finally:
5234 release(lock, wlock)
5234 release(lock, wlock)
5235
5235
5236 @command('tags', formatteropts, '')
5236 @command('tags', formatteropts, '')
5237 def tags(ui, repo, **opts):
5237 def tags(ui, repo, **opts):
5238 """list repository tags
5238 """list repository tags
5239
5239
5240 This lists both regular and local tags. When the -v/--verbose
5240 This lists both regular and local tags. When the -v/--verbose
5241 switch is used, a third column "local" is printed for local tags.
5241 switch is used, a third column "local" is printed for local tags.
5242 When the -q/--quiet switch is used, only the tag name is printed.
5242 When the -q/--quiet switch is used, only the tag name is printed.
5243
5243
5244 Returns 0 on success.
5244 Returns 0 on success.
5245 """
5245 """
5246
5246
5247 opts = pycompat.byteskwargs(opts)
5247 opts = pycompat.byteskwargs(opts)
5248 ui.pager('tags')
5248 ui.pager('tags')
5249 fm = ui.formatter('tags', opts)
5249 fm = ui.formatter('tags', opts)
5250 hexfunc = fm.hexfunc
5250 hexfunc = fm.hexfunc
5251 tagtype = ""
5251 tagtype = ""
5252
5252
5253 for t, n in reversed(repo.tagslist()):
5253 for t, n in reversed(repo.tagslist()):
5254 hn = hexfunc(n)
5254 hn = hexfunc(n)
5255 label = 'tags.normal'
5255 label = 'tags.normal'
5256 tagtype = ''
5256 tagtype = ''
5257 if repo.tagtype(t) == 'local':
5257 if repo.tagtype(t) == 'local':
5258 label = 'tags.local'
5258 label = 'tags.local'
5259 tagtype = 'local'
5259 tagtype = 'local'
5260
5260
5261 fm.startitem()
5261 fm.startitem()
5262 fm.write('tag', '%s', t, label=label)
5262 fm.write('tag', '%s', t, label=label)
5263 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5263 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5264 fm.condwrite(not ui.quiet, 'rev node', fmt,
5264 fm.condwrite(not ui.quiet, 'rev node', fmt,
5265 repo.changelog.rev(n), hn, label=label)
5265 repo.changelog.rev(n), hn, label=label)
5266 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5266 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5267 tagtype, label=label)
5267 tagtype, label=label)
5268 fm.plain('\n')
5268 fm.plain('\n')
5269 fm.end()
5269 fm.end()
5270
5270
5271 @command('tip',
5271 @command('tip',
5272 [('p', 'patch', None, _('show patch')),
5272 [('p', 'patch', None, _('show patch')),
5273 ('g', 'git', None, _('use git extended diff format')),
5273 ('g', 'git', None, _('use git extended diff format')),
5274 ] + templateopts,
5274 ] + templateopts,
5275 _('[-p] [-g]'))
5275 _('[-p] [-g]'))
5276 def tip(ui, repo, **opts):
5276 def tip(ui, repo, **opts):
5277 """show the tip revision (DEPRECATED)
5277 """show the tip revision (DEPRECATED)
5278
5278
5279 The tip revision (usually just called the tip) is the changeset
5279 The tip revision (usually just called the tip) is the changeset
5280 most recently added to the repository (and therefore the most
5280 most recently added to the repository (and therefore the most
5281 recently changed head).
5281 recently changed head).
5282
5282
5283 If you have just made a commit, that commit will be the tip. If
5283 If you have just made a commit, that commit will be the tip. If
5284 you have just pulled changes from another repository, the tip of
5284 you have just pulled changes from another repository, the tip of
5285 that repository becomes the current tip. The "tip" tag is special
5285 that repository becomes the current tip. The "tip" tag is special
5286 and cannot be renamed or assigned to a different changeset.
5286 and cannot be renamed or assigned to a different changeset.
5287
5287
5288 This command is deprecated, please use :hg:`heads` instead.
5288 This command is deprecated, please use :hg:`heads` instead.
5289
5289
5290 Returns 0 on success.
5290 Returns 0 on success.
5291 """
5291 """
5292 opts = pycompat.byteskwargs(opts)
5292 opts = pycompat.byteskwargs(opts)
5293 displayer = cmdutil.show_changeset(ui, repo, opts)
5293 displayer = cmdutil.show_changeset(ui, repo, opts)
5294 displayer.show(repo['tip'])
5294 displayer.show(repo['tip'])
5295 displayer.close()
5295 displayer.close()
5296
5296
5297 @command('unbundle',
5297 @command('unbundle',
5298 [('u', 'update', None,
5298 [('u', 'update', None,
5299 _('update to new branch head if changesets were unbundled'))],
5299 _('update to new branch head if changesets were unbundled'))],
5300 _('[-u] FILE...'))
5300 _('[-u] FILE...'))
5301 def unbundle(ui, repo, fname1, *fnames, **opts):
5301 def unbundle(ui, repo, fname1, *fnames, **opts):
5302 """apply one or more bundle files
5302 """apply one or more bundle files
5303
5303
5304 Apply one or more bundle files generated by :hg:`bundle`.
5304 Apply one or more bundle files generated by :hg:`bundle`.
5305
5305
5306 Returns 0 on success, 1 if an update has unresolved files.
5306 Returns 0 on success, 1 if an update has unresolved files.
5307 """
5307 """
5308 fnames = (fname1,) + fnames
5308 fnames = (fname1,) + fnames
5309
5309
5310 with repo.lock():
5310 with repo.lock():
5311 for fname in fnames:
5311 for fname in fnames:
5312 f = hg.openpath(ui, fname)
5312 f = hg.openpath(ui, fname)
5313 gen = exchange.readbundle(ui, f, fname)
5313 gen = exchange.readbundle(ui, f, fname)
5314 if isinstance(gen, bundle2.unbundle20):
5314 if isinstance(gen, bundle2.unbundle20):
5315 tr = repo.transaction('unbundle')
5315 tr = repo.transaction('unbundle')
5316 try:
5316 try:
5317 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
5317 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
5318 url='bundle:' + fname)
5318 url='bundle:' + fname)
5319 tr.close()
5319 tr.close()
5320 except error.BundleUnknownFeatureError as exc:
5320 except error.BundleUnknownFeatureError as exc:
5321 raise error.Abort(_('%s: unknown bundle feature, %s')
5321 raise error.Abort(_('%s: unknown bundle feature, %s')
5322 % (fname, exc),
5322 % (fname, exc),
5323 hint=_("see https://mercurial-scm.org/"
5323 hint=_("see https://mercurial-scm.org/"
5324 "wiki/BundleFeature for more "
5324 "wiki/BundleFeature for more "
5325 "information"))
5325 "information"))
5326 finally:
5326 finally:
5327 if tr:
5327 if tr:
5328 tr.release()
5328 tr.release()
5329 changes = [r.get('return', 0)
5329 changes = [r.get('return', 0)
5330 for r in op.records['changegroup']]
5330 for r in op.records['changegroup']]
5331 modheads = changegroup.combineresults(changes)
5331 modheads = changegroup.combineresults(changes)
5332 elif isinstance(gen, streamclone.streamcloneapplier):
5332 elif isinstance(gen, streamclone.streamcloneapplier):
5333 raise error.Abort(
5333 raise error.Abort(
5334 _('packed bundles cannot be applied with '
5334 _('packed bundles cannot be applied with '
5335 '"hg unbundle"'),
5335 '"hg unbundle"'),
5336 hint=_('use "hg debugapplystreamclonebundle"'))
5336 hint=_('use "hg debugapplystreamclonebundle"'))
5337 else:
5337 else:
5338 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
5338 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
5339
5339
5340 return postincoming(ui, repo, modheads, opts.get(r'update'), None, None)
5340 return postincoming(ui, repo, modheads, opts.get(r'update'), None, None)
5341
5341
5342 @command('^update|up|checkout|co',
5342 @command('^update|up|checkout|co',
5343 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5343 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5344 ('c', 'check', None, _('require clean working directory')),
5344 ('c', 'check', None, _('require clean working directory')),
5345 ('m', 'merge', None, _('merge uncommitted changes')),
5345 ('m', 'merge', None, _('merge uncommitted changes')),
5346 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5346 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5347 ('r', 'rev', '', _('revision'), _('REV'))
5347 ('r', 'rev', '', _('revision'), _('REV'))
5348 ] + mergetoolopts,
5348 ] + mergetoolopts,
5349 _('[-C|-c|-m] [-d DATE] [[-r] REV]'))
5349 _('[-C|-c|-m] [-d DATE] [[-r] REV]'))
5350 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
5350 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
5351 merge=None, tool=None):
5351 merge=None, tool=None):
5352 """update working directory (or switch revisions)
5352 """update working directory (or switch revisions)
5353
5353
5354 Update the repository's working directory to the specified
5354 Update the repository's working directory to the specified
5355 changeset. If no changeset is specified, update to the tip of the
5355 changeset. If no changeset is specified, update to the tip of the
5356 current named branch and move the active bookmark (see :hg:`help
5356 current named branch and move the active bookmark (see :hg:`help
5357 bookmarks`).
5357 bookmarks`).
5358
5358
5359 Update sets the working directory's parent revision to the specified
5359 Update sets the working directory's parent revision to the specified
5360 changeset (see :hg:`help parents`).
5360 changeset (see :hg:`help parents`).
5361
5361
5362 If the changeset is not a descendant or ancestor of the working
5362 If the changeset is not a descendant or ancestor of the working
5363 directory's parent and there are uncommitted changes, the update is
5363 directory's parent and there are uncommitted changes, the update is
5364 aborted. With the -c/--check option, the working directory is checked
5364 aborted. With the -c/--check option, the working directory is checked
5365 for uncommitted changes; if none are found, the working directory is
5365 for uncommitted changes; if none are found, the working directory is
5366 updated to the specified changeset.
5366 updated to the specified changeset.
5367
5367
5368 .. container:: verbose
5368 .. container:: verbose
5369
5369
5370 The -C/--clean, -c/--check, and -m/--merge options control what
5370 The -C/--clean, -c/--check, and -m/--merge options control what
5371 happens if the working directory contains uncommitted changes.
5371 happens if the working directory contains uncommitted changes.
5372 At most of one of them can be specified.
5372 At most of one of them can be specified.
5373
5373
5374 1. If no option is specified, and if
5374 1. If no option is specified, and if
5375 the requested changeset is an ancestor or descendant of
5375 the requested changeset is an ancestor or descendant of
5376 the working directory's parent, the uncommitted changes
5376 the working directory's parent, the uncommitted changes
5377 are merged into the requested changeset and the merged
5377 are merged into the requested changeset and the merged
5378 result is left uncommitted. If the requested changeset is
5378 result is left uncommitted. If the requested changeset is
5379 not an ancestor or descendant (that is, it is on another
5379 not an ancestor or descendant (that is, it is on another
5380 branch), the update is aborted and the uncommitted changes
5380 branch), the update is aborted and the uncommitted changes
5381 are preserved.
5381 are preserved.
5382
5382
5383 2. With the -m/--merge option, the update is allowed even if the
5383 2. With the -m/--merge option, the update is allowed even if the
5384 requested changeset is not an ancestor or descendant of
5384 requested changeset is not an ancestor or descendant of
5385 the working directory's parent.
5385 the working directory's parent.
5386
5386
5387 3. With the -c/--check option, the update is aborted and the
5387 3. With the -c/--check option, the update is aborted and the
5388 uncommitted changes are preserved.
5388 uncommitted changes are preserved.
5389
5389
5390 4. With the -C/--clean option, uncommitted changes are discarded and
5390 4. With the -C/--clean option, uncommitted changes are discarded and
5391 the working directory is updated to the requested changeset.
5391 the working directory is updated to the requested changeset.
5392
5392
5393 To cancel an uncommitted merge (and lose your changes), use
5393 To cancel an uncommitted merge (and lose your changes), use
5394 :hg:`update --clean .`.
5394 :hg:`update --clean .`.
5395
5395
5396 Use null as the changeset to remove the working directory (like
5396 Use null as the changeset to remove the working directory (like
5397 :hg:`clone -U`).
5397 :hg:`clone -U`).
5398
5398
5399 If you want to revert just one file to an older revision, use
5399 If you want to revert just one file to an older revision, use
5400 :hg:`revert [-r REV] NAME`.
5400 :hg:`revert [-r REV] NAME`.
5401
5401
5402 See :hg:`help dates` for a list of formats valid for -d/--date.
5402 See :hg:`help dates` for a list of formats valid for -d/--date.
5403
5403
5404 Returns 0 on success, 1 if there are unresolved files.
5404 Returns 0 on success, 1 if there are unresolved files.
5405 """
5405 """
5406 if rev and node:
5406 if rev and node:
5407 raise error.Abort(_("please specify just one revision"))
5407 raise error.Abort(_("please specify just one revision"))
5408
5408
5409 if ui.configbool('commands', 'update.requiredest'):
5409 if ui.configbool('commands', 'update.requiredest'):
5410 if not node and not rev and not date:
5410 if not node and not rev and not date:
5411 raise error.Abort(_('you must specify a destination'),
5411 raise error.Abort(_('you must specify a destination'),
5412 hint=_('for example: hg update ".::"'))
5412 hint=_('for example: hg update ".::"'))
5413
5413
5414 if rev is None or rev == '':
5414 if rev is None or rev == '':
5415 rev = node
5415 rev = node
5416
5416
5417 if date and rev is not None:
5417 if date and rev is not None:
5418 raise error.Abort(_("you can't specify a revision and a date"))
5418 raise error.Abort(_("you can't specify a revision and a date"))
5419
5419
5420 if len([x for x in (clean, check, merge) if x]) > 1:
5420 if len([x for x in (clean, check, merge) if x]) > 1:
5421 raise error.Abort(_("can only specify one of -C/--clean, -c/--check, "
5421 raise error.Abort(_("can only specify one of -C/--clean, -c/--check, "
5422 "or -m/merge"))
5422 "or -m/merge"))
5423
5423
5424 updatecheck = None
5424 updatecheck = None
5425 if check:
5425 if check:
5426 updatecheck = 'abort'
5426 updatecheck = 'abort'
5427 elif merge:
5427 elif merge:
5428 updatecheck = 'none'
5428 updatecheck = 'none'
5429
5429
5430 with repo.wlock():
5430 with repo.wlock():
5431 cmdutil.clearunfinished(repo)
5431 cmdutil.clearunfinished(repo)
5432
5432
5433 if date:
5433 if date:
5434 rev = cmdutil.finddate(ui, repo, date)
5434 rev = cmdutil.finddate(ui, repo, date)
5435
5435
5436 # if we defined a bookmark, we have to remember the original name
5436 # if we defined a bookmark, we have to remember the original name
5437 brev = rev
5437 brev = rev
5438 rev = scmutil.revsingle(repo, rev, rev).rev()
5438 rev = scmutil.revsingle(repo, rev, rev).rev()
5439
5439
5440 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
5440 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
5441
5441
5442 return hg.updatetotally(ui, repo, rev, brev, clean=clean,
5442 return hg.updatetotally(ui, repo, rev, brev, clean=clean,
5443 updatecheck=updatecheck)
5443 updatecheck=updatecheck)
5444
5444
5445 @command('verify', [])
5445 @command('verify', [])
5446 def verify(ui, repo):
5446 def verify(ui, repo):
5447 """verify the integrity of the repository
5447 """verify the integrity of the repository
5448
5448
5449 Verify the integrity of the current repository.
5449 Verify the integrity of the current repository.
5450
5450
5451 This will perform an extensive check of the repository's
5451 This will perform an extensive check of the repository's
5452 integrity, validating the hashes and checksums of each entry in
5452 integrity, validating the hashes and checksums of each entry in
5453 the changelog, manifest, and tracked files, as well as the
5453 the changelog, manifest, and tracked files, as well as the
5454 integrity of their crosslinks and indices.
5454 integrity of their crosslinks and indices.
5455
5455
5456 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
5456 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
5457 for more information about recovery from corruption of the
5457 for more information about recovery from corruption of the
5458 repository.
5458 repository.
5459
5459
5460 Returns 0 on success, 1 if errors are encountered.
5460 Returns 0 on success, 1 if errors are encountered.
5461 """
5461 """
5462 return hg.verify(repo)
5462 return hg.verify(repo)
5463
5463
5464 @command('version', [] + formatteropts, norepo=True)
5464 @command('version', [] + formatteropts, norepo=True)
5465 def version_(ui, **opts):
5465 def version_(ui, **opts):
5466 """output version and copyright information"""
5466 """output version and copyright information"""
5467 opts = pycompat.byteskwargs(opts)
5467 opts = pycompat.byteskwargs(opts)
5468 if ui.verbose:
5468 if ui.verbose:
5469 ui.pager('version')
5469 ui.pager('version')
5470 fm = ui.formatter("version", opts)
5470 fm = ui.formatter("version", opts)
5471 fm.startitem()
5471 fm.startitem()
5472 fm.write("ver", _("Mercurial Distributed SCM (version %s)\n"),
5472 fm.write("ver", _("Mercurial Distributed SCM (version %s)\n"),
5473 util.version())
5473 util.version())
5474 license = _(
5474 license = _(
5475 "(see https://mercurial-scm.org for more information)\n"
5475 "(see https://mercurial-scm.org for more information)\n"
5476 "\nCopyright (C) 2005-2017 Matt Mackall and others\n"
5476 "\nCopyright (C) 2005-2017 Matt Mackall and others\n"
5477 "This is free software; see the source for copying conditions. "
5477 "This is free software; see the source for copying conditions. "
5478 "There is NO\nwarranty; "
5478 "There is NO\nwarranty; "
5479 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5479 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5480 )
5480 )
5481 if not ui.quiet:
5481 if not ui.quiet:
5482 fm.plain(license)
5482 fm.plain(license)
5483
5483
5484 if ui.verbose:
5484 if ui.verbose:
5485 fm.plain(_("\nEnabled extensions:\n\n"))
5485 fm.plain(_("\nEnabled extensions:\n\n"))
5486 # format names and versions into columns
5486 # format names and versions into columns
5487 names = []
5487 names = []
5488 vers = []
5488 vers = []
5489 isinternals = []
5489 isinternals = []
5490 for name, module in extensions.extensions():
5490 for name, module in extensions.extensions():
5491 names.append(name)
5491 names.append(name)
5492 vers.append(extensions.moduleversion(module) or None)
5492 vers.append(extensions.moduleversion(module) or None)
5493 isinternals.append(extensions.ismoduleinternal(module))
5493 isinternals.append(extensions.ismoduleinternal(module))
5494 fn = fm.nested("extensions")
5494 fn = fm.nested("extensions")
5495 if names:
5495 if names:
5496 namefmt = " %%-%ds " % max(len(n) for n in names)
5496 namefmt = " %%-%ds " % max(len(n) for n in names)
5497 places = [_("external"), _("internal")]
5497 places = [_("external"), _("internal")]
5498 for n, v, p in zip(names, vers, isinternals):
5498 for n, v, p in zip(names, vers, isinternals):
5499 fn.startitem()
5499 fn.startitem()
5500 fn.condwrite(ui.verbose, "name", namefmt, n)
5500 fn.condwrite(ui.verbose, "name", namefmt, n)
5501 if ui.verbose:
5501 if ui.verbose:
5502 fn.plain("%s " % places[p])
5502 fn.plain("%s " % places[p])
5503 fn.data(bundled=p)
5503 fn.data(bundled=p)
5504 fn.condwrite(ui.verbose and v, "ver", "%s", v)
5504 fn.condwrite(ui.verbose and v, "ver", "%s", v)
5505 if ui.verbose:
5505 if ui.verbose:
5506 fn.plain("\n")
5506 fn.plain("\n")
5507 fn.end()
5507 fn.end()
5508 fm.end()
5508 fm.end()
5509
5509
5510 def loadcmdtable(ui, name, cmdtable):
5510 def loadcmdtable(ui, name, cmdtable):
5511 """Load command functions from specified cmdtable
5511 """Load command functions from specified cmdtable
5512 """
5512 """
5513 overrides = [cmd for cmd in cmdtable if cmd in table]
5513 overrides = [cmd for cmd in cmdtable if cmd in table]
5514 if overrides:
5514 if overrides:
5515 ui.warn(_("extension '%s' overrides commands: %s\n")
5515 ui.warn(_("extension '%s' overrides commands: %s\n")
5516 % (name, " ".join(overrides)))
5516 % (name, " ".join(overrides)))
5517 table.update(cmdtable)
5517 table.update(cmdtable)
General Comments 0
You need to be logged in to leave comments. Login now