##// END OF EJS Templates
diff: migrate to modern pager API
Augie Fackler -
r31030:ed0023e4 default
parent child Browse files
Show More
@@ -1,113 +1,113 b''
1 # pager.py - display output using a pager
1 # pager.py - display output using a pager
2 #
2 #
3 # Copyright 2008 David Soria Parra <dsp@php.net>
3 # Copyright 2008 David Soria Parra <dsp@php.net>
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 # To load the extension, add it to your configuration file:
8 # To load the extension, add it to your configuration file:
9 #
9 #
10 # [extension]
10 # [extension]
11 # pager =
11 # pager =
12 #
12 #
13 # Run 'hg help pager' to get info on configuration.
13 # Run 'hg help pager' to get info on configuration.
14
14
15 '''browse command output with an external pager
15 '''browse command output with an external pager
16
16
17 To set the pager that should be used, set the application variable::
17 To set the pager that should be used, set the application variable::
18
18
19 [pager]
19 [pager]
20 pager = less -FRX
20 pager = less -FRX
21
21
22 If no pager is set, the pager extensions uses the environment variable
22 If no pager is set, the pager extensions uses the environment variable
23 $PAGER. If neither pager.pager, nor $PAGER is set, no pager is used.
23 $PAGER. If neither pager.pager, nor $PAGER is set, no pager is used.
24
24
25 You can disable the pager for certain commands by adding them to the
25 You can disable the pager for certain commands by adding them to the
26 pager.ignore list::
26 pager.ignore list::
27
27
28 [pager]
28 [pager]
29 ignore = version, help, update
29 ignore = version, help, update
30
30
31 You can also enable the pager only for certain commands using
31 You can also enable the pager only for certain commands using
32 pager.attend. Below is the default list of commands to be paged::
32 pager.attend. Below is the default list of commands to be paged::
33
33
34 [pager]
34 [pager]
35 attend = annotate, cat, diff, export, glog, log, qdiff
35 attend = annotate, cat, diff, export, glog, log, qdiff
36
36
37 Setting pager.attend to an empty value will cause all commands to be
37 Setting pager.attend to an empty value will cause all commands to be
38 paged.
38 paged.
39
39
40 If pager.attend is present, pager.ignore will be ignored.
40 If pager.attend is present, pager.ignore will be ignored.
41
41
42 Lastly, you can enable and disable paging for individual commands with
42 Lastly, you can enable and disable paging for individual commands with
43 the attend-<command> option. This setting takes precedence over
43 the attend-<command> option. This setting takes precedence over
44 existing attend and ignore options and defaults::
44 existing attend and ignore options and defaults::
45
45
46 [pager]
46 [pager]
47 attend-cat = false
47 attend-cat = false
48
48
49 To ignore global commands like :hg:`version` or :hg:`help`, you have
49 To ignore global commands like :hg:`version` or :hg:`help`, you have
50 to specify them in your user configuration file.
50 to specify them in your user configuration file.
51
51
52 To control whether the pager is used at all for an individual command,
52 To control whether the pager is used at all for an individual command,
53 you can use --pager=<value>::
53 you can use --pager=<value>::
54
54
55 - use as needed: `auto`.
55 - use as needed: `auto`.
56 - require the pager: `yes` or `on`.
56 - require the pager: `yes` or `on`.
57 - suppress the pager: `no` or `off` (any unrecognized value
57 - suppress the pager: `no` or `off` (any unrecognized value
58 will also work).
58 will also work).
59
59
60 '''
60 '''
61 from __future__ import absolute_import
61 from __future__ import absolute_import
62
62
63 from mercurial import (
63 from mercurial import (
64 cmdutil,
64 cmdutil,
65 commands,
65 commands,
66 dispatch,
66 dispatch,
67 extensions,
67 extensions,
68 )
68 )
69
69
70 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
70 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
71 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
71 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
72 # be specifying the version(s) of Mercurial they are tested with, or
72 # be specifying the version(s) of Mercurial they are tested with, or
73 # leave the attribute unspecified.
73 # leave the attribute unspecified.
74 testedwith = 'ships-with-hg-core'
74 testedwith = 'ships-with-hg-core'
75
75
76 def uisetup(ui):
76 def uisetup(ui):
77
77
78 def pagecmd(orig, ui, options, cmd, cmdfunc):
78 def pagecmd(orig, ui, options, cmd, cmdfunc):
79 auto = options['pager'] == 'auto'
79 auto = options['pager'] == 'auto'
80 if auto and not ui.pageractive:
80 if auto and not ui.pageractive:
81 usepager = False
81 usepager = False
82 attend = ui.configlist('pager', 'attend', attended)
82 attend = ui.configlist('pager', 'attend', attended)
83 ignore = ui.configlist('pager', 'ignore')
83 ignore = ui.configlist('pager', 'ignore')
84 cmds, _ = cmdutil.findcmd(cmd, commands.table)
84 cmds, _ = cmdutil.findcmd(cmd, commands.table)
85
85
86 for cmd in cmds:
86 for cmd in cmds:
87 var = 'attend-%s' % cmd
87 var = 'attend-%s' % cmd
88 if ui.config('pager', var):
88 if ui.config('pager', var):
89 usepager = ui.configbool('pager', var)
89 usepager = ui.configbool('pager', var)
90 break
90 break
91 if (cmd in attend or
91 if (cmd in attend or
92 (cmd not in ignore and not attend)):
92 (cmd not in ignore and not attend)):
93 usepager = True
93 usepager = True
94 break
94 break
95
95
96 if usepager:
96 if usepager:
97 # Slight hack: the attend list is supposed to override
97 # Slight hack: the attend list is supposed to override
98 # the ignore list for the pager extension, but the
98 # the ignore list for the pager extension, but the
99 # core code doesn't know about attend, so we have to
99 # core code doesn't know about attend, so we have to
100 # lobotomize the ignore list so that the extension's
100 # lobotomize the ignore list so that the extension's
101 # behavior is preserved.
101 # behavior is preserved.
102 ui.setconfig('pager', 'ignore', '', 'pager')
102 ui.setconfig('pager', 'ignore', '', 'pager')
103 ui.pager('extension-via-attend-' + cmd)
103 ui.pager('extension-via-attend-' + cmd)
104 return orig(ui, options, cmd, cmdfunc)
104 return orig(ui, options, cmd, cmdfunc)
105
105
106 # Wrap dispatch._runcommand after color is loaded so color can see
106 # Wrap dispatch._runcommand after color is loaded so color can see
107 # ui.pageractive. Otherwise, if we loaded first, color's wrapped
107 # ui.pageractive. Otherwise, if we loaded first, color's wrapped
108 # dispatch._runcommand would run without having access to ui.pageractive.
108 # dispatch._runcommand would run without having access to ui.pageractive.
109 def afterloaded(loaded):
109 def afterloaded(loaded):
110 extensions.wrapfunction(dispatch, '_runcommand', pagecmd)
110 extensions.wrapfunction(dispatch, '_runcommand', pagecmd)
111 extensions.afterloaded('color', afterloaded)
111 extensions.afterloaded('color', afterloaded)
112
112
113 attended = ['diff', 'export', 'glog', 'log', 'qdiff']
113 attended = ['export', 'glog', 'log', 'qdiff']
@@ -1,5447 +1,5448 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 minirst,
42 minirst,
43 obsolete,
43 obsolete,
44 patch,
44 patch,
45 phases,
45 phases,
46 pycompat,
46 pycompat,
47 revsetlang,
47 revsetlang,
48 scmutil,
48 scmutil,
49 server,
49 server,
50 sshserver,
50 sshserver,
51 streamclone,
51 streamclone,
52 templatekw,
52 templatekw,
53 ui as uimod,
53 ui as uimod,
54 util,
54 util,
55 )
55 )
56
56
57 release = lockmod.release
57 release = lockmod.release
58
58
59 table = {}
59 table = {}
60
60
61 command = cmdutil.command(table)
61 command = cmdutil.command(table)
62
62
63 # label constants
63 # label constants
64 # until 3.5, bookmarks.current was the advertised name, not
64 # until 3.5, bookmarks.current was the advertised name, not
65 # bookmarks.active, so we must use both to avoid breaking old
65 # bookmarks.active, so we must use both to avoid breaking old
66 # custom styles
66 # custom styles
67 activebookmarklabel = 'bookmarks.active bookmarks.current'
67 activebookmarklabel = 'bookmarks.active bookmarks.current'
68
68
69 # common command options
69 # common command options
70
70
71 globalopts = [
71 globalopts = [
72 ('R', 'repository', '',
72 ('R', 'repository', '',
73 _('repository root directory or name of overlay bundle file'),
73 _('repository root directory or name of overlay bundle file'),
74 _('REPO')),
74 _('REPO')),
75 ('', 'cwd', '',
75 ('', 'cwd', '',
76 _('change working directory'), _('DIR')),
76 _('change working directory'), _('DIR')),
77 ('y', 'noninteractive', None,
77 ('y', 'noninteractive', None,
78 _('do not prompt, automatically pick the first choice for all prompts')),
78 _('do not prompt, automatically pick the first choice for all prompts')),
79 ('q', 'quiet', None, _('suppress output')),
79 ('q', 'quiet', None, _('suppress output')),
80 ('v', 'verbose', None, _('enable additional output')),
80 ('v', 'verbose', None, _('enable additional output')),
81 ('', 'config', [],
81 ('', 'config', [],
82 _('set/override config option (use \'section.name=value\')'),
82 _('set/override config option (use \'section.name=value\')'),
83 _('CONFIG')),
83 _('CONFIG')),
84 ('', 'debug', None, _('enable debugging output')),
84 ('', 'debug', None, _('enable debugging output')),
85 ('', 'debugger', None, _('start debugger')),
85 ('', 'debugger', None, _('start debugger')),
86 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
86 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
87 _('ENCODE')),
87 _('ENCODE')),
88 ('', 'encodingmode', encoding.encodingmode,
88 ('', 'encodingmode', encoding.encodingmode,
89 _('set the charset encoding mode'), _('MODE')),
89 _('set the charset encoding mode'), _('MODE')),
90 ('', 'traceback', None, _('always print a traceback on exception')),
90 ('', 'traceback', None, _('always print a traceback on exception')),
91 ('', 'time', None, _('time how long the command takes')),
91 ('', 'time', None, _('time how long the command takes')),
92 ('', 'profile', None, _('print command execution profile')),
92 ('', 'profile', None, _('print command execution profile')),
93 ('', 'version', None, _('output version information and exit')),
93 ('', 'version', None, _('output version information and exit')),
94 ('h', 'help', None, _('display help and exit')),
94 ('h', 'help', None, _('display help and exit')),
95 ('', 'hidden', False, _('consider hidden changesets')),
95 ('', 'hidden', False, _('consider hidden changesets')),
96 ('', 'pager', 'auto',
96 ('', 'pager', 'auto',
97 _("when to paginate (boolean, always, auto, or never)"), _('TYPE')),
97 _("when to paginate (boolean, always, auto, or never)"), _('TYPE')),
98 ]
98 ]
99
99
100 dryrunopts = [('n', 'dry-run', None,
100 dryrunopts = [('n', 'dry-run', None,
101 _('do not perform actions, just print output'))]
101 _('do not perform actions, just print output'))]
102
102
103 remoteopts = [
103 remoteopts = [
104 ('e', 'ssh', '',
104 ('e', 'ssh', '',
105 _('specify ssh command to use'), _('CMD')),
105 _('specify ssh command to use'), _('CMD')),
106 ('', 'remotecmd', '',
106 ('', 'remotecmd', '',
107 _('specify hg command to run on the remote side'), _('CMD')),
107 _('specify hg command to run on the remote side'), _('CMD')),
108 ('', 'insecure', None,
108 ('', 'insecure', None,
109 _('do not verify server certificate (ignoring web.cacerts config)')),
109 _('do not verify server certificate (ignoring web.cacerts config)')),
110 ]
110 ]
111
111
112 walkopts = [
112 walkopts = [
113 ('I', 'include', [],
113 ('I', 'include', [],
114 _('include names matching the given patterns'), _('PATTERN')),
114 _('include names matching the given patterns'), _('PATTERN')),
115 ('X', 'exclude', [],
115 ('X', 'exclude', [],
116 _('exclude names matching the given patterns'), _('PATTERN')),
116 _('exclude names matching the given patterns'), _('PATTERN')),
117 ]
117 ]
118
118
119 commitopts = [
119 commitopts = [
120 ('m', 'message', '',
120 ('m', 'message', '',
121 _('use text as commit message'), _('TEXT')),
121 _('use text as commit message'), _('TEXT')),
122 ('l', 'logfile', '',
122 ('l', 'logfile', '',
123 _('read commit message from file'), _('FILE')),
123 _('read commit message from file'), _('FILE')),
124 ]
124 ]
125
125
126 commitopts2 = [
126 commitopts2 = [
127 ('d', 'date', '',
127 ('d', 'date', '',
128 _('record the specified date as commit date'), _('DATE')),
128 _('record the specified date as commit date'), _('DATE')),
129 ('u', 'user', '',
129 ('u', 'user', '',
130 _('record the specified user as committer'), _('USER')),
130 _('record the specified user as committer'), _('USER')),
131 ]
131 ]
132
132
133 # hidden for now
133 # hidden for now
134 formatteropts = [
134 formatteropts = [
135 ('T', 'template', '',
135 ('T', 'template', '',
136 _('display with template (EXPERIMENTAL)'), _('TEMPLATE')),
136 _('display with template (EXPERIMENTAL)'), _('TEMPLATE')),
137 ]
137 ]
138
138
139 templateopts = [
139 templateopts = [
140 ('', 'style', '',
140 ('', 'style', '',
141 _('display using template map file (DEPRECATED)'), _('STYLE')),
141 _('display using template map file (DEPRECATED)'), _('STYLE')),
142 ('T', 'template', '',
142 ('T', 'template', '',
143 _('display with template'), _('TEMPLATE')),
143 _('display with template'), _('TEMPLATE')),
144 ]
144 ]
145
145
146 logopts = [
146 logopts = [
147 ('p', 'patch', None, _('show patch')),
147 ('p', 'patch', None, _('show patch')),
148 ('g', 'git', None, _('use git extended diff format')),
148 ('g', 'git', None, _('use git extended diff format')),
149 ('l', 'limit', '',
149 ('l', 'limit', '',
150 _('limit number of changes displayed'), _('NUM')),
150 _('limit number of changes displayed'), _('NUM')),
151 ('M', 'no-merges', None, _('do not show merges')),
151 ('M', 'no-merges', None, _('do not show merges')),
152 ('', 'stat', None, _('output diffstat-style summary of changes')),
152 ('', 'stat', None, _('output diffstat-style summary of changes')),
153 ('G', 'graph', None, _("show the revision DAG")),
153 ('G', 'graph', None, _("show the revision DAG")),
154 ] + templateopts
154 ] + templateopts
155
155
156 diffopts = [
156 diffopts = [
157 ('a', 'text', None, _('treat all files as text')),
157 ('a', 'text', None, _('treat all files as text')),
158 ('g', 'git', None, _('use git extended diff format')),
158 ('g', 'git', None, _('use git extended diff format')),
159 ('', 'nodates', None, _('omit dates from diff headers'))
159 ('', 'nodates', None, _('omit dates from diff headers'))
160 ]
160 ]
161
161
162 diffwsopts = [
162 diffwsopts = [
163 ('w', 'ignore-all-space', None,
163 ('w', 'ignore-all-space', None,
164 _('ignore white space when comparing lines')),
164 _('ignore white space when comparing lines')),
165 ('b', 'ignore-space-change', None,
165 ('b', 'ignore-space-change', None,
166 _('ignore changes in the amount of white space')),
166 _('ignore changes in the amount of white space')),
167 ('B', 'ignore-blank-lines', None,
167 ('B', 'ignore-blank-lines', None,
168 _('ignore changes whose lines are all blank')),
168 _('ignore changes whose lines are all blank')),
169 ]
169 ]
170
170
171 diffopts2 = [
171 diffopts2 = [
172 ('', 'noprefix', None, _('omit a/ and b/ prefixes from filenames')),
172 ('', 'noprefix', None, _('omit a/ and b/ prefixes from filenames')),
173 ('p', 'show-function', None, _('show which function each change is in')),
173 ('p', 'show-function', None, _('show which function each change is in')),
174 ('', 'reverse', None, _('produce a diff that undoes the changes')),
174 ('', 'reverse', None, _('produce a diff that undoes the changes')),
175 ] + diffwsopts + [
175 ] + diffwsopts + [
176 ('U', 'unified', '',
176 ('U', 'unified', '',
177 _('number of lines of context to show'), _('NUM')),
177 _('number of lines of context to show'), _('NUM')),
178 ('', 'stat', None, _('output diffstat-style summary of changes')),
178 ('', 'stat', None, _('output diffstat-style summary of changes')),
179 ('', 'root', '', _('produce diffs relative to subdirectory'), _('DIR')),
179 ('', 'root', '', _('produce diffs relative to subdirectory'), _('DIR')),
180 ]
180 ]
181
181
182 mergetoolopts = [
182 mergetoolopts = [
183 ('t', 'tool', '', _('specify merge tool')),
183 ('t', 'tool', '', _('specify merge tool')),
184 ]
184 ]
185
185
186 similarityopts = [
186 similarityopts = [
187 ('s', 'similarity', '',
187 ('s', 'similarity', '',
188 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
188 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
189 ]
189 ]
190
190
191 subrepoopts = [
191 subrepoopts = [
192 ('S', 'subrepos', None,
192 ('S', 'subrepos', None,
193 _('recurse into subrepositories'))
193 _('recurse into subrepositories'))
194 ]
194 ]
195
195
196 debugrevlogopts = [
196 debugrevlogopts = [
197 ('c', 'changelog', False, _('open changelog')),
197 ('c', 'changelog', False, _('open changelog')),
198 ('m', 'manifest', False, _('open manifest')),
198 ('m', 'manifest', False, _('open manifest')),
199 ('', 'dir', '', _('open directory manifest')),
199 ('', 'dir', '', _('open directory manifest')),
200 ]
200 ]
201
201
202 # Commands start here, listed alphabetically
202 # Commands start here, listed alphabetically
203
203
204 @command('^add',
204 @command('^add',
205 walkopts + subrepoopts + dryrunopts,
205 walkopts + subrepoopts + dryrunopts,
206 _('[OPTION]... [FILE]...'),
206 _('[OPTION]... [FILE]...'),
207 inferrepo=True)
207 inferrepo=True)
208 def add(ui, repo, *pats, **opts):
208 def add(ui, repo, *pats, **opts):
209 """add the specified files on the next commit
209 """add the specified files on the next commit
210
210
211 Schedule files to be version controlled and added to the
211 Schedule files to be version controlled and added to the
212 repository.
212 repository.
213
213
214 The files will be added to the repository at the next commit. To
214 The files will be added to the repository at the next commit. To
215 undo an add before that, see :hg:`forget`.
215 undo an add before that, see :hg:`forget`.
216
216
217 If no names are given, add all files to the repository (except
217 If no names are given, add all files to the repository (except
218 files matching ``.hgignore``).
218 files matching ``.hgignore``).
219
219
220 .. container:: verbose
220 .. container:: verbose
221
221
222 Examples:
222 Examples:
223
223
224 - New (unknown) files are added
224 - New (unknown) files are added
225 automatically by :hg:`add`::
225 automatically by :hg:`add`::
226
226
227 $ ls
227 $ ls
228 foo.c
228 foo.c
229 $ hg status
229 $ hg status
230 ? foo.c
230 ? foo.c
231 $ hg add
231 $ hg add
232 adding foo.c
232 adding foo.c
233 $ hg status
233 $ hg status
234 A foo.c
234 A foo.c
235
235
236 - Specific files to be added can be specified::
236 - Specific files to be added can be specified::
237
237
238 $ ls
238 $ ls
239 bar.c foo.c
239 bar.c foo.c
240 $ hg status
240 $ hg status
241 ? bar.c
241 ? bar.c
242 ? foo.c
242 ? foo.c
243 $ hg add bar.c
243 $ hg add bar.c
244 $ hg status
244 $ hg status
245 A bar.c
245 A bar.c
246 ? foo.c
246 ? foo.c
247
247
248 Returns 0 if all files are successfully added.
248 Returns 0 if all files are successfully added.
249 """
249 """
250
250
251 m = scmutil.match(repo[None], pats, opts)
251 m = scmutil.match(repo[None], pats, opts)
252 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
252 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
253 return rejected and 1 or 0
253 return rejected and 1 or 0
254
254
255 @command('addremove',
255 @command('addremove',
256 similarityopts + subrepoopts + walkopts + dryrunopts,
256 similarityopts + subrepoopts + walkopts + dryrunopts,
257 _('[OPTION]... [FILE]...'),
257 _('[OPTION]... [FILE]...'),
258 inferrepo=True)
258 inferrepo=True)
259 def addremove(ui, repo, *pats, **opts):
259 def addremove(ui, repo, *pats, **opts):
260 """add all new files, delete all missing files
260 """add all new files, delete all missing files
261
261
262 Add all new files and remove all missing files from the
262 Add all new files and remove all missing files from the
263 repository.
263 repository.
264
264
265 Unless names are given, new files are ignored if they match any of
265 Unless names are given, new files are ignored if they match any of
266 the patterns in ``.hgignore``. As with add, these changes take
266 the patterns in ``.hgignore``. As with add, these changes take
267 effect at the next commit.
267 effect at the next commit.
268
268
269 Use the -s/--similarity option to detect renamed files. This
269 Use the -s/--similarity option to detect renamed files. This
270 option takes a percentage between 0 (disabled) and 100 (files must
270 option takes a percentage between 0 (disabled) and 100 (files must
271 be identical) as its parameter. With a parameter greater than 0,
271 be identical) as its parameter. With a parameter greater than 0,
272 this compares every removed file with every added file and records
272 this compares every removed file with every added file and records
273 those similar enough as renames. Detecting renamed files this way
273 those similar enough as renames. Detecting renamed files this way
274 can be expensive. After using this option, :hg:`status -C` can be
274 can be expensive. After using this option, :hg:`status -C` can be
275 used to check which files were identified as moved or renamed. If
275 used to check which files were identified as moved or renamed. If
276 not specified, -s/--similarity defaults to 100 and only renames of
276 not specified, -s/--similarity defaults to 100 and only renames of
277 identical files are detected.
277 identical files are detected.
278
278
279 .. container:: verbose
279 .. container:: verbose
280
280
281 Examples:
281 Examples:
282
282
283 - A number of files (bar.c and foo.c) are new,
283 - A number of files (bar.c and foo.c) are new,
284 while foobar.c has been removed (without using :hg:`remove`)
284 while foobar.c has been removed (without using :hg:`remove`)
285 from the repository::
285 from the repository::
286
286
287 $ ls
287 $ ls
288 bar.c foo.c
288 bar.c foo.c
289 $ hg status
289 $ hg status
290 ! foobar.c
290 ! foobar.c
291 ? bar.c
291 ? bar.c
292 ? foo.c
292 ? foo.c
293 $ hg addremove
293 $ hg addremove
294 adding bar.c
294 adding bar.c
295 adding foo.c
295 adding foo.c
296 removing foobar.c
296 removing foobar.c
297 $ hg status
297 $ hg status
298 A bar.c
298 A bar.c
299 A foo.c
299 A foo.c
300 R foobar.c
300 R foobar.c
301
301
302 - A file foobar.c was moved to foo.c without using :hg:`rename`.
302 - A file foobar.c was moved to foo.c without using :hg:`rename`.
303 Afterwards, it was edited slightly::
303 Afterwards, it was edited slightly::
304
304
305 $ ls
305 $ ls
306 foo.c
306 foo.c
307 $ hg status
307 $ hg status
308 ! foobar.c
308 ! foobar.c
309 ? foo.c
309 ? foo.c
310 $ hg addremove --similarity 90
310 $ hg addremove --similarity 90
311 removing foobar.c
311 removing foobar.c
312 adding foo.c
312 adding foo.c
313 recording removal of foobar.c as rename to foo.c (94% similar)
313 recording removal of foobar.c as rename to foo.c (94% similar)
314 $ hg status -C
314 $ hg status -C
315 A foo.c
315 A foo.c
316 foobar.c
316 foobar.c
317 R foobar.c
317 R foobar.c
318
318
319 Returns 0 if all files are successfully added.
319 Returns 0 if all files are successfully added.
320 """
320 """
321 try:
321 try:
322 sim = float(opts.get('similarity') or 100)
322 sim = float(opts.get('similarity') or 100)
323 except ValueError:
323 except ValueError:
324 raise error.Abort(_('similarity must be a number'))
324 raise error.Abort(_('similarity must be a number'))
325 if sim < 0 or sim > 100:
325 if sim < 0 or sim > 100:
326 raise error.Abort(_('similarity must be between 0 and 100'))
326 raise error.Abort(_('similarity must be between 0 and 100'))
327 matcher = scmutil.match(repo[None], pats, opts)
327 matcher = scmutil.match(repo[None], pats, opts)
328 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
328 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
329
329
330 @command('^annotate|blame',
330 @command('^annotate|blame',
331 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
331 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
332 ('', 'follow', None,
332 ('', 'follow', None,
333 _('follow copies/renames and list the filename (DEPRECATED)')),
333 _('follow copies/renames and list the filename (DEPRECATED)')),
334 ('', 'no-follow', None, _("don't follow copies and renames")),
334 ('', 'no-follow', None, _("don't follow copies and renames")),
335 ('a', 'text', None, _('treat all files as text')),
335 ('a', 'text', None, _('treat all files as text')),
336 ('u', 'user', None, _('list the author (long with -v)')),
336 ('u', 'user', None, _('list the author (long with -v)')),
337 ('f', 'file', None, _('list the filename')),
337 ('f', 'file', None, _('list the filename')),
338 ('d', 'date', None, _('list the date (short with -q)')),
338 ('d', 'date', None, _('list the date (short with -q)')),
339 ('n', 'number', None, _('list the revision number (default)')),
339 ('n', 'number', None, _('list the revision number (default)')),
340 ('c', 'changeset', None, _('list the changeset')),
340 ('c', 'changeset', None, _('list the changeset')),
341 ('l', 'line-number', None, _('show line number at the first appearance'))
341 ('l', 'line-number', None, _('show line number at the first appearance'))
342 ] + diffwsopts + walkopts + formatteropts,
342 ] + diffwsopts + walkopts + formatteropts,
343 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
343 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
344 inferrepo=True)
344 inferrepo=True)
345 def annotate(ui, repo, *pats, **opts):
345 def annotate(ui, repo, *pats, **opts):
346 """show changeset information by line for each file
346 """show changeset information by line for each file
347
347
348 List changes in files, showing the revision id responsible for
348 List changes in files, showing the revision id responsible for
349 each line.
349 each line.
350
350
351 This command is useful for discovering when a change was made and
351 This command is useful for discovering when a change was made and
352 by whom.
352 by whom.
353
353
354 If you include --file, --user, or --date, the revision number is
354 If you include --file, --user, or --date, the revision number is
355 suppressed unless you also include --number.
355 suppressed unless you also include --number.
356
356
357 Without the -a/--text option, annotate will avoid processing files
357 Without the -a/--text option, annotate will avoid processing files
358 it detects as binary. With -a, annotate will annotate the file
358 it detects as binary. With -a, annotate will annotate the file
359 anyway, although the results will probably be neither useful
359 anyway, although the results will probably be neither useful
360 nor desirable.
360 nor desirable.
361
361
362 Returns 0 on success.
362 Returns 0 on success.
363 """
363 """
364 if not pats:
364 if not pats:
365 raise error.Abort(_('at least one filename or pattern is required'))
365 raise error.Abort(_('at least one filename or pattern is required'))
366
366
367 if opts.get('follow'):
367 if opts.get('follow'):
368 # --follow is deprecated and now just an alias for -f/--file
368 # --follow is deprecated and now just an alias for -f/--file
369 # to mimic the behavior of Mercurial before version 1.5
369 # to mimic the behavior of Mercurial before version 1.5
370 opts['file'] = True
370 opts['file'] = True
371
371
372 ctx = scmutil.revsingle(repo, opts.get('rev'))
372 ctx = scmutil.revsingle(repo, opts.get('rev'))
373
373
374 fm = ui.formatter('annotate', opts)
374 fm = ui.formatter('annotate', opts)
375 if ui.quiet:
375 if ui.quiet:
376 datefunc = util.shortdate
376 datefunc = util.shortdate
377 else:
377 else:
378 datefunc = util.datestr
378 datefunc = util.datestr
379 if ctx.rev() is None:
379 if ctx.rev() is None:
380 def hexfn(node):
380 def hexfn(node):
381 if node is None:
381 if node is None:
382 return None
382 return None
383 else:
383 else:
384 return fm.hexfunc(node)
384 return fm.hexfunc(node)
385 if opts.get('changeset'):
385 if opts.get('changeset'):
386 # omit "+" suffix which is appended to node hex
386 # omit "+" suffix which is appended to node hex
387 def formatrev(rev):
387 def formatrev(rev):
388 if rev is None:
388 if rev is None:
389 return '%d' % ctx.p1().rev()
389 return '%d' % ctx.p1().rev()
390 else:
390 else:
391 return '%d' % rev
391 return '%d' % rev
392 else:
392 else:
393 def formatrev(rev):
393 def formatrev(rev):
394 if rev is None:
394 if rev is None:
395 return '%d+' % ctx.p1().rev()
395 return '%d+' % ctx.p1().rev()
396 else:
396 else:
397 return '%d ' % rev
397 return '%d ' % rev
398 def formathex(hex):
398 def formathex(hex):
399 if hex is None:
399 if hex is None:
400 return '%s+' % fm.hexfunc(ctx.p1().node())
400 return '%s+' % fm.hexfunc(ctx.p1().node())
401 else:
401 else:
402 return '%s ' % hex
402 return '%s ' % hex
403 else:
403 else:
404 hexfn = fm.hexfunc
404 hexfn = fm.hexfunc
405 formatrev = formathex = str
405 formatrev = formathex = str
406
406
407 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
407 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
408 ('number', ' ', lambda x: x[0].rev(), formatrev),
408 ('number', ' ', lambda x: x[0].rev(), formatrev),
409 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
409 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
410 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
410 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
411 ('file', ' ', lambda x: x[0].path(), str),
411 ('file', ' ', lambda x: x[0].path(), str),
412 ('line_number', ':', lambda x: x[1], str),
412 ('line_number', ':', lambda x: x[1], str),
413 ]
413 ]
414 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
414 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
415
415
416 if (not opts.get('user') and not opts.get('changeset')
416 if (not opts.get('user') and not opts.get('changeset')
417 and not opts.get('date') and not opts.get('file')):
417 and not opts.get('date') and not opts.get('file')):
418 opts['number'] = True
418 opts['number'] = True
419
419
420 linenumber = opts.get('line_number') is not None
420 linenumber = opts.get('line_number') is not None
421 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
421 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
422 raise error.Abort(_('at least one of -n/-c is required for -l'))
422 raise error.Abort(_('at least one of -n/-c is required for -l'))
423
423
424 ui.pager('annotate')
424 ui.pager('annotate')
425
425
426 if fm.isplain():
426 if fm.isplain():
427 def makefunc(get, fmt):
427 def makefunc(get, fmt):
428 return lambda x: fmt(get(x))
428 return lambda x: fmt(get(x))
429 else:
429 else:
430 def makefunc(get, fmt):
430 def makefunc(get, fmt):
431 return get
431 return get
432 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
432 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
433 if opts.get(op)]
433 if opts.get(op)]
434 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
434 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
435 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
435 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
436 if opts.get(op))
436 if opts.get(op))
437
437
438 def bad(x, y):
438 def bad(x, y):
439 raise error.Abort("%s: %s" % (x, y))
439 raise error.Abort("%s: %s" % (x, y))
440
440
441 m = scmutil.match(ctx, pats, opts, badfn=bad)
441 m = scmutil.match(ctx, pats, opts, badfn=bad)
442
442
443 follow = not opts.get('no_follow')
443 follow = not opts.get('no_follow')
444 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
444 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
445 whitespace=True)
445 whitespace=True)
446 for abs in ctx.walk(m):
446 for abs in ctx.walk(m):
447 fctx = ctx[abs]
447 fctx = ctx[abs]
448 if not opts.get('text') and util.binary(fctx.data()):
448 if not opts.get('text') and util.binary(fctx.data()):
449 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
449 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
450 continue
450 continue
451
451
452 lines = fctx.annotate(follow=follow, linenumber=linenumber,
452 lines = fctx.annotate(follow=follow, linenumber=linenumber,
453 diffopts=diffopts)
453 diffopts=diffopts)
454 if not lines:
454 if not lines:
455 continue
455 continue
456 formats = []
456 formats = []
457 pieces = []
457 pieces = []
458
458
459 for f, sep in funcmap:
459 for f, sep in funcmap:
460 l = [f(n) for n, dummy in lines]
460 l = [f(n) for n, dummy in lines]
461 if fm.isplain():
461 if fm.isplain():
462 sizes = [encoding.colwidth(x) for x in l]
462 sizes = [encoding.colwidth(x) for x in l]
463 ml = max(sizes)
463 ml = max(sizes)
464 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
464 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
465 else:
465 else:
466 formats.append(['%s' for x in l])
466 formats.append(['%s' for x in l])
467 pieces.append(l)
467 pieces.append(l)
468
468
469 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
469 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
470 fm.startitem()
470 fm.startitem()
471 fm.write(fields, "".join(f), *p)
471 fm.write(fields, "".join(f), *p)
472 fm.write('line', ": %s", l[1])
472 fm.write('line', ": %s", l[1])
473
473
474 if not lines[-1][1].endswith('\n'):
474 if not lines[-1][1].endswith('\n'):
475 fm.plain('\n')
475 fm.plain('\n')
476
476
477 fm.end()
477 fm.end()
478
478
479 @command('archive',
479 @command('archive',
480 [('', 'no-decode', None, _('do not pass files through decoders')),
480 [('', 'no-decode', None, _('do not pass files through decoders')),
481 ('p', 'prefix', '', _('directory prefix for files in archive'),
481 ('p', 'prefix', '', _('directory prefix for files in archive'),
482 _('PREFIX')),
482 _('PREFIX')),
483 ('r', 'rev', '', _('revision to distribute'), _('REV')),
483 ('r', 'rev', '', _('revision to distribute'), _('REV')),
484 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
484 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
485 ] + subrepoopts + walkopts,
485 ] + subrepoopts + walkopts,
486 _('[OPTION]... DEST'))
486 _('[OPTION]... DEST'))
487 def archive(ui, repo, dest, **opts):
487 def archive(ui, repo, dest, **opts):
488 '''create an unversioned archive of a repository revision
488 '''create an unversioned archive of a repository revision
489
489
490 By default, the revision used is the parent of the working
490 By default, the revision used is the parent of the working
491 directory; use -r/--rev to specify a different revision.
491 directory; use -r/--rev to specify a different revision.
492
492
493 The archive type is automatically detected based on file
493 The archive type is automatically detected based on file
494 extension (to override, use -t/--type).
494 extension (to override, use -t/--type).
495
495
496 .. container:: verbose
496 .. container:: verbose
497
497
498 Examples:
498 Examples:
499
499
500 - create a zip file containing the 1.0 release::
500 - create a zip file containing the 1.0 release::
501
501
502 hg archive -r 1.0 project-1.0.zip
502 hg archive -r 1.0 project-1.0.zip
503
503
504 - create a tarball excluding .hg files::
504 - create a tarball excluding .hg files::
505
505
506 hg archive project.tar.gz -X ".hg*"
506 hg archive project.tar.gz -X ".hg*"
507
507
508 Valid types are:
508 Valid types are:
509
509
510 :``files``: a directory full of files (default)
510 :``files``: a directory full of files (default)
511 :``tar``: tar archive, uncompressed
511 :``tar``: tar archive, uncompressed
512 :``tbz2``: tar archive, compressed using bzip2
512 :``tbz2``: tar archive, compressed using bzip2
513 :``tgz``: tar archive, compressed using gzip
513 :``tgz``: tar archive, compressed using gzip
514 :``uzip``: zip archive, uncompressed
514 :``uzip``: zip archive, uncompressed
515 :``zip``: zip archive, compressed using deflate
515 :``zip``: zip archive, compressed using deflate
516
516
517 The exact name of the destination archive or directory is given
517 The exact name of the destination archive or directory is given
518 using a format string; see :hg:`help export` for details.
518 using a format string; see :hg:`help export` for details.
519
519
520 Each member added to an archive file has a directory prefix
520 Each member added to an archive file has a directory prefix
521 prepended. Use -p/--prefix to specify a format string for the
521 prepended. Use -p/--prefix to specify a format string for the
522 prefix. The default is the basename of the archive, with suffixes
522 prefix. The default is the basename of the archive, with suffixes
523 removed.
523 removed.
524
524
525 Returns 0 on success.
525 Returns 0 on success.
526 '''
526 '''
527
527
528 ctx = scmutil.revsingle(repo, opts.get('rev'))
528 ctx = scmutil.revsingle(repo, opts.get('rev'))
529 if not ctx:
529 if not ctx:
530 raise error.Abort(_('no working directory: please specify a revision'))
530 raise error.Abort(_('no working directory: please specify a revision'))
531 node = ctx.node()
531 node = ctx.node()
532 dest = cmdutil.makefilename(repo, dest, node)
532 dest = cmdutil.makefilename(repo, dest, node)
533 if os.path.realpath(dest) == repo.root:
533 if os.path.realpath(dest) == repo.root:
534 raise error.Abort(_('repository root cannot be destination'))
534 raise error.Abort(_('repository root cannot be destination'))
535
535
536 kind = opts.get('type') or archival.guesskind(dest) or 'files'
536 kind = opts.get('type') or archival.guesskind(dest) or 'files'
537 prefix = opts.get('prefix')
537 prefix = opts.get('prefix')
538
538
539 if dest == '-':
539 if dest == '-':
540 if kind == 'files':
540 if kind == 'files':
541 raise error.Abort(_('cannot archive plain files to stdout'))
541 raise error.Abort(_('cannot archive plain files to stdout'))
542 dest = cmdutil.makefileobj(repo, dest)
542 dest = cmdutil.makefileobj(repo, dest)
543 if not prefix:
543 if not prefix:
544 prefix = os.path.basename(repo.root) + '-%h'
544 prefix = os.path.basename(repo.root) + '-%h'
545
545
546 prefix = cmdutil.makefilename(repo, prefix, node)
546 prefix = cmdutil.makefilename(repo, prefix, node)
547 matchfn = scmutil.match(ctx, [], opts)
547 matchfn = scmutil.match(ctx, [], opts)
548 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
548 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
549 matchfn, prefix, subrepos=opts.get('subrepos'))
549 matchfn, prefix, subrepos=opts.get('subrepos'))
550
550
551 @command('backout',
551 @command('backout',
552 [('', 'merge', None, _('merge with old dirstate parent after backout')),
552 [('', 'merge', None, _('merge with old dirstate parent after backout')),
553 ('', 'commit', None,
553 ('', 'commit', None,
554 _('commit if no conflicts were encountered (DEPRECATED)')),
554 _('commit if no conflicts were encountered (DEPRECATED)')),
555 ('', 'no-commit', None, _('do not commit')),
555 ('', 'no-commit', None, _('do not commit')),
556 ('', 'parent', '',
556 ('', 'parent', '',
557 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
557 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
558 ('r', 'rev', '', _('revision to backout'), _('REV')),
558 ('r', 'rev', '', _('revision to backout'), _('REV')),
559 ('e', 'edit', False, _('invoke editor on commit messages')),
559 ('e', 'edit', False, _('invoke editor on commit messages')),
560 ] + mergetoolopts + walkopts + commitopts + commitopts2,
560 ] + mergetoolopts + walkopts + commitopts + commitopts2,
561 _('[OPTION]... [-r] REV'))
561 _('[OPTION]... [-r] REV'))
562 def backout(ui, repo, node=None, rev=None, **opts):
562 def backout(ui, repo, node=None, rev=None, **opts):
563 '''reverse effect of earlier changeset
563 '''reverse effect of earlier changeset
564
564
565 Prepare a new changeset with the effect of REV undone in the
565 Prepare a new changeset with the effect of REV undone in the
566 current working directory. If no conflicts were encountered,
566 current working directory. If no conflicts were encountered,
567 it will be committed immediately.
567 it will be committed immediately.
568
568
569 If REV is the parent of the working directory, then this new changeset
569 If REV is the parent of the working directory, then this new changeset
570 is committed automatically (unless --no-commit is specified).
570 is committed automatically (unless --no-commit is specified).
571
571
572 .. note::
572 .. note::
573
573
574 :hg:`backout` cannot be used to fix either an unwanted or
574 :hg:`backout` cannot be used to fix either an unwanted or
575 incorrect merge.
575 incorrect merge.
576
576
577 .. container:: verbose
577 .. container:: verbose
578
578
579 Examples:
579 Examples:
580
580
581 - Reverse the effect of the parent of the working directory.
581 - Reverse the effect of the parent of the working directory.
582 This backout will be committed immediately::
582 This backout will be committed immediately::
583
583
584 hg backout -r .
584 hg backout -r .
585
585
586 - Reverse the effect of previous bad revision 23::
586 - Reverse the effect of previous bad revision 23::
587
587
588 hg backout -r 23
588 hg backout -r 23
589
589
590 - Reverse the effect of previous bad revision 23 and
590 - Reverse the effect of previous bad revision 23 and
591 leave changes uncommitted::
591 leave changes uncommitted::
592
592
593 hg backout -r 23 --no-commit
593 hg backout -r 23 --no-commit
594 hg commit -m "Backout revision 23"
594 hg commit -m "Backout revision 23"
595
595
596 By default, the pending changeset will have one parent,
596 By default, the pending changeset will have one parent,
597 maintaining a linear history. With --merge, the pending
597 maintaining a linear history. With --merge, the pending
598 changeset will instead have two parents: the old parent of the
598 changeset will instead have two parents: the old parent of the
599 working directory and a new child of REV that simply undoes REV.
599 working directory and a new child of REV that simply undoes REV.
600
600
601 Before version 1.7, the behavior without --merge was equivalent
601 Before version 1.7, the behavior without --merge was equivalent
602 to specifying --merge followed by :hg:`update --clean .` to
602 to specifying --merge followed by :hg:`update --clean .` to
603 cancel the merge and leave the child of REV as a head to be
603 cancel the merge and leave the child of REV as a head to be
604 merged separately.
604 merged separately.
605
605
606 See :hg:`help dates` for a list of formats valid for -d/--date.
606 See :hg:`help dates` for a list of formats valid for -d/--date.
607
607
608 See :hg:`help revert` for a way to restore files to the state
608 See :hg:`help revert` for a way to restore files to the state
609 of another revision.
609 of another revision.
610
610
611 Returns 0 on success, 1 if nothing to backout or there are unresolved
611 Returns 0 on success, 1 if nothing to backout or there are unresolved
612 files.
612 files.
613 '''
613 '''
614 wlock = lock = None
614 wlock = lock = None
615 try:
615 try:
616 wlock = repo.wlock()
616 wlock = repo.wlock()
617 lock = repo.lock()
617 lock = repo.lock()
618 return _dobackout(ui, repo, node, rev, **opts)
618 return _dobackout(ui, repo, node, rev, **opts)
619 finally:
619 finally:
620 release(lock, wlock)
620 release(lock, wlock)
621
621
622 def _dobackout(ui, repo, node=None, rev=None, **opts):
622 def _dobackout(ui, repo, node=None, rev=None, **opts):
623 if opts.get('commit') and opts.get('no_commit'):
623 if opts.get('commit') and opts.get('no_commit'):
624 raise error.Abort(_("cannot use --commit with --no-commit"))
624 raise error.Abort(_("cannot use --commit with --no-commit"))
625 if opts.get('merge') and opts.get('no_commit'):
625 if opts.get('merge') and opts.get('no_commit'):
626 raise error.Abort(_("cannot use --merge with --no-commit"))
626 raise error.Abort(_("cannot use --merge with --no-commit"))
627
627
628 if rev and node:
628 if rev and node:
629 raise error.Abort(_("please specify just one revision"))
629 raise error.Abort(_("please specify just one revision"))
630
630
631 if not rev:
631 if not rev:
632 rev = node
632 rev = node
633
633
634 if not rev:
634 if not rev:
635 raise error.Abort(_("please specify a revision to backout"))
635 raise error.Abort(_("please specify a revision to backout"))
636
636
637 date = opts.get('date')
637 date = opts.get('date')
638 if date:
638 if date:
639 opts['date'] = util.parsedate(date)
639 opts['date'] = util.parsedate(date)
640
640
641 cmdutil.checkunfinished(repo)
641 cmdutil.checkunfinished(repo)
642 cmdutil.bailifchanged(repo)
642 cmdutil.bailifchanged(repo)
643 node = scmutil.revsingle(repo, rev).node()
643 node = scmutil.revsingle(repo, rev).node()
644
644
645 op1, op2 = repo.dirstate.parents()
645 op1, op2 = repo.dirstate.parents()
646 if not repo.changelog.isancestor(node, op1):
646 if not repo.changelog.isancestor(node, op1):
647 raise error.Abort(_('cannot backout change that is not an ancestor'))
647 raise error.Abort(_('cannot backout change that is not an ancestor'))
648
648
649 p1, p2 = repo.changelog.parents(node)
649 p1, p2 = repo.changelog.parents(node)
650 if p1 == nullid:
650 if p1 == nullid:
651 raise error.Abort(_('cannot backout a change with no parents'))
651 raise error.Abort(_('cannot backout a change with no parents'))
652 if p2 != nullid:
652 if p2 != nullid:
653 if not opts.get('parent'):
653 if not opts.get('parent'):
654 raise error.Abort(_('cannot backout a merge changeset'))
654 raise error.Abort(_('cannot backout a merge changeset'))
655 p = repo.lookup(opts['parent'])
655 p = repo.lookup(opts['parent'])
656 if p not in (p1, p2):
656 if p not in (p1, p2):
657 raise error.Abort(_('%s is not a parent of %s') %
657 raise error.Abort(_('%s is not a parent of %s') %
658 (short(p), short(node)))
658 (short(p), short(node)))
659 parent = p
659 parent = p
660 else:
660 else:
661 if opts.get('parent'):
661 if opts.get('parent'):
662 raise error.Abort(_('cannot use --parent on non-merge changeset'))
662 raise error.Abort(_('cannot use --parent on non-merge changeset'))
663 parent = p1
663 parent = p1
664
664
665 # the backout should appear on the same branch
665 # the backout should appear on the same branch
666 branch = repo.dirstate.branch()
666 branch = repo.dirstate.branch()
667 bheads = repo.branchheads(branch)
667 bheads = repo.branchheads(branch)
668 rctx = scmutil.revsingle(repo, hex(parent))
668 rctx = scmutil.revsingle(repo, hex(parent))
669 if not opts.get('merge') and op1 != node:
669 if not opts.get('merge') and op1 != node:
670 dsguard = dirstateguard.dirstateguard(repo, 'backout')
670 dsguard = dirstateguard.dirstateguard(repo, 'backout')
671 try:
671 try:
672 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
672 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
673 'backout')
673 'backout')
674 stats = mergemod.update(repo, parent, True, True, node, False)
674 stats = mergemod.update(repo, parent, True, True, node, False)
675 repo.setparents(op1, op2)
675 repo.setparents(op1, op2)
676 dsguard.close()
676 dsguard.close()
677 hg._showstats(repo, stats)
677 hg._showstats(repo, stats)
678 if stats[3]:
678 if stats[3]:
679 repo.ui.status(_("use 'hg resolve' to retry unresolved "
679 repo.ui.status(_("use 'hg resolve' to retry unresolved "
680 "file merges\n"))
680 "file merges\n"))
681 return 1
681 return 1
682 finally:
682 finally:
683 ui.setconfig('ui', 'forcemerge', '', '')
683 ui.setconfig('ui', 'forcemerge', '', '')
684 lockmod.release(dsguard)
684 lockmod.release(dsguard)
685 else:
685 else:
686 hg.clean(repo, node, show_stats=False)
686 hg.clean(repo, node, show_stats=False)
687 repo.dirstate.setbranch(branch)
687 repo.dirstate.setbranch(branch)
688 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
688 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
689
689
690 if opts.get('no_commit'):
690 if opts.get('no_commit'):
691 msg = _("changeset %s backed out, "
691 msg = _("changeset %s backed out, "
692 "don't forget to commit.\n")
692 "don't forget to commit.\n")
693 ui.status(msg % short(node))
693 ui.status(msg % short(node))
694 return 0
694 return 0
695
695
696 def commitfunc(ui, repo, message, match, opts):
696 def commitfunc(ui, repo, message, match, opts):
697 editform = 'backout'
697 editform = 'backout'
698 e = cmdutil.getcommiteditor(editform=editform, **opts)
698 e = cmdutil.getcommiteditor(editform=editform, **opts)
699 if not message:
699 if not message:
700 # we don't translate commit messages
700 # we don't translate commit messages
701 message = "Backed out changeset %s" % short(node)
701 message = "Backed out changeset %s" % short(node)
702 e = cmdutil.getcommiteditor(edit=True, editform=editform)
702 e = cmdutil.getcommiteditor(edit=True, editform=editform)
703 return repo.commit(message, opts.get('user'), opts.get('date'),
703 return repo.commit(message, opts.get('user'), opts.get('date'),
704 match, editor=e)
704 match, editor=e)
705 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
705 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
706 if not newnode:
706 if not newnode:
707 ui.status(_("nothing changed\n"))
707 ui.status(_("nothing changed\n"))
708 return 1
708 return 1
709 cmdutil.commitstatus(repo, newnode, branch, bheads)
709 cmdutil.commitstatus(repo, newnode, branch, bheads)
710
710
711 def nice(node):
711 def nice(node):
712 return '%d:%s' % (repo.changelog.rev(node), short(node))
712 return '%d:%s' % (repo.changelog.rev(node), short(node))
713 ui.status(_('changeset %s backs out changeset %s\n') %
713 ui.status(_('changeset %s backs out changeset %s\n') %
714 (nice(repo.changelog.tip()), nice(node)))
714 (nice(repo.changelog.tip()), nice(node)))
715 if opts.get('merge') and op1 != node:
715 if opts.get('merge') and op1 != node:
716 hg.clean(repo, op1, show_stats=False)
716 hg.clean(repo, op1, show_stats=False)
717 ui.status(_('merging with changeset %s\n')
717 ui.status(_('merging with changeset %s\n')
718 % nice(repo.changelog.tip()))
718 % nice(repo.changelog.tip()))
719 try:
719 try:
720 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
720 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
721 'backout')
721 'backout')
722 return hg.merge(repo, hex(repo.changelog.tip()))
722 return hg.merge(repo, hex(repo.changelog.tip()))
723 finally:
723 finally:
724 ui.setconfig('ui', 'forcemerge', '', '')
724 ui.setconfig('ui', 'forcemerge', '', '')
725 return 0
725 return 0
726
726
727 @command('bisect',
727 @command('bisect',
728 [('r', 'reset', False, _('reset bisect state')),
728 [('r', 'reset', False, _('reset bisect state')),
729 ('g', 'good', False, _('mark changeset good')),
729 ('g', 'good', False, _('mark changeset good')),
730 ('b', 'bad', False, _('mark changeset bad')),
730 ('b', 'bad', False, _('mark changeset bad')),
731 ('s', 'skip', False, _('skip testing changeset')),
731 ('s', 'skip', False, _('skip testing changeset')),
732 ('e', 'extend', False, _('extend the bisect range')),
732 ('e', 'extend', False, _('extend the bisect range')),
733 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
733 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
734 ('U', 'noupdate', False, _('do not update to target'))],
734 ('U', 'noupdate', False, _('do not update to target'))],
735 _("[-gbsr] [-U] [-c CMD] [REV]"))
735 _("[-gbsr] [-U] [-c CMD] [REV]"))
736 def bisect(ui, repo, rev=None, extra=None, command=None,
736 def bisect(ui, repo, rev=None, extra=None, command=None,
737 reset=None, good=None, bad=None, skip=None, extend=None,
737 reset=None, good=None, bad=None, skip=None, extend=None,
738 noupdate=None):
738 noupdate=None):
739 """subdivision search of changesets
739 """subdivision search of changesets
740
740
741 This command helps to find changesets which introduce problems. To
741 This command helps to find changesets which introduce problems. To
742 use, mark the earliest changeset you know exhibits the problem as
742 use, mark the earliest changeset you know exhibits the problem as
743 bad, then mark the latest changeset which is free from the problem
743 bad, then mark the latest changeset which is free from the problem
744 as good. Bisect will update your working directory to a revision
744 as good. Bisect will update your working directory to a revision
745 for testing (unless the -U/--noupdate option is specified). Once
745 for testing (unless the -U/--noupdate option is specified). Once
746 you have performed tests, mark the working directory as good or
746 you have performed tests, mark the working directory as good or
747 bad, and bisect will either update to another candidate changeset
747 bad, and bisect will either update to another candidate changeset
748 or announce that it has found the bad revision.
748 or announce that it has found the bad revision.
749
749
750 As a shortcut, you can also use the revision argument to mark a
750 As a shortcut, you can also use the revision argument to mark a
751 revision as good or bad without checking it out first.
751 revision as good or bad without checking it out first.
752
752
753 If you supply a command, it will be used for automatic bisection.
753 If you supply a command, it will be used for automatic bisection.
754 The environment variable HG_NODE will contain the ID of the
754 The environment variable HG_NODE will contain the ID of the
755 changeset being tested. The exit status of the command will be
755 changeset being tested. The exit status of the command will be
756 used to mark revisions as good or bad: status 0 means good, 125
756 used to mark revisions as good or bad: status 0 means good, 125
757 means to skip the revision, 127 (command not found) will abort the
757 means to skip the revision, 127 (command not found) will abort the
758 bisection, and any other non-zero exit status means the revision
758 bisection, and any other non-zero exit status means the revision
759 is bad.
759 is bad.
760
760
761 .. container:: verbose
761 .. container:: verbose
762
762
763 Some examples:
763 Some examples:
764
764
765 - start a bisection with known bad revision 34, and good revision 12::
765 - start a bisection with known bad revision 34, and good revision 12::
766
766
767 hg bisect --bad 34
767 hg bisect --bad 34
768 hg bisect --good 12
768 hg bisect --good 12
769
769
770 - advance the current bisection by marking current revision as good or
770 - advance the current bisection by marking current revision as good or
771 bad::
771 bad::
772
772
773 hg bisect --good
773 hg bisect --good
774 hg bisect --bad
774 hg bisect --bad
775
775
776 - mark the current revision, or a known revision, to be skipped (e.g. if
776 - mark the current revision, or a known revision, to be skipped (e.g. if
777 that revision is not usable because of another issue)::
777 that revision is not usable because of another issue)::
778
778
779 hg bisect --skip
779 hg bisect --skip
780 hg bisect --skip 23
780 hg bisect --skip 23
781
781
782 - skip all revisions that do not touch directories ``foo`` or ``bar``::
782 - skip all revisions that do not touch directories ``foo`` or ``bar``::
783
783
784 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
784 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
785
785
786 - forget the current bisection::
786 - forget the current bisection::
787
787
788 hg bisect --reset
788 hg bisect --reset
789
789
790 - use 'make && make tests' to automatically find the first broken
790 - use 'make && make tests' to automatically find the first broken
791 revision::
791 revision::
792
792
793 hg bisect --reset
793 hg bisect --reset
794 hg bisect --bad 34
794 hg bisect --bad 34
795 hg bisect --good 12
795 hg bisect --good 12
796 hg bisect --command "make && make tests"
796 hg bisect --command "make && make tests"
797
797
798 - see all changesets whose states are already known in the current
798 - see all changesets whose states are already known in the current
799 bisection::
799 bisection::
800
800
801 hg log -r "bisect(pruned)"
801 hg log -r "bisect(pruned)"
802
802
803 - see the changeset currently being bisected (especially useful
803 - see the changeset currently being bisected (especially useful
804 if running with -U/--noupdate)::
804 if running with -U/--noupdate)::
805
805
806 hg log -r "bisect(current)"
806 hg log -r "bisect(current)"
807
807
808 - see all changesets that took part in the current bisection::
808 - see all changesets that took part in the current bisection::
809
809
810 hg log -r "bisect(range)"
810 hg log -r "bisect(range)"
811
811
812 - you can even get a nice graph::
812 - you can even get a nice graph::
813
813
814 hg log --graph -r "bisect(range)"
814 hg log --graph -r "bisect(range)"
815
815
816 See :hg:`help revisions.bisect` for more about the `bisect()` predicate.
816 See :hg:`help revisions.bisect` for more about the `bisect()` predicate.
817
817
818 Returns 0 on success.
818 Returns 0 on success.
819 """
819 """
820 # backward compatibility
820 # backward compatibility
821 if rev in "good bad reset init".split():
821 if rev in "good bad reset init".split():
822 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
822 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
823 cmd, rev, extra = rev, extra, None
823 cmd, rev, extra = rev, extra, None
824 if cmd == "good":
824 if cmd == "good":
825 good = True
825 good = True
826 elif cmd == "bad":
826 elif cmd == "bad":
827 bad = True
827 bad = True
828 else:
828 else:
829 reset = True
829 reset = True
830 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
830 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
831 raise error.Abort(_('incompatible arguments'))
831 raise error.Abort(_('incompatible arguments'))
832
832
833 cmdutil.checkunfinished(repo)
833 cmdutil.checkunfinished(repo)
834
834
835 if reset:
835 if reset:
836 hbisect.resetstate(repo)
836 hbisect.resetstate(repo)
837 return
837 return
838
838
839 state = hbisect.load_state(repo)
839 state = hbisect.load_state(repo)
840
840
841 # update state
841 # update state
842 if good or bad or skip:
842 if good or bad or skip:
843 if rev:
843 if rev:
844 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
844 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
845 else:
845 else:
846 nodes = [repo.lookup('.')]
846 nodes = [repo.lookup('.')]
847 if good:
847 if good:
848 state['good'] += nodes
848 state['good'] += nodes
849 elif bad:
849 elif bad:
850 state['bad'] += nodes
850 state['bad'] += nodes
851 elif skip:
851 elif skip:
852 state['skip'] += nodes
852 state['skip'] += nodes
853 hbisect.save_state(repo, state)
853 hbisect.save_state(repo, state)
854 if not (state['good'] and state['bad']):
854 if not (state['good'] and state['bad']):
855 return
855 return
856
856
857 def mayupdate(repo, node, show_stats=True):
857 def mayupdate(repo, node, show_stats=True):
858 """common used update sequence"""
858 """common used update sequence"""
859 if noupdate:
859 if noupdate:
860 return
860 return
861 cmdutil.bailifchanged(repo)
861 cmdutil.bailifchanged(repo)
862 return hg.clean(repo, node, show_stats=show_stats)
862 return hg.clean(repo, node, show_stats=show_stats)
863
863
864 displayer = cmdutil.show_changeset(ui, repo, {})
864 displayer = cmdutil.show_changeset(ui, repo, {})
865
865
866 if command:
866 if command:
867 changesets = 1
867 changesets = 1
868 if noupdate:
868 if noupdate:
869 try:
869 try:
870 node = state['current'][0]
870 node = state['current'][0]
871 except LookupError:
871 except LookupError:
872 raise error.Abort(_('current bisect revision is unknown - '
872 raise error.Abort(_('current bisect revision is unknown - '
873 'start a new bisect to fix'))
873 'start a new bisect to fix'))
874 else:
874 else:
875 node, p2 = repo.dirstate.parents()
875 node, p2 = repo.dirstate.parents()
876 if p2 != nullid:
876 if p2 != nullid:
877 raise error.Abort(_('current bisect revision is a merge'))
877 raise error.Abort(_('current bisect revision is a merge'))
878 if rev:
878 if rev:
879 node = repo[scmutil.revsingle(repo, rev, node)].node()
879 node = repo[scmutil.revsingle(repo, rev, node)].node()
880 try:
880 try:
881 while changesets:
881 while changesets:
882 # update state
882 # update state
883 state['current'] = [node]
883 state['current'] = [node]
884 hbisect.save_state(repo, state)
884 hbisect.save_state(repo, state)
885 status = ui.system(command, environ={'HG_NODE': hex(node)})
885 status = ui.system(command, environ={'HG_NODE': hex(node)})
886 if status == 125:
886 if status == 125:
887 transition = "skip"
887 transition = "skip"
888 elif status == 0:
888 elif status == 0:
889 transition = "good"
889 transition = "good"
890 # status < 0 means process was killed
890 # status < 0 means process was killed
891 elif status == 127:
891 elif status == 127:
892 raise error.Abort(_("failed to execute %s") % command)
892 raise error.Abort(_("failed to execute %s") % command)
893 elif status < 0:
893 elif status < 0:
894 raise error.Abort(_("%s killed") % command)
894 raise error.Abort(_("%s killed") % command)
895 else:
895 else:
896 transition = "bad"
896 transition = "bad"
897 state[transition].append(node)
897 state[transition].append(node)
898 ctx = repo[node]
898 ctx = repo[node]
899 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
899 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
900 hbisect.checkstate(state)
900 hbisect.checkstate(state)
901 # bisect
901 # bisect
902 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
902 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
903 # update to next check
903 # update to next check
904 node = nodes[0]
904 node = nodes[0]
905 mayupdate(repo, node, show_stats=False)
905 mayupdate(repo, node, show_stats=False)
906 finally:
906 finally:
907 state['current'] = [node]
907 state['current'] = [node]
908 hbisect.save_state(repo, state)
908 hbisect.save_state(repo, state)
909 hbisect.printresult(ui, repo, state, displayer, nodes, bgood)
909 hbisect.printresult(ui, repo, state, displayer, nodes, bgood)
910 return
910 return
911
911
912 hbisect.checkstate(state)
912 hbisect.checkstate(state)
913
913
914 # actually bisect
914 # actually bisect
915 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
915 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
916 if extend:
916 if extend:
917 if not changesets:
917 if not changesets:
918 extendnode = hbisect.extendrange(repo, state, nodes, good)
918 extendnode = hbisect.extendrange(repo, state, nodes, good)
919 if extendnode is not None:
919 if extendnode is not None:
920 ui.write(_("Extending search to changeset %d:%s\n")
920 ui.write(_("Extending search to changeset %d:%s\n")
921 % (extendnode.rev(), extendnode))
921 % (extendnode.rev(), extendnode))
922 state['current'] = [extendnode.node()]
922 state['current'] = [extendnode.node()]
923 hbisect.save_state(repo, state)
923 hbisect.save_state(repo, state)
924 return mayupdate(repo, extendnode.node())
924 return mayupdate(repo, extendnode.node())
925 raise error.Abort(_("nothing to extend"))
925 raise error.Abort(_("nothing to extend"))
926
926
927 if changesets == 0:
927 if changesets == 0:
928 hbisect.printresult(ui, repo, state, displayer, nodes, good)
928 hbisect.printresult(ui, repo, state, displayer, nodes, good)
929 else:
929 else:
930 assert len(nodes) == 1 # only a single node can be tested next
930 assert len(nodes) == 1 # only a single node can be tested next
931 node = nodes[0]
931 node = nodes[0]
932 # compute the approximate number of remaining tests
932 # compute the approximate number of remaining tests
933 tests, size = 0, 2
933 tests, size = 0, 2
934 while size <= changesets:
934 while size <= changesets:
935 tests, size = tests + 1, size * 2
935 tests, size = tests + 1, size * 2
936 rev = repo.changelog.rev(node)
936 rev = repo.changelog.rev(node)
937 ui.write(_("Testing changeset %d:%s "
937 ui.write(_("Testing changeset %d:%s "
938 "(%d changesets remaining, ~%d tests)\n")
938 "(%d changesets remaining, ~%d tests)\n")
939 % (rev, short(node), changesets, tests))
939 % (rev, short(node), changesets, tests))
940 state['current'] = [node]
940 state['current'] = [node]
941 hbisect.save_state(repo, state)
941 hbisect.save_state(repo, state)
942 return mayupdate(repo, node)
942 return mayupdate(repo, node)
943
943
944 @command('bookmarks|bookmark',
944 @command('bookmarks|bookmark',
945 [('f', 'force', False, _('force')),
945 [('f', 'force', False, _('force')),
946 ('r', 'rev', '', _('revision for bookmark action'), _('REV')),
946 ('r', 'rev', '', _('revision for bookmark action'), _('REV')),
947 ('d', 'delete', False, _('delete a given bookmark')),
947 ('d', 'delete', False, _('delete a given bookmark')),
948 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
948 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
949 ('i', 'inactive', False, _('mark a bookmark inactive')),
949 ('i', 'inactive', False, _('mark a bookmark inactive')),
950 ] + formatteropts,
950 ] + formatteropts,
951 _('hg bookmarks [OPTIONS]... [NAME]...'))
951 _('hg bookmarks [OPTIONS]... [NAME]...'))
952 def bookmark(ui, repo, *names, **opts):
952 def bookmark(ui, repo, *names, **opts):
953 '''create a new bookmark or list existing bookmarks
953 '''create a new bookmark or list existing bookmarks
954
954
955 Bookmarks are labels on changesets to help track lines of development.
955 Bookmarks are labels on changesets to help track lines of development.
956 Bookmarks are unversioned and can be moved, renamed and deleted.
956 Bookmarks are unversioned and can be moved, renamed and deleted.
957 Deleting or moving a bookmark has no effect on the associated changesets.
957 Deleting or moving a bookmark has no effect on the associated changesets.
958
958
959 Creating or updating to a bookmark causes it to be marked as 'active'.
959 Creating or updating to a bookmark causes it to be marked as 'active'.
960 The active bookmark is indicated with a '*'.
960 The active bookmark is indicated with a '*'.
961 When a commit is made, the active bookmark will advance to the new commit.
961 When a commit is made, the active bookmark will advance to the new commit.
962 A plain :hg:`update` will also advance an active bookmark, if possible.
962 A plain :hg:`update` will also advance an active bookmark, if possible.
963 Updating away from a bookmark will cause it to be deactivated.
963 Updating away from a bookmark will cause it to be deactivated.
964
964
965 Bookmarks can be pushed and pulled between repositories (see
965 Bookmarks can be pushed and pulled between repositories (see
966 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
966 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
967 diverged, a new 'divergent bookmark' of the form 'name@path' will
967 diverged, a new 'divergent bookmark' of the form 'name@path' will
968 be created. Using :hg:`merge` will resolve the divergence.
968 be created. Using :hg:`merge` will resolve the divergence.
969
969
970 A bookmark named '@' has the special property that :hg:`clone` will
970 A bookmark named '@' has the special property that :hg:`clone` will
971 check it out by default if it exists.
971 check it out by default if it exists.
972
972
973 .. container:: verbose
973 .. container:: verbose
974
974
975 Examples:
975 Examples:
976
976
977 - create an active bookmark for a new line of development::
977 - create an active bookmark for a new line of development::
978
978
979 hg book new-feature
979 hg book new-feature
980
980
981 - create an inactive bookmark as a place marker::
981 - create an inactive bookmark as a place marker::
982
982
983 hg book -i reviewed
983 hg book -i reviewed
984
984
985 - create an inactive bookmark on another changeset::
985 - create an inactive bookmark on another changeset::
986
986
987 hg book -r .^ tested
987 hg book -r .^ tested
988
988
989 - rename bookmark turkey to dinner::
989 - rename bookmark turkey to dinner::
990
990
991 hg book -m turkey dinner
991 hg book -m turkey dinner
992
992
993 - move the '@' bookmark from another branch::
993 - move the '@' bookmark from another branch::
994
994
995 hg book -f @
995 hg book -f @
996 '''
996 '''
997 force = opts.get('force')
997 force = opts.get('force')
998 rev = opts.get('rev')
998 rev = opts.get('rev')
999 delete = opts.get('delete')
999 delete = opts.get('delete')
1000 rename = opts.get('rename')
1000 rename = opts.get('rename')
1001 inactive = opts.get('inactive')
1001 inactive = opts.get('inactive')
1002
1002
1003 def checkformat(mark):
1003 def checkformat(mark):
1004 mark = mark.strip()
1004 mark = mark.strip()
1005 if not mark:
1005 if not mark:
1006 raise error.Abort(_("bookmark names cannot consist entirely of "
1006 raise error.Abort(_("bookmark names cannot consist entirely of "
1007 "whitespace"))
1007 "whitespace"))
1008 scmutil.checknewlabel(repo, mark, 'bookmark')
1008 scmutil.checknewlabel(repo, mark, 'bookmark')
1009 return mark
1009 return mark
1010
1010
1011 def checkconflict(repo, mark, cur, force=False, target=None):
1011 def checkconflict(repo, mark, cur, force=False, target=None):
1012 if mark in marks and not force:
1012 if mark in marks and not force:
1013 if target:
1013 if target:
1014 if marks[mark] == target and target == cur:
1014 if marks[mark] == target and target == cur:
1015 # re-activating a bookmark
1015 # re-activating a bookmark
1016 return
1016 return
1017 anc = repo.changelog.ancestors([repo[target].rev()])
1017 anc = repo.changelog.ancestors([repo[target].rev()])
1018 bmctx = repo[marks[mark]]
1018 bmctx = repo[marks[mark]]
1019 divs = [repo[b].node() for b in marks
1019 divs = [repo[b].node() for b in marks
1020 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
1020 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
1021
1021
1022 # allow resolving a single divergent bookmark even if moving
1022 # allow resolving a single divergent bookmark even if moving
1023 # the bookmark across branches when a revision is specified
1023 # the bookmark across branches when a revision is specified
1024 # that contains a divergent bookmark
1024 # that contains a divergent bookmark
1025 if bmctx.rev() not in anc and target in divs:
1025 if bmctx.rev() not in anc and target in divs:
1026 bookmarks.deletedivergent(repo, [target], mark)
1026 bookmarks.deletedivergent(repo, [target], mark)
1027 return
1027 return
1028
1028
1029 deletefrom = [b for b in divs
1029 deletefrom = [b for b in divs
1030 if repo[b].rev() in anc or b == target]
1030 if repo[b].rev() in anc or b == target]
1031 bookmarks.deletedivergent(repo, deletefrom, mark)
1031 bookmarks.deletedivergent(repo, deletefrom, mark)
1032 if bookmarks.validdest(repo, bmctx, repo[target]):
1032 if bookmarks.validdest(repo, bmctx, repo[target]):
1033 ui.status(_("moving bookmark '%s' forward from %s\n") %
1033 ui.status(_("moving bookmark '%s' forward from %s\n") %
1034 (mark, short(bmctx.node())))
1034 (mark, short(bmctx.node())))
1035 return
1035 return
1036 raise error.Abort(_("bookmark '%s' already exists "
1036 raise error.Abort(_("bookmark '%s' already exists "
1037 "(use -f to force)") % mark)
1037 "(use -f to force)") % mark)
1038 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
1038 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
1039 and not force):
1039 and not force):
1040 raise error.Abort(
1040 raise error.Abort(
1041 _("a bookmark cannot have the name of an existing branch"))
1041 _("a bookmark cannot have the name of an existing branch"))
1042
1042
1043 if delete and rename:
1043 if delete and rename:
1044 raise error.Abort(_("--delete and --rename are incompatible"))
1044 raise error.Abort(_("--delete and --rename are incompatible"))
1045 if delete and rev:
1045 if delete and rev:
1046 raise error.Abort(_("--rev is incompatible with --delete"))
1046 raise error.Abort(_("--rev is incompatible with --delete"))
1047 if rename and rev:
1047 if rename and rev:
1048 raise error.Abort(_("--rev is incompatible with --rename"))
1048 raise error.Abort(_("--rev is incompatible with --rename"))
1049 if not names and (delete or rev):
1049 if not names and (delete or rev):
1050 raise error.Abort(_("bookmark name required"))
1050 raise error.Abort(_("bookmark name required"))
1051
1051
1052 if delete or rename or names or inactive:
1052 if delete or rename or names or inactive:
1053 wlock = lock = tr = None
1053 wlock = lock = tr = None
1054 try:
1054 try:
1055 wlock = repo.wlock()
1055 wlock = repo.wlock()
1056 lock = repo.lock()
1056 lock = repo.lock()
1057 cur = repo.changectx('.').node()
1057 cur = repo.changectx('.').node()
1058 marks = repo._bookmarks
1058 marks = repo._bookmarks
1059 if delete:
1059 if delete:
1060 tr = repo.transaction('bookmark')
1060 tr = repo.transaction('bookmark')
1061 for mark in names:
1061 for mark in names:
1062 if mark not in marks:
1062 if mark not in marks:
1063 raise error.Abort(_("bookmark '%s' does not exist") %
1063 raise error.Abort(_("bookmark '%s' does not exist") %
1064 mark)
1064 mark)
1065 if mark == repo._activebookmark:
1065 if mark == repo._activebookmark:
1066 bookmarks.deactivate(repo)
1066 bookmarks.deactivate(repo)
1067 del marks[mark]
1067 del marks[mark]
1068
1068
1069 elif rename:
1069 elif rename:
1070 tr = repo.transaction('bookmark')
1070 tr = repo.transaction('bookmark')
1071 if not names:
1071 if not names:
1072 raise error.Abort(_("new bookmark name required"))
1072 raise error.Abort(_("new bookmark name required"))
1073 elif len(names) > 1:
1073 elif len(names) > 1:
1074 raise error.Abort(_("only one new bookmark name allowed"))
1074 raise error.Abort(_("only one new bookmark name allowed"))
1075 mark = checkformat(names[0])
1075 mark = checkformat(names[0])
1076 if rename not in marks:
1076 if rename not in marks:
1077 raise error.Abort(_("bookmark '%s' does not exist")
1077 raise error.Abort(_("bookmark '%s' does not exist")
1078 % rename)
1078 % rename)
1079 checkconflict(repo, mark, cur, force)
1079 checkconflict(repo, mark, cur, force)
1080 marks[mark] = marks[rename]
1080 marks[mark] = marks[rename]
1081 if repo._activebookmark == rename and not inactive:
1081 if repo._activebookmark == rename and not inactive:
1082 bookmarks.activate(repo, mark)
1082 bookmarks.activate(repo, mark)
1083 del marks[rename]
1083 del marks[rename]
1084 elif names:
1084 elif names:
1085 tr = repo.transaction('bookmark')
1085 tr = repo.transaction('bookmark')
1086 newact = None
1086 newact = None
1087 for mark in names:
1087 for mark in names:
1088 mark = checkformat(mark)
1088 mark = checkformat(mark)
1089 if newact is None:
1089 if newact is None:
1090 newact = mark
1090 newact = mark
1091 if inactive and mark == repo._activebookmark:
1091 if inactive and mark == repo._activebookmark:
1092 bookmarks.deactivate(repo)
1092 bookmarks.deactivate(repo)
1093 return
1093 return
1094 tgt = cur
1094 tgt = cur
1095 if rev:
1095 if rev:
1096 tgt = scmutil.revsingle(repo, rev).node()
1096 tgt = scmutil.revsingle(repo, rev).node()
1097 checkconflict(repo, mark, cur, force, tgt)
1097 checkconflict(repo, mark, cur, force, tgt)
1098 marks[mark] = tgt
1098 marks[mark] = tgt
1099 if not inactive and cur == marks[newact] and not rev:
1099 if not inactive and cur == marks[newact] and not rev:
1100 bookmarks.activate(repo, newact)
1100 bookmarks.activate(repo, newact)
1101 elif cur != tgt and newact == repo._activebookmark:
1101 elif cur != tgt and newact == repo._activebookmark:
1102 bookmarks.deactivate(repo)
1102 bookmarks.deactivate(repo)
1103 elif inactive:
1103 elif inactive:
1104 if len(marks) == 0:
1104 if len(marks) == 0:
1105 ui.status(_("no bookmarks set\n"))
1105 ui.status(_("no bookmarks set\n"))
1106 elif not repo._activebookmark:
1106 elif not repo._activebookmark:
1107 ui.status(_("no active bookmark\n"))
1107 ui.status(_("no active bookmark\n"))
1108 else:
1108 else:
1109 bookmarks.deactivate(repo)
1109 bookmarks.deactivate(repo)
1110 if tr is not None:
1110 if tr is not None:
1111 marks.recordchange(tr)
1111 marks.recordchange(tr)
1112 tr.close()
1112 tr.close()
1113 finally:
1113 finally:
1114 lockmod.release(tr, lock, wlock)
1114 lockmod.release(tr, lock, wlock)
1115 else: # show bookmarks
1115 else: # show bookmarks
1116 fm = ui.formatter('bookmarks', opts)
1116 fm = ui.formatter('bookmarks', opts)
1117 hexfn = fm.hexfunc
1117 hexfn = fm.hexfunc
1118 marks = repo._bookmarks
1118 marks = repo._bookmarks
1119 if len(marks) == 0 and fm.isplain():
1119 if len(marks) == 0 and fm.isplain():
1120 ui.status(_("no bookmarks set\n"))
1120 ui.status(_("no bookmarks set\n"))
1121 for bmark, n in sorted(marks.iteritems()):
1121 for bmark, n in sorted(marks.iteritems()):
1122 active = repo._activebookmark
1122 active = repo._activebookmark
1123 if bmark == active:
1123 if bmark == active:
1124 prefix, label = '*', activebookmarklabel
1124 prefix, label = '*', activebookmarklabel
1125 else:
1125 else:
1126 prefix, label = ' ', ''
1126 prefix, label = ' ', ''
1127
1127
1128 fm.startitem()
1128 fm.startitem()
1129 if not ui.quiet:
1129 if not ui.quiet:
1130 fm.plain(' %s ' % prefix, label=label)
1130 fm.plain(' %s ' % prefix, label=label)
1131 fm.write('bookmark', '%s', bmark, label=label)
1131 fm.write('bookmark', '%s', bmark, label=label)
1132 pad = " " * (25 - encoding.colwidth(bmark))
1132 pad = " " * (25 - encoding.colwidth(bmark))
1133 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1133 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1134 repo.changelog.rev(n), hexfn(n), label=label)
1134 repo.changelog.rev(n), hexfn(n), label=label)
1135 fm.data(active=(bmark == active))
1135 fm.data(active=(bmark == active))
1136 fm.plain('\n')
1136 fm.plain('\n')
1137 fm.end()
1137 fm.end()
1138
1138
1139 @command('branch',
1139 @command('branch',
1140 [('f', 'force', None,
1140 [('f', 'force', None,
1141 _('set branch name even if it shadows an existing branch')),
1141 _('set branch name even if it shadows an existing branch')),
1142 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1142 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1143 _('[-fC] [NAME]'))
1143 _('[-fC] [NAME]'))
1144 def branch(ui, repo, label=None, **opts):
1144 def branch(ui, repo, label=None, **opts):
1145 """set or show the current branch name
1145 """set or show the current branch name
1146
1146
1147 .. note::
1147 .. note::
1148
1148
1149 Branch names are permanent and global. Use :hg:`bookmark` to create a
1149 Branch names are permanent and global. Use :hg:`bookmark` to create a
1150 light-weight bookmark instead. See :hg:`help glossary` for more
1150 light-weight bookmark instead. See :hg:`help glossary` for more
1151 information about named branches and bookmarks.
1151 information about named branches and bookmarks.
1152
1152
1153 With no argument, show the current branch name. With one argument,
1153 With no argument, show the current branch name. With one argument,
1154 set the working directory branch name (the branch will not exist
1154 set the working directory branch name (the branch will not exist
1155 in the repository until the next commit). Standard practice
1155 in the repository until the next commit). Standard practice
1156 recommends that primary development take place on the 'default'
1156 recommends that primary development take place on the 'default'
1157 branch.
1157 branch.
1158
1158
1159 Unless -f/--force is specified, branch will not let you set a
1159 Unless -f/--force is specified, branch will not let you set a
1160 branch name that already exists.
1160 branch name that already exists.
1161
1161
1162 Use -C/--clean to reset the working directory branch to that of
1162 Use -C/--clean to reset the working directory branch to that of
1163 the parent of the working directory, negating a previous branch
1163 the parent of the working directory, negating a previous branch
1164 change.
1164 change.
1165
1165
1166 Use the command :hg:`update` to switch to an existing branch. Use
1166 Use the command :hg:`update` to switch to an existing branch. Use
1167 :hg:`commit --close-branch` to mark this branch head as closed.
1167 :hg:`commit --close-branch` to mark this branch head as closed.
1168 When all heads of a branch are closed, the branch will be
1168 When all heads of a branch are closed, the branch will be
1169 considered closed.
1169 considered closed.
1170
1170
1171 Returns 0 on success.
1171 Returns 0 on success.
1172 """
1172 """
1173 if label:
1173 if label:
1174 label = label.strip()
1174 label = label.strip()
1175
1175
1176 if not opts.get('clean') and not label:
1176 if not opts.get('clean') and not label:
1177 ui.write("%s\n" % repo.dirstate.branch())
1177 ui.write("%s\n" % repo.dirstate.branch())
1178 return
1178 return
1179
1179
1180 with repo.wlock():
1180 with repo.wlock():
1181 if opts.get('clean'):
1181 if opts.get('clean'):
1182 label = repo[None].p1().branch()
1182 label = repo[None].p1().branch()
1183 repo.dirstate.setbranch(label)
1183 repo.dirstate.setbranch(label)
1184 ui.status(_('reset working directory to branch %s\n') % label)
1184 ui.status(_('reset working directory to branch %s\n') % label)
1185 elif label:
1185 elif label:
1186 if not opts.get('force') and label in repo.branchmap():
1186 if not opts.get('force') and label in repo.branchmap():
1187 if label not in [p.branch() for p in repo[None].parents()]:
1187 if label not in [p.branch() for p in repo[None].parents()]:
1188 raise error.Abort(_('a branch of the same name already'
1188 raise error.Abort(_('a branch of the same name already'
1189 ' exists'),
1189 ' exists'),
1190 # i18n: "it" refers to an existing branch
1190 # i18n: "it" refers to an existing branch
1191 hint=_("use 'hg update' to switch to it"))
1191 hint=_("use 'hg update' to switch to it"))
1192 scmutil.checknewlabel(repo, label, 'branch')
1192 scmutil.checknewlabel(repo, label, 'branch')
1193 repo.dirstate.setbranch(label)
1193 repo.dirstate.setbranch(label)
1194 ui.status(_('marked working directory as branch %s\n') % label)
1194 ui.status(_('marked working directory as branch %s\n') % label)
1195
1195
1196 # find any open named branches aside from default
1196 # find any open named branches aside from default
1197 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1197 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1198 if n != "default" and not c]
1198 if n != "default" and not c]
1199 if not others:
1199 if not others:
1200 ui.status(_('(branches are permanent and global, '
1200 ui.status(_('(branches are permanent and global, '
1201 'did you want a bookmark?)\n'))
1201 'did you want a bookmark?)\n'))
1202
1202
1203 @command('branches',
1203 @command('branches',
1204 [('a', 'active', False,
1204 [('a', 'active', False,
1205 _('show only branches that have unmerged heads (DEPRECATED)')),
1205 _('show only branches that have unmerged heads (DEPRECATED)')),
1206 ('c', 'closed', False, _('show normal and closed branches')),
1206 ('c', 'closed', False, _('show normal and closed branches')),
1207 ] + formatteropts,
1207 ] + formatteropts,
1208 _('[-c]'))
1208 _('[-c]'))
1209 def branches(ui, repo, active=False, closed=False, **opts):
1209 def branches(ui, repo, active=False, closed=False, **opts):
1210 """list repository named branches
1210 """list repository named branches
1211
1211
1212 List the repository's named branches, indicating which ones are
1212 List the repository's named branches, indicating which ones are
1213 inactive. If -c/--closed is specified, also list branches which have
1213 inactive. If -c/--closed is specified, also list branches which have
1214 been marked closed (see :hg:`commit --close-branch`).
1214 been marked closed (see :hg:`commit --close-branch`).
1215
1215
1216 Use the command :hg:`update` to switch to an existing branch.
1216 Use the command :hg:`update` to switch to an existing branch.
1217
1217
1218 Returns 0.
1218 Returns 0.
1219 """
1219 """
1220
1220
1221 fm = ui.formatter('branches', opts)
1221 fm = ui.formatter('branches', opts)
1222 hexfunc = fm.hexfunc
1222 hexfunc = fm.hexfunc
1223
1223
1224 allheads = set(repo.heads())
1224 allheads = set(repo.heads())
1225 branches = []
1225 branches = []
1226 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1226 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1227 isactive = not isclosed and bool(set(heads) & allheads)
1227 isactive = not isclosed and bool(set(heads) & allheads)
1228 branches.append((tag, repo[tip], isactive, not isclosed))
1228 branches.append((tag, repo[tip], isactive, not isclosed))
1229 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1229 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1230 reverse=True)
1230 reverse=True)
1231
1231
1232 for tag, ctx, isactive, isopen in branches:
1232 for tag, ctx, isactive, isopen in branches:
1233 if active and not isactive:
1233 if active and not isactive:
1234 continue
1234 continue
1235 if isactive:
1235 if isactive:
1236 label = 'branches.active'
1236 label = 'branches.active'
1237 notice = ''
1237 notice = ''
1238 elif not isopen:
1238 elif not isopen:
1239 if not closed:
1239 if not closed:
1240 continue
1240 continue
1241 label = 'branches.closed'
1241 label = 'branches.closed'
1242 notice = _(' (closed)')
1242 notice = _(' (closed)')
1243 else:
1243 else:
1244 label = 'branches.inactive'
1244 label = 'branches.inactive'
1245 notice = _(' (inactive)')
1245 notice = _(' (inactive)')
1246 current = (tag == repo.dirstate.branch())
1246 current = (tag == repo.dirstate.branch())
1247 if current:
1247 if current:
1248 label = 'branches.current'
1248 label = 'branches.current'
1249
1249
1250 fm.startitem()
1250 fm.startitem()
1251 fm.write('branch', '%s', tag, label=label)
1251 fm.write('branch', '%s', tag, label=label)
1252 rev = ctx.rev()
1252 rev = ctx.rev()
1253 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1253 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1254 fmt = ' ' * padsize + ' %d:%s'
1254 fmt = ' ' * padsize + ' %d:%s'
1255 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1255 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1256 label='log.changeset changeset.%s' % ctx.phasestr())
1256 label='log.changeset changeset.%s' % ctx.phasestr())
1257 fm.data(active=isactive, closed=not isopen, current=current)
1257 fm.data(active=isactive, closed=not isopen, current=current)
1258 if not ui.quiet:
1258 if not ui.quiet:
1259 fm.plain(notice)
1259 fm.plain(notice)
1260 fm.plain('\n')
1260 fm.plain('\n')
1261 fm.end()
1261 fm.end()
1262
1262
1263 @command('bundle',
1263 @command('bundle',
1264 [('f', 'force', None, _('run even when the destination is unrelated')),
1264 [('f', 'force', None, _('run even when the destination is unrelated')),
1265 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1265 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1266 _('REV')),
1266 _('REV')),
1267 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1267 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1268 _('BRANCH')),
1268 _('BRANCH')),
1269 ('', 'base', [],
1269 ('', 'base', [],
1270 _('a base changeset assumed to be available at the destination'),
1270 _('a base changeset assumed to be available at the destination'),
1271 _('REV')),
1271 _('REV')),
1272 ('a', 'all', None, _('bundle all changesets in the repository')),
1272 ('a', 'all', None, _('bundle all changesets in the repository')),
1273 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1273 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1274 ] + remoteopts,
1274 ] + remoteopts,
1275 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1275 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1276 def bundle(ui, repo, fname, dest=None, **opts):
1276 def bundle(ui, repo, fname, dest=None, **opts):
1277 """create a changegroup file
1277 """create a changegroup file
1278
1278
1279 Generate a changegroup file collecting changesets to be added
1279 Generate a changegroup file collecting changesets to be added
1280 to a repository.
1280 to a repository.
1281
1281
1282 To create a bundle containing all changesets, use -a/--all
1282 To create a bundle containing all changesets, use -a/--all
1283 (or --base null). Otherwise, hg assumes the destination will have
1283 (or --base null). Otherwise, hg assumes the destination will have
1284 all the nodes you specify with --base parameters. Otherwise, hg
1284 all the nodes you specify with --base parameters. Otherwise, hg
1285 will assume the repository has all the nodes in destination, or
1285 will assume the repository has all the nodes in destination, or
1286 default-push/default if no destination is specified.
1286 default-push/default if no destination is specified.
1287
1287
1288 You can change bundle format with the -t/--type option. You can
1288 You can change bundle format with the -t/--type option. You can
1289 specify a compression, a bundle version or both using a dash
1289 specify a compression, a bundle version or both using a dash
1290 (comp-version). The available compression methods are: none, bzip2,
1290 (comp-version). The available compression methods are: none, bzip2,
1291 and gzip (by default, bundles are compressed using bzip2). The
1291 and gzip (by default, bundles are compressed using bzip2). The
1292 available formats are: v1, v2 (default to most suitable).
1292 available formats are: v1, v2 (default to most suitable).
1293
1293
1294 The bundle file can then be transferred using conventional means
1294 The bundle file can then be transferred using conventional means
1295 and applied to another repository with the unbundle or pull
1295 and applied to another repository with the unbundle or pull
1296 command. This is useful when direct push and pull are not
1296 command. This is useful when direct push and pull are not
1297 available or when exporting an entire repository is undesirable.
1297 available or when exporting an entire repository is undesirable.
1298
1298
1299 Applying bundles preserves all changeset contents including
1299 Applying bundles preserves all changeset contents including
1300 permissions, copy/rename information, and revision history.
1300 permissions, copy/rename information, and revision history.
1301
1301
1302 Returns 0 on success, 1 if no changes found.
1302 Returns 0 on success, 1 if no changes found.
1303 """
1303 """
1304 revs = None
1304 revs = None
1305 if 'rev' in opts:
1305 if 'rev' in opts:
1306 revstrings = opts['rev']
1306 revstrings = opts['rev']
1307 revs = scmutil.revrange(repo, revstrings)
1307 revs = scmutil.revrange(repo, revstrings)
1308 if revstrings and not revs:
1308 if revstrings and not revs:
1309 raise error.Abort(_('no commits to bundle'))
1309 raise error.Abort(_('no commits to bundle'))
1310
1310
1311 bundletype = opts.get('type', 'bzip2').lower()
1311 bundletype = opts.get('type', 'bzip2').lower()
1312 try:
1312 try:
1313 bcompression, cgversion, params = exchange.parsebundlespec(
1313 bcompression, cgversion, params = exchange.parsebundlespec(
1314 repo, bundletype, strict=False)
1314 repo, bundletype, strict=False)
1315 except error.UnsupportedBundleSpecification as e:
1315 except error.UnsupportedBundleSpecification as e:
1316 raise error.Abort(str(e),
1316 raise error.Abort(str(e),
1317 hint=_("see 'hg help bundle' for supported "
1317 hint=_("see 'hg help bundle' for supported "
1318 "values for --type"))
1318 "values for --type"))
1319
1319
1320 # Packed bundles are a pseudo bundle format for now.
1320 # Packed bundles are a pseudo bundle format for now.
1321 if cgversion == 's1':
1321 if cgversion == 's1':
1322 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1322 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1323 hint=_("use 'hg debugcreatestreamclonebundle'"))
1323 hint=_("use 'hg debugcreatestreamclonebundle'"))
1324
1324
1325 if opts.get('all'):
1325 if opts.get('all'):
1326 if dest:
1326 if dest:
1327 raise error.Abort(_("--all is incompatible with specifying "
1327 raise error.Abort(_("--all is incompatible with specifying "
1328 "a destination"))
1328 "a destination"))
1329 if opts.get('base'):
1329 if opts.get('base'):
1330 ui.warn(_("ignoring --base because --all was specified\n"))
1330 ui.warn(_("ignoring --base because --all was specified\n"))
1331 base = ['null']
1331 base = ['null']
1332 else:
1332 else:
1333 base = scmutil.revrange(repo, opts.get('base'))
1333 base = scmutil.revrange(repo, opts.get('base'))
1334 # TODO: get desired bundlecaps from command line.
1334 # TODO: get desired bundlecaps from command line.
1335 bundlecaps = None
1335 bundlecaps = None
1336 if cgversion not in changegroup.supportedoutgoingversions(repo):
1336 if cgversion not in changegroup.supportedoutgoingversions(repo):
1337 raise error.Abort(_("repository does not support bundle version %s") %
1337 raise error.Abort(_("repository does not support bundle version %s") %
1338 cgversion)
1338 cgversion)
1339
1339
1340 if base:
1340 if base:
1341 if dest:
1341 if dest:
1342 raise error.Abort(_("--base is incompatible with specifying "
1342 raise error.Abort(_("--base is incompatible with specifying "
1343 "a destination"))
1343 "a destination"))
1344 common = [repo.lookup(rev) for rev in base]
1344 common = [repo.lookup(rev) for rev in base]
1345 heads = revs and map(repo.lookup, revs) or None
1345 heads = revs and map(repo.lookup, revs) or None
1346 outgoing = discovery.outgoing(repo, common, heads)
1346 outgoing = discovery.outgoing(repo, common, heads)
1347 cg = changegroup.getchangegroup(repo, 'bundle', outgoing,
1347 cg = changegroup.getchangegroup(repo, 'bundle', outgoing,
1348 bundlecaps=bundlecaps,
1348 bundlecaps=bundlecaps,
1349 version=cgversion)
1349 version=cgversion)
1350 outgoing = None
1350 outgoing = None
1351 else:
1351 else:
1352 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1352 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1353 dest, branches = hg.parseurl(dest, opts.get('branch'))
1353 dest, branches = hg.parseurl(dest, opts.get('branch'))
1354 other = hg.peer(repo, opts, dest)
1354 other = hg.peer(repo, opts, dest)
1355 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1355 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1356 heads = revs and map(repo.lookup, revs) or revs
1356 heads = revs and map(repo.lookup, revs) or revs
1357 outgoing = discovery.findcommonoutgoing(repo, other,
1357 outgoing = discovery.findcommonoutgoing(repo, other,
1358 onlyheads=heads,
1358 onlyheads=heads,
1359 force=opts.get('force'),
1359 force=opts.get('force'),
1360 portable=True)
1360 portable=True)
1361 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1361 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1362 bundlecaps, version=cgversion)
1362 bundlecaps, version=cgversion)
1363 if not cg:
1363 if not cg:
1364 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1364 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1365 return 1
1365 return 1
1366
1366
1367 if cgversion == '01': #bundle1
1367 if cgversion == '01': #bundle1
1368 if bcompression is None:
1368 if bcompression is None:
1369 bcompression = 'UN'
1369 bcompression = 'UN'
1370 bversion = 'HG10' + bcompression
1370 bversion = 'HG10' + bcompression
1371 bcompression = None
1371 bcompression = None
1372 else:
1372 else:
1373 assert cgversion == '02'
1373 assert cgversion == '02'
1374 bversion = 'HG20'
1374 bversion = 'HG20'
1375
1375
1376 # TODO compression options should be derived from bundlespec parsing.
1376 # TODO compression options should be derived from bundlespec parsing.
1377 # This is a temporary hack to allow adjusting bundle compression
1377 # This is a temporary hack to allow adjusting bundle compression
1378 # level without a) formalizing the bundlespec changes to declare it
1378 # level without a) formalizing the bundlespec changes to declare it
1379 # b) introducing a command flag.
1379 # b) introducing a command flag.
1380 compopts = {}
1380 compopts = {}
1381 complevel = ui.configint('experimental', 'bundlecomplevel')
1381 complevel = ui.configint('experimental', 'bundlecomplevel')
1382 if complevel is not None:
1382 if complevel is not None:
1383 compopts['level'] = complevel
1383 compopts['level'] = complevel
1384
1384
1385 bundle2.writebundle(ui, cg, fname, bversion, compression=bcompression,
1385 bundle2.writebundle(ui, cg, fname, bversion, compression=bcompression,
1386 compopts=compopts)
1386 compopts=compopts)
1387
1387
1388 @command('cat',
1388 @command('cat',
1389 [('o', 'output', '',
1389 [('o', 'output', '',
1390 _('print output to file with formatted name'), _('FORMAT')),
1390 _('print output to file with formatted name'), _('FORMAT')),
1391 ('r', 'rev', '', _('print the given revision'), _('REV')),
1391 ('r', 'rev', '', _('print the given revision'), _('REV')),
1392 ('', 'decode', None, _('apply any matching decode filter')),
1392 ('', 'decode', None, _('apply any matching decode filter')),
1393 ] + walkopts,
1393 ] + walkopts,
1394 _('[OPTION]... FILE...'),
1394 _('[OPTION]... FILE...'),
1395 inferrepo=True)
1395 inferrepo=True)
1396 def cat(ui, repo, file1, *pats, **opts):
1396 def cat(ui, repo, file1, *pats, **opts):
1397 """output the current or given revision of files
1397 """output the current or given revision of files
1398
1398
1399 Print the specified files as they were at the given revision. If
1399 Print the specified files as they were at the given revision. If
1400 no revision is given, the parent of the working directory is used.
1400 no revision is given, the parent of the working directory is used.
1401
1401
1402 Output may be to a file, in which case the name of the file is
1402 Output may be to a file, in which case the name of the file is
1403 given using a format string. The formatting rules as follows:
1403 given using a format string. The formatting rules as follows:
1404
1404
1405 :``%%``: literal "%" character
1405 :``%%``: literal "%" character
1406 :``%s``: basename of file being printed
1406 :``%s``: basename of file being printed
1407 :``%d``: dirname of file being printed, or '.' if in repository root
1407 :``%d``: dirname of file being printed, or '.' if in repository root
1408 :``%p``: root-relative path name of file being printed
1408 :``%p``: root-relative path name of file being printed
1409 :``%H``: changeset hash (40 hexadecimal digits)
1409 :``%H``: changeset hash (40 hexadecimal digits)
1410 :``%R``: changeset revision number
1410 :``%R``: changeset revision number
1411 :``%h``: short-form changeset hash (12 hexadecimal digits)
1411 :``%h``: short-form changeset hash (12 hexadecimal digits)
1412 :``%r``: zero-padded changeset revision number
1412 :``%r``: zero-padded changeset revision number
1413 :``%b``: basename of the exporting repository
1413 :``%b``: basename of the exporting repository
1414
1414
1415 Returns 0 on success.
1415 Returns 0 on success.
1416 """
1416 """
1417 ctx = scmutil.revsingle(repo, opts.get('rev'))
1417 ctx = scmutil.revsingle(repo, opts.get('rev'))
1418 m = scmutil.match(ctx, (file1,) + pats, opts)
1418 m = scmutil.match(ctx, (file1,) + pats, opts)
1419
1419
1420 ui.pager('cat')
1420 ui.pager('cat')
1421 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1421 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1422
1422
1423 @command('^clone',
1423 @command('^clone',
1424 [('U', 'noupdate', None, _('the clone will include an empty working '
1424 [('U', 'noupdate', None, _('the clone will include an empty working '
1425 'directory (only a repository)')),
1425 'directory (only a repository)')),
1426 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1426 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1427 _('REV')),
1427 _('REV')),
1428 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1428 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1429 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1429 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1430 ('', 'pull', None, _('use pull protocol to copy metadata')),
1430 ('', 'pull', None, _('use pull protocol to copy metadata')),
1431 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1431 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1432 ] + remoteopts,
1432 ] + remoteopts,
1433 _('[OPTION]... SOURCE [DEST]'),
1433 _('[OPTION]... SOURCE [DEST]'),
1434 norepo=True)
1434 norepo=True)
1435 def clone(ui, source, dest=None, **opts):
1435 def clone(ui, source, dest=None, **opts):
1436 """make a copy of an existing repository
1436 """make a copy of an existing repository
1437
1437
1438 Create a copy of an existing repository in a new directory.
1438 Create a copy of an existing repository in a new directory.
1439
1439
1440 If no destination directory name is specified, it defaults to the
1440 If no destination directory name is specified, it defaults to the
1441 basename of the source.
1441 basename of the source.
1442
1442
1443 The location of the source is added to the new repository's
1443 The location of the source is added to the new repository's
1444 ``.hg/hgrc`` file, as the default to be used for future pulls.
1444 ``.hg/hgrc`` file, as the default to be used for future pulls.
1445
1445
1446 Only local paths and ``ssh://`` URLs are supported as
1446 Only local paths and ``ssh://`` URLs are supported as
1447 destinations. For ``ssh://`` destinations, no working directory or
1447 destinations. For ``ssh://`` destinations, no working directory or
1448 ``.hg/hgrc`` will be created on the remote side.
1448 ``.hg/hgrc`` will be created on the remote side.
1449
1449
1450 If the source repository has a bookmark called '@' set, that
1450 If the source repository has a bookmark called '@' set, that
1451 revision will be checked out in the new repository by default.
1451 revision will be checked out in the new repository by default.
1452
1452
1453 To check out a particular version, use -u/--update, or
1453 To check out a particular version, use -u/--update, or
1454 -U/--noupdate to create a clone with no working directory.
1454 -U/--noupdate to create a clone with no working directory.
1455
1455
1456 To pull only a subset of changesets, specify one or more revisions
1456 To pull only a subset of changesets, specify one or more revisions
1457 identifiers with -r/--rev or branches with -b/--branch. The
1457 identifiers with -r/--rev or branches with -b/--branch. The
1458 resulting clone will contain only the specified changesets and
1458 resulting clone will contain only the specified changesets and
1459 their ancestors. These options (or 'clone src#rev dest') imply
1459 their ancestors. These options (or 'clone src#rev dest') imply
1460 --pull, even for local source repositories.
1460 --pull, even for local source repositories.
1461
1461
1462 .. note::
1462 .. note::
1463
1463
1464 Specifying a tag will include the tagged changeset but not the
1464 Specifying a tag will include the tagged changeset but not the
1465 changeset containing the tag.
1465 changeset containing the tag.
1466
1466
1467 .. container:: verbose
1467 .. container:: verbose
1468
1468
1469 For efficiency, hardlinks are used for cloning whenever the
1469 For efficiency, hardlinks are used for cloning whenever the
1470 source and destination are on the same filesystem (note this
1470 source and destination are on the same filesystem (note this
1471 applies only to the repository data, not to the working
1471 applies only to the repository data, not to the working
1472 directory). Some filesystems, such as AFS, implement hardlinking
1472 directory). Some filesystems, such as AFS, implement hardlinking
1473 incorrectly, but do not report errors. In these cases, use the
1473 incorrectly, but do not report errors. In these cases, use the
1474 --pull option to avoid hardlinking.
1474 --pull option to avoid hardlinking.
1475
1475
1476 In some cases, you can clone repositories and the working
1476 In some cases, you can clone repositories and the working
1477 directory using full hardlinks with ::
1477 directory using full hardlinks with ::
1478
1478
1479 $ cp -al REPO REPOCLONE
1479 $ cp -al REPO REPOCLONE
1480
1480
1481 This is the fastest way to clone, but it is not always safe. The
1481 This is the fastest way to clone, but it is not always safe. The
1482 operation is not atomic (making sure REPO is not modified during
1482 operation is not atomic (making sure REPO is not modified during
1483 the operation is up to you) and you have to make sure your
1483 the operation is up to you) and you have to make sure your
1484 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1484 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1485 so). Also, this is not compatible with certain extensions that
1485 so). Also, this is not compatible with certain extensions that
1486 place their metadata under the .hg directory, such as mq.
1486 place their metadata under the .hg directory, such as mq.
1487
1487
1488 Mercurial will update the working directory to the first applicable
1488 Mercurial will update the working directory to the first applicable
1489 revision from this list:
1489 revision from this list:
1490
1490
1491 a) null if -U or the source repository has no changesets
1491 a) null if -U or the source repository has no changesets
1492 b) if -u . and the source repository is local, the first parent of
1492 b) if -u . and the source repository is local, the first parent of
1493 the source repository's working directory
1493 the source repository's working directory
1494 c) the changeset specified with -u (if a branch name, this means the
1494 c) the changeset specified with -u (if a branch name, this means the
1495 latest head of that branch)
1495 latest head of that branch)
1496 d) the changeset specified with -r
1496 d) the changeset specified with -r
1497 e) the tipmost head specified with -b
1497 e) the tipmost head specified with -b
1498 f) the tipmost head specified with the url#branch source syntax
1498 f) the tipmost head specified with the url#branch source syntax
1499 g) the revision marked with the '@' bookmark, if present
1499 g) the revision marked with the '@' bookmark, if present
1500 h) the tipmost head of the default branch
1500 h) the tipmost head of the default branch
1501 i) tip
1501 i) tip
1502
1502
1503 When cloning from servers that support it, Mercurial may fetch
1503 When cloning from servers that support it, Mercurial may fetch
1504 pre-generated data from a server-advertised URL. When this is done,
1504 pre-generated data from a server-advertised URL. When this is done,
1505 hooks operating on incoming changesets and changegroups may fire twice,
1505 hooks operating on incoming changesets and changegroups may fire twice,
1506 once for the bundle fetched from the URL and another for any additional
1506 once for the bundle fetched from the URL and another for any additional
1507 data not fetched from this URL. In addition, if an error occurs, the
1507 data not fetched from this URL. In addition, if an error occurs, the
1508 repository may be rolled back to a partial clone. This behavior may
1508 repository may be rolled back to a partial clone. This behavior may
1509 change in future releases. See :hg:`help -e clonebundles` for more.
1509 change in future releases. See :hg:`help -e clonebundles` for more.
1510
1510
1511 Examples:
1511 Examples:
1512
1512
1513 - clone a remote repository to a new directory named hg/::
1513 - clone a remote repository to a new directory named hg/::
1514
1514
1515 hg clone https://www.mercurial-scm.org/repo/hg/
1515 hg clone https://www.mercurial-scm.org/repo/hg/
1516
1516
1517 - create a lightweight local clone::
1517 - create a lightweight local clone::
1518
1518
1519 hg clone project/ project-feature/
1519 hg clone project/ project-feature/
1520
1520
1521 - clone from an absolute path on an ssh server (note double-slash)::
1521 - clone from an absolute path on an ssh server (note double-slash)::
1522
1522
1523 hg clone ssh://user@server//home/projects/alpha/
1523 hg clone ssh://user@server//home/projects/alpha/
1524
1524
1525 - do a high-speed clone over a LAN while checking out a
1525 - do a high-speed clone over a LAN while checking out a
1526 specified version::
1526 specified version::
1527
1527
1528 hg clone --uncompressed http://server/repo -u 1.5
1528 hg clone --uncompressed http://server/repo -u 1.5
1529
1529
1530 - create a repository without changesets after a particular revision::
1530 - create a repository without changesets after a particular revision::
1531
1531
1532 hg clone -r 04e544 experimental/ good/
1532 hg clone -r 04e544 experimental/ good/
1533
1533
1534 - clone (and track) a particular named branch::
1534 - clone (and track) a particular named branch::
1535
1535
1536 hg clone https://www.mercurial-scm.org/repo/hg/#stable
1536 hg clone https://www.mercurial-scm.org/repo/hg/#stable
1537
1537
1538 See :hg:`help urls` for details on specifying URLs.
1538 See :hg:`help urls` for details on specifying URLs.
1539
1539
1540 Returns 0 on success.
1540 Returns 0 on success.
1541 """
1541 """
1542 if opts.get('noupdate') and opts.get('updaterev'):
1542 if opts.get('noupdate') and opts.get('updaterev'):
1543 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1543 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1544
1544
1545 r = hg.clone(ui, opts, source, dest,
1545 r = hg.clone(ui, opts, source, dest,
1546 pull=opts.get('pull'),
1546 pull=opts.get('pull'),
1547 stream=opts.get('uncompressed'),
1547 stream=opts.get('uncompressed'),
1548 rev=opts.get('rev'),
1548 rev=opts.get('rev'),
1549 update=opts.get('updaterev') or not opts.get('noupdate'),
1549 update=opts.get('updaterev') or not opts.get('noupdate'),
1550 branch=opts.get('branch'),
1550 branch=opts.get('branch'),
1551 shareopts=opts.get('shareopts'))
1551 shareopts=opts.get('shareopts'))
1552
1552
1553 return r is None
1553 return r is None
1554
1554
1555 @command('^commit|ci',
1555 @command('^commit|ci',
1556 [('A', 'addremove', None,
1556 [('A', 'addremove', None,
1557 _('mark new/missing files as added/removed before committing')),
1557 _('mark new/missing files as added/removed before committing')),
1558 ('', 'close-branch', None,
1558 ('', 'close-branch', None,
1559 _('mark a branch head as closed')),
1559 _('mark a branch head as closed')),
1560 ('', 'amend', None, _('amend the parent of the working directory')),
1560 ('', 'amend', None, _('amend the parent of the working directory')),
1561 ('s', 'secret', None, _('use the secret phase for committing')),
1561 ('s', 'secret', None, _('use the secret phase for committing')),
1562 ('e', 'edit', None, _('invoke editor on commit messages')),
1562 ('e', 'edit', None, _('invoke editor on commit messages')),
1563 ('i', 'interactive', None, _('use interactive mode')),
1563 ('i', 'interactive', None, _('use interactive mode')),
1564 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1564 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1565 _('[OPTION]... [FILE]...'),
1565 _('[OPTION]... [FILE]...'),
1566 inferrepo=True)
1566 inferrepo=True)
1567 def commit(ui, repo, *pats, **opts):
1567 def commit(ui, repo, *pats, **opts):
1568 """commit the specified files or all outstanding changes
1568 """commit the specified files or all outstanding changes
1569
1569
1570 Commit changes to the given files into the repository. Unlike a
1570 Commit changes to the given files into the repository. Unlike a
1571 centralized SCM, this operation is a local operation. See
1571 centralized SCM, this operation is a local operation. See
1572 :hg:`push` for a way to actively distribute your changes.
1572 :hg:`push` for a way to actively distribute your changes.
1573
1573
1574 If a list of files is omitted, all changes reported by :hg:`status`
1574 If a list of files is omitted, all changes reported by :hg:`status`
1575 will be committed.
1575 will be committed.
1576
1576
1577 If you are committing the result of a merge, do not provide any
1577 If you are committing the result of a merge, do not provide any
1578 filenames or -I/-X filters.
1578 filenames or -I/-X filters.
1579
1579
1580 If no commit message is specified, Mercurial starts your
1580 If no commit message is specified, Mercurial starts your
1581 configured editor where you can enter a message. In case your
1581 configured editor where you can enter a message. In case your
1582 commit fails, you will find a backup of your message in
1582 commit fails, you will find a backup of your message in
1583 ``.hg/last-message.txt``.
1583 ``.hg/last-message.txt``.
1584
1584
1585 The --close-branch flag can be used to mark the current branch
1585 The --close-branch flag can be used to mark the current branch
1586 head closed. When all heads of a branch are closed, the branch
1586 head closed. When all heads of a branch are closed, the branch
1587 will be considered closed and no longer listed.
1587 will be considered closed and no longer listed.
1588
1588
1589 The --amend flag can be used to amend the parent of the
1589 The --amend flag can be used to amend the parent of the
1590 working directory with a new commit that contains the changes
1590 working directory with a new commit that contains the changes
1591 in the parent in addition to those currently reported by :hg:`status`,
1591 in the parent in addition to those currently reported by :hg:`status`,
1592 if there are any. The old commit is stored in a backup bundle in
1592 if there are any. The old commit is stored in a backup bundle in
1593 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1593 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1594 on how to restore it).
1594 on how to restore it).
1595
1595
1596 Message, user and date are taken from the amended commit unless
1596 Message, user and date are taken from the amended commit unless
1597 specified. When a message isn't specified on the command line,
1597 specified. When a message isn't specified on the command line,
1598 the editor will open with the message of the amended commit.
1598 the editor will open with the message of the amended commit.
1599
1599
1600 It is not possible to amend public changesets (see :hg:`help phases`)
1600 It is not possible to amend public changesets (see :hg:`help phases`)
1601 or changesets that have children.
1601 or changesets that have children.
1602
1602
1603 See :hg:`help dates` for a list of formats valid for -d/--date.
1603 See :hg:`help dates` for a list of formats valid for -d/--date.
1604
1604
1605 Returns 0 on success, 1 if nothing changed.
1605 Returns 0 on success, 1 if nothing changed.
1606
1606
1607 .. container:: verbose
1607 .. container:: verbose
1608
1608
1609 Examples:
1609 Examples:
1610
1610
1611 - commit all files ending in .py::
1611 - commit all files ending in .py::
1612
1612
1613 hg commit --include "set:**.py"
1613 hg commit --include "set:**.py"
1614
1614
1615 - commit all non-binary files::
1615 - commit all non-binary files::
1616
1616
1617 hg commit --exclude "set:binary()"
1617 hg commit --exclude "set:binary()"
1618
1618
1619 - amend the current commit and set the date to now::
1619 - amend the current commit and set the date to now::
1620
1620
1621 hg commit --amend --date now
1621 hg commit --amend --date now
1622 """
1622 """
1623 wlock = lock = None
1623 wlock = lock = None
1624 try:
1624 try:
1625 wlock = repo.wlock()
1625 wlock = repo.wlock()
1626 lock = repo.lock()
1626 lock = repo.lock()
1627 return _docommit(ui, repo, *pats, **opts)
1627 return _docommit(ui, repo, *pats, **opts)
1628 finally:
1628 finally:
1629 release(lock, wlock)
1629 release(lock, wlock)
1630
1630
1631 def _docommit(ui, repo, *pats, **opts):
1631 def _docommit(ui, repo, *pats, **opts):
1632 if opts.get('interactive'):
1632 if opts.get('interactive'):
1633 opts.pop('interactive')
1633 opts.pop('interactive')
1634 ret = cmdutil.dorecord(ui, repo, commit, None, False,
1634 ret = cmdutil.dorecord(ui, repo, commit, None, False,
1635 cmdutil.recordfilter, *pats, **opts)
1635 cmdutil.recordfilter, *pats, **opts)
1636 # ret can be 0 (no changes to record) or the value returned by
1636 # ret can be 0 (no changes to record) or the value returned by
1637 # commit(), 1 if nothing changed or None on success.
1637 # commit(), 1 if nothing changed or None on success.
1638 return 1 if ret == 0 else ret
1638 return 1 if ret == 0 else ret
1639
1639
1640 if opts.get('subrepos'):
1640 if opts.get('subrepos'):
1641 if opts.get('amend'):
1641 if opts.get('amend'):
1642 raise error.Abort(_('cannot amend with --subrepos'))
1642 raise error.Abort(_('cannot amend with --subrepos'))
1643 # Let --subrepos on the command line override config setting.
1643 # Let --subrepos on the command line override config setting.
1644 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1644 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1645
1645
1646 cmdutil.checkunfinished(repo, commit=True)
1646 cmdutil.checkunfinished(repo, commit=True)
1647
1647
1648 branch = repo[None].branch()
1648 branch = repo[None].branch()
1649 bheads = repo.branchheads(branch)
1649 bheads = repo.branchheads(branch)
1650
1650
1651 extra = {}
1651 extra = {}
1652 if opts.get('close_branch'):
1652 if opts.get('close_branch'):
1653 extra['close'] = 1
1653 extra['close'] = 1
1654
1654
1655 if not bheads:
1655 if not bheads:
1656 raise error.Abort(_('can only close branch heads'))
1656 raise error.Abort(_('can only close branch heads'))
1657 elif opts.get('amend'):
1657 elif opts.get('amend'):
1658 if repo[None].parents()[0].p1().branch() != branch and \
1658 if repo[None].parents()[0].p1().branch() != branch and \
1659 repo[None].parents()[0].p2().branch() != branch:
1659 repo[None].parents()[0].p2().branch() != branch:
1660 raise error.Abort(_('can only close branch heads'))
1660 raise error.Abort(_('can only close branch heads'))
1661
1661
1662 if opts.get('amend'):
1662 if opts.get('amend'):
1663 if ui.configbool('ui', 'commitsubrepos'):
1663 if ui.configbool('ui', 'commitsubrepos'):
1664 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1664 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1665
1665
1666 old = repo['.']
1666 old = repo['.']
1667 if not old.mutable():
1667 if not old.mutable():
1668 raise error.Abort(_('cannot amend public changesets'))
1668 raise error.Abort(_('cannot amend public changesets'))
1669 if len(repo[None].parents()) > 1:
1669 if len(repo[None].parents()) > 1:
1670 raise error.Abort(_('cannot amend while merging'))
1670 raise error.Abort(_('cannot amend while merging'))
1671 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1671 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1672 if not allowunstable and old.children():
1672 if not allowunstable and old.children():
1673 raise error.Abort(_('cannot amend changeset with children'))
1673 raise error.Abort(_('cannot amend changeset with children'))
1674
1674
1675 # Currently histedit gets confused if an amend happens while histedit
1675 # Currently histedit gets confused if an amend happens while histedit
1676 # is in progress. Since we have a checkunfinished command, we are
1676 # is in progress. Since we have a checkunfinished command, we are
1677 # temporarily honoring it.
1677 # temporarily honoring it.
1678 #
1678 #
1679 # Note: eventually this guard will be removed. Please do not expect
1679 # Note: eventually this guard will be removed. Please do not expect
1680 # this behavior to remain.
1680 # this behavior to remain.
1681 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
1681 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
1682 cmdutil.checkunfinished(repo)
1682 cmdutil.checkunfinished(repo)
1683
1683
1684 # commitfunc is used only for temporary amend commit by cmdutil.amend
1684 # commitfunc is used only for temporary amend commit by cmdutil.amend
1685 def commitfunc(ui, repo, message, match, opts):
1685 def commitfunc(ui, repo, message, match, opts):
1686 return repo.commit(message,
1686 return repo.commit(message,
1687 opts.get('user') or old.user(),
1687 opts.get('user') or old.user(),
1688 opts.get('date') or old.date(),
1688 opts.get('date') or old.date(),
1689 match,
1689 match,
1690 extra=extra)
1690 extra=extra)
1691
1691
1692 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1692 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1693 if node == old.node():
1693 if node == old.node():
1694 ui.status(_("nothing changed\n"))
1694 ui.status(_("nothing changed\n"))
1695 return 1
1695 return 1
1696 else:
1696 else:
1697 def commitfunc(ui, repo, message, match, opts):
1697 def commitfunc(ui, repo, message, match, opts):
1698 backup = ui.backupconfig('phases', 'new-commit')
1698 backup = ui.backupconfig('phases', 'new-commit')
1699 baseui = repo.baseui
1699 baseui = repo.baseui
1700 basebackup = baseui.backupconfig('phases', 'new-commit')
1700 basebackup = baseui.backupconfig('phases', 'new-commit')
1701 try:
1701 try:
1702 if opts.get('secret'):
1702 if opts.get('secret'):
1703 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1703 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1704 # Propagate to subrepos
1704 # Propagate to subrepos
1705 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1705 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1706
1706
1707 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1707 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1708 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1708 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1709 return repo.commit(message, opts.get('user'), opts.get('date'),
1709 return repo.commit(message, opts.get('user'), opts.get('date'),
1710 match,
1710 match,
1711 editor=editor,
1711 editor=editor,
1712 extra=extra)
1712 extra=extra)
1713 finally:
1713 finally:
1714 ui.restoreconfig(backup)
1714 ui.restoreconfig(backup)
1715 repo.baseui.restoreconfig(basebackup)
1715 repo.baseui.restoreconfig(basebackup)
1716
1716
1717
1717
1718 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1718 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1719
1719
1720 if not node:
1720 if not node:
1721 stat = cmdutil.postcommitstatus(repo, pats, opts)
1721 stat = cmdutil.postcommitstatus(repo, pats, opts)
1722 if stat[3]:
1722 if stat[3]:
1723 ui.status(_("nothing changed (%d missing files, see "
1723 ui.status(_("nothing changed (%d missing files, see "
1724 "'hg status')\n") % len(stat[3]))
1724 "'hg status')\n") % len(stat[3]))
1725 else:
1725 else:
1726 ui.status(_("nothing changed\n"))
1726 ui.status(_("nothing changed\n"))
1727 return 1
1727 return 1
1728
1728
1729 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1729 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1730
1730
1731 @command('config|showconfig|debugconfig',
1731 @command('config|showconfig|debugconfig',
1732 [('u', 'untrusted', None, _('show untrusted configuration options')),
1732 [('u', 'untrusted', None, _('show untrusted configuration options')),
1733 ('e', 'edit', None, _('edit user config')),
1733 ('e', 'edit', None, _('edit user config')),
1734 ('l', 'local', None, _('edit repository config')),
1734 ('l', 'local', None, _('edit repository config')),
1735 ('g', 'global', None, _('edit global config'))] + formatteropts,
1735 ('g', 'global', None, _('edit global config'))] + formatteropts,
1736 _('[-u] [NAME]...'),
1736 _('[-u] [NAME]...'),
1737 optionalrepo=True)
1737 optionalrepo=True)
1738 def config(ui, repo, *values, **opts):
1738 def config(ui, repo, *values, **opts):
1739 """show combined config settings from all hgrc files
1739 """show combined config settings from all hgrc files
1740
1740
1741 With no arguments, print names and values of all config items.
1741 With no arguments, print names and values of all config items.
1742
1742
1743 With one argument of the form section.name, print just the value
1743 With one argument of the form section.name, print just the value
1744 of that config item.
1744 of that config item.
1745
1745
1746 With multiple arguments, print names and values of all config
1746 With multiple arguments, print names and values of all config
1747 items with matching section names.
1747 items with matching section names.
1748
1748
1749 With --edit, start an editor on the user-level config file. With
1749 With --edit, start an editor on the user-level config file. With
1750 --global, edit the system-wide config file. With --local, edit the
1750 --global, edit the system-wide config file. With --local, edit the
1751 repository-level config file.
1751 repository-level config file.
1752
1752
1753 With --debug, the source (filename and line number) is printed
1753 With --debug, the source (filename and line number) is printed
1754 for each config item.
1754 for each config item.
1755
1755
1756 See :hg:`help config` for more information about config files.
1756 See :hg:`help config` for more information about config files.
1757
1757
1758 Returns 0 on success, 1 if NAME does not exist.
1758 Returns 0 on success, 1 if NAME does not exist.
1759
1759
1760 """
1760 """
1761
1761
1762 if opts.get('edit') or opts.get('local') or opts.get('global'):
1762 if opts.get('edit') or opts.get('local') or opts.get('global'):
1763 if opts.get('local') and opts.get('global'):
1763 if opts.get('local') and opts.get('global'):
1764 raise error.Abort(_("can't use --local and --global together"))
1764 raise error.Abort(_("can't use --local and --global together"))
1765
1765
1766 if opts.get('local'):
1766 if opts.get('local'):
1767 if not repo:
1767 if not repo:
1768 raise error.Abort(_("can't use --local outside a repository"))
1768 raise error.Abort(_("can't use --local outside a repository"))
1769 paths = [repo.join('hgrc')]
1769 paths = [repo.join('hgrc')]
1770 elif opts.get('global'):
1770 elif opts.get('global'):
1771 paths = scmutil.systemrcpath()
1771 paths = scmutil.systemrcpath()
1772 else:
1772 else:
1773 paths = scmutil.userrcpath()
1773 paths = scmutil.userrcpath()
1774
1774
1775 for f in paths:
1775 for f in paths:
1776 if os.path.exists(f):
1776 if os.path.exists(f):
1777 break
1777 break
1778 else:
1778 else:
1779 if opts.get('global'):
1779 if opts.get('global'):
1780 samplehgrc = uimod.samplehgrcs['global']
1780 samplehgrc = uimod.samplehgrcs['global']
1781 elif opts.get('local'):
1781 elif opts.get('local'):
1782 samplehgrc = uimod.samplehgrcs['local']
1782 samplehgrc = uimod.samplehgrcs['local']
1783 else:
1783 else:
1784 samplehgrc = uimod.samplehgrcs['user']
1784 samplehgrc = uimod.samplehgrcs['user']
1785
1785
1786 f = paths[0]
1786 f = paths[0]
1787 fp = open(f, "w")
1787 fp = open(f, "w")
1788 fp.write(samplehgrc)
1788 fp.write(samplehgrc)
1789 fp.close()
1789 fp.close()
1790
1790
1791 editor = ui.geteditor()
1791 editor = ui.geteditor()
1792 ui.system("%s \"%s\"" % (editor, f),
1792 ui.system("%s \"%s\"" % (editor, f),
1793 onerr=error.Abort, errprefix=_("edit failed"))
1793 onerr=error.Abort, errprefix=_("edit failed"))
1794 return
1794 return
1795
1795
1796 fm = ui.formatter('config', opts)
1796 fm = ui.formatter('config', opts)
1797 for f in scmutil.rcpath():
1797 for f in scmutil.rcpath():
1798 ui.debug('read config from: %s\n' % f)
1798 ui.debug('read config from: %s\n' % f)
1799 untrusted = bool(opts.get('untrusted'))
1799 untrusted = bool(opts.get('untrusted'))
1800 if values:
1800 if values:
1801 sections = [v for v in values if '.' not in v]
1801 sections = [v for v in values if '.' not in v]
1802 items = [v for v in values if '.' in v]
1802 items = [v for v in values if '.' in v]
1803 if len(items) > 1 or items and sections:
1803 if len(items) > 1 or items and sections:
1804 raise error.Abort(_('only one config item permitted'))
1804 raise error.Abort(_('only one config item permitted'))
1805 matched = False
1805 matched = False
1806 for section, name, value in ui.walkconfig(untrusted=untrusted):
1806 for section, name, value in ui.walkconfig(untrusted=untrusted):
1807 source = ui.configsource(section, name, untrusted)
1807 source = ui.configsource(section, name, untrusted)
1808 value = str(value)
1808 value = str(value)
1809 if fm.isplain():
1809 if fm.isplain():
1810 source = source or 'none'
1810 source = source or 'none'
1811 value = value.replace('\n', '\\n')
1811 value = value.replace('\n', '\\n')
1812 entryname = section + '.' + name
1812 entryname = section + '.' + name
1813 if values:
1813 if values:
1814 for v in values:
1814 for v in values:
1815 if v == section:
1815 if v == section:
1816 fm.startitem()
1816 fm.startitem()
1817 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1817 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1818 fm.write('name value', '%s=%s\n', entryname, value)
1818 fm.write('name value', '%s=%s\n', entryname, value)
1819 matched = True
1819 matched = True
1820 elif v == entryname:
1820 elif v == entryname:
1821 fm.startitem()
1821 fm.startitem()
1822 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1822 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1823 fm.write('value', '%s\n', value)
1823 fm.write('value', '%s\n', value)
1824 fm.data(name=entryname)
1824 fm.data(name=entryname)
1825 matched = True
1825 matched = True
1826 else:
1826 else:
1827 fm.startitem()
1827 fm.startitem()
1828 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1828 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1829 fm.write('name value', '%s=%s\n', entryname, value)
1829 fm.write('name value', '%s=%s\n', entryname, value)
1830 matched = True
1830 matched = True
1831 fm.end()
1831 fm.end()
1832 if matched:
1832 if matched:
1833 return 0
1833 return 0
1834 return 1
1834 return 1
1835
1835
1836 @command('copy|cp',
1836 @command('copy|cp',
1837 [('A', 'after', None, _('record a copy that has already occurred')),
1837 [('A', 'after', None, _('record a copy that has already occurred')),
1838 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1838 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1839 ] + walkopts + dryrunopts,
1839 ] + walkopts + dryrunopts,
1840 _('[OPTION]... [SOURCE]... DEST'))
1840 _('[OPTION]... [SOURCE]... DEST'))
1841 def copy(ui, repo, *pats, **opts):
1841 def copy(ui, repo, *pats, **opts):
1842 """mark files as copied for the next commit
1842 """mark files as copied for the next commit
1843
1843
1844 Mark dest as having copies of source files. If dest is a
1844 Mark dest as having copies of source files. If dest is a
1845 directory, copies are put in that directory. If dest is a file,
1845 directory, copies are put in that directory. If dest is a file,
1846 the source must be a single file.
1846 the source must be a single file.
1847
1847
1848 By default, this command copies the contents of files as they
1848 By default, this command copies the contents of files as they
1849 exist in the working directory. If invoked with -A/--after, the
1849 exist in the working directory. If invoked with -A/--after, the
1850 operation is recorded, but no copying is performed.
1850 operation is recorded, but no copying is performed.
1851
1851
1852 This command takes effect with the next commit. To undo a copy
1852 This command takes effect with the next commit. To undo a copy
1853 before that, see :hg:`revert`.
1853 before that, see :hg:`revert`.
1854
1854
1855 Returns 0 on success, 1 if errors are encountered.
1855 Returns 0 on success, 1 if errors are encountered.
1856 """
1856 """
1857 with repo.wlock(False):
1857 with repo.wlock(False):
1858 return cmdutil.copy(ui, repo, pats, opts)
1858 return cmdutil.copy(ui, repo, pats, opts)
1859
1859
1860 @command('^diff',
1860 @command('^diff',
1861 [('r', 'rev', [], _('revision'), _('REV')),
1861 [('r', 'rev', [], _('revision'), _('REV')),
1862 ('c', 'change', '', _('change made by revision'), _('REV'))
1862 ('c', 'change', '', _('change made by revision'), _('REV'))
1863 ] + diffopts + diffopts2 + walkopts + subrepoopts,
1863 ] + diffopts + diffopts2 + walkopts + subrepoopts,
1864 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
1864 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
1865 inferrepo=True)
1865 inferrepo=True)
1866 def diff(ui, repo, *pats, **opts):
1866 def diff(ui, repo, *pats, **opts):
1867 """diff repository (or selected files)
1867 """diff repository (or selected files)
1868
1868
1869 Show differences between revisions for the specified files.
1869 Show differences between revisions for the specified files.
1870
1870
1871 Differences between files are shown using the unified diff format.
1871 Differences between files are shown using the unified diff format.
1872
1872
1873 .. note::
1873 .. note::
1874
1874
1875 :hg:`diff` may generate unexpected results for merges, as it will
1875 :hg:`diff` may generate unexpected results for merges, as it will
1876 default to comparing against the working directory's first
1876 default to comparing against the working directory's first
1877 parent changeset if no revisions are specified.
1877 parent changeset if no revisions are specified.
1878
1878
1879 When two revision arguments are given, then changes are shown
1879 When two revision arguments are given, then changes are shown
1880 between those revisions. If only one revision is specified then
1880 between those revisions. If only one revision is specified then
1881 that revision is compared to the working directory, and, when no
1881 that revision is compared to the working directory, and, when no
1882 revisions are specified, the working directory files are compared
1882 revisions are specified, the working directory files are compared
1883 to its first parent.
1883 to its first parent.
1884
1884
1885 Alternatively you can specify -c/--change with a revision to see
1885 Alternatively you can specify -c/--change with a revision to see
1886 the changes in that changeset relative to its first parent.
1886 the changes in that changeset relative to its first parent.
1887
1887
1888 Without the -a/--text option, diff will avoid generating diffs of
1888 Without the -a/--text option, diff will avoid generating diffs of
1889 files it detects as binary. With -a, diff will generate a diff
1889 files it detects as binary. With -a, diff will generate a diff
1890 anyway, probably with undesirable results.
1890 anyway, probably with undesirable results.
1891
1891
1892 Use the -g/--git option to generate diffs in the git extended diff
1892 Use the -g/--git option to generate diffs in the git extended diff
1893 format. For more information, read :hg:`help diffs`.
1893 format. For more information, read :hg:`help diffs`.
1894
1894
1895 .. container:: verbose
1895 .. container:: verbose
1896
1896
1897 Examples:
1897 Examples:
1898
1898
1899 - compare a file in the current working directory to its parent::
1899 - compare a file in the current working directory to its parent::
1900
1900
1901 hg diff foo.c
1901 hg diff foo.c
1902
1902
1903 - compare two historical versions of a directory, with rename info::
1903 - compare two historical versions of a directory, with rename info::
1904
1904
1905 hg diff --git -r 1.0:1.2 lib/
1905 hg diff --git -r 1.0:1.2 lib/
1906
1906
1907 - get change stats relative to the last change on some date::
1907 - get change stats relative to the last change on some date::
1908
1908
1909 hg diff --stat -r "date('may 2')"
1909 hg diff --stat -r "date('may 2')"
1910
1910
1911 - diff all newly-added files that contain a keyword::
1911 - diff all newly-added files that contain a keyword::
1912
1912
1913 hg diff "set:added() and grep(GNU)"
1913 hg diff "set:added() and grep(GNU)"
1914
1914
1915 - compare a revision and its parents::
1915 - compare a revision and its parents::
1916
1916
1917 hg diff -c 9353 # compare against first parent
1917 hg diff -c 9353 # compare against first parent
1918 hg diff -r 9353^:9353 # same using revset syntax
1918 hg diff -r 9353^:9353 # same using revset syntax
1919 hg diff -r 9353^2:9353 # compare against the second parent
1919 hg diff -r 9353^2:9353 # compare against the second parent
1920
1920
1921 Returns 0 on success.
1921 Returns 0 on success.
1922 """
1922 """
1923
1923
1924 revs = opts.get('rev')
1924 revs = opts.get('rev')
1925 change = opts.get('change')
1925 change = opts.get('change')
1926 stat = opts.get('stat')
1926 stat = opts.get('stat')
1927 reverse = opts.get('reverse')
1927 reverse = opts.get('reverse')
1928
1928
1929 if revs and change:
1929 if revs and change:
1930 msg = _('cannot specify --rev and --change at the same time')
1930 msg = _('cannot specify --rev and --change at the same time')
1931 raise error.Abort(msg)
1931 raise error.Abort(msg)
1932 elif change:
1932 elif change:
1933 node2 = scmutil.revsingle(repo, change, None).node()
1933 node2 = scmutil.revsingle(repo, change, None).node()
1934 node1 = repo[node2].p1().node()
1934 node1 = repo[node2].p1().node()
1935 else:
1935 else:
1936 node1, node2 = scmutil.revpair(repo, revs)
1936 node1, node2 = scmutil.revpair(repo, revs)
1937
1937
1938 if reverse:
1938 if reverse:
1939 node1, node2 = node2, node1
1939 node1, node2 = node2, node1
1940
1940
1941 diffopts = patch.diffallopts(ui, opts)
1941 diffopts = patch.diffallopts(ui, opts)
1942 m = scmutil.match(repo[node2], pats, opts)
1942 m = scmutil.match(repo[node2], pats, opts)
1943 ui.pager('diff')
1943 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
1944 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
1944 listsubrepos=opts.get('subrepos'),
1945 listsubrepos=opts.get('subrepos'),
1945 root=opts.get('root'))
1946 root=opts.get('root'))
1946
1947
1947 @command('^export',
1948 @command('^export',
1948 [('o', 'output', '',
1949 [('o', 'output', '',
1949 _('print output to file with formatted name'), _('FORMAT')),
1950 _('print output to file with formatted name'), _('FORMAT')),
1950 ('', 'switch-parent', None, _('diff against the second parent')),
1951 ('', 'switch-parent', None, _('diff against the second parent')),
1951 ('r', 'rev', [], _('revisions to export'), _('REV')),
1952 ('r', 'rev', [], _('revisions to export'), _('REV')),
1952 ] + diffopts,
1953 ] + diffopts,
1953 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
1954 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
1954 def export(ui, repo, *changesets, **opts):
1955 def export(ui, repo, *changesets, **opts):
1955 """dump the header and diffs for one or more changesets
1956 """dump the header and diffs for one or more changesets
1956
1957
1957 Print the changeset header and diffs for one or more revisions.
1958 Print the changeset header and diffs for one or more revisions.
1958 If no revision is given, the parent of the working directory is used.
1959 If no revision is given, the parent of the working directory is used.
1959
1960
1960 The information shown in the changeset header is: author, date,
1961 The information shown in the changeset header is: author, date,
1961 branch name (if non-default), changeset hash, parent(s) and commit
1962 branch name (if non-default), changeset hash, parent(s) and commit
1962 comment.
1963 comment.
1963
1964
1964 .. note::
1965 .. note::
1965
1966
1966 :hg:`export` may generate unexpected diff output for merge
1967 :hg:`export` may generate unexpected diff output for merge
1967 changesets, as it will compare the merge changeset against its
1968 changesets, as it will compare the merge changeset against its
1968 first parent only.
1969 first parent only.
1969
1970
1970 Output may be to a file, in which case the name of the file is
1971 Output may be to a file, in which case the name of the file is
1971 given using a format string. The formatting rules are as follows:
1972 given using a format string. The formatting rules are as follows:
1972
1973
1973 :``%%``: literal "%" character
1974 :``%%``: literal "%" character
1974 :``%H``: changeset hash (40 hexadecimal digits)
1975 :``%H``: changeset hash (40 hexadecimal digits)
1975 :``%N``: number of patches being generated
1976 :``%N``: number of patches being generated
1976 :``%R``: changeset revision number
1977 :``%R``: changeset revision number
1977 :``%b``: basename of the exporting repository
1978 :``%b``: basename of the exporting repository
1978 :``%h``: short-form changeset hash (12 hexadecimal digits)
1979 :``%h``: short-form changeset hash (12 hexadecimal digits)
1979 :``%m``: first line of the commit message (only alphanumeric characters)
1980 :``%m``: first line of the commit message (only alphanumeric characters)
1980 :``%n``: zero-padded sequence number, starting at 1
1981 :``%n``: zero-padded sequence number, starting at 1
1981 :``%r``: zero-padded changeset revision number
1982 :``%r``: zero-padded changeset revision number
1982
1983
1983 Without the -a/--text option, export will avoid generating diffs
1984 Without the -a/--text option, export will avoid generating diffs
1984 of files it detects as binary. With -a, export will generate a
1985 of files it detects as binary. With -a, export will generate a
1985 diff anyway, probably with undesirable results.
1986 diff anyway, probably with undesirable results.
1986
1987
1987 Use the -g/--git option to generate diffs in the git extended diff
1988 Use the -g/--git option to generate diffs in the git extended diff
1988 format. See :hg:`help diffs` for more information.
1989 format. See :hg:`help diffs` for more information.
1989
1990
1990 With the --switch-parent option, the diff will be against the
1991 With the --switch-parent option, the diff will be against the
1991 second parent. It can be useful to review a merge.
1992 second parent. It can be useful to review a merge.
1992
1993
1993 .. container:: verbose
1994 .. container:: verbose
1994
1995
1995 Examples:
1996 Examples:
1996
1997
1997 - use export and import to transplant a bugfix to the current
1998 - use export and import to transplant a bugfix to the current
1998 branch::
1999 branch::
1999
2000
2000 hg export -r 9353 | hg import -
2001 hg export -r 9353 | hg import -
2001
2002
2002 - export all the changesets between two revisions to a file with
2003 - export all the changesets between two revisions to a file with
2003 rename information::
2004 rename information::
2004
2005
2005 hg export --git -r 123:150 > changes.txt
2006 hg export --git -r 123:150 > changes.txt
2006
2007
2007 - split outgoing changes into a series of patches with
2008 - split outgoing changes into a series of patches with
2008 descriptive names::
2009 descriptive names::
2009
2010
2010 hg export -r "outgoing()" -o "%n-%m.patch"
2011 hg export -r "outgoing()" -o "%n-%m.patch"
2011
2012
2012 Returns 0 on success.
2013 Returns 0 on success.
2013 """
2014 """
2014 changesets += tuple(opts.get('rev', []))
2015 changesets += tuple(opts.get('rev', []))
2015 if not changesets:
2016 if not changesets:
2016 changesets = ['.']
2017 changesets = ['.']
2017 revs = scmutil.revrange(repo, changesets)
2018 revs = scmutil.revrange(repo, changesets)
2018 if not revs:
2019 if not revs:
2019 raise error.Abort(_("export requires at least one changeset"))
2020 raise error.Abort(_("export requires at least one changeset"))
2020 if len(revs) > 1:
2021 if len(revs) > 1:
2021 ui.note(_('exporting patches:\n'))
2022 ui.note(_('exporting patches:\n'))
2022 else:
2023 else:
2023 ui.note(_('exporting patch:\n'))
2024 ui.note(_('exporting patch:\n'))
2024 cmdutil.export(repo, revs, template=opts.get('output'),
2025 cmdutil.export(repo, revs, template=opts.get('output'),
2025 switch_parent=opts.get('switch_parent'),
2026 switch_parent=opts.get('switch_parent'),
2026 opts=patch.diffallopts(ui, opts))
2027 opts=patch.diffallopts(ui, opts))
2027
2028
2028 @command('files',
2029 @command('files',
2029 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
2030 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
2030 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
2031 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
2031 ] + walkopts + formatteropts + subrepoopts,
2032 ] + walkopts + formatteropts + subrepoopts,
2032 _('[OPTION]... [FILE]...'))
2033 _('[OPTION]... [FILE]...'))
2033 def files(ui, repo, *pats, **opts):
2034 def files(ui, repo, *pats, **opts):
2034 """list tracked files
2035 """list tracked files
2035
2036
2036 Print files under Mercurial control in the working directory or
2037 Print files under Mercurial control in the working directory or
2037 specified revision for given files (excluding removed files).
2038 specified revision for given files (excluding removed files).
2038 Files can be specified as filenames or filesets.
2039 Files can be specified as filenames or filesets.
2039
2040
2040 If no files are given to match, this command prints the names
2041 If no files are given to match, this command prints the names
2041 of all files under Mercurial control.
2042 of all files under Mercurial control.
2042
2043
2043 .. container:: verbose
2044 .. container:: verbose
2044
2045
2045 Examples:
2046 Examples:
2046
2047
2047 - list all files under the current directory::
2048 - list all files under the current directory::
2048
2049
2049 hg files .
2050 hg files .
2050
2051
2051 - shows sizes and flags for current revision::
2052 - shows sizes and flags for current revision::
2052
2053
2053 hg files -vr .
2054 hg files -vr .
2054
2055
2055 - list all files named README::
2056 - list all files named README::
2056
2057
2057 hg files -I "**/README"
2058 hg files -I "**/README"
2058
2059
2059 - list all binary files::
2060 - list all binary files::
2060
2061
2061 hg files "set:binary()"
2062 hg files "set:binary()"
2062
2063
2063 - find files containing a regular expression::
2064 - find files containing a regular expression::
2064
2065
2065 hg files "set:grep('bob')"
2066 hg files "set:grep('bob')"
2066
2067
2067 - search tracked file contents with xargs and grep::
2068 - search tracked file contents with xargs and grep::
2068
2069
2069 hg files -0 | xargs -0 grep foo
2070 hg files -0 | xargs -0 grep foo
2070
2071
2071 See :hg:`help patterns` and :hg:`help filesets` for more information
2072 See :hg:`help patterns` and :hg:`help filesets` for more information
2072 on specifying file patterns.
2073 on specifying file patterns.
2073
2074
2074 Returns 0 if a match is found, 1 otherwise.
2075 Returns 0 if a match is found, 1 otherwise.
2075
2076
2076 """
2077 """
2077 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2078 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2078
2079
2079 end = '\n'
2080 end = '\n'
2080 if opts.get('print0'):
2081 if opts.get('print0'):
2081 end = '\0'
2082 end = '\0'
2082 fmt = '%s' + end
2083 fmt = '%s' + end
2083
2084
2084 m = scmutil.match(ctx, pats, opts)
2085 m = scmutil.match(ctx, pats, opts)
2085 with ui.formatter('files', opts) as fm:
2086 with ui.formatter('files', opts) as fm:
2086 return cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
2087 return cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
2087
2088
2088 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
2089 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
2089 def forget(ui, repo, *pats, **opts):
2090 def forget(ui, repo, *pats, **opts):
2090 """forget the specified files on the next commit
2091 """forget the specified files on the next commit
2091
2092
2092 Mark the specified files so they will no longer be tracked
2093 Mark the specified files so they will no longer be tracked
2093 after the next commit.
2094 after the next commit.
2094
2095
2095 This only removes files from the current branch, not from the
2096 This only removes files from the current branch, not from the
2096 entire project history, and it does not delete them from the
2097 entire project history, and it does not delete them from the
2097 working directory.
2098 working directory.
2098
2099
2099 To delete the file from the working directory, see :hg:`remove`.
2100 To delete the file from the working directory, see :hg:`remove`.
2100
2101
2101 To undo a forget before the next commit, see :hg:`add`.
2102 To undo a forget before the next commit, see :hg:`add`.
2102
2103
2103 .. container:: verbose
2104 .. container:: verbose
2104
2105
2105 Examples:
2106 Examples:
2106
2107
2107 - forget newly-added binary files::
2108 - forget newly-added binary files::
2108
2109
2109 hg forget "set:added() and binary()"
2110 hg forget "set:added() and binary()"
2110
2111
2111 - forget files that would be excluded by .hgignore::
2112 - forget files that would be excluded by .hgignore::
2112
2113
2113 hg forget "set:hgignore()"
2114 hg forget "set:hgignore()"
2114
2115
2115 Returns 0 on success.
2116 Returns 0 on success.
2116 """
2117 """
2117
2118
2118 if not pats:
2119 if not pats:
2119 raise error.Abort(_('no files specified'))
2120 raise error.Abort(_('no files specified'))
2120
2121
2121 m = scmutil.match(repo[None], pats, opts)
2122 m = scmutil.match(repo[None], pats, opts)
2122 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2123 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2123 return rejected and 1 or 0
2124 return rejected and 1 or 0
2124
2125
2125 @command(
2126 @command(
2126 'graft',
2127 'graft',
2127 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2128 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2128 ('c', 'continue', False, _('resume interrupted graft')),
2129 ('c', 'continue', False, _('resume interrupted graft')),
2129 ('e', 'edit', False, _('invoke editor on commit messages')),
2130 ('e', 'edit', False, _('invoke editor on commit messages')),
2130 ('', 'log', None, _('append graft info to log message')),
2131 ('', 'log', None, _('append graft info to log message')),
2131 ('f', 'force', False, _('force graft')),
2132 ('f', 'force', False, _('force graft')),
2132 ('D', 'currentdate', False,
2133 ('D', 'currentdate', False,
2133 _('record the current date as commit date')),
2134 _('record the current date as commit date')),
2134 ('U', 'currentuser', False,
2135 ('U', 'currentuser', False,
2135 _('record the current user as committer'), _('DATE'))]
2136 _('record the current user as committer'), _('DATE'))]
2136 + commitopts2 + mergetoolopts + dryrunopts,
2137 + commitopts2 + mergetoolopts + dryrunopts,
2137 _('[OPTION]... [-r REV]... REV...'))
2138 _('[OPTION]... [-r REV]... REV...'))
2138 def graft(ui, repo, *revs, **opts):
2139 def graft(ui, repo, *revs, **opts):
2139 '''copy changes from other branches onto the current branch
2140 '''copy changes from other branches onto the current branch
2140
2141
2141 This command uses Mercurial's merge logic to copy individual
2142 This command uses Mercurial's merge logic to copy individual
2142 changes from other branches without merging branches in the
2143 changes from other branches without merging branches in the
2143 history graph. This is sometimes known as 'backporting' or
2144 history graph. This is sometimes known as 'backporting' or
2144 'cherry-picking'. By default, graft will copy user, date, and
2145 'cherry-picking'. By default, graft will copy user, date, and
2145 description from the source changesets.
2146 description from the source changesets.
2146
2147
2147 Changesets that are ancestors of the current revision, that have
2148 Changesets that are ancestors of the current revision, that have
2148 already been grafted, or that are merges will be skipped.
2149 already been grafted, or that are merges will be skipped.
2149
2150
2150 If --log is specified, log messages will have a comment appended
2151 If --log is specified, log messages will have a comment appended
2151 of the form::
2152 of the form::
2152
2153
2153 (grafted from CHANGESETHASH)
2154 (grafted from CHANGESETHASH)
2154
2155
2155 If --force is specified, revisions will be grafted even if they
2156 If --force is specified, revisions will be grafted even if they
2156 are already ancestors of or have been grafted to the destination.
2157 are already ancestors of or have been grafted to the destination.
2157 This is useful when the revisions have since been backed out.
2158 This is useful when the revisions have since been backed out.
2158
2159
2159 If a graft merge results in conflicts, the graft process is
2160 If a graft merge results in conflicts, the graft process is
2160 interrupted so that the current merge can be manually resolved.
2161 interrupted so that the current merge can be manually resolved.
2161 Once all conflicts are addressed, the graft process can be
2162 Once all conflicts are addressed, the graft process can be
2162 continued with the -c/--continue option.
2163 continued with the -c/--continue option.
2163
2164
2164 .. note::
2165 .. note::
2165
2166
2166 The -c/--continue option does not reapply earlier options, except
2167 The -c/--continue option does not reapply earlier options, except
2167 for --force.
2168 for --force.
2168
2169
2169 .. container:: verbose
2170 .. container:: verbose
2170
2171
2171 Examples:
2172 Examples:
2172
2173
2173 - copy a single change to the stable branch and edit its description::
2174 - copy a single change to the stable branch and edit its description::
2174
2175
2175 hg update stable
2176 hg update stable
2176 hg graft --edit 9393
2177 hg graft --edit 9393
2177
2178
2178 - graft a range of changesets with one exception, updating dates::
2179 - graft a range of changesets with one exception, updating dates::
2179
2180
2180 hg graft -D "2085::2093 and not 2091"
2181 hg graft -D "2085::2093 and not 2091"
2181
2182
2182 - continue a graft after resolving conflicts::
2183 - continue a graft after resolving conflicts::
2183
2184
2184 hg graft -c
2185 hg graft -c
2185
2186
2186 - show the source of a grafted changeset::
2187 - show the source of a grafted changeset::
2187
2188
2188 hg log --debug -r .
2189 hg log --debug -r .
2189
2190
2190 - show revisions sorted by date::
2191 - show revisions sorted by date::
2191
2192
2192 hg log -r "sort(all(), date)"
2193 hg log -r "sort(all(), date)"
2193
2194
2194 See :hg:`help revisions` for more about specifying revisions.
2195 See :hg:`help revisions` for more about specifying revisions.
2195
2196
2196 Returns 0 on successful completion.
2197 Returns 0 on successful completion.
2197 '''
2198 '''
2198 with repo.wlock():
2199 with repo.wlock():
2199 return _dograft(ui, repo, *revs, **opts)
2200 return _dograft(ui, repo, *revs, **opts)
2200
2201
2201 def _dograft(ui, repo, *revs, **opts):
2202 def _dograft(ui, repo, *revs, **opts):
2202 if revs and opts.get('rev'):
2203 if revs and opts.get('rev'):
2203 ui.warn(_('warning: inconsistent use of --rev might give unexpected '
2204 ui.warn(_('warning: inconsistent use of --rev might give unexpected '
2204 'revision ordering!\n'))
2205 'revision ordering!\n'))
2205
2206
2206 revs = list(revs)
2207 revs = list(revs)
2207 revs.extend(opts.get('rev'))
2208 revs.extend(opts.get('rev'))
2208
2209
2209 if not opts.get('user') and opts.get('currentuser'):
2210 if not opts.get('user') and opts.get('currentuser'):
2210 opts['user'] = ui.username()
2211 opts['user'] = ui.username()
2211 if not opts.get('date') and opts.get('currentdate'):
2212 if not opts.get('date') and opts.get('currentdate'):
2212 opts['date'] = "%d %d" % util.makedate()
2213 opts['date'] = "%d %d" % util.makedate()
2213
2214
2214 editor = cmdutil.getcommiteditor(editform='graft', **opts)
2215 editor = cmdutil.getcommiteditor(editform='graft', **opts)
2215
2216
2216 cont = False
2217 cont = False
2217 if opts.get('continue'):
2218 if opts.get('continue'):
2218 cont = True
2219 cont = True
2219 if revs:
2220 if revs:
2220 raise error.Abort(_("can't specify --continue and revisions"))
2221 raise error.Abort(_("can't specify --continue and revisions"))
2221 # read in unfinished revisions
2222 # read in unfinished revisions
2222 try:
2223 try:
2223 nodes = repo.vfs.read('graftstate').splitlines()
2224 nodes = repo.vfs.read('graftstate').splitlines()
2224 revs = [repo[node].rev() for node in nodes]
2225 revs = [repo[node].rev() for node in nodes]
2225 except IOError as inst:
2226 except IOError as inst:
2226 if inst.errno != errno.ENOENT:
2227 if inst.errno != errno.ENOENT:
2227 raise
2228 raise
2228 cmdutil.wrongtooltocontinue(repo, _('graft'))
2229 cmdutil.wrongtooltocontinue(repo, _('graft'))
2229 else:
2230 else:
2230 cmdutil.checkunfinished(repo)
2231 cmdutil.checkunfinished(repo)
2231 cmdutil.bailifchanged(repo)
2232 cmdutil.bailifchanged(repo)
2232 if not revs:
2233 if not revs:
2233 raise error.Abort(_('no revisions specified'))
2234 raise error.Abort(_('no revisions specified'))
2234 revs = scmutil.revrange(repo, revs)
2235 revs = scmutil.revrange(repo, revs)
2235
2236
2236 skipped = set()
2237 skipped = set()
2237 # check for merges
2238 # check for merges
2238 for rev in repo.revs('%ld and merge()', revs):
2239 for rev in repo.revs('%ld and merge()', revs):
2239 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2240 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2240 skipped.add(rev)
2241 skipped.add(rev)
2241 revs = [r for r in revs if r not in skipped]
2242 revs = [r for r in revs if r not in skipped]
2242 if not revs:
2243 if not revs:
2243 return -1
2244 return -1
2244
2245
2245 # Don't check in the --continue case, in effect retaining --force across
2246 # Don't check in the --continue case, in effect retaining --force across
2246 # --continues. That's because without --force, any revisions we decided to
2247 # --continues. That's because without --force, any revisions we decided to
2247 # skip would have been filtered out here, so they wouldn't have made their
2248 # skip would have been filtered out here, so they wouldn't have made their
2248 # way to the graftstate. With --force, any revisions we would have otherwise
2249 # way to the graftstate. With --force, any revisions we would have otherwise
2249 # skipped would not have been filtered out, and if they hadn't been applied
2250 # skipped would not have been filtered out, and if they hadn't been applied
2250 # already, they'd have been in the graftstate.
2251 # already, they'd have been in the graftstate.
2251 if not (cont or opts.get('force')):
2252 if not (cont or opts.get('force')):
2252 # check for ancestors of dest branch
2253 # check for ancestors of dest branch
2253 crev = repo['.'].rev()
2254 crev = repo['.'].rev()
2254 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2255 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2255 # XXX make this lazy in the future
2256 # XXX make this lazy in the future
2256 # don't mutate while iterating, create a copy
2257 # don't mutate while iterating, create a copy
2257 for rev in list(revs):
2258 for rev in list(revs):
2258 if rev in ancestors:
2259 if rev in ancestors:
2259 ui.warn(_('skipping ancestor revision %d:%s\n') %
2260 ui.warn(_('skipping ancestor revision %d:%s\n') %
2260 (rev, repo[rev]))
2261 (rev, repo[rev]))
2261 # XXX remove on list is slow
2262 # XXX remove on list is slow
2262 revs.remove(rev)
2263 revs.remove(rev)
2263 if not revs:
2264 if not revs:
2264 return -1
2265 return -1
2265
2266
2266 # analyze revs for earlier grafts
2267 # analyze revs for earlier grafts
2267 ids = {}
2268 ids = {}
2268 for ctx in repo.set("%ld", revs):
2269 for ctx in repo.set("%ld", revs):
2269 ids[ctx.hex()] = ctx.rev()
2270 ids[ctx.hex()] = ctx.rev()
2270 n = ctx.extra().get('source')
2271 n = ctx.extra().get('source')
2271 if n:
2272 if n:
2272 ids[n] = ctx.rev()
2273 ids[n] = ctx.rev()
2273
2274
2274 # check ancestors for earlier grafts
2275 # check ancestors for earlier grafts
2275 ui.debug('scanning for duplicate grafts\n')
2276 ui.debug('scanning for duplicate grafts\n')
2276
2277
2277 for rev in repo.changelog.findmissingrevs(revs, [crev]):
2278 for rev in repo.changelog.findmissingrevs(revs, [crev]):
2278 ctx = repo[rev]
2279 ctx = repo[rev]
2279 n = ctx.extra().get('source')
2280 n = ctx.extra().get('source')
2280 if n in ids:
2281 if n in ids:
2281 try:
2282 try:
2282 r = repo[n].rev()
2283 r = repo[n].rev()
2283 except error.RepoLookupError:
2284 except error.RepoLookupError:
2284 r = None
2285 r = None
2285 if r in revs:
2286 if r in revs:
2286 ui.warn(_('skipping revision %d:%s '
2287 ui.warn(_('skipping revision %d:%s '
2287 '(already grafted to %d:%s)\n')
2288 '(already grafted to %d:%s)\n')
2288 % (r, repo[r], rev, ctx))
2289 % (r, repo[r], rev, ctx))
2289 revs.remove(r)
2290 revs.remove(r)
2290 elif ids[n] in revs:
2291 elif ids[n] in revs:
2291 if r is None:
2292 if r is None:
2292 ui.warn(_('skipping already grafted revision %d:%s '
2293 ui.warn(_('skipping already grafted revision %d:%s '
2293 '(%d:%s also has unknown origin %s)\n')
2294 '(%d:%s also has unknown origin %s)\n')
2294 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
2295 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
2295 else:
2296 else:
2296 ui.warn(_('skipping already grafted revision %d:%s '
2297 ui.warn(_('skipping already grafted revision %d:%s '
2297 '(%d:%s also has origin %d:%s)\n')
2298 '(%d:%s also has origin %d:%s)\n')
2298 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
2299 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
2299 revs.remove(ids[n])
2300 revs.remove(ids[n])
2300 elif ctx.hex() in ids:
2301 elif ctx.hex() in ids:
2301 r = ids[ctx.hex()]
2302 r = ids[ctx.hex()]
2302 ui.warn(_('skipping already grafted revision %d:%s '
2303 ui.warn(_('skipping already grafted revision %d:%s '
2303 '(was grafted from %d:%s)\n') %
2304 '(was grafted from %d:%s)\n') %
2304 (r, repo[r], rev, ctx))
2305 (r, repo[r], rev, ctx))
2305 revs.remove(r)
2306 revs.remove(r)
2306 if not revs:
2307 if not revs:
2307 return -1
2308 return -1
2308
2309
2309 for pos, ctx in enumerate(repo.set("%ld", revs)):
2310 for pos, ctx in enumerate(repo.set("%ld", revs)):
2310 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
2311 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
2311 ctx.description().split('\n', 1)[0])
2312 ctx.description().split('\n', 1)[0])
2312 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
2313 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
2313 if names:
2314 if names:
2314 desc += ' (%s)' % ' '.join(names)
2315 desc += ' (%s)' % ' '.join(names)
2315 ui.status(_('grafting %s\n') % desc)
2316 ui.status(_('grafting %s\n') % desc)
2316 if opts.get('dry_run'):
2317 if opts.get('dry_run'):
2317 continue
2318 continue
2318
2319
2319 source = ctx.extra().get('source')
2320 source = ctx.extra().get('source')
2320 extra = {}
2321 extra = {}
2321 if source:
2322 if source:
2322 extra['source'] = source
2323 extra['source'] = source
2323 extra['intermediate-source'] = ctx.hex()
2324 extra['intermediate-source'] = ctx.hex()
2324 else:
2325 else:
2325 extra['source'] = ctx.hex()
2326 extra['source'] = ctx.hex()
2326 user = ctx.user()
2327 user = ctx.user()
2327 if opts.get('user'):
2328 if opts.get('user'):
2328 user = opts['user']
2329 user = opts['user']
2329 date = ctx.date()
2330 date = ctx.date()
2330 if opts.get('date'):
2331 if opts.get('date'):
2331 date = opts['date']
2332 date = opts['date']
2332 message = ctx.description()
2333 message = ctx.description()
2333 if opts.get('log'):
2334 if opts.get('log'):
2334 message += '\n(grafted from %s)' % ctx.hex()
2335 message += '\n(grafted from %s)' % ctx.hex()
2335
2336
2336 # we don't merge the first commit when continuing
2337 # we don't merge the first commit when continuing
2337 if not cont:
2338 if not cont:
2338 # perform the graft merge with p1(rev) as 'ancestor'
2339 # perform the graft merge with p1(rev) as 'ancestor'
2339 try:
2340 try:
2340 # ui.forcemerge is an internal variable, do not document
2341 # ui.forcemerge is an internal variable, do not document
2341 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
2342 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
2342 'graft')
2343 'graft')
2343 stats = mergemod.graft(repo, ctx, ctx.p1(),
2344 stats = mergemod.graft(repo, ctx, ctx.p1(),
2344 ['local', 'graft'])
2345 ['local', 'graft'])
2345 finally:
2346 finally:
2346 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
2347 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
2347 # report any conflicts
2348 # report any conflicts
2348 if stats and stats[3] > 0:
2349 if stats and stats[3] > 0:
2349 # write out state for --continue
2350 # write out state for --continue
2350 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2351 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2351 repo.vfs.write('graftstate', ''.join(nodelines))
2352 repo.vfs.write('graftstate', ''.join(nodelines))
2352 extra = ''
2353 extra = ''
2353 if opts.get('user'):
2354 if opts.get('user'):
2354 extra += ' --user %s' % util.shellquote(opts['user'])
2355 extra += ' --user %s' % util.shellquote(opts['user'])
2355 if opts.get('date'):
2356 if opts.get('date'):
2356 extra += ' --date %s' % util.shellquote(opts['date'])
2357 extra += ' --date %s' % util.shellquote(opts['date'])
2357 if opts.get('log'):
2358 if opts.get('log'):
2358 extra += ' --log'
2359 extra += ' --log'
2359 hint=_("use 'hg resolve' and 'hg graft --continue%s'") % extra
2360 hint=_("use 'hg resolve' and 'hg graft --continue%s'") % extra
2360 raise error.Abort(
2361 raise error.Abort(
2361 _("unresolved conflicts, can't continue"),
2362 _("unresolved conflicts, can't continue"),
2362 hint=hint)
2363 hint=hint)
2363 else:
2364 else:
2364 cont = False
2365 cont = False
2365
2366
2366 # commit
2367 # commit
2367 node = repo.commit(text=message, user=user,
2368 node = repo.commit(text=message, user=user,
2368 date=date, extra=extra, editor=editor)
2369 date=date, extra=extra, editor=editor)
2369 if node is None:
2370 if node is None:
2370 ui.warn(
2371 ui.warn(
2371 _('note: graft of %d:%s created no changes to commit\n') %
2372 _('note: graft of %d:%s created no changes to commit\n') %
2372 (ctx.rev(), ctx))
2373 (ctx.rev(), ctx))
2373
2374
2374 # remove state when we complete successfully
2375 # remove state when we complete successfully
2375 if not opts.get('dry_run'):
2376 if not opts.get('dry_run'):
2376 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
2377 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
2377
2378
2378 return 0
2379 return 0
2379
2380
2380 @command('grep',
2381 @command('grep',
2381 [('0', 'print0', None, _('end fields with NUL')),
2382 [('0', 'print0', None, _('end fields with NUL')),
2382 ('', 'all', None, _('print all revisions that match')),
2383 ('', 'all', None, _('print all revisions that match')),
2383 ('a', 'text', None, _('treat all files as text')),
2384 ('a', 'text', None, _('treat all files as text')),
2384 ('f', 'follow', None,
2385 ('f', 'follow', None,
2385 _('follow changeset history,'
2386 _('follow changeset history,'
2386 ' or file history across copies and renames')),
2387 ' or file history across copies and renames')),
2387 ('i', 'ignore-case', None, _('ignore case when matching')),
2388 ('i', 'ignore-case', None, _('ignore case when matching')),
2388 ('l', 'files-with-matches', None,
2389 ('l', 'files-with-matches', None,
2389 _('print only filenames and revisions that match')),
2390 _('print only filenames and revisions that match')),
2390 ('n', 'line-number', None, _('print matching line numbers')),
2391 ('n', 'line-number', None, _('print matching line numbers')),
2391 ('r', 'rev', [],
2392 ('r', 'rev', [],
2392 _('only search files changed within revision range'), _('REV')),
2393 _('only search files changed within revision range'), _('REV')),
2393 ('u', 'user', None, _('list the author (long with -v)')),
2394 ('u', 'user', None, _('list the author (long with -v)')),
2394 ('d', 'date', None, _('list the date (short with -q)')),
2395 ('d', 'date', None, _('list the date (short with -q)')),
2395 ] + formatteropts + walkopts,
2396 ] + formatteropts + walkopts,
2396 _('[OPTION]... PATTERN [FILE]...'),
2397 _('[OPTION]... PATTERN [FILE]...'),
2397 inferrepo=True)
2398 inferrepo=True)
2398 def grep(ui, repo, pattern, *pats, **opts):
2399 def grep(ui, repo, pattern, *pats, **opts):
2399 """search revision history for a pattern in specified files
2400 """search revision history for a pattern in specified files
2400
2401
2401 Search revision history for a regular expression in the specified
2402 Search revision history for a regular expression in the specified
2402 files or the entire project.
2403 files or the entire project.
2403
2404
2404 By default, grep prints the most recent revision number for each
2405 By default, grep prints the most recent revision number for each
2405 file in which it finds a match. To get it to print every revision
2406 file in which it finds a match. To get it to print every revision
2406 that contains a change in match status ("-" for a match that becomes
2407 that contains a change in match status ("-" for a match that becomes
2407 a non-match, or "+" for a non-match that becomes a match), use the
2408 a non-match, or "+" for a non-match that becomes a match), use the
2408 --all flag.
2409 --all flag.
2409
2410
2410 PATTERN can be any Python (roughly Perl-compatible) regular
2411 PATTERN can be any Python (roughly Perl-compatible) regular
2411 expression.
2412 expression.
2412
2413
2413 If no FILEs are specified (and -f/--follow isn't set), all files in
2414 If no FILEs are specified (and -f/--follow isn't set), all files in
2414 the repository are searched, including those that don't exist in the
2415 the repository are searched, including those that don't exist in the
2415 current branch or have been deleted in a prior changeset.
2416 current branch or have been deleted in a prior changeset.
2416
2417
2417 Returns 0 if a match is found, 1 otherwise.
2418 Returns 0 if a match is found, 1 otherwise.
2418 """
2419 """
2419 reflags = re.M
2420 reflags = re.M
2420 if opts.get('ignore_case'):
2421 if opts.get('ignore_case'):
2421 reflags |= re.I
2422 reflags |= re.I
2422 try:
2423 try:
2423 regexp = util.re.compile(pattern, reflags)
2424 regexp = util.re.compile(pattern, reflags)
2424 except re.error as inst:
2425 except re.error as inst:
2425 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2426 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2426 return 1
2427 return 1
2427 sep, eol = ':', '\n'
2428 sep, eol = ':', '\n'
2428 if opts.get('print0'):
2429 if opts.get('print0'):
2429 sep = eol = '\0'
2430 sep = eol = '\0'
2430
2431
2431 getfile = util.lrucachefunc(repo.file)
2432 getfile = util.lrucachefunc(repo.file)
2432
2433
2433 def matchlines(body):
2434 def matchlines(body):
2434 begin = 0
2435 begin = 0
2435 linenum = 0
2436 linenum = 0
2436 while begin < len(body):
2437 while begin < len(body):
2437 match = regexp.search(body, begin)
2438 match = regexp.search(body, begin)
2438 if not match:
2439 if not match:
2439 break
2440 break
2440 mstart, mend = match.span()
2441 mstart, mend = match.span()
2441 linenum += body.count('\n', begin, mstart) + 1
2442 linenum += body.count('\n', begin, mstart) + 1
2442 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2443 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2443 begin = body.find('\n', mend) + 1 or len(body) + 1
2444 begin = body.find('\n', mend) + 1 or len(body) + 1
2444 lend = begin - 1
2445 lend = begin - 1
2445 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2446 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2446
2447
2447 class linestate(object):
2448 class linestate(object):
2448 def __init__(self, line, linenum, colstart, colend):
2449 def __init__(self, line, linenum, colstart, colend):
2449 self.line = line
2450 self.line = line
2450 self.linenum = linenum
2451 self.linenum = linenum
2451 self.colstart = colstart
2452 self.colstart = colstart
2452 self.colend = colend
2453 self.colend = colend
2453
2454
2454 def __hash__(self):
2455 def __hash__(self):
2455 return hash((self.linenum, self.line))
2456 return hash((self.linenum, self.line))
2456
2457
2457 def __eq__(self, other):
2458 def __eq__(self, other):
2458 return self.line == other.line
2459 return self.line == other.line
2459
2460
2460 def findpos(self):
2461 def findpos(self):
2461 """Iterate all (start, end) indices of matches"""
2462 """Iterate all (start, end) indices of matches"""
2462 yield self.colstart, self.colend
2463 yield self.colstart, self.colend
2463 p = self.colend
2464 p = self.colend
2464 while p < len(self.line):
2465 while p < len(self.line):
2465 m = regexp.search(self.line, p)
2466 m = regexp.search(self.line, p)
2466 if not m:
2467 if not m:
2467 break
2468 break
2468 yield m.span()
2469 yield m.span()
2469 p = m.end()
2470 p = m.end()
2470
2471
2471 matches = {}
2472 matches = {}
2472 copies = {}
2473 copies = {}
2473 def grepbody(fn, rev, body):
2474 def grepbody(fn, rev, body):
2474 matches[rev].setdefault(fn, [])
2475 matches[rev].setdefault(fn, [])
2475 m = matches[rev][fn]
2476 m = matches[rev][fn]
2476 for lnum, cstart, cend, line in matchlines(body):
2477 for lnum, cstart, cend, line in matchlines(body):
2477 s = linestate(line, lnum, cstart, cend)
2478 s = linestate(line, lnum, cstart, cend)
2478 m.append(s)
2479 m.append(s)
2479
2480
2480 def difflinestates(a, b):
2481 def difflinestates(a, b):
2481 sm = difflib.SequenceMatcher(None, a, b)
2482 sm = difflib.SequenceMatcher(None, a, b)
2482 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2483 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2483 if tag == 'insert':
2484 if tag == 'insert':
2484 for i in xrange(blo, bhi):
2485 for i in xrange(blo, bhi):
2485 yield ('+', b[i])
2486 yield ('+', b[i])
2486 elif tag == 'delete':
2487 elif tag == 'delete':
2487 for i in xrange(alo, ahi):
2488 for i in xrange(alo, ahi):
2488 yield ('-', a[i])
2489 yield ('-', a[i])
2489 elif tag == 'replace':
2490 elif tag == 'replace':
2490 for i in xrange(alo, ahi):
2491 for i in xrange(alo, ahi):
2491 yield ('-', a[i])
2492 yield ('-', a[i])
2492 for i in xrange(blo, bhi):
2493 for i in xrange(blo, bhi):
2493 yield ('+', b[i])
2494 yield ('+', b[i])
2494
2495
2495 def display(fm, fn, ctx, pstates, states):
2496 def display(fm, fn, ctx, pstates, states):
2496 rev = ctx.rev()
2497 rev = ctx.rev()
2497 if fm.isplain():
2498 if fm.isplain():
2498 formatuser = ui.shortuser
2499 formatuser = ui.shortuser
2499 else:
2500 else:
2500 formatuser = str
2501 formatuser = str
2501 if ui.quiet:
2502 if ui.quiet:
2502 datefmt = '%Y-%m-%d'
2503 datefmt = '%Y-%m-%d'
2503 else:
2504 else:
2504 datefmt = '%a %b %d %H:%M:%S %Y %1%2'
2505 datefmt = '%a %b %d %H:%M:%S %Y %1%2'
2505 found = False
2506 found = False
2506 @util.cachefunc
2507 @util.cachefunc
2507 def binary():
2508 def binary():
2508 flog = getfile(fn)
2509 flog = getfile(fn)
2509 return util.binary(flog.read(ctx.filenode(fn)))
2510 return util.binary(flog.read(ctx.filenode(fn)))
2510
2511
2511 fieldnamemap = {'filename': 'file', 'linenumber': 'line_number'}
2512 fieldnamemap = {'filename': 'file', 'linenumber': 'line_number'}
2512 if opts.get('all'):
2513 if opts.get('all'):
2513 iter = difflinestates(pstates, states)
2514 iter = difflinestates(pstates, states)
2514 else:
2515 else:
2515 iter = [('', l) for l in states]
2516 iter = [('', l) for l in states]
2516 for change, l in iter:
2517 for change, l in iter:
2517 fm.startitem()
2518 fm.startitem()
2518 fm.data(node=fm.hexfunc(ctx.node()))
2519 fm.data(node=fm.hexfunc(ctx.node()))
2519 cols = [
2520 cols = [
2520 ('filename', fn, True),
2521 ('filename', fn, True),
2521 ('rev', rev, True),
2522 ('rev', rev, True),
2522 ('linenumber', l.linenum, opts.get('line_number')),
2523 ('linenumber', l.linenum, opts.get('line_number')),
2523 ]
2524 ]
2524 if opts.get('all'):
2525 if opts.get('all'):
2525 cols.append(('change', change, True))
2526 cols.append(('change', change, True))
2526 cols.extend([
2527 cols.extend([
2527 ('user', formatuser(ctx.user()), opts.get('user')),
2528 ('user', formatuser(ctx.user()), opts.get('user')),
2528 ('date', fm.formatdate(ctx.date(), datefmt), opts.get('date')),
2529 ('date', fm.formatdate(ctx.date(), datefmt), opts.get('date')),
2529 ])
2530 ])
2530 lastcol = next(name for name, data, cond in reversed(cols) if cond)
2531 lastcol = next(name for name, data, cond in reversed(cols) if cond)
2531 for name, data, cond in cols:
2532 for name, data, cond in cols:
2532 field = fieldnamemap.get(name, name)
2533 field = fieldnamemap.get(name, name)
2533 fm.condwrite(cond, field, '%s', data, label='grep.%s' % name)
2534 fm.condwrite(cond, field, '%s', data, label='grep.%s' % name)
2534 if cond and name != lastcol:
2535 if cond and name != lastcol:
2535 fm.plain(sep, label='grep.sep')
2536 fm.plain(sep, label='grep.sep')
2536 if not opts.get('files_with_matches'):
2537 if not opts.get('files_with_matches'):
2537 fm.plain(sep, label='grep.sep')
2538 fm.plain(sep, label='grep.sep')
2538 if not opts.get('text') and binary():
2539 if not opts.get('text') and binary():
2539 fm.plain(_(" Binary file matches"))
2540 fm.plain(_(" Binary file matches"))
2540 else:
2541 else:
2541 displaymatches(fm.nested('texts'), l)
2542 displaymatches(fm.nested('texts'), l)
2542 fm.plain(eol)
2543 fm.plain(eol)
2543 found = True
2544 found = True
2544 if opts.get('files_with_matches'):
2545 if opts.get('files_with_matches'):
2545 break
2546 break
2546 return found
2547 return found
2547
2548
2548 def displaymatches(fm, l):
2549 def displaymatches(fm, l):
2549 p = 0
2550 p = 0
2550 for s, e in l.findpos():
2551 for s, e in l.findpos():
2551 if p < s:
2552 if p < s:
2552 fm.startitem()
2553 fm.startitem()
2553 fm.write('text', '%s', l.line[p:s])
2554 fm.write('text', '%s', l.line[p:s])
2554 fm.data(matched=False)
2555 fm.data(matched=False)
2555 fm.startitem()
2556 fm.startitem()
2556 fm.write('text', '%s', l.line[s:e], label='grep.match')
2557 fm.write('text', '%s', l.line[s:e], label='grep.match')
2557 fm.data(matched=True)
2558 fm.data(matched=True)
2558 p = e
2559 p = e
2559 if p < len(l.line):
2560 if p < len(l.line):
2560 fm.startitem()
2561 fm.startitem()
2561 fm.write('text', '%s', l.line[p:])
2562 fm.write('text', '%s', l.line[p:])
2562 fm.data(matched=False)
2563 fm.data(matched=False)
2563 fm.end()
2564 fm.end()
2564
2565
2565 skip = {}
2566 skip = {}
2566 revfiles = {}
2567 revfiles = {}
2567 matchfn = scmutil.match(repo[None], pats, opts)
2568 matchfn = scmutil.match(repo[None], pats, opts)
2568 found = False
2569 found = False
2569 follow = opts.get('follow')
2570 follow = opts.get('follow')
2570
2571
2571 def prep(ctx, fns):
2572 def prep(ctx, fns):
2572 rev = ctx.rev()
2573 rev = ctx.rev()
2573 pctx = ctx.p1()
2574 pctx = ctx.p1()
2574 parent = pctx.rev()
2575 parent = pctx.rev()
2575 matches.setdefault(rev, {})
2576 matches.setdefault(rev, {})
2576 matches.setdefault(parent, {})
2577 matches.setdefault(parent, {})
2577 files = revfiles.setdefault(rev, [])
2578 files = revfiles.setdefault(rev, [])
2578 for fn in fns:
2579 for fn in fns:
2579 flog = getfile(fn)
2580 flog = getfile(fn)
2580 try:
2581 try:
2581 fnode = ctx.filenode(fn)
2582 fnode = ctx.filenode(fn)
2582 except error.LookupError:
2583 except error.LookupError:
2583 continue
2584 continue
2584
2585
2585 copied = flog.renamed(fnode)
2586 copied = flog.renamed(fnode)
2586 copy = follow and copied and copied[0]
2587 copy = follow and copied and copied[0]
2587 if copy:
2588 if copy:
2588 copies.setdefault(rev, {})[fn] = copy
2589 copies.setdefault(rev, {})[fn] = copy
2589 if fn in skip:
2590 if fn in skip:
2590 if copy:
2591 if copy:
2591 skip[copy] = True
2592 skip[copy] = True
2592 continue
2593 continue
2593 files.append(fn)
2594 files.append(fn)
2594
2595
2595 if fn not in matches[rev]:
2596 if fn not in matches[rev]:
2596 grepbody(fn, rev, flog.read(fnode))
2597 grepbody(fn, rev, flog.read(fnode))
2597
2598
2598 pfn = copy or fn
2599 pfn = copy or fn
2599 if pfn not in matches[parent]:
2600 if pfn not in matches[parent]:
2600 try:
2601 try:
2601 fnode = pctx.filenode(pfn)
2602 fnode = pctx.filenode(pfn)
2602 grepbody(pfn, parent, flog.read(fnode))
2603 grepbody(pfn, parent, flog.read(fnode))
2603 except error.LookupError:
2604 except error.LookupError:
2604 pass
2605 pass
2605
2606
2606 fm = ui.formatter('grep', opts)
2607 fm = ui.formatter('grep', opts)
2607 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2608 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2608 rev = ctx.rev()
2609 rev = ctx.rev()
2609 parent = ctx.p1().rev()
2610 parent = ctx.p1().rev()
2610 for fn in sorted(revfiles.get(rev, [])):
2611 for fn in sorted(revfiles.get(rev, [])):
2611 states = matches[rev][fn]
2612 states = matches[rev][fn]
2612 copy = copies.get(rev, {}).get(fn)
2613 copy = copies.get(rev, {}).get(fn)
2613 if fn in skip:
2614 if fn in skip:
2614 if copy:
2615 if copy:
2615 skip[copy] = True
2616 skip[copy] = True
2616 continue
2617 continue
2617 pstates = matches.get(parent, {}).get(copy or fn, [])
2618 pstates = matches.get(parent, {}).get(copy or fn, [])
2618 if pstates or states:
2619 if pstates or states:
2619 r = display(fm, fn, ctx, pstates, states)
2620 r = display(fm, fn, ctx, pstates, states)
2620 found = found or r
2621 found = found or r
2621 if r and not opts.get('all'):
2622 if r and not opts.get('all'):
2622 skip[fn] = True
2623 skip[fn] = True
2623 if copy:
2624 if copy:
2624 skip[copy] = True
2625 skip[copy] = True
2625 del matches[rev]
2626 del matches[rev]
2626 del revfiles[rev]
2627 del revfiles[rev]
2627 fm.end()
2628 fm.end()
2628
2629
2629 return not found
2630 return not found
2630
2631
2631 @command('heads',
2632 @command('heads',
2632 [('r', 'rev', '',
2633 [('r', 'rev', '',
2633 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2634 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2634 ('t', 'topo', False, _('show topological heads only')),
2635 ('t', 'topo', False, _('show topological heads only')),
2635 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2636 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2636 ('c', 'closed', False, _('show normal and closed branch heads')),
2637 ('c', 'closed', False, _('show normal and closed branch heads')),
2637 ] + templateopts,
2638 ] + templateopts,
2638 _('[-ct] [-r STARTREV] [REV]...'))
2639 _('[-ct] [-r STARTREV] [REV]...'))
2639 def heads(ui, repo, *branchrevs, **opts):
2640 def heads(ui, repo, *branchrevs, **opts):
2640 """show branch heads
2641 """show branch heads
2641
2642
2642 With no arguments, show all open branch heads in the repository.
2643 With no arguments, show all open branch heads in the repository.
2643 Branch heads are changesets that have no descendants on the
2644 Branch heads are changesets that have no descendants on the
2644 same branch. They are where development generally takes place and
2645 same branch. They are where development generally takes place and
2645 are the usual targets for update and merge operations.
2646 are the usual targets for update and merge operations.
2646
2647
2647 If one or more REVs are given, only open branch heads on the
2648 If one or more REVs are given, only open branch heads on the
2648 branches associated with the specified changesets are shown. This
2649 branches associated with the specified changesets are shown. This
2649 means that you can use :hg:`heads .` to see the heads on the
2650 means that you can use :hg:`heads .` to see the heads on the
2650 currently checked-out branch.
2651 currently checked-out branch.
2651
2652
2652 If -c/--closed is specified, also show branch heads marked closed
2653 If -c/--closed is specified, also show branch heads marked closed
2653 (see :hg:`commit --close-branch`).
2654 (see :hg:`commit --close-branch`).
2654
2655
2655 If STARTREV is specified, only those heads that are descendants of
2656 If STARTREV is specified, only those heads that are descendants of
2656 STARTREV will be displayed.
2657 STARTREV will be displayed.
2657
2658
2658 If -t/--topo is specified, named branch mechanics will be ignored and only
2659 If -t/--topo is specified, named branch mechanics will be ignored and only
2659 topological heads (changesets with no children) will be shown.
2660 topological heads (changesets with no children) will be shown.
2660
2661
2661 Returns 0 if matching heads are found, 1 if not.
2662 Returns 0 if matching heads are found, 1 if not.
2662 """
2663 """
2663
2664
2664 start = None
2665 start = None
2665 if 'rev' in opts:
2666 if 'rev' in opts:
2666 start = scmutil.revsingle(repo, opts['rev'], None).node()
2667 start = scmutil.revsingle(repo, opts['rev'], None).node()
2667
2668
2668 if opts.get('topo'):
2669 if opts.get('topo'):
2669 heads = [repo[h] for h in repo.heads(start)]
2670 heads = [repo[h] for h in repo.heads(start)]
2670 else:
2671 else:
2671 heads = []
2672 heads = []
2672 for branch in repo.branchmap():
2673 for branch in repo.branchmap():
2673 heads += repo.branchheads(branch, start, opts.get('closed'))
2674 heads += repo.branchheads(branch, start, opts.get('closed'))
2674 heads = [repo[h] for h in heads]
2675 heads = [repo[h] for h in heads]
2675
2676
2676 if branchrevs:
2677 if branchrevs:
2677 branches = set(repo[br].branch() for br in branchrevs)
2678 branches = set(repo[br].branch() for br in branchrevs)
2678 heads = [h for h in heads if h.branch() in branches]
2679 heads = [h for h in heads if h.branch() in branches]
2679
2680
2680 if opts.get('active') and branchrevs:
2681 if opts.get('active') and branchrevs:
2681 dagheads = repo.heads(start)
2682 dagheads = repo.heads(start)
2682 heads = [h for h in heads if h.node() in dagheads]
2683 heads = [h for h in heads if h.node() in dagheads]
2683
2684
2684 if branchrevs:
2685 if branchrevs:
2685 haveheads = set(h.branch() for h in heads)
2686 haveheads = set(h.branch() for h in heads)
2686 if branches - haveheads:
2687 if branches - haveheads:
2687 headless = ', '.join(b for b in branches - haveheads)
2688 headless = ', '.join(b for b in branches - haveheads)
2688 msg = _('no open branch heads found on branches %s')
2689 msg = _('no open branch heads found on branches %s')
2689 if opts.get('rev'):
2690 if opts.get('rev'):
2690 msg += _(' (started at %s)') % opts['rev']
2691 msg += _(' (started at %s)') % opts['rev']
2691 ui.warn((msg + '\n') % headless)
2692 ui.warn((msg + '\n') % headless)
2692
2693
2693 if not heads:
2694 if not heads:
2694 return 1
2695 return 1
2695
2696
2696 heads = sorted(heads, key=lambda x: -x.rev())
2697 heads = sorted(heads, key=lambda x: -x.rev())
2697 displayer = cmdutil.show_changeset(ui, repo, opts)
2698 displayer = cmdutil.show_changeset(ui, repo, opts)
2698 for ctx in heads:
2699 for ctx in heads:
2699 displayer.show(ctx)
2700 displayer.show(ctx)
2700 displayer.close()
2701 displayer.close()
2701
2702
2702 @command('help',
2703 @command('help',
2703 [('e', 'extension', None, _('show only help for extensions')),
2704 [('e', 'extension', None, _('show only help for extensions')),
2704 ('c', 'command', None, _('show only help for commands')),
2705 ('c', 'command', None, _('show only help for commands')),
2705 ('k', 'keyword', None, _('show topics matching keyword')),
2706 ('k', 'keyword', None, _('show topics matching keyword')),
2706 ('s', 'system', [], _('show help for specific platform(s)')),
2707 ('s', 'system', [], _('show help for specific platform(s)')),
2707 ],
2708 ],
2708 _('[-ecks] [TOPIC]'),
2709 _('[-ecks] [TOPIC]'),
2709 norepo=True)
2710 norepo=True)
2710 def help_(ui, name=None, **opts):
2711 def help_(ui, name=None, **opts):
2711 """show help for a given topic or a help overview
2712 """show help for a given topic or a help overview
2712
2713
2713 With no arguments, print a list of commands with short help messages.
2714 With no arguments, print a list of commands with short help messages.
2714
2715
2715 Given a topic, extension, or command name, print help for that
2716 Given a topic, extension, or command name, print help for that
2716 topic.
2717 topic.
2717
2718
2718 Returns 0 if successful.
2719 Returns 0 if successful.
2719 """
2720 """
2720
2721
2721 textwidth = ui.configint('ui', 'textwidth', 78)
2722 textwidth = ui.configint('ui', 'textwidth', 78)
2722 termwidth = ui.termwidth() - 2
2723 termwidth = ui.termwidth() - 2
2723 if textwidth <= 0 or termwidth < textwidth:
2724 if textwidth <= 0 or termwidth < textwidth:
2724 textwidth = termwidth
2725 textwidth = termwidth
2725
2726
2726 keep = opts.get('system') or []
2727 keep = opts.get('system') or []
2727 if len(keep) == 0:
2728 if len(keep) == 0:
2728 if pycompat.sysplatform.startswith('win'):
2729 if pycompat.sysplatform.startswith('win'):
2729 keep.append('windows')
2730 keep.append('windows')
2730 elif pycompat.sysplatform == 'OpenVMS':
2731 elif pycompat.sysplatform == 'OpenVMS':
2731 keep.append('vms')
2732 keep.append('vms')
2732 elif pycompat.sysplatform == 'plan9':
2733 elif pycompat.sysplatform == 'plan9':
2733 keep.append('plan9')
2734 keep.append('plan9')
2734 else:
2735 else:
2735 keep.append('unix')
2736 keep.append('unix')
2736 keep.append(pycompat.sysplatform.lower())
2737 keep.append(pycompat.sysplatform.lower())
2737 if ui.verbose:
2738 if ui.verbose:
2738 keep.append('verbose')
2739 keep.append('verbose')
2739
2740
2740 fullname = name
2741 fullname = name
2741 section = None
2742 section = None
2742 subtopic = None
2743 subtopic = None
2743 if name and '.' in name:
2744 if name and '.' in name:
2744 name, remaining = name.split('.', 1)
2745 name, remaining = name.split('.', 1)
2745 remaining = encoding.lower(remaining)
2746 remaining = encoding.lower(remaining)
2746 if '.' in remaining:
2747 if '.' in remaining:
2747 subtopic, section = remaining.split('.', 1)
2748 subtopic, section = remaining.split('.', 1)
2748 else:
2749 else:
2749 if name in help.subtopics:
2750 if name in help.subtopics:
2750 subtopic = remaining
2751 subtopic = remaining
2751 else:
2752 else:
2752 section = remaining
2753 section = remaining
2753
2754
2754 text = help.help_(ui, name, subtopic=subtopic, **opts)
2755 text = help.help_(ui, name, subtopic=subtopic, **opts)
2755
2756
2756 formatted, pruned = minirst.format(text, textwidth, keep=keep,
2757 formatted, pruned = minirst.format(text, textwidth, keep=keep,
2757 section=section)
2758 section=section)
2758
2759
2759 # We could have been given a weird ".foo" section without a name
2760 # We could have been given a weird ".foo" section without a name
2760 # to look for, or we could have simply failed to found "foo.bar"
2761 # to look for, or we could have simply failed to found "foo.bar"
2761 # because bar isn't a section of foo
2762 # because bar isn't a section of foo
2762 if section and not (formatted and name):
2763 if section and not (formatted and name):
2763 raise error.Abort(_("help section not found: %s") % fullname)
2764 raise error.Abort(_("help section not found: %s") % fullname)
2764
2765
2765 if 'verbose' in pruned:
2766 if 'verbose' in pruned:
2766 keep.append('omitted')
2767 keep.append('omitted')
2767 else:
2768 else:
2768 keep.append('notomitted')
2769 keep.append('notomitted')
2769 formatted, pruned = minirst.format(text, textwidth, keep=keep,
2770 formatted, pruned = minirst.format(text, textwidth, keep=keep,
2770 section=section)
2771 section=section)
2771 ui.write(formatted)
2772 ui.write(formatted)
2772
2773
2773
2774
2774 @command('identify|id',
2775 @command('identify|id',
2775 [('r', 'rev', '',
2776 [('r', 'rev', '',
2776 _('identify the specified revision'), _('REV')),
2777 _('identify the specified revision'), _('REV')),
2777 ('n', 'num', None, _('show local revision number')),
2778 ('n', 'num', None, _('show local revision number')),
2778 ('i', 'id', None, _('show global revision id')),
2779 ('i', 'id', None, _('show global revision id')),
2779 ('b', 'branch', None, _('show branch')),
2780 ('b', 'branch', None, _('show branch')),
2780 ('t', 'tags', None, _('show tags')),
2781 ('t', 'tags', None, _('show tags')),
2781 ('B', 'bookmarks', None, _('show bookmarks')),
2782 ('B', 'bookmarks', None, _('show bookmarks')),
2782 ] + remoteopts,
2783 ] + remoteopts,
2783 _('[-nibtB] [-r REV] [SOURCE]'),
2784 _('[-nibtB] [-r REV] [SOURCE]'),
2784 optionalrepo=True)
2785 optionalrepo=True)
2785 def identify(ui, repo, source=None, rev=None,
2786 def identify(ui, repo, source=None, rev=None,
2786 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
2787 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
2787 """identify the working directory or specified revision
2788 """identify the working directory or specified revision
2788
2789
2789 Print a summary identifying the repository state at REV using one or
2790 Print a summary identifying the repository state at REV using one or
2790 two parent hash identifiers, followed by a "+" if the working
2791 two parent hash identifiers, followed by a "+" if the working
2791 directory has uncommitted changes, the branch name (if not default),
2792 directory has uncommitted changes, the branch name (if not default),
2792 a list of tags, and a list of bookmarks.
2793 a list of tags, and a list of bookmarks.
2793
2794
2794 When REV is not given, print a summary of the current state of the
2795 When REV is not given, print a summary of the current state of the
2795 repository.
2796 repository.
2796
2797
2797 Specifying a path to a repository root or Mercurial bundle will
2798 Specifying a path to a repository root or Mercurial bundle will
2798 cause lookup to operate on that repository/bundle.
2799 cause lookup to operate on that repository/bundle.
2799
2800
2800 .. container:: verbose
2801 .. container:: verbose
2801
2802
2802 Examples:
2803 Examples:
2803
2804
2804 - generate a build identifier for the working directory::
2805 - generate a build identifier for the working directory::
2805
2806
2806 hg id --id > build-id.dat
2807 hg id --id > build-id.dat
2807
2808
2808 - find the revision corresponding to a tag::
2809 - find the revision corresponding to a tag::
2809
2810
2810 hg id -n -r 1.3
2811 hg id -n -r 1.3
2811
2812
2812 - check the most recent revision of a remote repository::
2813 - check the most recent revision of a remote repository::
2813
2814
2814 hg id -r tip https://www.mercurial-scm.org/repo/hg/
2815 hg id -r tip https://www.mercurial-scm.org/repo/hg/
2815
2816
2816 See :hg:`log` for generating more information about specific revisions,
2817 See :hg:`log` for generating more information about specific revisions,
2817 including full hash identifiers.
2818 including full hash identifiers.
2818
2819
2819 Returns 0 if successful.
2820 Returns 0 if successful.
2820 """
2821 """
2821
2822
2822 if not repo and not source:
2823 if not repo and not source:
2823 raise error.Abort(_("there is no Mercurial repository here "
2824 raise error.Abort(_("there is no Mercurial repository here "
2824 "(.hg not found)"))
2825 "(.hg not found)"))
2825
2826
2826 if ui.debugflag:
2827 if ui.debugflag:
2827 hexfunc = hex
2828 hexfunc = hex
2828 else:
2829 else:
2829 hexfunc = short
2830 hexfunc = short
2830 default = not (num or id or branch or tags or bookmarks)
2831 default = not (num or id or branch or tags or bookmarks)
2831 output = []
2832 output = []
2832 revs = []
2833 revs = []
2833
2834
2834 if source:
2835 if source:
2835 source, branches = hg.parseurl(ui.expandpath(source))
2836 source, branches = hg.parseurl(ui.expandpath(source))
2836 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
2837 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
2837 repo = peer.local()
2838 repo = peer.local()
2838 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
2839 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
2839
2840
2840 if not repo:
2841 if not repo:
2841 if num or branch or tags:
2842 if num or branch or tags:
2842 raise error.Abort(
2843 raise error.Abort(
2843 _("can't query remote revision number, branch, or tags"))
2844 _("can't query remote revision number, branch, or tags"))
2844 if not rev and revs:
2845 if not rev and revs:
2845 rev = revs[0]
2846 rev = revs[0]
2846 if not rev:
2847 if not rev:
2847 rev = "tip"
2848 rev = "tip"
2848
2849
2849 remoterev = peer.lookup(rev)
2850 remoterev = peer.lookup(rev)
2850 if default or id:
2851 if default or id:
2851 output = [hexfunc(remoterev)]
2852 output = [hexfunc(remoterev)]
2852
2853
2853 def getbms():
2854 def getbms():
2854 bms = []
2855 bms = []
2855
2856
2856 if 'bookmarks' in peer.listkeys('namespaces'):
2857 if 'bookmarks' in peer.listkeys('namespaces'):
2857 hexremoterev = hex(remoterev)
2858 hexremoterev = hex(remoterev)
2858 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
2859 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
2859 if bmr == hexremoterev]
2860 if bmr == hexremoterev]
2860
2861
2861 return sorted(bms)
2862 return sorted(bms)
2862
2863
2863 if bookmarks:
2864 if bookmarks:
2864 output.extend(getbms())
2865 output.extend(getbms())
2865 elif default and not ui.quiet:
2866 elif default and not ui.quiet:
2866 # multiple bookmarks for a single parent separated by '/'
2867 # multiple bookmarks for a single parent separated by '/'
2867 bm = '/'.join(getbms())
2868 bm = '/'.join(getbms())
2868 if bm:
2869 if bm:
2869 output.append(bm)
2870 output.append(bm)
2870 else:
2871 else:
2871 ctx = scmutil.revsingle(repo, rev, None)
2872 ctx = scmutil.revsingle(repo, rev, None)
2872
2873
2873 if ctx.rev() is None:
2874 if ctx.rev() is None:
2874 ctx = repo[None]
2875 ctx = repo[None]
2875 parents = ctx.parents()
2876 parents = ctx.parents()
2876 taglist = []
2877 taglist = []
2877 for p in parents:
2878 for p in parents:
2878 taglist.extend(p.tags())
2879 taglist.extend(p.tags())
2879
2880
2880 changed = ""
2881 changed = ""
2881 if default or id or num:
2882 if default or id or num:
2882 if (any(repo.status())
2883 if (any(repo.status())
2883 or any(ctx.sub(s).dirty() for s in ctx.substate)):
2884 or any(ctx.sub(s).dirty() for s in ctx.substate)):
2884 changed = '+'
2885 changed = '+'
2885 if default or id:
2886 if default or id:
2886 output = ["%s%s" %
2887 output = ["%s%s" %
2887 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
2888 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
2888 if num:
2889 if num:
2889 output.append("%s%s" %
2890 output.append("%s%s" %
2890 ('+'.join([str(p.rev()) for p in parents]), changed))
2891 ('+'.join([str(p.rev()) for p in parents]), changed))
2891 else:
2892 else:
2892 if default or id:
2893 if default or id:
2893 output = [hexfunc(ctx.node())]
2894 output = [hexfunc(ctx.node())]
2894 if num:
2895 if num:
2895 output.append(str(ctx.rev()))
2896 output.append(str(ctx.rev()))
2896 taglist = ctx.tags()
2897 taglist = ctx.tags()
2897
2898
2898 if default and not ui.quiet:
2899 if default and not ui.quiet:
2899 b = ctx.branch()
2900 b = ctx.branch()
2900 if b != 'default':
2901 if b != 'default':
2901 output.append("(%s)" % b)
2902 output.append("(%s)" % b)
2902
2903
2903 # multiple tags for a single parent separated by '/'
2904 # multiple tags for a single parent separated by '/'
2904 t = '/'.join(taglist)
2905 t = '/'.join(taglist)
2905 if t:
2906 if t:
2906 output.append(t)
2907 output.append(t)
2907
2908
2908 # multiple bookmarks for a single parent separated by '/'
2909 # multiple bookmarks for a single parent separated by '/'
2909 bm = '/'.join(ctx.bookmarks())
2910 bm = '/'.join(ctx.bookmarks())
2910 if bm:
2911 if bm:
2911 output.append(bm)
2912 output.append(bm)
2912 else:
2913 else:
2913 if branch:
2914 if branch:
2914 output.append(ctx.branch())
2915 output.append(ctx.branch())
2915
2916
2916 if tags:
2917 if tags:
2917 output.extend(taglist)
2918 output.extend(taglist)
2918
2919
2919 if bookmarks:
2920 if bookmarks:
2920 output.extend(ctx.bookmarks())
2921 output.extend(ctx.bookmarks())
2921
2922
2922 ui.write("%s\n" % ' '.join(output))
2923 ui.write("%s\n" % ' '.join(output))
2923
2924
2924 @command('import|patch',
2925 @command('import|patch',
2925 [('p', 'strip', 1,
2926 [('p', 'strip', 1,
2926 _('directory strip option for patch. This has the same '
2927 _('directory strip option for patch. This has the same '
2927 'meaning as the corresponding patch option'), _('NUM')),
2928 'meaning as the corresponding patch option'), _('NUM')),
2928 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
2929 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
2929 ('e', 'edit', False, _('invoke editor on commit messages')),
2930 ('e', 'edit', False, _('invoke editor on commit messages')),
2930 ('f', 'force', None,
2931 ('f', 'force', None,
2931 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
2932 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
2932 ('', 'no-commit', None,
2933 ('', 'no-commit', None,
2933 _("don't commit, just update the working directory")),
2934 _("don't commit, just update the working directory")),
2934 ('', 'bypass', None,
2935 ('', 'bypass', None,
2935 _("apply patch without touching the working directory")),
2936 _("apply patch without touching the working directory")),
2936 ('', 'partial', None,
2937 ('', 'partial', None,
2937 _('commit even if some hunks fail')),
2938 _('commit even if some hunks fail')),
2938 ('', 'exact', None,
2939 ('', 'exact', None,
2939 _('abort if patch would apply lossily')),
2940 _('abort if patch would apply lossily')),
2940 ('', 'prefix', '',
2941 ('', 'prefix', '',
2941 _('apply patch to subdirectory'), _('DIR')),
2942 _('apply patch to subdirectory'), _('DIR')),
2942 ('', 'import-branch', None,
2943 ('', 'import-branch', None,
2943 _('use any branch information in patch (implied by --exact)'))] +
2944 _('use any branch information in patch (implied by --exact)'))] +
2944 commitopts + commitopts2 + similarityopts,
2945 commitopts + commitopts2 + similarityopts,
2945 _('[OPTION]... PATCH...'))
2946 _('[OPTION]... PATCH...'))
2946 def import_(ui, repo, patch1=None, *patches, **opts):
2947 def import_(ui, repo, patch1=None, *patches, **opts):
2947 """import an ordered set of patches
2948 """import an ordered set of patches
2948
2949
2949 Import a list of patches and commit them individually (unless
2950 Import a list of patches and commit them individually (unless
2950 --no-commit is specified).
2951 --no-commit is specified).
2951
2952
2952 To read a patch from standard input (stdin), use "-" as the patch
2953 To read a patch from standard input (stdin), use "-" as the patch
2953 name. If a URL is specified, the patch will be downloaded from
2954 name. If a URL is specified, the patch will be downloaded from
2954 there.
2955 there.
2955
2956
2956 Import first applies changes to the working directory (unless
2957 Import first applies changes to the working directory (unless
2957 --bypass is specified), import will abort if there are outstanding
2958 --bypass is specified), import will abort if there are outstanding
2958 changes.
2959 changes.
2959
2960
2960 Use --bypass to apply and commit patches directly to the
2961 Use --bypass to apply and commit patches directly to the
2961 repository, without affecting the working directory. Without
2962 repository, without affecting the working directory. Without
2962 --exact, patches will be applied on top of the working directory
2963 --exact, patches will be applied on top of the working directory
2963 parent revision.
2964 parent revision.
2964
2965
2965 You can import a patch straight from a mail message. Even patches
2966 You can import a patch straight from a mail message. Even patches
2966 as attachments work (to use the body part, it must have type
2967 as attachments work (to use the body part, it must have type
2967 text/plain or text/x-patch). From and Subject headers of email
2968 text/plain or text/x-patch). From and Subject headers of email
2968 message are used as default committer and commit message. All
2969 message are used as default committer and commit message. All
2969 text/plain body parts before first diff are added to the commit
2970 text/plain body parts before first diff are added to the commit
2970 message.
2971 message.
2971
2972
2972 If the imported patch was generated by :hg:`export`, user and
2973 If the imported patch was generated by :hg:`export`, user and
2973 description from patch override values from message headers and
2974 description from patch override values from message headers and
2974 body. Values given on command line with -m/--message and -u/--user
2975 body. Values given on command line with -m/--message and -u/--user
2975 override these.
2976 override these.
2976
2977
2977 If --exact is specified, import will set the working directory to
2978 If --exact is specified, import will set the working directory to
2978 the parent of each patch before applying it, and will abort if the
2979 the parent of each patch before applying it, and will abort if the
2979 resulting changeset has a different ID than the one recorded in
2980 resulting changeset has a different ID than the one recorded in
2980 the patch. This will guard against various ways that portable
2981 the patch. This will guard against various ways that portable
2981 patch formats and mail systems might fail to transfer Mercurial
2982 patch formats and mail systems might fail to transfer Mercurial
2982 data or metadata. See :hg:`bundle` for lossless transmission.
2983 data or metadata. See :hg:`bundle` for lossless transmission.
2983
2984
2984 Use --partial to ensure a changeset will be created from the patch
2985 Use --partial to ensure a changeset will be created from the patch
2985 even if some hunks fail to apply. Hunks that fail to apply will be
2986 even if some hunks fail to apply. Hunks that fail to apply will be
2986 written to a <target-file>.rej file. Conflicts can then be resolved
2987 written to a <target-file>.rej file. Conflicts can then be resolved
2987 by hand before :hg:`commit --amend` is run to update the created
2988 by hand before :hg:`commit --amend` is run to update the created
2988 changeset. This flag exists to let people import patches that
2989 changeset. This flag exists to let people import patches that
2989 partially apply without losing the associated metadata (author,
2990 partially apply without losing the associated metadata (author,
2990 date, description, ...).
2991 date, description, ...).
2991
2992
2992 .. note::
2993 .. note::
2993
2994
2994 When no hunks apply cleanly, :hg:`import --partial` will create
2995 When no hunks apply cleanly, :hg:`import --partial` will create
2995 an empty changeset, importing only the patch metadata.
2996 an empty changeset, importing only the patch metadata.
2996
2997
2997 With -s/--similarity, hg will attempt to discover renames and
2998 With -s/--similarity, hg will attempt to discover renames and
2998 copies in the patch in the same way as :hg:`addremove`.
2999 copies in the patch in the same way as :hg:`addremove`.
2999
3000
3000 It is possible to use external patch programs to perform the patch
3001 It is possible to use external patch programs to perform the patch
3001 by setting the ``ui.patch`` configuration option. For the default
3002 by setting the ``ui.patch`` configuration option. For the default
3002 internal tool, the fuzz can also be configured via ``patch.fuzz``.
3003 internal tool, the fuzz can also be configured via ``patch.fuzz``.
3003 See :hg:`help config` for more information about configuration
3004 See :hg:`help config` for more information about configuration
3004 files and how to use these options.
3005 files and how to use these options.
3005
3006
3006 See :hg:`help dates` for a list of formats valid for -d/--date.
3007 See :hg:`help dates` for a list of formats valid for -d/--date.
3007
3008
3008 .. container:: verbose
3009 .. container:: verbose
3009
3010
3010 Examples:
3011 Examples:
3011
3012
3012 - import a traditional patch from a website and detect renames::
3013 - import a traditional patch from a website and detect renames::
3013
3014
3014 hg import -s 80 http://example.com/bugfix.patch
3015 hg import -s 80 http://example.com/bugfix.patch
3015
3016
3016 - import a changeset from an hgweb server::
3017 - import a changeset from an hgweb server::
3017
3018
3018 hg import https://www.mercurial-scm.org/repo/hg/rev/5ca8c111e9aa
3019 hg import https://www.mercurial-scm.org/repo/hg/rev/5ca8c111e9aa
3019
3020
3020 - import all the patches in an Unix-style mbox::
3021 - import all the patches in an Unix-style mbox::
3021
3022
3022 hg import incoming-patches.mbox
3023 hg import incoming-patches.mbox
3023
3024
3024 - import patches from stdin::
3025 - import patches from stdin::
3025
3026
3026 hg import -
3027 hg import -
3027
3028
3028 - attempt to exactly restore an exported changeset (not always
3029 - attempt to exactly restore an exported changeset (not always
3029 possible)::
3030 possible)::
3030
3031
3031 hg import --exact proposed-fix.patch
3032 hg import --exact proposed-fix.patch
3032
3033
3033 - use an external tool to apply a patch which is too fuzzy for
3034 - use an external tool to apply a patch which is too fuzzy for
3034 the default internal tool.
3035 the default internal tool.
3035
3036
3036 hg import --config ui.patch="patch --merge" fuzzy.patch
3037 hg import --config ui.patch="patch --merge" fuzzy.patch
3037
3038
3038 - change the default fuzzing from 2 to a less strict 7
3039 - change the default fuzzing from 2 to a less strict 7
3039
3040
3040 hg import --config ui.fuzz=7 fuzz.patch
3041 hg import --config ui.fuzz=7 fuzz.patch
3041
3042
3042 Returns 0 on success, 1 on partial success (see --partial).
3043 Returns 0 on success, 1 on partial success (see --partial).
3043 """
3044 """
3044
3045
3045 if not patch1:
3046 if not patch1:
3046 raise error.Abort(_('need at least one patch to import'))
3047 raise error.Abort(_('need at least one patch to import'))
3047
3048
3048 patches = (patch1,) + patches
3049 patches = (patch1,) + patches
3049
3050
3050 date = opts.get('date')
3051 date = opts.get('date')
3051 if date:
3052 if date:
3052 opts['date'] = util.parsedate(date)
3053 opts['date'] = util.parsedate(date)
3053
3054
3054 exact = opts.get('exact')
3055 exact = opts.get('exact')
3055 update = not opts.get('bypass')
3056 update = not opts.get('bypass')
3056 if not update and opts.get('no_commit'):
3057 if not update and opts.get('no_commit'):
3057 raise error.Abort(_('cannot use --no-commit with --bypass'))
3058 raise error.Abort(_('cannot use --no-commit with --bypass'))
3058 try:
3059 try:
3059 sim = float(opts.get('similarity') or 0)
3060 sim = float(opts.get('similarity') or 0)
3060 except ValueError:
3061 except ValueError:
3061 raise error.Abort(_('similarity must be a number'))
3062 raise error.Abort(_('similarity must be a number'))
3062 if sim < 0 or sim > 100:
3063 if sim < 0 or sim > 100:
3063 raise error.Abort(_('similarity must be between 0 and 100'))
3064 raise error.Abort(_('similarity must be between 0 and 100'))
3064 if sim and not update:
3065 if sim and not update:
3065 raise error.Abort(_('cannot use --similarity with --bypass'))
3066 raise error.Abort(_('cannot use --similarity with --bypass'))
3066 if exact:
3067 if exact:
3067 if opts.get('edit'):
3068 if opts.get('edit'):
3068 raise error.Abort(_('cannot use --exact with --edit'))
3069 raise error.Abort(_('cannot use --exact with --edit'))
3069 if opts.get('prefix'):
3070 if opts.get('prefix'):
3070 raise error.Abort(_('cannot use --exact with --prefix'))
3071 raise error.Abort(_('cannot use --exact with --prefix'))
3071
3072
3072 base = opts["base"]
3073 base = opts["base"]
3073 wlock = dsguard = lock = tr = None
3074 wlock = dsguard = lock = tr = None
3074 msgs = []
3075 msgs = []
3075 ret = 0
3076 ret = 0
3076
3077
3077
3078
3078 try:
3079 try:
3079 wlock = repo.wlock()
3080 wlock = repo.wlock()
3080
3081
3081 if update:
3082 if update:
3082 cmdutil.checkunfinished(repo)
3083 cmdutil.checkunfinished(repo)
3083 if (exact or not opts.get('force')):
3084 if (exact or not opts.get('force')):
3084 cmdutil.bailifchanged(repo)
3085 cmdutil.bailifchanged(repo)
3085
3086
3086 if not opts.get('no_commit'):
3087 if not opts.get('no_commit'):
3087 lock = repo.lock()
3088 lock = repo.lock()
3088 tr = repo.transaction('import')
3089 tr = repo.transaction('import')
3089 else:
3090 else:
3090 dsguard = dirstateguard.dirstateguard(repo, 'import')
3091 dsguard = dirstateguard.dirstateguard(repo, 'import')
3091 parents = repo[None].parents()
3092 parents = repo[None].parents()
3092 for patchurl in patches:
3093 for patchurl in patches:
3093 if patchurl == '-':
3094 if patchurl == '-':
3094 ui.status(_('applying patch from stdin\n'))
3095 ui.status(_('applying patch from stdin\n'))
3095 patchfile = ui.fin
3096 patchfile = ui.fin
3096 patchurl = 'stdin' # for error message
3097 patchurl = 'stdin' # for error message
3097 else:
3098 else:
3098 patchurl = os.path.join(base, patchurl)
3099 patchurl = os.path.join(base, patchurl)
3099 ui.status(_('applying %s\n') % patchurl)
3100 ui.status(_('applying %s\n') % patchurl)
3100 patchfile = hg.openpath(ui, patchurl)
3101 patchfile = hg.openpath(ui, patchurl)
3101
3102
3102 haspatch = False
3103 haspatch = False
3103 for hunk in patch.split(patchfile):
3104 for hunk in patch.split(patchfile):
3104 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
3105 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
3105 parents, opts,
3106 parents, opts,
3106 msgs, hg.clean)
3107 msgs, hg.clean)
3107 if msg:
3108 if msg:
3108 haspatch = True
3109 haspatch = True
3109 ui.note(msg + '\n')
3110 ui.note(msg + '\n')
3110 if update or exact:
3111 if update or exact:
3111 parents = repo[None].parents()
3112 parents = repo[None].parents()
3112 else:
3113 else:
3113 parents = [repo[node]]
3114 parents = [repo[node]]
3114 if rej:
3115 if rej:
3115 ui.write_err(_("patch applied partially\n"))
3116 ui.write_err(_("patch applied partially\n"))
3116 ui.write_err(_("(fix the .rej files and run "
3117 ui.write_err(_("(fix the .rej files and run "
3117 "`hg commit --amend`)\n"))
3118 "`hg commit --amend`)\n"))
3118 ret = 1
3119 ret = 1
3119 break
3120 break
3120
3121
3121 if not haspatch:
3122 if not haspatch:
3122 raise error.Abort(_('%s: no diffs found') % patchurl)
3123 raise error.Abort(_('%s: no diffs found') % patchurl)
3123
3124
3124 if tr:
3125 if tr:
3125 tr.close()
3126 tr.close()
3126 if msgs:
3127 if msgs:
3127 repo.savecommitmessage('\n* * *\n'.join(msgs))
3128 repo.savecommitmessage('\n* * *\n'.join(msgs))
3128 if dsguard:
3129 if dsguard:
3129 dsguard.close()
3130 dsguard.close()
3130 return ret
3131 return ret
3131 finally:
3132 finally:
3132 if tr:
3133 if tr:
3133 tr.release()
3134 tr.release()
3134 release(lock, dsguard, wlock)
3135 release(lock, dsguard, wlock)
3135
3136
3136 @command('incoming|in',
3137 @command('incoming|in',
3137 [('f', 'force', None,
3138 [('f', 'force', None,
3138 _('run even if remote repository is unrelated')),
3139 _('run even if remote repository is unrelated')),
3139 ('n', 'newest-first', None, _('show newest record first')),
3140 ('n', 'newest-first', None, _('show newest record first')),
3140 ('', 'bundle', '',
3141 ('', 'bundle', '',
3141 _('file to store the bundles into'), _('FILE')),
3142 _('file to store the bundles into'), _('FILE')),
3142 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3143 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3143 ('B', 'bookmarks', False, _("compare bookmarks")),
3144 ('B', 'bookmarks', False, _("compare bookmarks")),
3144 ('b', 'branch', [],
3145 ('b', 'branch', [],
3145 _('a specific branch you would like to pull'), _('BRANCH')),
3146 _('a specific branch you would like to pull'), _('BRANCH')),
3146 ] + logopts + remoteopts + subrepoopts,
3147 ] + logopts + remoteopts + subrepoopts,
3147 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3148 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3148 def incoming(ui, repo, source="default", **opts):
3149 def incoming(ui, repo, source="default", **opts):
3149 """show new changesets found in source
3150 """show new changesets found in source
3150
3151
3151 Show new changesets found in the specified path/URL or the default
3152 Show new changesets found in the specified path/URL or the default
3152 pull location. These are the changesets that would have been pulled
3153 pull location. These are the changesets that would have been pulled
3153 if a pull at the time you issued this command.
3154 if a pull at the time you issued this command.
3154
3155
3155 See pull for valid source format details.
3156 See pull for valid source format details.
3156
3157
3157 .. container:: verbose
3158 .. container:: verbose
3158
3159
3159 With -B/--bookmarks, the result of bookmark comparison between
3160 With -B/--bookmarks, the result of bookmark comparison between
3160 local and remote repositories is displayed. With -v/--verbose,
3161 local and remote repositories is displayed. With -v/--verbose,
3161 status is also displayed for each bookmark like below::
3162 status is also displayed for each bookmark like below::
3162
3163
3163 BM1 01234567890a added
3164 BM1 01234567890a added
3164 BM2 1234567890ab advanced
3165 BM2 1234567890ab advanced
3165 BM3 234567890abc diverged
3166 BM3 234567890abc diverged
3166 BM4 34567890abcd changed
3167 BM4 34567890abcd changed
3167
3168
3168 The action taken locally when pulling depends on the
3169 The action taken locally when pulling depends on the
3169 status of each bookmark:
3170 status of each bookmark:
3170
3171
3171 :``added``: pull will create it
3172 :``added``: pull will create it
3172 :``advanced``: pull will update it
3173 :``advanced``: pull will update it
3173 :``diverged``: pull will create a divergent bookmark
3174 :``diverged``: pull will create a divergent bookmark
3174 :``changed``: result depends on remote changesets
3175 :``changed``: result depends on remote changesets
3175
3176
3176 From the point of view of pulling behavior, bookmark
3177 From the point of view of pulling behavior, bookmark
3177 existing only in the remote repository are treated as ``added``,
3178 existing only in the remote repository are treated as ``added``,
3178 even if it is in fact locally deleted.
3179 even if it is in fact locally deleted.
3179
3180
3180 .. container:: verbose
3181 .. container:: verbose
3181
3182
3182 For remote repository, using --bundle avoids downloading the
3183 For remote repository, using --bundle avoids downloading the
3183 changesets twice if the incoming is followed by a pull.
3184 changesets twice if the incoming is followed by a pull.
3184
3185
3185 Examples:
3186 Examples:
3186
3187
3187 - show incoming changes with patches and full description::
3188 - show incoming changes with patches and full description::
3188
3189
3189 hg incoming -vp
3190 hg incoming -vp
3190
3191
3191 - show incoming changes excluding merges, store a bundle::
3192 - show incoming changes excluding merges, store a bundle::
3192
3193
3193 hg in -vpM --bundle incoming.hg
3194 hg in -vpM --bundle incoming.hg
3194 hg pull incoming.hg
3195 hg pull incoming.hg
3195
3196
3196 - briefly list changes inside a bundle::
3197 - briefly list changes inside a bundle::
3197
3198
3198 hg in changes.hg -T "{desc|firstline}\\n"
3199 hg in changes.hg -T "{desc|firstline}\\n"
3199
3200
3200 Returns 0 if there are incoming changes, 1 otherwise.
3201 Returns 0 if there are incoming changes, 1 otherwise.
3201 """
3202 """
3202 if opts.get('graph'):
3203 if opts.get('graph'):
3203 cmdutil.checkunsupportedgraphflags([], opts)
3204 cmdutil.checkunsupportedgraphflags([], opts)
3204 def display(other, chlist, displayer):
3205 def display(other, chlist, displayer):
3205 revdag = cmdutil.graphrevs(other, chlist, opts)
3206 revdag = cmdutil.graphrevs(other, chlist, opts)
3206 cmdutil.displaygraph(ui, repo, revdag, displayer,
3207 cmdutil.displaygraph(ui, repo, revdag, displayer,
3207 graphmod.asciiedges)
3208 graphmod.asciiedges)
3208
3209
3209 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3210 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3210 return 0
3211 return 0
3211
3212
3212 if opts.get('bundle') and opts.get('subrepos'):
3213 if opts.get('bundle') and opts.get('subrepos'):
3213 raise error.Abort(_('cannot combine --bundle and --subrepos'))
3214 raise error.Abort(_('cannot combine --bundle and --subrepos'))
3214
3215
3215 if opts.get('bookmarks'):
3216 if opts.get('bookmarks'):
3216 source, branches = hg.parseurl(ui.expandpath(source),
3217 source, branches = hg.parseurl(ui.expandpath(source),
3217 opts.get('branch'))
3218 opts.get('branch'))
3218 other = hg.peer(repo, opts, source)
3219 other = hg.peer(repo, opts, source)
3219 if 'bookmarks' not in other.listkeys('namespaces'):
3220 if 'bookmarks' not in other.listkeys('namespaces'):
3220 ui.warn(_("remote doesn't support bookmarks\n"))
3221 ui.warn(_("remote doesn't support bookmarks\n"))
3221 return 0
3222 return 0
3222 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3223 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3223 return bookmarks.incoming(ui, repo, other)
3224 return bookmarks.incoming(ui, repo, other)
3224
3225
3225 repo._subtoppath = ui.expandpath(source)
3226 repo._subtoppath = ui.expandpath(source)
3226 try:
3227 try:
3227 return hg.incoming(ui, repo, source, opts)
3228 return hg.incoming(ui, repo, source, opts)
3228 finally:
3229 finally:
3229 del repo._subtoppath
3230 del repo._subtoppath
3230
3231
3231
3232
3232 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
3233 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
3233 norepo=True)
3234 norepo=True)
3234 def init(ui, dest=".", **opts):
3235 def init(ui, dest=".", **opts):
3235 """create a new repository in the given directory
3236 """create a new repository in the given directory
3236
3237
3237 Initialize a new repository in the given directory. If the given
3238 Initialize a new repository in the given directory. If the given
3238 directory does not exist, it will be created.
3239 directory does not exist, it will be created.
3239
3240
3240 If no directory is given, the current directory is used.
3241 If no directory is given, the current directory is used.
3241
3242
3242 It is possible to specify an ``ssh://`` URL as the destination.
3243 It is possible to specify an ``ssh://`` URL as the destination.
3243 See :hg:`help urls` for more information.
3244 See :hg:`help urls` for more information.
3244
3245
3245 Returns 0 on success.
3246 Returns 0 on success.
3246 """
3247 """
3247 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3248 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3248
3249
3249 @command('locate',
3250 @command('locate',
3250 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3251 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3251 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3252 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3252 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3253 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3253 ] + walkopts,
3254 ] + walkopts,
3254 _('[OPTION]... [PATTERN]...'))
3255 _('[OPTION]... [PATTERN]...'))
3255 def locate(ui, repo, *pats, **opts):
3256 def locate(ui, repo, *pats, **opts):
3256 """locate files matching specific patterns (DEPRECATED)
3257 """locate files matching specific patterns (DEPRECATED)
3257
3258
3258 Print files under Mercurial control in the working directory whose
3259 Print files under Mercurial control in the working directory whose
3259 names match the given patterns.
3260 names match the given patterns.
3260
3261
3261 By default, this command searches all directories in the working
3262 By default, this command searches all directories in the working
3262 directory. To search just the current directory and its
3263 directory. To search just the current directory and its
3263 subdirectories, use "--include .".
3264 subdirectories, use "--include .".
3264
3265
3265 If no patterns are given to match, this command prints the names
3266 If no patterns are given to match, this command prints the names
3266 of all files under Mercurial control in the working directory.
3267 of all files under Mercurial control in the working directory.
3267
3268
3268 If you want to feed the output of this command into the "xargs"
3269 If you want to feed the output of this command into the "xargs"
3269 command, use the -0 option to both this command and "xargs". This
3270 command, use the -0 option to both this command and "xargs". This
3270 will avoid the problem of "xargs" treating single filenames that
3271 will avoid the problem of "xargs" treating single filenames that
3271 contain whitespace as multiple filenames.
3272 contain whitespace as multiple filenames.
3272
3273
3273 See :hg:`help files` for a more versatile command.
3274 See :hg:`help files` for a more versatile command.
3274
3275
3275 Returns 0 if a match is found, 1 otherwise.
3276 Returns 0 if a match is found, 1 otherwise.
3276 """
3277 """
3277 if opts.get('print0'):
3278 if opts.get('print0'):
3278 end = '\0'
3279 end = '\0'
3279 else:
3280 else:
3280 end = '\n'
3281 end = '\n'
3281 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3282 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3282
3283
3283 ret = 1
3284 ret = 1
3284 ctx = repo[rev]
3285 ctx = repo[rev]
3285 m = scmutil.match(ctx, pats, opts, default='relglob',
3286 m = scmutil.match(ctx, pats, opts, default='relglob',
3286 badfn=lambda x, y: False)
3287 badfn=lambda x, y: False)
3287
3288
3288 for abs in ctx.matches(m):
3289 for abs in ctx.matches(m):
3289 if opts.get('fullpath'):
3290 if opts.get('fullpath'):
3290 ui.write(repo.wjoin(abs), end)
3291 ui.write(repo.wjoin(abs), end)
3291 else:
3292 else:
3292 ui.write(((pats and m.rel(abs)) or abs), end)
3293 ui.write(((pats and m.rel(abs)) or abs), end)
3293 ret = 0
3294 ret = 0
3294
3295
3295 return ret
3296 return ret
3296
3297
3297 @command('^log|history',
3298 @command('^log|history',
3298 [('f', 'follow', None,
3299 [('f', 'follow', None,
3299 _('follow changeset history, or file history across copies and renames')),
3300 _('follow changeset history, or file history across copies and renames')),
3300 ('', 'follow-first', None,
3301 ('', 'follow-first', None,
3301 _('only follow the first parent of merge changesets (DEPRECATED)')),
3302 _('only follow the first parent of merge changesets (DEPRECATED)')),
3302 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3303 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3303 ('C', 'copies', None, _('show copied files')),
3304 ('C', 'copies', None, _('show copied files')),
3304 ('k', 'keyword', [],
3305 ('k', 'keyword', [],
3305 _('do case-insensitive search for a given text'), _('TEXT')),
3306 _('do case-insensitive search for a given text'), _('TEXT')),
3306 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
3307 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
3307 ('', 'removed', None, _('include revisions where files were removed')),
3308 ('', 'removed', None, _('include revisions where files were removed')),
3308 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3309 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3309 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3310 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3310 ('', 'only-branch', [],
3311 ('', 'only-branch', [],
3311 _('show only changesets within the given named branch (DEPRECATED)'),
3312 _('show only changesets within the given named branch (DEPRECATED)'),
3312 _('BRANCH')),
3313 _('BRANCH')),
3313 ('b', 'branch', [],
3314 ('b', 'branch', [],
3314 _('show changesets within the given named branch'), _('BRANCH')),
3315 _('show changesets within the given named branch'), _('BRANCH')),
3315 ('P', 'prune', [],
3316 ('P', 'prune', [],
3316 _('do not display revision or any of its ancestors'), _('REV')),
3317 _('do not display revision or any of its ancestors'), _('REV')),
3317 ] + logopts + walkopts,
3318 ] + logopts + walkopts,
3318 _('[OPTION]... [FILE]'),
3319 _('[OPTION]... [FILE]'),
3319 inferrepo=True)
3320 inferrepo=True)
3320 def log(ui, repo, *pats, **opts):
3321 def log(ui, repo, *pats, **opts):
3321 """show revision history of entire repository or files
3322 """show revision history of entire repository or files
3322
3323
3323 Print the revision history of the specified files or the entire
3324 Print the revision history of the specified files or the entire
3324 project.
3325 project.
3325
3326
3326 If no revision range is specified, the default is ``tip:0`` unless
3327 If no revision range is specified, the default is ``tip:0`` unless
3327 --follow is set, in which case the working directory parent is
3328 --follow is set, in which case the working directory parent is
3328 used as the starting revision.
3329 used as the starting revision.
3329
3330
3330 File history is shown without following rename or copy history of
3331 File history is shown without following rename or copy history of
3331 files. Use -f/--follow with a filename to follow history across
3332 files. Use -f/--follow with a filename to follow history across
3332 renames and copies. --follow without a filename will only show
3333 renames and copies. --follow without a filename will only show
3333 ancestors or descendants of the starting revision.
3334 ancestors or descendants of the starting revision.
3334
3335
3335 By default this command prints revision number and changeset id,
3336 By default this command prints revision number and changeset id,
3336 tags, non-trivial parents, user, date and time, and a summary for
3337 tags, non-trivial parents, user, date and time, and a summary for
3337 each commit. When the -v/--verbose switch is used, the list of
3338 each commit. When the -v/--verbose switch is used, the list of
3338 changed files and full commit message are shown.
3339 changed files and full commit message are shown.
3339
3340
3340 With --graph the revisions are shown as an ASCII art DAG with the most
3341 With --graph the revisions are shown as an ASCII art DAG with the most
3341 recent changeset at the top.
3342 recent changeset at the top.
3342 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
3343 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
3343 and '+' represents a fork where the changeset from the lines below is a
3344 and '+' represents a fork where the changeset from the lines below is a
3344 parent of the 'o' merge on the same line.
3345 parent of the 'o' merge on the same line.
3345
3346
3346 .. note::
3347 .. note::
3347
3348
3348 :hg:`log --patch` may generate unexpected diff output for merge
3349 :hg:`log --patch` may generate unexpected diff output for merge
3349 changesets, as it will only compare the merge changeset against
3350 changesets, as it will only compare the merge changeset against
3350 its first parent. Also, only files different from BOTH parents
3351 its first parent. Also, only files different from BOTH parents
3351 will appear in files:.
3352 will appear in files:.
3352
3353
3353 .. note::
3354 .. note::
3354
3355
3355 For performance reasons, :hg:`log FILE` may omit duplicate changes
3356 For performance reasons, :hg:`log FILE` may omit duplicate changes
3356 made on branches and will not show removals or mode changes. To
3357 made on branches and will not show removals or mode changes. To
3357 see all such changes, use the --removed switch.
3358 see all such changes, use the --removed switch.
3358
3359
3359 .. container:: verbose
3360 .. container:: verbose
3360
3361
3361 Some examples:
3362 Some examples:
3362
3363
3363 - changesets with full descriptions and file lists::
3364 - changesets with full descriptions and file lists::
3364
3365
3365 hg log -v
3366 hg log -v
3366
3367
3367 - changesets ancestral to the working directory::
3368 - changesets ancestral to the working directory::
3368
3369
3369 hg log -f
3370 hg log -f
3370
3371
3371 - last 10 commits on the current branch::
3372 - last 10 commits on the current branch::
3372
3373
3373 hg log -l 10 -b .
3374 hg log -l 10 -b .
3374
3375
3375 - changesets showing all modifications of a file, including removals::
3376 - changesets showing all modifications of a file, including removals::
3376
3377
3377 hg log --removed file.c
3378 hg log --removed file.c
3378
3379
3379 - all changesets that touch a directory, with diffs, excluding merges::
3380 - all changesets that touch a directory, with diffs, excluding merges::
3380
3381
3381 hg log -Mp lib/
3382 hg log -Mp lib/
3382
3383
3383 - all revision numbers that match a keyword::
3384 - all revision numbers that match a keyword::
3384
3385
3385 hg log -k bug --template "{rev}\\n"
3386 hg log -k bug --template "{rev}\\n"
3386
3387
3387 - the full hash identifier of the working directory parent::
3388 - the full hash identifier of the working directory parent::
3388
3389
3389 hg log -r . --template "{node}\\n"
3390 hg log -r . --template "{node}\\n"
3390
3391
3391 - list available log templates::
3392 - list available log templates::
3392
3393
3393 hg log -T list
3394 hg log -T list
3394
3395
3395 - check if a given changeset is included in a tagged release::
3396 - check if a given changeset is included in a tagged release::
3396
3397
3397 hg log -r "a21ccf and ancestor(1.9)"
3398 hg log -r "a21ccf and ancestor(1.9)"
3398
3399
3399 - find all changesets by some user in a date range::
3400 - find all changesets by some user in a date range::
3400
3401
3401 hg log -k alice -d "may 2008 to jul 2008"
3402 hg log -k alice -d "may 2008 to jul 2008"
3402
3403
3403 - summary of all changesets after the last tag::
3404 - summary of all changesets after the last tag::
3404
3405
3405 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3406 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3406
3407
3407 See :hg:`help dates` for a list of formats valid for -d/--date.
3408 See :hg:`help dates` for a list of formats valid for -d/--date.
3408
3409
3409 See :hg:`help revisions` for more about specifying and ordering
3410 See :hg:`help revisions` for more about specifying and ordering
3410 revisions.
3411 revisions.
3411
3412
3412 See :hg:`help templates` for more about pre-packaged styles and
3413 See :hg:`help templates` for more about pre-packaged styles and
3413 specifying custom templates.
3414 specifying custom templates.
3414
3415
3415 Returns 0 on success.
3416 Returns 0 on success.
3416
3417
3417 """
3418 """
3418 if opts.get('follow') and opts.get('rev'):
3419 if opts.get('follow') and opts.get('rev'):
3419 opts['rev'] = [revsetlang.formatspec('reverse(::%lr)', opts.get('rev'))]
3420 opts['rev'] = [revsetlang.formatspec('reverse(::%lr)', opts.get('rev'))]
3420 del opts['follow']
3421 del opts['follow']
3421
3422
3422 if opts.get('graph'):
3423 if opts.get('graph'):
3423 return cmdutil.graphlog(ui, repo, *pats, **opts)
3424 return cmdutil.graphlog(ui, repo, *pats, **opts)
3424
3425
3425 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
3426 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
3426 limit = cmdutil.loglimit(opts)
3427 limit = cmdutil.loglimit(opts)
3427 count = 0
3428 count = 0
3428
3429
3429 getrenamed = None
3430 getrenamed = None
3430 if opts.get('copies'):
3431 if opts.get('copies'):
3431 endrev = None
3432 endrev = None
3432 if opts.get('rev'):
3433 if opts.get('rev'):
3433 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
3434 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
3434 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3435 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3435
3436
3436 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
3437 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
3437 for rev in revs:
3438 for rev in revs:
3438 if count == limit:
3439 if count == limit:
3439 break
3440 break
3440 ctx = repo[rev]
3441 ctx = repo[rev]
3441 copies = None
3442 copies = None
3442 if getrenamed is not None and rev:
3443 if getrenamed is not None and rev:
3443 copies = []
3444 copies = []
3444 for fn in ctx.files():
3445 for fn in ctx.files():
3445 rename = getrenamed(fn, rev)
3446 rename = getrenamed(fn, rev)
3446 if rename:
3447 if rename:
3447 copies.append((fn, rename[0]))
3448 copies.append((fn, rename[0]))
3448 if filematcher:
3449 if filematcher:
3449 revmatchfn = filematcher(ctx.rev())
3450 revmatchfn = filematcher(ctx.rev())
3450 else:
3451 else:
3451 revmatchfn = None
3452 revmatchfn = None
3452 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
3453 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
3453 if displayer.flush(ctx):
3454 if displayer.flush(ctx):
3454 count += 1
3455 count += 1
3455
3456
3456 displayer.close()
3457 displayer.close()
3457
3458
3458 @command('manifest',
3459 @command('manifest',
3459 [('r', 'rev', '', _('revision to display'), _('REV')),
3460 [('r', 'rev', '', _('revision to display'), _('REV')),
3460 ('', 'all', False, _("list files from all revisions"))]
3461 ('', 'all', False, _("list files from all revisions"))]
3461 + formatteropts,
3462 + formatteropts,
3462 _('[-r REV]'))
3463 _('[-r REV]'))
3463 def manifest(ui, repo, node=None, rev=None, **opts):
3464 def manifest(ui, repo, node=None, rev=None, **opts):
3464 """output the current or given revision of the project manifest
3465 """output the current or given revision of the project manifest
3465
3466
3466 Print a list of version controlled files for the given revision.
3467 Print a list of version controlled files for the given revision.
3467 If no revision is given, the first parent of the working directory
3468 If no revision is given, the first parent of the working directory
3468 is used, or the null revision if no revision is checked out.
3469 is used, or the null revision if no revision is checked out.
3469
3470
3470 With -v, print file permissions, symlink and executable bits.
3471 With -v, print file permissions, symlink and executable bits.
3471 With --debug, print file revision hashes.
3472 With --debug, print file revision hashes.
3472
3473
3473 If option --all is specified, the list of all files from all revisions
3474 If option --all is specified, the list of all files from all revisions
3474 is printed. This includes deleted and renamed files.
3475 is printed. This includes deleted and renamed files.
3475
3476
3476 Returns 0 on success.
3477 Returns 0 on success.
3477 """
3478 """
3478
3479
3479 fm = ui.formatter('manifest', opts)
3480 fm = ui.formatter('manifest', opts)
3480
3481
3481 if opts.get('all'):
3482 if opts.get('all'):
3482 if rev or node:
3483 if rev or node:
3483 raise error.Abort(_("can't specify a revision with --all"))
3484 raise error.Abort(_("can't specify a revision with --all"))
3484
3485
3485 res = []
3486 res = []
3486 prefix = "data/"
3487 prefix = "data/"
3487 suffix = ".i"
3488 suffix = ".i"
3488 plen = len(prefix)
3489 plen = len(prefix)
3489 slen = len(suffix)
3490 slen = len(suffix)
3490 with repo.lock():
3491 with repo.lock():
3491 for fn, b, size in repo.store.datafiles():
3492 for fn, b, size in repo.store.datafiles():
3492 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
3493 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
3493 res.append(fn[plen:-slen])
3494 res.append(fn[plen:-slen])
3494 for f in res:
3495 for f in res:
3495 fm.startitem()
3496 fm.startitem()
3496 fm.write("path", '%s\n', f)
3497 fm.write("path", '%s\n', f)
3497 fm.end()
3498 fm.end()
3498 return
3499 return
3499
3500
3500 if rev and node:
3501 if rev and node:
3501 raise error.Abort(_("please specify just one revision"))
3502 raise error.Abort(_("please specify just one revision"))
3502
3503
3503 if not node:
3504 if not node:
3504 node = rev
3505 node = rev
3505
3506
3506 char = {'l': '@', 'x': '*', '': ''}
3507 char = {'l': '@', 'x': '*', '': ''}
3507 mode = {'l': '644', 'x': '755', '': '644'}
3508 mode = {'l': '644', 'x': '755', '': '644'}
3508 ctx = scmutil.revsingle(repo, node)
3509 ctx = scmutil.revsingle(repo, node)
3509 mf = ctx.manifest()
3510 mf = ctx.manifest()
3510 for f in ctx:
3511 for f in ctx:
3511 fm.startitem()
3512 fm.startitem()
3512 fl = ctx[f].flags()
3513 fl = ctx[f].flags()
3513 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
3514 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
3514 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
3515 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
3515 fm.write('path', '%s\n', f)
3516 fm.write('path', '%s\n', f)
3516 fm.end()
3517 fm.end()
3517
3518
3518 @command('^merge',
3519 @command('^merge',
3519 [('f', 'force', None,
3520 [('f', 'force', None,
3520 _('force a merge including outstanding changes (DEPRECATED)')),
3521 _('force a merge including outstanding changes (DEPRECATED)')),
3521 ('r', 'rev', '', _('revision to merge'), _('REV')),
3522 ('r', 'rev', '', _('revision to merge'), _('REV')),
3522 ('P', 'preview', None,
3523 ('P', 'preview', None,
3523 _('review revisions to merge (no merge is performed)'))
3524 _('review revisions to merge (no merge is performed)'))
3524 ] + mergetoolopts,
3525 ] + mergetoolopts,
3525 _('[-P] [[-r] REV]'))
3526 _('[-P] [[-r] REV]'))
3526 def merge(ui, repo, node=None, **opts):
3527 def merge(ui, repo, node=None, **opts):
3527 """merge another revision into working directory
3528 """merge another revision into working directory
3528
3529
3529 The current working directory is updated with all changes made in
3530 The current working directory is updated with all changes made in
3530 the requested revision since the last common predecessor revision.
3531 the requested revision since the last common predecessor revision.
3531
3532
3532 Files that changed between either parent are marked as changed for
3533 Files that changed between either parent are marked as changed for
3533 the next commit and a commit must be performed before any further
3534 the next commit and a commit must be performed before any further
3534 updates to the repository are allowed. The next commit will have
3535 updates to the repository are allowed. The next commit will have
3535 two parents.
3536 two parents.
3536
3537
3537 ``--tool`` can be used to specify the merge tool used for file
3538 ``--tool`` can be used to specify the merge tool used for file
3538 merges. It overrides the HGMERGE environment variable and your
3539 merges. It overrides the HGMERGE environment variable and your
3539 configuration files. See :hg:`help merge-tools` for options.
3540 configuration files. See :hg:`help merge-tools` for options.
3540
3541
3541 If no revision is specified, the working directory's parent is a
3542 If no revision is specified, the working directory's parent is a
3542 head revision, and the current branch contains exactly one other
3543 head revision, and the current branch contains exactly one other
3543 head, the other head is merged with by default. Otherwise, an
3544 head, the other head is merged with by default. Otherwise, an
3544 explicit revision with which to merge with must be provided.
3545 explicit revision with which to merge with must be provided.
3545
3546
3546 See :hg:`help resolve` for information on handling file conflicts.
3547 See :hg:`help resolve` for information on handling file conflicts.
3547
3548
3548 To undo an uncommitted merge, use :hg:`update --clean .` which
3549 To undo an uncommitted merge, use :hg:`update --clean .` which
3549 will check out a clean copy of the original merge parent, losing
3550 will check out a clean copy of the original merge parent, losing
3550 all changes.
3551 all changes.
3551
3552
3552 Returns 0 on success, 1 if there are unresolved files.
3553 Returns 0 on success, 1 if there are unresolved files.
3553 """
3554 """
3554
3555
3555 if opts.get('rev') and node:
3556 if opts.get('rev') and node:
3556 raise error.Abort(_("please specify just one revision"))
3557 raise error.Abort(_("please specify just one revision"))
3557 if not node:
3558 if not node:
3558 node = opts.get('rev')
3559 node = opts.get('rev')
3559
3560
3560 if node:
3561 if node:
3561 node = scmutil.revsingle(repo, node).node()
3562 node = scmutil.revsingle(repo, node).node()
3562
3563
3563 if not node:
3564 if not node:
3564 node = repo[destutil.destmerge(repo)].node()
3565 node = repo[destutil.destmerge(repo)].node()
3565
3566
3566 if opts.get('preview'):
3567 if opts.get('preview'):
3567 # find nodes that are ancestors of p2 but not of p1
3568 # find nodes that are ancestors of p2 but not of p1
3568 p1 = repo.lookup('.')
3569 p1 = repo.lookup('.')
3569 p2 = repo.lookup(node)
3570 p2 = repo.lookup(node)
3570 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
3571 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
3571
3572
3572 displayer = cmdutil.show_changeset(ui, repo, opts)
3573 displayer = cmdutil.show_changeset(ui, repo, opts)
3573 for node in nodes:
3574 for node in nodes:
3574 displayer.show(repo[node])
3575 displayer.show(repo[node])
3575 displayer.close()
3576 displayer.close()
3576 return 0
3577 return 0
3577
3578
3578 try:
3579 try:
3579 # ui.forcemerge is an internal variable, do not document
3580 # ui.forcemerge is an internal variable, do not document
3580 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
3581 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
3581 force = opts.get('force')
3582 force = opts.get('force')
3582 labels = ['working copy', 'merge rev']
3583 labels = ['working copy', 'merge rev']
3583 return hg.merge(repo, node, force=force, mergeforce=force,
3584 return hg.merge(repo, node, force=force, mergeforce=force,
3584 labels=labels)
3585 labels=labels)
3585 finally:
3586 finally:
3586 ui.setconfig('ui', 'forcemerge', '', 'merge')
3587 ui.setconfig('ui', 'forcemerge', '', 'merge')
3587
3588
3588 @command('outgoing|out',
3589 @command('outgoing|out',
3589 [('f', 'force', None, _('run even when the destination is unrelated')),
3590 [('f', 'force', None, _('run even when the destination is unrelated')),
3590 ('r', 'rev', [],
3591 ('r', 'rev', [],
3591 _('a changeset intended to be included in the destination'), _('REV')),
3592 _('a changeset intended to be included in the destination'), _('REV')),
3592 ('n', 'newest-first', None, _('show newest record first')),
3593 ('n', 'newest-first', None, _('show newest record first')),
3593 ('B', 'bookmarks', False, _('compare bookmarks')),
3594 ('B', 'bookmarks', False, _('compare bookmarks')),
3594 ('b', 'branch', [], _('a specific branch you would like to push'),
3595 ('b', 'branch', [], _('a specific branch you would like to push'),
3595 _('BRANCH')),
3596 _('BRANCH')),
3596 ] + logopts + remoteopts + subrepoopts,
3597 ] + logopts + remoteopts + subrepoopts,
3597 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
3598 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
3598 def outgoing(ui, repo, dest=None, **opts):
3599 def outgoing(ui, repo, dest=None, **opts):
3599 """show changesets not found in the destination
3600 """show changesets not found in the destination
3600
3601
3601 Show changesets not found in the specified destination repository
3602 Show changesets not found in the specified destination repository
3602 or the default push location. These are the changesets that would
3603 or the default push location. These are the changesets that would
3603 be pushed if a push was requested.
3604 be pushed if a push was requested.
3604
3605
3605 See pull for details of valid destination formats.
3606 See pull for details of valid destination formats.
3606
3607
3607 .. container:: verbose
3608 .. container:: verbose
3608
3609
3609 With -B/--bookmarks, the result of bookmark comparison between
3610 With -B/--bookmarks, the result of bookmark comparison between
3610 local and remote repositories is displayed. With -v/--verbose,
3611 local and remote repositories is displayed. With -v/--verbose,
3611 status is also displayed for each bookmark like below::
3612 status is also displayed for each bookmark like below::
3612
3613
3613 BM1 01234567890a added
3614 BM1 01234567890a added
3614 BM2 deleted
3615 BM2 deleted
3615 BM3 234567890abc advanced
3616 BM3 234567890abc advanced
3616 BM4 34567890abcd diverged
3617 BM4 34567890abcd diverged
3617 BM5 4567890abcde changed
3618 BM5 4567890abcde changed
3618
3619
3619 The action taken when pushing depends on the
3620 The action taken when pushing depends on the
3620 status of each bookmark:
3621 status of each bookmark:
3621
3622
3622 :``added``: push with ``-B`` will create it
3623 :``added``: push with ``-B`` will create it
3623 :``deleted``: push with ``-B`` will delete it
3624 :``deleted``: push with ``-B`` will delete it
3624 :``advanced``: push will update it
3625 :``advanced``: push will update it
3625 :``diverged``: push with ``-B`` will update it
3626 :``diverged``: push with ``-B`` will update it
3626 :``changed``: push with ``-B`` will update it
3627 :``changed``: push with ``-B`` will update it
3627
3628
3628 From the point of view of pushing behavior, bookmarks
3629 From the point of view of pushing behavior, bookmarks
3629 existing only in the remote repository are treated as
3630 existing only in the remote repository are treated as
3630 ``deleted``, even if it is in fact added remotely.
3631 ``deleted``, even if it is in fact added remotely.
3631
3632
3632 Returns 0 if there are outgoing changes, 1 otherwise.
3633 Returns 0 if there are outgoing changes, 1 otherwise.
3633 """
3634 """
3634 if opts.get('graph'):
3635 if opts.get('graph'):
3635 cmdutil.checkunsupportedgraphflags([], opts)
3636 cmdutil.checkunsupportedgraphflags([], opts)
3636 o, other = hg._outgoing(ui, repo, dest, opts)
3637 o, other = hg._outgoing(ui, repo, dest, opts)
3637 if not o:
3638 if not o:
3638 cmdutil.outgoinghooks(ui, repo, other, opts, o)
3639 cmdutil.outgoinghooks(ui, repo, other, opts, o)
3639 return
3640 return
3640
3641
3641 revdag = cmdutil.graphrevs(repo, o, opts)
3642 revdag = cmdutil.graphrevs(repo, o, opts)
3642 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
3643 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
3643 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
3644 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
3644 cmdutil.outgoinghooks(ui, repo, other, opts, o)
3645 cmdutil.outgoinghooks(ui, repo, other, opts, o)
3645 return 0
3646 return 0
3646
3647
3647 if opts.get('bookmarks'):
3648 if opts.get('bookmarks'):
3648 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3649 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3649 dest, branches = hg.parseurl(dest, opts.get('branch'))
3650 dest, branches = hg.parseurl(dest, opts.get('branch'))
3650 other = hg.peer(repo, opts, dest)
3651 other = hg.peer(repo, opts, dest)
3651 if 'bookmarks' not in other.listkeys('namespaces'):
3652 if 'bookmarks' not in other.listkeys('namespaces'):
3652 ui.warn(_("remote doesn't support bookmarks\n"))
3653 ui.warn(_("remote doesn't support bookmarks\n"))
3653 return 0
3654 return 0
3654 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
3655 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
3655 return bookmarks.outgoing(ui, repo, other)
3656 return bookmarks.outgoing(ui, repo, other)
3656
3657
3657 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
3658 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
3658 try:
3659 try:
3659 return hg.outgoing(ui, repo, dest, opts)
3660 return hg.outgoing(ui, repo, dest, opts)
3660 finally:
3661 finally:
3661 del repo._subtoppath
3662 del repo._subtoppath
3662
3663
3663 @command('parents',
3664 @command('parents',
3664 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
3665 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
3665 ] + templateopts,
3666 ] + templateopts,
3666 _('[-r REV] [FILE]'),
3667 _('[-r REV] [FILE]'),
3667 inferrepo=True)
3668 inferrepo=True)
3668 def parents(ui, repo, file_=None, **opts):
3669 def parents(ui, repo, file_=None, **opts):
3669 """show the parents of the working directory or revision (DEPRECATED)
3670 """show the parents of the working directory or revision (DEPRECATED)
3670
3671
3671 Print the working directory's parent revisions. If a revision is
3672 Print the working directory's parent revisions. If a revision is
3672 given via -r/--rev, the parent of that revision will be printed.
3673 given via -r/--rev, the parent of that revision will be printed.
3673 If a file argument is given, the revision in which the file was
3674 If a file argument is given, the revision in which the file was
3674 last changed (before the working directory revision or the
3675 last changed (before the working directory revision or the
3675 argument to --rev if given) is printed.
3676 argument to --rev if given) is printed.
3676
3677
3677 This command is equivalent to::
3678 This command is equivalent to::
3678
3679
3679 hg log -r "p1()+p2()" or
3680 hg log -r "p1()+p2()" or
3680 hg log -r "p1(REV)+p2(REV)" or
3681 hg log -r "p1(REV)+p2(REV)" or
3681 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
3682 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
3682 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
3683 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
3683
3684
3684 See :hg:`summary` and :hg:`help revsets` for related information.
3685 See :hg:`summary` and :hg:`help revsets` for related information.
3685
3686
3686 Returns 0 on success.
3687 Returns 0 on success.
3687 """
3688 """
3688
3689
3689 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3690 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3690
3691
3691 if file_:
3692 if file_:
3692 m = scmutil.match(ctx, (file_,), opts)
3693 m = scmutil.match(ctx, (file_,), opts)
3693 if m.anypats() or len(m.files()) != 1:
3694 if m.anypats() or len(m.files()) != 1:
3694 raise error.Abort(_('can only specify an explicit filename'))
3695 raise error.Abort(_('can only specify an explicit filename'))
3695 file_ = m.files()[0]
3696 file_ = m.files()[0]
3696 filenodes = []
3697 filenodes = []
3697 for cp in ctx.parents():
3698 for cp in ctx.parents():
3698 if not cp:
3699 if not cp:
3699 continue
3700 continue
3700 try:
3701 try:
3701 filenodes.append(cp.filenode(file_))
3702 filenodes.append(cp.filenode(file_))
3702 except error.LookupError:
3703 except error.LookupError:
3703 pass
3704 pass
3704 if not filenodes:
3705 if not filenodes:
3705 raise error.Abort(_("'%s' not found in manifest!") % file_)
3706 raise error.Abort(_("'%s' not found in manifest!") % file_)
3706 p = []
3707 p = []
3707 for fn in filenodes:
3708 for fn in filenodes:
3708 fctx = repo.filectx(file_, fileid=fn)
3709 fctx = repo.filectx(file_, fileid=fn)
3709 p.append(fctx.node())
3710 p.append(fctx.node())
3710 else:
3711 else:
3711 p = [cp.node() for cp in ctx.parents()]
3712 p = [cp.node() for cp in ctx.parents()]
3712
3713
3713 displayer = cmdutil.show_changeset(ui, repo, opts)
3714 displayer = cmdutil.show_changeset(ui, repo, opts)
3714 for n in p:
3715 for n in p:
3715 if n != nullid:
3716 if n != nullid:
3716 displayer.show(repo[n])
3717 displayer.show(repo[n])
3717 displayer.close()
3718 displayer.close()
3718
3719
3719 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True)
3720 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True)
3720 def paths(ui, repo, search=None, **opts):
3721 def paths(ui, repo, search=None, **opts):
3721 """show aliases for remote repositories
3722 """show aliases for remote repositories
3722
3723
3723 Show definition of symbolic path name NAME. If no name is given,
3724 Show definition of symbolic path name NAME. If no name is given,
3724 show definition of all available names.
3725 show definition of all available names.
3725
3726
3726 Option -q/--quiet suppresses all output when searching for NAME
3727 Option -q/--quiet suppresses all output when searching for NAME
3727 and shows only the path names when listing all definitions.
3728 and shows only the path names when listing all definitions.
3728
3729
3729 Path names are defined in the [paths] section of your
3730 Path names are defined in the [paths] section of your
3730 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
3731 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
3731 repository, ``.hg/hgrc`` is used, too.
3732 repository, ``.hg/hgrc`` is used, too.
3732
3733
3733 The path names ``default`` and ``default-push`` have a special
3734 The path names ``default`` and ``default-push`` have a special
3734 meaning. When performing a push or pull operation, they are used
3735 meaning. When performing a push or pull operation, they are used
3735 as fallbacks if no location is specified on the command-line.
3736 as fallbacks if no location is specified on the command-line.
3736 When ``default-push`` is set, it will be used for push and
3737 When ``default-push`` is set, it will be used for push and
3737 ``default`` will be used for pull; otherwise ``default`` is used
3738 ``default`` will be used for pull; otherwise ``default`` is used
3738 as the fallback for both. When cloning a repository, the clone
3739 as the fallback for both. When cloning a repository, the clone
3739 source is written as ``default`` in ``.hg/hgrc``.
3740 source is written as ``default`` in ``.hg/hgrc``.
3740
3741
3741 .. note::
3742 .. note::
3742
3743
3743 ``default`` and ``default-push`` apply to all inbound (e.g.
3744 ``default`` and ``default-push`` apply to all inbound (e.g.
3744 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
3745 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
3745 and :hg:`bundle`) operations.
3746 and :hg:`bundle`) operations.
3746
3747
3747 See :hg:`help urls` for more information.
3748 See :hg:`help urls` for more information.
3748
3749
3749 Returns 0 on success.
3750 Returns 0 on success.
3750 """
3751 """
3751 if search:
3752 if search:
3752 pathitems = [(name, path) for name, path in ui.paths.iteritems()
3753 pathitems = [(name, path) for name, path in ui.paths.iteritems()
3753 if name == search]
3754 if name == search]
3754 else:
3755 else:
3755 pathitems = sorted(ui.paths.iteritems())
3756 pathitems = sorted(ui.paths.iteritems())
3756
3757
3757 fm = ui.formatter('paths', opts)
3758 fm = ui.formatter('paths', opts)
3758 if fm.isplain():
3759 if fm.isplain():
3759 hidepassword = util.hidepassword
3760 hidepassword = util.hidepassword
3760 else:
3761 else:
3761 hidepassword = str
3762 hidepassword = str
3762 if ui.quiet:
3763 if ui.quiet:
3763 namefmt = '%s\n'
3764 namefmt = '%s\n'
3764 else:
3765 else:
3765 namefmt = '%s = '
3766 namefmt = '%s = '
3766 showsubopts = not search and not ui.quiet
3767 showsubopts = not search and not ui.quiet
3767
3768
3768 for name, path in pathitems:
3769 for name, path in pathitems:
3769 fm.startitem()
3770 fm.startitem()
3770 fm.condwrite(not search, 'name', namefmt, name)
3771 fm.condwrite(not search, 'name', namefmt, name)
3771 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
3772 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
3772 for subopt, value in sorted(path.suboptions.items()):
3773 for subopt, value in sorted(path.suboptions.items()):
3773 assert subopt not in ('name', 'url')
3774 assert subopt not in ('name', 'url')
3774 if showsubopts:
3775 if showsubopts:
3775 fm.plain('%s:%s = ' % (name, subopt))
3776 fm.plain('%s:%s = ' % (name, subopt))
3776 fm.condwrite(showsubopts, subopt, '%s\n', value)
3777 fm.condwrite(showsubopts, subopt, '%s\n', value)
3777
3778
3778 fm.end()
3779 fm.end()
3779
3780
3780 if search and not pathitems:
3781 if search and not pathitems:
3781 if not ui.quiet:
3782 if not ui.quiet:
3782 ui.warn(_("not found!\n"))
3783 ui.warn(_("not found!\n"))
3783 return 1
3784 return 1
3784 else:
3785 else:
3785 return 0
3786 return 0
3786
3787
3787 @command('phase',
3788 @command('phase',
3788 [('p', 'public', False, _('set changeset phase to public')),
3789 [('p', 'public', False, _('set changeset phase to public')),
3789 ('d', 'draft', False, _('set changeset phase to draft')),
3790 ('d', 'draft', False, _('set changeset phase to draft')),
3790 ('s', 'secret', False, _('set changeset phase to secret')),
3791 ('s', 'secret', False, _('set changeset phase to secret')),
3791 ('f', 'force', False, _('allow to move boundary backward')),
3792 ('f', 'force', False, _('allow to move boundary backward')),
3792 ('r', 'rev', [], _('target revision'), _('REV')),
3793 ('r', 'rev', [], _('target revision'), _('REV')),
3793 ],
3794 ],
3794 _('[-p|-d|-s] [-f] [-r] [REV...]'))
3795 _('[-p|-d|-s] [-f] [-r] [REV...]'))
3795 def phase(ui, repo, *revs, **opts):
3796 def phase(ui, repo, *revs, **opts):
3796 """set or show the current phase name
3797 """set or show the current phase name
3797
3798
3798 With no argument, show the phase name of the current revision(s).
3799 With no argument, show the phase name of the current revision(s).
3799
3800
3800 With one of -p/--public, -d/--draft or -s/--secret, change the
3801 With one of -p/--public, -d/--draft or -s/--secret, change the
3801 phase value of the specified revisions.
3802 phase value of the specified revisions.
3802
3803
3803 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
3804 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
3804 lower phase to an higher phase. Phases are ordered as follows::
3805 lower phase to an higher phase. Phases are ordered as follows::
3805
3806
3806 public < draft < secret
3807 public < draft < secret
3807
3808
3808 Returns 0 on success, 1 if some phases could not be changed.
3809 Returns 0 on success, 1 if some phases could not be changed.
3809
3810
3810 (For more information about the phases concept, see :hg:`help phases`.)
3811 (For more information about the phases concept, see :hg:`help phases`.)
3811 """
3812 """
3812 # search for a unique phase argument
3813 # search for a unique phase argument
3813 targetphase = None
3814 targetphase = None
3814 for idx, name in enumerate(phases.phasenames):
3815 for idx, name in enumerate(phases.phasenames):
3815 if opts[name]:
3816 if opts[name]:
3816 if targetphase is not None:
3817 if targetphase is not None:
3817 raise error.Abort(_('only one phase can be specified'))
3818 raise error.Abort(_('only one phase can be specified'))
3818 targetphase = idx
3819 targetphase = idx
3819
3820
3820 # look for specified revision
3821 # look for specified revision
3821 revs = list(revs)
3822 revs = list(revs)
3822 revs.extend(opts['rev'])
3823 revs.extend(opts['rev'])
3823 if not revs:
3824 if not revs:
3824 # display both parents as the second parent phase can influence
3825 # display both parents as the second parent phase can influence
3825 # the phase of a merge commit
3826 # the phase of a merge commit
3826 revs = [c.rev() for c in repo[None].parents()]
3827 revs = [c.rev() for c in repo[None].parents()]
3827
3828
3828 revs = scmutil.revrange(repo, revs)
3829 revs = scmutil.revrange(repo, revs)
3829
3830
3830 lock = None
3831 lock = None
3831 ret = 0
3832 ret = 0
3832 if targetphase is None:
3833 if targetphase is None:
3833 # display
3834 # display
3834 for r in revs:
3835 for r in revs:
3835 ctx = repo[r]
3836 ctx = repo[r]
3836 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
3837 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
3837 else:
3838 else:
3838 tr = None
3839 tr = None
3839 lock = repo.lock()
3840 lock = repo.lock()
3840 try:
3841 try:
3841 tr = repo.transaction("phase")
3842 tr = repo.transaction("phase")
3842 # set phase
3843 # set phase
3843 if not revs:
3844 if not revs:
3844 raise error.Abort(_('empty revision set'))
3845 raise error.Abort(_('empty revision set'))
3845 nodes = [repo[r].node() for r in revs]
3846 nodes = [repo[r].node() for r in revs]
3846 # moving revision from public to draft may hide them
3847 # moving revision from public to draft may hide them
3847 # We have to check result on an unfiltered repository
3848 # We have to check result on an unfiltered repository
3848 unfi = repo.unfiltered()
3849 unfi = repo.unfiltered()
3849 getphase = unfi._phasecache.phase
3850 getphase = unfi._phasecache.phase
3850 olddata = [getphase(unfi, r) for r in unfi]
3851 olddata = [getphase(unfi, r) for r in unfi]
3851 phases.advanceboundary(repo, tr, targetphase, nodes)
3852 phases.advanceboundary(repo, tr, targetphase, nodes)
3852 if opts['force']:
3853 if opts['force']:
3853 phases.retractboundary(repo, tr, targetphase, nodes)
3854 phases.retractboundary(repo, tr, targetphase, nodes)
3854 tr.close()
3855 tr.close()
3855 finally:
3856 finally:
3856 if tr is not None:
3857 if tr is not None:
3857 tr.release()
3858 tr.release()
3858 lock.release()
3859 lock.release()
3859 getphase = unfi._phasecache.phase
3860 getphase = unfi._phasecache.phase
3860 newdata = [getphase(unfi, r) for r in unfi]
3861 newdata = [getphase(unfi, r) for r in unfi]
3861 changes = sum(newdata[r] != olddata[r] for r in unfi)
3862 changes = sum(newdata[r] != olddata[r] for r in unfi)
3862 cl = unfi.changelog
3863 cl = unfi.changelog
3863 rejected = [n for n in nodes
3864 rejected = [n for n in nodes
3864 if newdata[cl.rev(n)] < targetphase]
3865 if newdata[cl.rev(n)] < targetphase]
3865 if rejected:
3866 if rejected:
3866 ui.warn(_('cannot move %i changesets to a higher '
3867 ui.warn(_('cannot move %i changesets to a higher '
3867 'phase, use --force\n') % len(rejected))
3868 'phase, use --force\n') % len(rejected))
3868 ret = 1
3869 ret = 1
3869 if changes:
3870 if changes:
3870 msg = _('phase changed for %i changesets\n') % changes
3871 msg = _('phase changed for %i changesets\n') % changes
3871 if ret:
3872 if ret:
3872 ui.status(msg)
3873 ui.status(msg)
3873 else:
3874 else:
3874 ui.note(msg)
3875 ui.note(msg)
3875 else:
3876 else:
3876 ui.warn(_('no phases changed\n'))
3877 ui.warn(_('no phases changed\n'))
3877 return ret
3878 return ret
3878
3879
3879 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
3880 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
3880 """Run after a changegroup has been added via pull/unbundle
3881 """Run after a changegroup has been added via pull/unbundle
3881
3882
3882 This takes arguments below:
3883 This takes arguments below:
3883
3884
3884 :modheads: change of heads by pull/unbundle
3885 :modheads: change of heads by pull/unbundle
3885 :optupdate: updating working directory is needed or not
3886 :optupdate: updating working directory is needed or not
3886 :checkout: update destination revision (or None to default destination)
3887 :checkout: update destination revision (or None to default destination)
3887 :brev: a name, which might be a bookmark to be activated after updating
3888 :brev: a name, which might be a bookmark to be activated after updating
3888 """
3889 """
3889 if modheads == 0:
3890 if modheads == 0:
3890 return
3891 return
3891 if optupdate:
3892 if optupdate:
3892 try:
3893 try:
3893 return hg.updatetotally(ui, repo, checkout, brev)
3894 return hg.updatetotally(ui, repo, checkout, brev)
3894 except error.UpdateAbort as inst:
3895 except error.UpdateAbort as inst:
3895 msg = _("not updating: %s") % str(inst)
3896 msg = _("not updating: %s") % str(inst)
3896 hint = inst.hint
3897 hint = inst.hint
3897 raise error.UpdateAbort(msg, hint=hint)
3898 raise error.UpdateAbort(msg, hint=hint)
3898 if modheads > 1:
3899 if modheads > 1:
3899 currentbranchheads = len(repo.branchheads())
3900 currentbranchheads = len(repo.branchheads())
3900 if currentbranchheads == modheads:
3901 if currentbranchheads == modheads:
3901 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
3902 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
3902 elif currentbranchheads > 1:
3903 elif currentbranchheads > 1:
3903 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
3904 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
3904 "merge)\n"))
3905 "merge)\n"))
3905 else:
3906 else:
3906 ui.status(_("(run 'hg heads' to see heads)\n"))
3907 ui.status(_("(run 'hg heads' to see heads)\n"))
3907 else:
3908 else:
3908 ui.status(_("(run 'hg update' to get a working copy)\n"))
3909 ui.status(_("(run 'hg update' to get a working copy)\n"))
3909
3910
3910 @command('^pull',
3911 @command('^pull',
3911 [('u', 'update', None,
3912 [('u', 'update', None,
3912 _('update to new branch head if changesets were pulled')),
3913 _('update to new branch head if changesets were pulled')),
3913 ('f', 'force', None, _('run even when remote repository is unrelated')),
3914 ('f', 'force', None, _('run even when remote repository is unrelated')),
3914 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3915 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3915 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
3916 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
3916 ('b', 'branch', [], _('a specific branch you would like to pull'),
3917 ('b', 'branch', [], _('a specific branch you would like to pull'),
3917 _('BRANCH')),
3918 _('BRANCH')),
3918 ] + remoteopts,
3919 ] + remoteopts,
3919 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
3920 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
3920 def pull(ui, repo, source="default", **opts):
3921 def pull(ui, repo, source="default", **opts):
3921 """pull changes from the specified source
3922 """pull changes from the specified source
3922
3923
3923 Pull changes from a remote repository to a local one.
3924 Pull changes from a remote repository to a local one.
3924
3925
3925 This finds all changes from the repository at the specified path
3926 This finds all changes from the repository at the specified path
3926 or URL and adds them to a local repository (the current one unless
3927 or URL and adds them to a local repository (the current one unless
3927 -R is specified). By default, this does not update the copy of the
3928 -R is specified). By default, this does not update the copy of the
3928 project in the working directory.
3929 project in the working directory.
3929
3930
3930 Use :hg:`incoming` if you want to see what would have been added
3931 Use :hg:`incoming` if you want to see what would have been added
3931 by a pull at the time you issued this command. If you then decide
3932 by a pull at the time you issued this command. If you then decide
3932 to add those changes to the repository, you should use :hg:`pull
3933 to add those changes to the repository, you should use :hg:`pull
3933 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
3934 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
3934
3935
3935 If SOURCE is omitted, the 'default' path will be used.
3936 If SOURCE is omitted, the 'default' path will be used.
3936 See :hg:`help urls` for more information.
3937 See :hg:`help urls` for more information.
3937
3938
3938 Specifying bookmark as ``.`` is equivalent to specifying the active
3939 Specifying bookmark as ``.`` is equivalent to specifying the active
3939 bookmark's name.
3940 bookmark's name.
3940
3941
3941 Returns 0 on success, 1 if an update had unresolved files.
3942 Returns 0 on success, 1 if an update had unresolved files.
3942 """
3943 """
3943 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
3944 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
3944 ui.status(_('pulling from %s\n') % util.hidepassword(source))
3945 ui.status(_('pulling from %s\n') % util.hidepassword(source))
3945 other = hg.peer(repo, opts, source)
3946 other = hg.peer(repo, opts, source)
3946 try:
3947 try:
3947 revs, checkout = hg.addbranchrevs(repo, other, branches,
3948 revs, checkout = hg.addbranchrevs(repo, other, branches,
3948 opts.get('rev'))
3949 opts.get('rev'))
3949
3950
3950
3951
3951 pullopargs = {}
3952 pullopargs = {}
3952 if opts.get('bookmark'):
3953 if opts.get('bookmark'):
3953 if not revs:
3954 if not revs:
3954 revs = []
3955 revs = []
3955 # The list of bookmark used here is not the one used to actually
3956 # The list of bookmark used here is not the one used to actually
3956 # update the bookmark name. This can result in the revision pulled
3957 # update the bookmark name. This can result in the revision pulled
3957 # not ending up with the name of the bookmark because of a race
3958 # not ending up with the name of the bookmark because of a race
3958 # condition on the server. (See issue 4689 for details)
3959 # condition on the server. (See issue 4689 for details)
3959 remotebookmarks = other.listkeys('bookmarks')
3960 remotebookmarks = other.listkeys('bookmarks')
3960 pullopargs['remotebookmarks'] = remotebookmarks
3961 pullopargs['remotebookmarks'] = remotebookmarks
3961 for b in opts['bookmark']:
3962 for b in opts['bookmark']:
3962 b = repo._bookmarks.expandname(b)
3963 b = repo._bookmarks.expandname(b)
3963 if b not in remotebookmarks:
3964 if b not in remotebookmarks:
3964 raise error.Abort(_('remote bookmark %s not found!') % b)
3965 raise error.Abort(_('remote bookmark %s not found!') % b)
3965 revs.append(remotebookmarks[b])
3966 revs.append(remotebookmarks[b])
3966
3967
3967 if revs:
3968 if revs:
3968 try:
3969 try:
3969 # When 'rev' is a bookmark name, we cannot guarantee that it
3970 # When 'rev' is a bookmark name, we cannot guarantee that it
3970 # will be updated with that name because of a race condition
3971 # will be updated with that name because of a race condition
3971 # server side. (See issue 4689 for details)
3972 # server side. (See issue 4689 for details)
3972 oldrevs = revs
3973 oldrevs = revs
3973 revs = [] # actually, nodes
3974 revs = [] # actually, nodes
3974 for r in oldrevs:
3975 for r in oldrevs:
3975 node = other.lookup(r)
3976 node = other.lookup(r)
3976 revs.append(node)
3977 revs.append(node)
3977 if r == checkout:
3978 if r == checkout:
3978 checkout = node
3979 checkout = node
3979 except error.CapabilityError:
3980 except error.CapabilityError:
3980 err = _("other repository doesn't support revision lookup, "
3981 err = _("other repository doesn't support revision lookup, "
3981 "so a rev cannot be specified.")
3982 "so a rev cannot be specified.")
3982 raise error.Abort(err)
3983 raise error.Abort(err)
3983
3984
3984 pullopargs.update(opts.get('opargs', {}))
3985 pullopargs.update(opts.get('opargs', {}))
3985 modheads = exchange.pull(repo, other, heads=revs,
3986 modheads = exchange.pull(repo, other, heads=revs,
3986 force=opts.get('force'),
3987 force=opts.get('force'),
3987 bookmarks=opts.get('bookmark', ()),
3988 bookmarks=opts.get('bookmark', ()),
3988 opargs=pullopargs).cgresult
3989 opargs=pullopargs).cgresult
3989
3990
3990 # brev is a name, which might be a bookmark to be activated at
3991 # brev is a name, which might be a bookmark to be activated at
3991 # the end of the update. In other words, it is an explicit
3992 # the end of the update. In other words, it is an explicit
3992 # destination of the update
3993 # destination of the update
3993 brev = None
3994 brev = None
3994
3995
3995 if checkout:
3996 if checkout:
3996 checkout = str(repo.changelog.rev(checkout))
3997 checkout = str(repo.changelog.rev(checkout))
3997
3998
3998 # order below depends on implementation of
3999 # order below depends on implementation of
3999 # hg.addbranchrevs(). opts['bookmark'] is ignored,
4000 # hg.addbranchrevs(). opts['bookmark'] is ignored,
4000 # because 'checkout' is determined without it.
4001 # because 'checkout' is determined without it.
4001 if opts.get('rev'):
4002 if opts.get('rev'):
4002 brev = opts['rev'][0]
4003 brev = opts['rev'][0]
4003 elif opts.get('branch'):
4004 elif opts.get('branch'):
4004 brev = opts['branch'][0]
4005 brev = opts['branch'][0]
4005 else:
4006 else:
4006 brev = branches[0]
4007 brev = branches[0]
4007 repo._subtoppath = source
4008 repo._subtoppath = source
4008 try:
4009 try:
4009 ret = postincoming(ui, repo, modheads, opts.get('update'),
4010 ret = postincoming(ui, repo, modheads, opts.get('update'),
4010 checkout, brev)
4011 checkout, brev)
4011
4012
4012 finally:
4013 finally:
4013 del repo._subtoppath
4014 del repo._subtoppath
4014
4015
4015 finally:
4016 finally:
4016 other.close()
4017 other.close()
4017 return ret
4018 return ret
4018
4019
4019 @command('^push',
4020 @command('^push',
4020 [('f', 'force', None, _('force push')),
4021 [('f', 'force', None, _('force push')),
4021 ('r', 'rev', [],
4022 ('r', 'rev', [],
4022 _('a changeset intended to be included in the destination'),
4023 _('a changeset intended to be included in the destination'),
4023 _('REV')),
4024 _('REV')),
4024 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4025 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4025 ('b', 'branch', [],
4026 ('b', 'branch', [],
4026 _('a specific branch you would like to push'), _('BRANCH')),
4027 _('a specific branch you would like to push'), _('BRANCH')),
4027 ('', 'new-branch', False, _('allow pushing a new branch')),
4028 ('', 'new-branch', False, _('allow pushing a new branch')),
4028 ] + remoteopts,
4029 ] + remoteopts,
4029 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4030 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4030 def push(ui, repo, dest=None, **opts):
4031 def push(ui, repo, dest=None, **opts):
4031 """push changes to the specified destination
4032 """push changes to the specified destination
4032
4033
4033 Push changesets from the local repository to the specified
4034 Push changesets from the local repository to the specified
4034 destination.
4035 destination.
4035
4036
4036 This operation is symmetrical to pull: it is identical to a pull
4037 This operation is symmetrical to pull: it is identical to a pull
4037 in the destination repository from the current one.
4038 in the destination repository from the current one.
4038
4039
4039 By default, push will not allow creation of new heads at the
4040 By default, push will not allow creation of new heads at the
4040 destination, since multiple heads would make it unclear which head
4041 destination, since multiple heads would make it unclear which head
4041 to use. In this situation, it is recommended to pull and merge
4042 to use. In this situation, it is recommended to pull and merge
4042 before pushing.
4043 before pushing.
4043
4044
4044 Use --new-branch if you want to allow push to create a new named
4045 Use --new-branch if you want to allow push to create a new named
4045 branch that is not present at the destination. This allows you to
4046 branch that is not present at the destination. This allows you to
4046 only create a new branch without forcing other changes.
4047 only create a new branch without forcing other changes.
4047
4048
4048 .. note::
4049 .. note::
4049
4050
4050 Extra care should be taken with the -f/--force option,
4051 Extra care should be taken with the -f/--force option,
4051 which will push all new heads on all branches, an action which will
4052 which will push all new heads on all branches, an action which will
4052 almost always cause confusion for collaborators.
4053 almost always cause confusion for collaborators.
4053
4054
4054 If -r/--rev is used, the specified revision and all its ancestors
4055 If -r/--rev is used, the specified revision and all its ancestors
4055 will be pushed to the remote repository.
4056 will be pushed to the remote repository.
4056
4057
4057 If -B/--bookmark is used, the specified bookmarked revision, its
4058 If -B/--bookmark is used, the specified bookmarked revision, its
4058 ancestors, and the bookmark will be pushed to the remote
4059 ancestors, and the bookmark will be pushed to the remote
4059 repository. Specifying ``.`` is equivalent to specifying the active
4060 repository. Specifying ``.`` is equivalent to specifying the active
4060 bookmark's name.
4061 bookmark's name.
4061
4062
4062 Please see :hg:`help urls` for important details about ``ssh://``
4063 Please see :hg:`help urls` for important details about ``ssh://``
4063 URLs. If DESTINATION is omitted, a default path will be used.
4064 URLs. If DESTINATION is omitted, a default path will be used.
4064
4065
4065 Returns 0 if push was successful, 1 if nothing to push.
4066 Returns 0 if push was successful, 1 if nothing to push.
4066 """
4067 """
4067
4068
4068 if opts.get('bookmark'):
4069 if opts.get('bookmark'):
4069 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
4070 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
4070 for b in opts['bookmark']:
4071 for b in opts['bookmark']:
4071 # translate -B options to -r so changesets get pushed
4072 # translate -B options to -r so changesets get pushed
4072 b = repo._bookmarks.expandname(b)
4073 b = repo._bookmarks.expandname(b)
4073 if b in repo._bookmarks:
4074 if b in repo._bookmarks:
4074 opts.setdefault('rev', []).append(b)
4075 opts.setdefault('rev', []).append(b)
4075 else:
4076 else:
4076 # if we try to push a deleted bookmark, translate it to null
4077 # if we try to push a deleted bookmark, translate it to null
4077 # this lets simultaneous -r, -b options continue working
4078 # this lets simultaneous -r, -b options continue working
4078 opts.setdefault('rev', []).append("null")
4079 opts.setdefault('rev', []).append("null")
4079
4080
4080 path = ui.paths.getpath(dest, default=('default-push', 'default'))
4081 path = ui.paths.getpath(dest, default=('default-push', 'default'))
4081 if not path:
4082 if not path:
4082 raise error.Abort(_('default repository not configured!'),
4083 raise error.Abort(_('default repository not configured!'),
4083 hint=_("see 'hg help config.paths'"))
4084 hint=_("see 'hg help config.paths'"))
4084 dest = path.pushloc or path.loc
4085 dest = path.pushloc or path.loc
4085 branches = (path.branch, opts.get('branch') or [])
4086 branches = (path.branch, opts.get('branch') or [])
4086 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4087 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4087 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4088 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4088 other = hg.peer(repo, opts, dest)
4089 other = hg.peer(repo, opts, dest)
4089
4090
4090 if revs:
4091 if revs:
4091 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4092 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4092 if not revs:
4093 if not revs:
4093 raise error.Abort(_("specified revisions evaluate to an empty set"),
4094 raise error.Abort(_("specified revisions evaluate to an empty set"),
4094 hint=_("use different revision arguments"))
4095 hint=_("use different revision arguments"))
4095 elif path.pushrev:
4096 elif path.pushrev:
4096 # It doesn't make any sense to specify ancestor revisions. So limit
4097 # It doesn't make any sense to specify ancestor revisions. So limit
4097 # to DAG heads to make discovery simpler.
4098 # to DAG heads to make discovery simpler.
4098 expr = revsetlang.formatspec('heads(%r)', path.pushrev)
4099 expr = revsetlang.formatspec('heads(%r)', path.pushrev)
4099 revs = scmutil.revrange(repo, [expr])
4100 revs = scmutil.revrange(repo, [expr])
4100 revs = [repo[rev].node() for rev in revs]
4101 revs = [repo[rev].node() for rev in revs]
4101 if not revs:
4102 if not revs:
4102 raise error.Abort(_('default push revset for path evaluates to an '
4103 raise error.Abort(_('default push revset for path evaluates to an '
4103 'empty set'))
4104 'empty set'))
4104
4105
4105 repo._subtoppath = dest
4106 repo._subtoppath = dest
4106 try:
4107 try:
4107 # push subrepos depth-first for coherent ordering
4108 # push subrepos depth-first for coherent ordering
4108 c = repo['']
4109 c = repo['']
4109 subs = c.substate # only repos that are committed
4110 subs = c.substate # only repos that are committed
4110 for s in sorted(subs):
4111 for s in sorted(subs):
4111 result = c.sub(s).push(opts)
4112 result = c.sub(s).push(opts)
4112 if result == 0:
4113 if result == 0:
4113 return not result
4114 return not result
4114 finally:
4115 finally:
4115 del repo._subtoppath
4116 del repo._subtoppath
4116 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
4117 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
4117 newbranch=opts.get('new_branch'),
4118 newbranch=opts.get('new_branch'),
4118 bookmarks=opts.get('bookmark', ()),
4119 bookmarks=opts.get('bookmark', ()),
4119 opargs=opts.get('opargs'))
4120 opargs=opts.get('opargs'))
4120
4121
4121 result = not pushop.cgresult
4122 result = not pushop.cgresult
4122
4123
4123 if pushop.bkresult is not None:
4124 if pushop.bkresult is not None:
4124 if pushop.bkresult == 2:
4125 if pushop.bkresult == 2:
4125 result = 2
4126 result = 2
4126 elif not result and pushop.bkresult:
4127 elif not result and pushop.bkresult:
4127 result = 2
4128 result = 2
4128
4129
4129 return result
4130 return result
4130
4131
4131 @command('recover', [])
4132 @command('recover', [])
4132 def recover(ui, repo):
4133 def recover(ui, repo):
4133 """roll back an interrupted transaction
4134 """roll back an interrupted transaction
4134
4135
4135 Recover from an interrupted commit or pull.
4136 Recover from an interrupted commit or pull.
4136
4137
4137 This command tries to fix the repository status after an
4138 This command tries to fix the repository status after an
4138 interrupted operation. It should only be necessary when Mercurial
4139 interrupted operation. It should only be necessary when Mercurial
4139 suggests it.
4140 suggests it.
4140
4141
4141 Returns 0 if successful, 1 if nothing to recover or verify fails.
4142 Returns 0 if successful, 1 if nothing to recover or verify fails.
4142 """
4143 """
4143 if repo.recover():
4144 if repo.recover():
4144 return hg.verify(repo)
4145 return hg.verify(repo)
4145 return 1
4146 return 1
4146
4147
4147 @command('^remove|rm',
4148 @command('^remove|rm',
4148 [('A', 'after', None, _('record delete for missing files')),
4149 [('A', 'after', None, _('record delete for missing files')),
4149 ('f', 'force', None,
4150 ('f', 'force', None,
4150 _('forget added files, delete modified files')),
4151 _('forget added files, delete modified files')),
4151 ] + subrepoopts + walkopts,
4152 ] + subrepoopts + walkopts,
4152 _('[OPTION]... FILE...'),
4153 _('[OPTION]... FILE...'),
4153 inferrepo=True)
4154 inferrepo=True)
4154 def remove(ui, repo, *pats, **opts):
4155 def remove(ui, repo, *pats, **opts):
4155 """remove the specified files on the next commit
4156 """remove the specified files on the next commit
4156
4157
4157 Schedule the indicated files for removal from the current branch.
4158 Schedule the indicated files for removal from the current branch.
4158
4159
4159 This command schedules the files to be removed at the next commit.
4160 This command schedules the files to be removed at the next commit.
4160 To undo a remove before that, see :hg:`revert`. To undo added
4161 To undo a remove before that, see :hg:`revert`. To undo added
4161 files, see :hg:`forget`.
4162 files, see :hg:`forget`.
4162
4163
4163 .. container:: verbose
4164 .. container:: verbose
4164
4165
4165 -A/--after can be used to remove only files that have already
4166 -A/--after can be used to remove only files that have already
4166 been deleted, -f/--force can be used to force deletion, and -Af
4167 been deleted, -f/--force can be used to force deletion, and -Af
4167 can be used to remove files from the next revision without
4168 can be used to remove files from the next revision without
4168 deleting them from the working directory.
4169 deleting them from the working directory.
4169
4170
4170 The following table details the behavior of remove for different
4171 The following table details the behavior of remove for different
4171 file states (columns) and option combinations (rows). The file
4172 file states (columns) and option combinations (rows). The file
4172 states are Added [A], Clean [C], Modified [M] and Missing [!]
4173 states are Added [A], Clean [C], Modified [M] and Missing [!]
4173 (as reported by :hg:`status`). The actions are Warn, Remove
4174 (as reported by :hg:`status`). The actions are Warn, Remove
4174 (from branch) and Delete (from disk):
4175 (from branch) and Delete (from disk):
4175
4176
4176 ========= == == == ==
4177 ========= == == == ==
4177 opt/state A C M !
4178 opt/state A C M !
4178 ========= == == == ==
4179 ========= == == == ==
4179 none W RD W R
4180 none W RD W R
4180 -f R RD RD R
4181 -f R RD RD R
4181 -A W W W R
4182 -A W W W R
4182 -Af R R R R
4183 -Af R R R R
4183 ========= == == == ==
4184 ========= == == == ==
4184
4185
4185 .. note::
4186 .. note::
4186
4187
4187 :hg:`remove` never deletes files in Added [A] state from the
4188 :hg:`remove` never deletes files in Added [A] state from the
4188 working directory, not even if ``--force`` is specified.
4189 working directory, not even if ``--force`` is specified.
4189
4190
4190 Returns 0 on success, 1 if any warnings encountered.
4191 Returns 0 on success, 1 if any warnings encountered.
4191 """
4192 """
4192
4193
4193 after, force = opts.get('after'), opts.get('force')
4194 after, force = opts.get('after'), opts.get('force')
4194 if not pats and not after:
4195 if not pats and not after:
4195 raise error.Abort(_('no files specified'))
4196 raise error.Abort(_('no files specified'))
4196
4197
4197 m = scmutil.match(repo[None], pats, opts)
4198 m = scmutil.match(repo[None], pats, opts)
4198 subrepos = opts.get('subrepos')
4199 subrepos = opts.get('subrepos')
4199 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
4200 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
4200
4201
4201 @command('rename|move|mv',
4202 @command('rename|move|mv',
4202 [('A', 'after', None, _('record a rename that has already occurred')),
4203 [('A', 'after', None, _('record a rename that has already occurred')),
4203 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4204 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4204 ] + walkopts + dryrunopts,
4205 ] + walkopts + dryrunopts,
4205 _('[OPTION]... SOURCE... DEST'))
4206 _('[OPTION]... SOURCE... DEST'))
4206 def rename(ui, repo, *pats, **opts):
4207 def rename(ui, repo, *pats, **opts):
4207 """rename files; equivalent of copy + remove
4208 """rename files; equivalent of copy + remove
4208
4209
4209 Mark dest as copies of sources; mark sources for deletion. If dest
4210 Mark dest as copies of sources; mark sources for deletion. If dest
4210 is a directory, copies are put in that directory. If dest is a
4211 is a directory, copies are put in that directory. If dest is a
4211 file, there can only be one source.
4212 file, there can only be one source.
4212
4213
4213 By default, this command copies the contents of files as they
4214 By default, this command copies the contents of files as they
4214 exist in the working directory. If invoked with -A/--after, the
4215 exist in the working directory. If invoked with -A/--after, the
4215 operation is recorded, but no copying is performed.
4216 operation is recorded, but no copying is performed.
4216
4217
4217 This command takes effect at the next commit. To undo a rename
4218 This command takes effect at the next commit. To undo a rename
4218 before that, see :hg:`revert`.
4219 before that, see :hg:`revert`.
4219
4220
4220 Returns 0 on success, 1 if errors are encountered.
4221 Returns 0 on success, 1 if errors are encountered.
4221 """
4222 """
4222 with repo.wlock(False):
4223 with repo.wlock(False):
4223 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4224 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4224
4225
4225 @command('resolve',
4226 @command('resolve',
4226 [('a', 'all', None, _('select all unresolved files')),
4227 [('a', 'all', None, _('select all unresolved files')),
4227 ('l', 'list', None, _('list state of files needing merge')),
4228 ('l', 'list', None, _('list state of files needing merge')),
4228 ('m', 'mark', None, _('mark files as resolved')),
4229 ('m', 'mark', None, _('mark files as resolved')),
4229 ('u', 'unmark', None, _('mark files as unresolved')),
4230 ('u', 'unmark', None, _('mark files as unresolved')),
4230 ('n', 'no-status', None, _('hide status prefix'))]
4231 ('n', 'no-status', None, _('hide status prefix'))]
4231 + mergetoolopts + walkopts + formatteropts,
4232 + mergetoolopts + walkopts + formatteropts,
4232 _('[OPTION]... [FILE]...'),
4233 _('[OPTION]... [FILE]...'),
4233 inferrepo=True)
4234 inferrepo=True)
4234 def resolve(ui, repo, *pats, **opts):
4235 def resolve(ui, repo, *pats, **opts):
4235 """redo merges or set/view the merge status of files
4236 """redo merges or set/view the merge status of files
4236
4237
4237 Merges with unresolved conflicts are often the result of
4238 Merges with unresolved conflicts are often the result of
4238 non-interactive merging using the ``internal:merge`` configuration
4239 non-interactive merging using the ``internal:merge`` configuration
4239 setting, or a command-line merge tool like ``diff3``. The resolve
4240 setting, or a command-line merge tool like ``diff3``. The resolve
4240 command is used to manage the files involved in a merge, after
4241 command is used to manage the files involved in a merge, after
4241 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4242 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4242 working directory must have two parents). See :hg:`help
4243 working directory must have two parents). See :hg:`help
4243 merge-tools` for information on configuring merge tools.
4244 merge-tools` for information on configuring merge tools.
4244
4245
4245 The resolve command can be used in the following ways:
4246 The resolve command can be used in the following ways:
4246
4247
4247 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4248 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4248 files, discarding any previous merge attempts. Re-merging is not
4249 files, discarding any previous merge attempts. Re-merging is not
4249 performed for files already marked as resolved. Use ``--all/-a``
4250 performed for files already marked as resolved. Use ``--all/-a``
4250 to select all unresolved files. ``--tool`` can be used to specify
4251 to select all unresolved files. ``--tool`` can be used to specify
4251 the merge tool used for the given files. It overrides the HGMERGE
4252 the merge tool used for the given files. It overrides the HGMERGE
4252 environment variable and your configuration files. Previous file
4253 environment variable and your configuration files. Previous file
4253 contents are saved with a ``.orig`` suffix.
4254 contents are saved with a ``.orig`` suffix.
4254
4255
4255 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4256 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4256 (e.g. after having manually fixed-up the files). The default is
4257 (e.g. after having manually fixed-up the files). The default is
4257 to mark all unresolved files.
4258 to mark all unresolved files.
4258
4259
4259 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4260 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4260 default is to mark all resolved files.
4261 default is to mark all resolved files.
4261
4262
4262 - :hg:`resolve -l`: list files which had or still have conflicts.
4263 - :hg:`resolve -l`: list files which had or still have conflicts.
4263 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4264 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4264 You can use ``set:unresolved()`` or ``set:resolved()`` to filter
4265 You can use ``set:unresolved()`` or ``set:resolved()`` to filter
4265 the list. See :hg:`help filesets` for details.
4266 the list. See :hg:`help filesets` for details.
4266
4267
4267 .. note::
4268 .. note::
4268
4269
4269 Mercurial will not let you commit files with unresolved merge
4270 Mercurial will not let you commit files with unresolved merge
4270 conflicts. You must use :hg:`resolve -m ...` before you can
4271 conflicts. You must use :hg:`resolve -m ...` before you can
4271 commit after a conflicting merge.
4272 commit after a conflicting merge.
4272
4273
4273 Returns 0 on success, 1 if any files fail a resolve attempt.
4274 Returns 0 on success, 1 if any files fail a resolve attempt.
4274 """
4275 """
4275
4276
4276 flaglist = 'all mark unmark list no_status'.split()
4277 flaglist = 'all mark unmark list no_status'.split()
4277 all, mark, unmark, show, nostatus = \
4278 all, mark, unmark, show, nostatus = \
4278 [opts.get(o) for o in flaglist]
4279 [opts.get(o) for o in flaglist]
4279
4280
4280 if (show and (mark or unmark)) or (mark and unmark):
4281 if (show and (mark or unmark)) or (mark and unmark):
4281 raise error.Abort(_("too many options specified"))
4282 raise error.Abort(_("too many options specified"))
4282 if pats and all:
4283 if pats and all:
4283 raise error.Abort(_("can't specify --all and patterns"))
4284 raise error.Abort(_("can't specify --all and patterns"))
4284 if not (all or pats or show or mark or unmark):
4285 if not (all or pats or show or mark or unmark):
4285 raise error.Abort(_('no files or directories specified'),
4286 raise error.Abort(_('no files or directories specified'),
4286 hint=('use --all to re-merge all unresolved files'))
4287 hint=('use --all to re-merge all unresolved files'))
4287
4288
4288 if show:
4289 if show:
4289 fm = ui.formatter('resolve', opts)
4290 fm = ui.formatter('resolve', opts)
4290 ms = mergemod.mergestate.read(repo)
4291 ms = mergemod.mergestate.read(repo)
4291 m = scmutil.match(repo[None], pats, opts)
4292 m = scmutil.match(repo[None], pats, opts)
4292 for f in ms:
4293 for f in ms:
4293 if not m(f):
4294 if not m(f):
4294 continue
4295 continue
4295 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
4296 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
4296 'd': 'driverresolved'}[ms[f]]
4297 'd': 'driverresolved'}[ms[f]]
4297 fm.startitem()
4298 fm.startitem()
4298 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
4299 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
4299 fm.write('path', '%s\n', f, label=l)
4300 fm.write('path', '%s\n', f, label=l)
4300 fm.end()
4301 fm.end()
4301 return 0
4302 return 0
4302
4303
4303 with repo.wlock():
4304 with repo.wlock():
4304 ms = mergemod.mergestate.read(repo)
4305 ms = mergemod.mergestate.read(repo)
4305
4306
4306 if not (ms.active() or repo.dirstate.p2() != nullid):
4307 if not (ms.active() or repo.dirstate.p2() != nullid):
4307 raise error.Abort(
4308 raise error.Abort(
4308 _('resolve command not applicable when not merging'))
4309 _('resolve command not applicable when not merging'))
4309
4310
4310 wctx = repo[None]
4311 wctx = repo[None]
4311
4312
4312 if ms.mergedriver and ms.mdstate() == 'u':
4313 if ms.mergedriver and ms.mdstate() == 'u':
4313 proceed = mergemod.driverpreprocess(repo, ms, wctx)
4314 proceed = mergemod.driverpreprocess(repo, ms, wctx)
4314 ms.commit()
4315 ms.commit()
4315 # allow mark and unmark to go through
4316 # allow mark and unmark to go through
4316 if not mark and not unmark and not proceed:
4317 if not mark and not unmark and not proceed:
4317 return 1
4318 return 1
4318
4319
4319 m = scmutil.match(wctx, pats, opts)
4320 m = scmutil.match(wctx, pats, opts)
4320 ret = 0
4321 ret = 0
4321 didwork = False
4322 didwork = False
4322 runconclude = False
4323 runconclude = False
4323
4324
4324 tocomplete = []
4325 tocomplete = []
4325 for f in ms:
4326 for f in ms:
4326 if not m(f):
4327 if not m(f):
4327 continue
4328 continue
4328
4329
4329 didwork = True
4330 didwork = True
4330
4331
4331 # don't let driver-resolved files be marked, and run the conclude
4332 # don't let driver-resolved files be marked, and run the conclude
4332 # step if asked to resolve
4333 # step if asked to resolve
4333 if ms[f] == "d":
4334 if ms[f] == "d":
4334 exact = m.exact(f)
4335 exact = m.exact(f)
4335 if mark:
4336 if mark:
4336 if exact:
4337 if exact:
4337 ui.warn(_('not marking %s as it is driver-resolved\n')
4338 ui.warn(_('not marking %s as it is driver-resolved\n')
4338 % f)
4339 % f)
4339 elif unmark:
4340 elif unmark:
4340 if exact:
4341 if exact:
4341 ui.warn(_('not unmarking %s as it is driver-resolved\n')
4342 ui.warn(_('not unmarking %s as it is driver-resolved\n')
4342 % f)
4343 % f)
4343 else:
4344 else:
4344 runconclude = True
4345 runconclude = True
4345 continue
4346 continue
4346
4347
4347 if mark:
4348 if mark:
4348 ms.mark(f, "r")
4349 ms.mark(f, "r")
4349 elif unmark:
4350 elif unmark:
4350 ms.mark(f, "u")
4351 ms.mark(f, "u")
4351 else:
4352 else:
4352 # backup pre-resolve (merge uses .orig for its own purposes)
4353 # backup pre-resolve (merge uses .orig for its own purposes)
4353 a = repo.wjoin(f)
4354 a = repo.wjoin(f)
4354 try:
4355 try:
4355 util.copyfile(a, a + ".resolve")
4356 util.copyfile(a, a + ".resolve")
4356 except (IOError, OSError) as inst:
4357 except (IOError, OSError) as inst:
4357 if inst.errno != errno.ENOENT:
4358 if inst.errno != errno.ENOENT:
4358 raise
4359 raise
4359
4360
4360 try:
4361 try:
4361 # preresolve file
4362 # preresolve file
4362 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4363 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4363 'resolve')
4364 'resolve')
4364 complete, r = ms.preresolve(f, wctx)
4365 complete, r = ms.preresolve(f, wctx)
4365 if not complete:
4366 if not complete:
4366 tocomplete.append(f)
4367 tocomplete.append(f)
4367 elif r:
4368 elif r:
4368 ret = 1
4369 ret = 1
4369 finally:
4370 finally:
4370 ui.setconfig('ui', 'forcemerge', '', 'resolve')
4371 ui.setconfig('ui', 'forcemerge', '', 'resolve')
4371 ms.commit()
4372 ms.commit()
4372
4373
4373 # replace filemerge's .orig file with our resolve file, but only
4374 # replace filemerge's .orig file with our resolve file, but only
4374 # for merges that are complete
4375 # for merges that are complete
4375 if complete:
4376 if complete:
4376 try:
4377 try:
4377 util.rename(a + ".resolve",
4378 util.rename(a + ".resolve",
4378 scmutil.origpath(ui, repo, a))
4379 scmutil.origpath(ui, repo, a))
4379 except OSError as inst:
4380 except OSError as inst:
4380 if inst.errno != errno.ENOENT:
4381 if inst.errno != errno.ENOENT:
4381 raise
4382 raise
4382
4383
4383 for f in tocomplete:
4384 for f in tocomplete:
4384 try:
4385 try:
4385 # resolve file
4386 # resolve file
4386 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4387 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4387 'resolve')
4388 'resolve')
4388 r = ms.resolve(f, wctx)
4389 r = ms.resolve(f, wctx)
4389 if r:
4390 if r:
4390 ret = 1
4391 ret = 1
4391 finally:
4392 finally:
4392 ui.setconfig('ui', 'forcemerge', '', 'resolve')
4393 ui.setconfig('ui', 'forcemerge', '', 'resolve')
4393 ms.commit()
4394 ms.commit()
4394
4395
4395 # replace filemerge's .orig file with our resolve file
4396 # replace filemerge's .orig file with our resolve file
4396 a = repo.wjoin(f)
4397 a = repo.wjoin(f)
4397 try:
4398 try:
4398 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
4399 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
4399 except OSError as inst:
4400 except OSError as inst:
4400 if inst.errno != errno.ENOENT:
4401 if inst.errno != errno.ENOENT:
4401 raise
4402 raise
4402
4403
4403 ms.commit()
4404 ms.commit()
4404 ms.recordactions()
4405 ms.recordactions()
4405
4406
4406 if not didwork and pats:
4407 if not didwork and pats:
4407 hint = None
4408 hint = None
4408 if not any([p for p in pats if p.find(':') >= 0]):
4409 if not any([p for p in pats if p.find(':') >= 0]):
4409 pats = ['path:%s' % p for p in pats]
4410 pats = ['path:%s' % p for p in pats]
4410 m = scmutil.match(wctx, pats, opts)
4411 m = scmutil.match(wctx, pats, opts)
4411 for f in ms:
4412 for f in ms:
4412 if not m(f):
4413 if not m(f):
4413 continue
4414 continue
4414 flags = ''.join(['-%s ' % o[0] for o in flaglist
4415 flags = ''.join(['-%s ' % o[0] for o in flaglist
4415 if opts.get(o)])
4416 if opts.get(o)])
4416 hint = _("(try: hg resolve %s%s)\n") % (
4417 hint = _("(try: hg resolve %s%s)\n") % (
4417 flags,
4418 flags,
4418 ' '.join(pats))
4419 ' '.join(pats))
4419 break
4420 break
4420 ui.warn(_("arguments do not match paths that need resolving\n"))
4421 ui.warn(_("arguments do not match paths that need resolving\n"))
4421 if hint:
4422 if hint:
4422 ui.warn(hint)
4423 ui.warn(hint)
4423 elif ms.mergedriver and ms.mdstate() != 's':
4424 elif ms.mergedriver and ms.mdstate() != 's':
4424 # run conclude step when either a driver-resolved file is requested
4425 # run conclude step when either a driver-resolved file is requested
4425 # or there are no driver-resolved files
4426 # or there are no driver-resolved files
4426 # we can't use 'ret' to determine whether any files are unresolved
4427 # we can't use 'ret' to determine whether any files are unresolved
4427 # because we might not have tried to resolve some
4428 # because we might not have tried to resolve some
4428 if ((runconclude or not list(ms.driverresolved()))
4429 if ((runconclude or not list(ms.driverresolved()))
4429 and not list(ms.unresolved())):
4430 and not list(ms.unresolved())):
4430 proceed = mergemod.driverconclude(repo, ms, wctx)
4431 proceed = mergemod.driverconclude(repo, ms, wctx)
4431 ms.commit()
4432 ms.commit()
4432 if not proceed:
4433 if not proceed:
4433 return 1
4434 return 1
4434
4435
4435 # Nudge users into finishing an unfinished operation
4436 # Nudge users into finishing an unfinished operation
4436 unresolvedf = list(ms.unresolved())
4437 unresolvedf = list(ms.unresolved())
4437 driverresolvedf = list(ms.driverresolved())
4438 driverresolvedf = list(ms.driverresolved())
4438 if not unresolvedf and not driverresolvedf:
4439 if not unresolvedf and not driverresolvedf:
4439 ui.status(_('(no more unresolved files)\n'))
4440 ui.status(_('(no more unresolved files)\n'))
4440 cmdutil.checkafterresolved(repo)
4441 cmdutil.checkafterresolved(repo)
4441 elif not unresolvedf:
4442 elif not unresolvedf:
4442 ui.status(_('(no more unresolved files -- '
4443 ui.status(_('(no more unresolved files -- '
4443 'run "hg resolve --all" to conclude)\n'))
4444 'run "hg resolve --all" to conclude)\n'))
4444
4445
4445 return ret
4446 return ret
4446
4447
4447 @command('revert',
4448 @command('revert',
4448 [('a', 'all', None, _('revert all changes when no arguments given')),
4449 [('a', 'all', None, _('revert all changes when no arguments given')),
4449 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4450 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4450 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4451 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4451 ('C', 'no-backup', None, _('do not save backup copies of files')),
4452 ('C', 'no-backup', None, _('do not save backup copies of files')),
4452 ('i', 'interactive', None,
4453 ('i', 'interactive', None,
4453 _('interactively select the changes (EXPERIMENTAL)')),
4454 _('interactively select the changes (EXPERIMENTAL)')),
4454 ] + walkopts + dryrunopts,
4455 ] + walkopts + dryrunopts,
4455 _('[OPTION]... [-r REV] [NAME]...'))
4456 _('[OPTION]... [-r REV] [NAME]...'))
4456 def revert(ui, repo, *pats, **opts):
4457 def revert(ui, repo, *pats, **opts):
4457 """restore files to their checkout state
4458 """restore files to their checkout state
4458
4459
4459 .. note::
4460 .. note::
4460
4461
4461 To check out earlier revisions, you should use :hg:`update REV`.
4462 To check out earlier revisions, you should use :hg:`update REV`.
4462 To cancel an uncommitted merge (and lose your changes),
4463 To cancel an uncommitted merge (and lose your changes),
4463 use :hg:`update --clean .`.
4464 use :hg:`update --clean .`.
4464
4465
4465 With no revision specified, revert the specified files or directories
4466 With no revision specified, revert the specified files or directories
4466 to the contents they had in the parent of the working directory.
4467 to the contents they had in the parent of the working directory.
4467 This restores the contents of files to an unmodified
4468 This restores the contents of files to an unmodified
4468 state and unschedules adds, removes, copies, and renames. If the
4469 state and unschedules adds, removes, copies, and renames. If the
4469 working directory has two parents, you must explicitly specify a
4470 working directory has two parents, you must explicitly specify a
4470 revision.
4471 revision.
4471
4472
4472 Using the -r/--rev or -d/--date options, revert the given files or
4473 Using the -r/--rev or -d/--date options, revert the given files or
4473 directories to their states as of a specific revision. Because
4474 directories to their states as of a specific revision. Because
4474 revert does not change the working directory parents, this will
4475 revert does not change the working directory parents, this will
4475 cause these files to appear modified. This can be helpful to "back
4476 cause these files to appear modified. This can be helpful to "back
4476 out" some or all of an earlier change. See :hg:`backout` for a
4477 out" some or all of an earlier change. See :hg:`backout` for a
4477 related method.
4478 related method.
4478
4479
4479 Modified files are saved with a .orig suffix before reverting.
4480 Modified files are saved with a .orig suffix before reverting.
4480 To disable these backups, use --no-backup. It is possible to store
4481 To disable these backups, use --no-backup. It is possible to store
4481 the backup files in a custom directory relative to the root of the
4482 the backup files in a custom directory relative to the root of the
4482 repository by setting the ``ui.origbackuppath`` configuration
4483 repository by setting the ``ui.origbackuppath`` configuration
4483 option.
4484 option.
4484
4485
4485 See :hg:`help dates` for a list of formats valid for -d/--date.
4486 See :hg:`help dates` for a list of formats valid for -d/--date.
4486
4487
4487 See :hg:`help backout` for a way to reverse the effect of an
4488 See :hg:`help backout` for a way to reverse the effect of an
4488 earlier changeset.
4489 earlier changeset.
4489
4490
4490 Returns 0 on success.
4491 Returns 0 on success.
4491 """
4492 """
4492
4493
4493 if opts.get("date"):
4494 if opts.get("date"):
4494 if opts.get("rev"):
4495 if opts.get("rev"):
4495 raise error.Abort(_("you can't specify a revision and a date"))
4496 raise error.Abort(_("you can't specify a revision and a date"))
4496 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4497 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4497
4498
4498 parent, p2 = repo.dirstate.parents()
4499 parent, p2 = repo.dirstate.parents()
4499 if not opts.get('rev') and p2 != nullid:
4500 if not opts.get('rev') and p2 != nullid:
4500 # revert after merge is a trap for new users (issue2915)
4501 # revert after merge is a trap for new users (issue2915)
4501 raise error.Abort(_('uncommitted merge with no revision specified'),
4502 raise error.Abort(_('uncommitted merge with no revision specified'),
4502 hint=_("use 'hg update' or see 'hg help revert'"))
4503 hint=_("use 'hg update' or see 'hg help revert'"))
4503
4504
4504 ctx = scmutil.revsingle(repo, opts.get('rev'))
4505 ctx = scmutil.revsingle(repo, opts.get('rev'))
4505
4506
4506 if (not (pats or opts.get('include') or opts.get('exclude') or
4507 if (not (pats or opts.get('include') or opts.get('exclude') or
4507 opts.get('all') or opts.get('interactive'))):
4508 opts.get('all') or opts.get('interactive'))):
4508 msg = _("no files or directories specified")
4509 msg = _("no files or directories specified")
4509 if p2 != nullid:
4510 if p2 != nullid:
4510 hint = _("uncommitted merge, use --all to discard all changes,"
4511 hint = _("uncommitted merge, use --all to discard all changes,"
4511 " or 'hg update -C .' to abort the merge")
4512 " or 'hg update -C .' to abort the merge")
4512 raise error.Abort(msg, hint=hint)
4513 raise error.Abort(msg, hint=hint)
4513 dirty = any(repo.status())
4514 dirty = any(repo.status())
4514 node = ctx.node()
4515 node = ctx.node()
4515 if node != parent:
4516 if node != parent:
4516 if dirty:
4517 if dirty:
4517 hint = _("uncommitted changes, use --all to discard all"
4518 hint = _("uncommitted changes, use --all to discard all"
4518 " changes, or 'hg update %s' to update") % ctx.rev()
4519 " changes, or 'hg update %s' to update") % ctx.rev()
4519 else:
4520 else:
4520 hint = _("use --all to revert all files,"
4521 hint = _("use --all to revert all files,"
4521 " or 'hg update %s' to update") % ctx.rev()
4522 " or 'hg update %s' to update") % ctx.rev()
4522 elif dirty:
4523 elif dirty:
4523 hint = _("uncommitted changes, use --all to discard all changes")
4524 hint = _("uncommitted changes, use --all to discard all changes")
4524 else:
4525 else:
4525 hint = _("use --all to revert all files")
4526 hint = _("use --all to revert all files")
4526 raise error.Abort(msg, hint=hint)
4527 raise error.Abort(msg, hint=hint)
4527
4528
4528 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
4529 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
4529
4530
4530 @command('rollback', dryrunopts +
4531 @command('rollback', dryrunopts +
4531 [('f', 'force', False, _('ignore safety measures'))])
4532 [('f', 'force', False, _('ignore safety measures'))])
4532 def rollback(ui, repo, **opts):
4533 def rollback(ui, repo, **opts):
4533 """roll back the last transaction (DANGEROUS) (DEPRECATED)
4534 """roll back the last transaction (DANGEROUS) (DEPRECATED)
4534
4535
4535 Please use :hg:`commit --amend` instead of rollback to correct
4536 Please use :hg:`commit --amend` instead of rollback to correct
4536 mistakes in the last commit.
4537 mistakes in the last commit.
4537
4538
4538 This command should be used with care. There is only one level of
4539 This command should be used with care. There is only one level of
4539 rollback, and there is no way to undo a rollback. It will also
4540 rollback, and there is no way to undo a rollback. It will also
4540 restore the dirstate at the time of the last transaction, losing
4541 restore the dirstate at the time of the last transaction, losing
4541 any dirstate changes since that time. This command does not alter
4542 any dirstate changes since that time. This command does not alter
4542 the working directory.
4543 the working directory.
4543
4544
4544 Transactions are used to encapsulate the effects of all commands
4545 Transactions are used to encapsulate the effects of all commands
4545 that create new changesets or propagate existing changesets into a
4546 that create new changesets or propagate existing changesets into a
4546 repository.
4547 repository.
4547
4548
4548 .. container:: verbose
4549 .. container:: verbose
4549
4550
4550 For example, the following commands are transactional, and their
4551 For example, the following commands are transactional, and their
4551 effects can be rolled back:
4552 effects can be rolled back:
4552
4553
4553 - commit
4554 - commit
4554 - import
4555 - import
4555 - pull
4556 - pull
4556 - push (with this repository as the destination)
4557 - push (with this repository as the destination)
4557 - unbundle
4558 - unbundle
4558
4559
4559 To avoid permanent data loss, rollback will refuse to rollback a
4560 To avoid permanent data loss, rollback will refuse to rollback a
4560 commit transaction if it isn't checked out. Use --force to
4561 commit transaction if it isn't checked out. Use --force to
4561 override this protection.
4562 override this protection.
4562
4563
4563 The rollback command can be entirely disabled by setting the
4564 The rollback command can be entirely disabled by setting the
4564 ``ui.rollback`` configuration setting to false. If you're here
4565 ``ui.rollback`` configuration setting to false. If you're here
4565 because you want to use rollback and it's disabled, you can
4566 because you want to use rollback and it's disabled, you can
4566 re-enable the command by setting ``ui.rollback`` to true.
4567 re-enable the command by setting ``ui.rollback`` to true.
4567
4568
4568 This command is not intended for use on public repositories. Once
4569 This command is not intended for use on public repositories. Once
4569 changes are visible for pull by other users, rolling a transaction
4570 changes are visible for pull by other users, rolling a transaction
4570 back locally is ineffective (someone else may already have pulled
4571 back locally is ineffective (someone else may already have pulled
4571 the changes). Furthermore, a race is possible with readers of the
4572 the changes). Furthermore, a race is possible with readers of the
4572 repository; for example an in-progress pull from the repository
4573 repository; for example an in-progress pull from the repository
4573 may fail if a rollback is performed.
4574 may fail if a rollback is performed.
4574
4575
4575 Returns 0 on success, 1 if no rollback data is available.
4576 Returns 0 on success, 1 if no rollback data is available.
4576 """
4577 """
4577 if not ui.configbool('ui', 'rollback', True):
4578 if not ui.configbool('ui', 'rollback', True):
4578 raise error.Abort(_('rollback is disabled because it is unsafe'),
4579 raise error.Abort(_('rollback is disabled because it is unsafe'),
4579 hint=('see `hg help -v rollback` for information'))
4580 hint=('see `hg help -v rollback` for information'))
4580 return repo.rollback(dryrun=opts.get('dry_run'),
4581 return repo.rollback(dryrun=opts.get('dry_run'),
4581 force=opts.get('force'))
4582 force=opts.get('force'))
4582
4583
4583 @command('root', [])
4584 @command('root', [])
4584 def root(ui, repo):
4585 def root(ui, repo):
4585 """print the root (top) of the current working directory
4586 """print the root (top) of the current working directory
4586
4587
4587 Print the root directory of the current repository.
4588 Print the root directory of the current repository.
4588
4589
4589 Returns 0 on success.
4590 Returns 0 on success.
4590 """
4591 """
4591 ui.write(repo.root + "\n")
4592 ui.write(repo.root + "\n")
4592
4593
4593 @command('^serve',
4594 @command('^serve',
4594 [('A', 'accesslog', '', _('name of access log file to write to'),
4595 [('A', 'accesslog', '', _('name of access log file to write to'),
4595 _('FILE')),
4596 _('FILE')),
4596 ('d', 'daemon', None, _('run server in background')),
4597 ('d', 'daemon', None, _('run server in background')),
4597 ('', 'daemon-postexec', [], _('used internally by daemon mode')),
4598 ('', 'daemon-postexec', [], _('used internally by daemon mode')),
4598 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4599 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4599 # use string type, then we can check if something was passed
4600 # use string type, then we can check if something was passed
4600 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4601 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4601 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4602 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4602 _('ADDR')),
4603 _('ADDR')),
4603 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4604 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4604 _('PREFIX')),
4605 _('PREFIX')),
4605 ('n', 'name', '',
4606 ('n', 'name', '',
4606 _('name to show in web pages (default: working directory)'), _('NAME')),
4607 _('name to show in web pages (default: working directory)'), _('NAME')),
4607 ('', 'web-conf', '',
4608 ('', 'web-conf', '',
4608 _("name of the hgweb config file (see 'hg help hgweb')"), _('FILE')),
4609 _("name of the hgweb config file (see 'hg help hgweb')"), _('FILE')),
4609 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4610 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4610 _('FILE')),
4611 _('FILE')),
4611 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4612 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4612 ('', 'stdio', None, _('for remote clients')),
4613 ('', 'stdio', None, _('for remote clients')),
4613 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
4614 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
4614 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4615 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4615 ('', 'style', '', _('template style to use'), _('STYLE')),
4616 ('', 'style', '', _('template style to use'), _('STYLE')),
4616 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4617 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4617 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
4618 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
4618 _('[OPTION]...'),
4619 _('[OPTION]...'),
4619 optionalrepo=True)
4620 optionalrepo=True)
4620 def serve(ui, repo, **opts):
4621 def serve(ui, repo, **opts):
4621 """start stand-alone webserver
4622 """start stand-alone webserver
4622
4623
4623 Start a local HTTP repository browser and pull server. You can use
4624 Start a local HTTP repository browser and pull server. You can use
4624 this for ad-hoc sharing and browsing of repositories. It is
4625 this for ad-hoc sharing and browsing of repositories. It is
4625 recommended to use a real web server to serve a repository for
4626 recommended to use a real web server to serve a repository for
4626 longer periods of time.
4627 longer periods of time.
4627
4628
4628 Please note that the server does not implement access control.
4629 Please note that the server does not implement access control.
4629 This means that, by default, anybody can read from the server and
4630 This means that, by default, anybody can read from the server and
4630 nobody can write to it by default. Set the ``web.allow_push``
4631 nobody can write to it by default. Set the ``web.allow_push``
4631 option to ``*`` to allow everybody to push to the server. You
4632 option to ``*`` to allow everybody to push to the server. You
4632 should use a real web server if you need to authenticate users.
4633 should use a real web server if you need to authenticate users.
4633
4634
4634 By default, the server logs accesses to stdout and errors to
4635 By default, the server logs accesses to stdout and errors to
4635 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
4636 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
4636 files.
4637 files.
4637
4638
4638 To have the server choose a free port number to listen on, specify
4639 To have the server choose a free port number to listen on, specify
4639 a port number of 0; in this case, the server will print the port
4640 a port number of 0; in this case, the server will print the port
4640 number it uses.
4641 number it uses.
4641
4642
4642 Returns 0 on success.
4643 Returns 0 on success.
4643 """
4644 """
4644
4645
4645 if opts["stdio"] and opts["cmdserver"]:
4646 if opts["stdio"] and opts["cmdserver"]:
4646 raise error.Abort(_("cannot use --stdio with --cmdserver"))
4647 raise error.Abort(_("cannot use --stdio with --cmdserver"))
4647
4648
4648 if opts["stdio"]:
4649 if opts["stdio"]:
4649 if repo is None:
4650 if repo is None:
4650 raise error.RepoError(_("there is no Mercurial repository here"
4651 raise error.RepoError(_("there is no Mercurial repository here"
4651 " (.hg not found)"))
4652 " (.hg not found)"))
4652 s = sshserver.sshserver(ui, repo)
4653 s = sshserver.sshserver(ui, repo)
4653 s.serve_forever()
4654 s.serve_forever()
4654
4655
4655 service = server.createservice(ui, repo, opts)
4656 service = server.createservice(ui, repo, opts)
4656 return server.runservice(opts, initfn=service.init, runfn=service.run)
4657 return server.runservice(opts, initfn=service.init, runfn=service.run)
4657
4658
4658 @command('^status|st',
4659 @command('^status|st',
4659 [('A', 'all', None, _('show status of all files')),
4660 [('A', 'all', None, _('show status of all files')),
4660 ('m', 'modified', None, _('show only modified files')),
4661 ('m', 'modified', None, _('show only modified files')),
4661 ('a', 'added', None, _('show only added files')),
4662 ('a', 'added', None, _('show only added files')),
4662 ('r', 'removed', None, _('show only removed files')),
4663 ('r', 'removed', None, _('show only removed files')),
4663 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4664 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4664 ('c', 'clean', None, _('show only files without changes')),
4665 ('c', 'clean', None, _('show only files without changes')),
4665 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4666 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4666 ('i', 'ignored', None, _('show only ignored files')),
4667 ('i', 'ignored', None, _('show only ignored files')),
4667 ('n', 'no-status', None, _('hide status prefix')),
4668 ('n', 'no-status', None, _('hide status prefix')),
4668 ('C', 'copies', None, _('show source of copied files')),
4669 ('C', 'copies', None, _('show source of copied files')),
4669 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4670 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4670 ('', 'rev', [], _('show difference from revision'), _('REV')),
4671 ('', 'rev', [], _('show difference from revision'), _('REV')),
4671 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
4672 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
4672 ] + walkopts + subrepoopts + formatteropts,
4673 ] + walkopts + subrepoopts + formatteropts,
4673 _('[OPTION]... [FILE]...'),
4674 _('[OPTION]... [FILE]...'),
4674 inferrepo=True)
4675 inferrepo=True)
4675 def status(ui, repo, *pats, **opts):
4676 def status(ui, repo, *pats, **opts):
4676 """show changed files in the working directory
4677 """show changed files in the working directory
4677
4678
4678 Show status of files in the repository. If names are given, only
4679 Show status of files in the repository. If names are given, only
4679 files that match are shown. Files that are clean or ignored or
4680 files that match are shown. Files that are clean or ignored or
4680 the source of a copy/move operation, are not listed unless
4681 the source of a copy/move operation, are not listed unless
4681 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
4682 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
4682 Unless options described with "show only ..." are given, the
4683 Unless options described with "show only ..." are given, the
4683 options -mardu are used.
4684 options -mardu are used.
4684
4685
4685 Option -q/--quiet hides untracked (unknown and ignored) files
4686 Option -q/--quiet hides untracked (unknown and ignored) files
4686 unless explicitly requested with -u/--unknown or -i/--ignored.
4687 unless explicitly requested with -u/--unknown or -i/--ignored.
4687
4688
4688 .. note::
4689 .. note::
4689
4690
4690 :hg:`status` may appear to disagree with diff if permissions have
4691 :hg:`status` may appear to disagree with diff if permissions have
4691 changed or a merge has occurred. The standard diff format does
4692 changed or a merge has occurred. The standard diff format does
4692 not report permission changes and diff only reports changes
4693 not report permission changes and diff only reports changes
4693 relative to one merge parent.
4694 relative to one merge parent.
4694
4695
4695 If one revision is given, it is used as the base revision.
4696 If one revision is given, it is used as the base revision.
4696 If two revisions are given, the differences between them are
4697 If two revisions are given, the differences between them are
4697 shown. The --change option can also be used as a shortcut to list
4698 shown. The --change option can also be used as a shortcut to list
4698 the changed files of a revision from its first parent.
4699 the changed files of a revision from its first parent.
4699
4700
4700 The codes used to show the status of files are::
4701 The codes used to show the status of files are::
4701
4702
4702 M = modified
4703 M = modified
4703 A = added
4704 A = added
4704 R = removed
4705 R = removed
4705 C = clean
4706 C = clean
4706 ! = missing (deleted by non-hg command, but still tracked)
4707 ! = missing (deleted by non-hg command, but still tracked)
4707 ? = not tracked
4708 ? = not tracked
4708 I = ignored
4709 I = ignored
4709 = origin of the previous file (with --copies)
4710 = origin of the previous file (with --copies)
4710
4711
4711 .. container:: verbose
4712 .. container:: verbose
4712
4713
4713 Examples:
4714 Examples:
4714
4715
4715 - show changes in the working directory relative to a
4716 - show changes in the working directory relative to a
4716 changeset::
4717 changeset::
4717
4718
4718 hg status --rev 9353
4719 hg status --rev 9353
4719
4720
4720 - show changes in the working directory relative to the
4721 - show changes in the working directory relative to the
4721 current directory (see :hg:`help patterns` for more information)::
4722 current directory (see :hg:`help patterns` for more information)::
4722
4723
4723 hg status re:
4724 hg status re:
4724
4725
4725 - show all changes including copies in an existing changeset::
4726 - show all changes including copies in an existing changeset::
4726
4727
4727 hg status --copies --change 9353
4728 hg status --copies --change 9353
4728
4729
4729 - get a NUL separated list of added files, suitable for xargs::
4730 - get a NUL separated list of added files, suitable for xargs::
4730
4731
4731 hg status -an0
4732 hg status -an0
4732
4733
4733 Returns 0 on success.
4734 Returns 0 on success.
4734 """
4735 """
4735
4736
4736 revs = opts.get('rev')
4737 revs = opts.get('rev')
4737 change = opts.get('change')
4738 change = opts.get('change')
4738
4739
4739 if revs and change:
4740 if revs and change:
4740 msg = _('cannot specify --rev and --change at the same time')
4741 msg = _('cannot specify --rev and --change at the same time')
4741 raise error.Abort(msg)
4742 raise error.Abort(msg)
4742 elif change:
4743 elif change:
4743 node2 = scmutil.revsingle(repo, change, None).node()
4744 node2 = scmutil.revsingle(repo, change, None).node()
4744 node1 = repo[node2].p1().node()
4745 node1 = repo[node2].p1().node()
4745 else:
4746 else:
4746 node1, node2 = scmutil.revpair(repo, revs)
4747 node1, node2 = scmutil.revpair(repo, revs)
4747
4748
4748 if pats:
4749 if pats:
4749 cwd = repo.getcwd()
4750 cwd = repo.getcwd()
4750 else:
4751 else:
4751 cwd = ''
4752 cwd = ''
4752
4753
4753 if opts.get('print0'):
4754 if opts.get('print0'):
4754 end = '\0'
4755 end = '\0'
4755 else:
4756 else:
4756 end = '\n'
4757 end = '\n'
4757 copy = {}
4758 copy = {}
4758 states = 'modified added removed deleted unknown ignored clean'.split()
4759 states = 'modified added removed deleted unknown ignored clean'.split()
4759 show = [k for k in states if opts.get(k)]
4760 show = [k for k in states if opts.get(k)]
4760 if opts.get('all'):
4761 if opts.get('all'):
4761 show += ui.quiet and (states[:4] + ['clean']) or states
4762 show += ui.quiet and (states[:4] + ['clean']) or states
4762 if not show:
4763 if not show:
4763 if ui.quiet:
4764 if ui.quiet:
4764 show = states[:4]
4765 show = states[:4]
4765 else:
4766 else:
4766 show = states[:5]
4767 show = states[:5]
4767
4768
4768 m = scmutil.match(repo[node2], pats, opts)
4769 m = scmutil.match(repo[node2], pats, opts)
4769 stat = repo.status(node1, node2, m,
4770 stat = repo.status(node1, node2, m,
4770 'ignored' in show, 'clean' in show, 'unknown' in show,
4771 'ignored' in show, 'clean' in show, 'unknown' in show,
4771 opts.get('subrepos'))
4772 opts.get('subrepos'))
4772 changestates = zip(states, 'MAR!?IC', stat)
4773 changestates = zip(states, 'MAR!?IC', stat)
4773
4774
4774 if (opts.get('all') or opts.get('copies')
4775 if (opts.get('all') or opts.get('copies')
4775 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
4776 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
4776 copy = copies.pathcopies(repo[node1], repo[node2], m)
4777 copy = copies.pathcopies(repo[node1], repo[node2], m)
4777
4778
4778 fm = ui.formatter('status', opts)
4779 fm = ui.formatter('status', opts)
4779 fmt = '%s' + end
4780 fmt = '%s' + end
4780 showchar = not opts.get('no_status')
4781 showchar = not opts.get('no_status')
4781
4782
4782 for state, char, files in changestates:
4783 for state, char, files in changestates:
4783 if state in show:
4784 if state in show:
4784 label = 'status.' + state
4785 label = 'status.' + state
4785 for f in files:
4786 for f in files:
4786 fm.startitem()
4787 fm.startitem()
4787 fm.condwrite(showchar, 'status', '%s ', char, label=label)
4788 fm.condwrite(showchar, 'status', '%s ', char, label=label)
4788 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
4789 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
4789 if f in copy:
4790 if f in copy:
4790 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
4791 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
4791 label='status.copied')
4792 label='status.copied')
4792 fm.end()
4793 fm.end()
4793
4794
4794 @command('^summary|sum',
4795 @command('^summary|sum',
4795 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
4796 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
4796 def summary(ui, repo, **opts):
4797 def summary(ui, repo, **opts):
4797 """summarize working directory state
4798 """summarize working directory state
4798
4799
4799 This generates a brief summary of the working directory state,
4800 This generates a brief summary of the working directory state,
4800 including parents, branch, commit status, phase and available updates.
4801 including parents, branch, commit status, phase and available updates.
4801
4802
4802 With the --remote option, this will check the default paths for
4803 With the --remote option, this will check the default paths for
4803 incoming and outgoing changes. This can be time-consuming.
4804 incoming and outgoing changes. This can be time-consuming.
4804
4805
4805 Returns 0 on success.
4806 Returns 0 on success.
4806 """
4807 """
4807
4808
4808 ctx = repo[None]
4809 ctx = repo[None]
4809 parents = ctx.parents()
4810 parents = ctx.parents()
4810 pnode = parents[0].node()
4811 pnode = parents[0].node()
4811 marks = []
4812 marks = []
4812
4813
4813 ms = None
4814 ms = None
4814 try:
4815 try:
4815 ms = mergemod.mergestate.read(repo)
4816 ms = mergemod.mergestate.read(repo)
4816 except error.UnsupportedMergeRecords as e:
4817 except error.UnsupportedMergeRecords as e:
4817 s = ' '.join(e.recordtypes)
4818 s = ' '.join(e.recordtypes)
4818 ui.warn(
4819 ui.warn(
4819 _('warning: merge state has unsupported record types: %s\n') % s)
4820 _('warning: merge state has unsupported record types: %s\n') % s)
4820 unresolved = 0
4821 unresolved = 0
4821 else:
4822 else:
4822 unresolved = [f for f in ms if ms[f] == 'u']
4823 unresolved = [f for f in ms if ms[f] == 'u']
4823
4824
4824 for p in parents:
4825 for p in parents:
4825 # label with log.changeset (instead of log.parent) since this
4826 # label with log.changeset (instead of log.parent) since this
4826 # shows a working directory parent *changeset*:
4827 # shows a working directory parent *changeset*:
4827 # i18n: column positioning for "hg summary"
4828 # i18n: column positioning for "hg summary"
4828 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
4829 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
4829 label=cmdutil._changesetlabels(p))
4830 label=cmdutil._changesetlabels(p))
4830 ui.write(' '.join(p.tags()), label='log.tag')
4831 ui.write(' '.join(p.tags()), label='log.tag')
4831 if p.bookmarks():
4832 if p.bookmarks():
4832 marks.extend(p.bookmarks())
4833 marks.extend(p.bookmarks())
4833 if p.rev() == -1:
4834 if p.rev() == -1:
4834 if not len(repo):
4835 if not len(repo):
4835 ui.write(_(' (empty repository)'))
4836 ui.write(_(' (empty repository)'))
4836 else:
4837 else:
4837 ui.write(_(' (no revision checked out)'))
4838 ui.write(_(' (no revision checked out)'))
4838 if p.troubled():
4839 if p.troubled():
4839 ui.write(' ('
4840 ui.write(' ('
4840 + ', '.join(ui.label(trouble, 'trouble.%s' % trouble)
4841 + ', '.join(ui.label(trouble, 'trouble.%s' % trouble)
4841 for trouble in p.troubles())
4842 for trouble in p.troubles())
4842 + ')')
4843 + ')')
4843 ui.write('\n')
4844 ui.write('\n')
4844 if p.description():
4845 if p.description():
4845 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
4846 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
4846 label='log.summary')
4847 label='log.summary')
4847
4848
4848 branch = ctx.branch()
4849 branch = ctx.branch()
4849 bheads = repo.branchheads(branch)
4850 bheads = repo.branchheads(branch)
4850 # i18n: column positioning for "hg summary"
4851 # i18n: column positioning for "hg summary"
4851 m = _('branch: %s\n') % branch
4852 m = _('branch: %s\n') % branch
4852 if branch != 'default':
4853 if branch != 'default':
4853 ui.write(m, label='log.branch')
4854 ui.write(m, label='log.branch')
4854 else:
4855 else:
4855 ui.status(m, label='log.branch')
4856 ui.status(m, label='log.branch')
4856
4857
4857 if marks:
4858 if marks:
4858 active = repo._activebookmark
4859 active = repo._activebookmark
4859 # i18n: column positioning for "hg summary"
4860 # i18n: column positioning for "hg summary"
4860 ui.write(_('bookmarks:'), label='log.bookmark')
4861 ui.write(_('bookmarks:'), label='log.bookmark')
4861 if active is not None:
4862 if active is not None:
4862 if active in marks:
4863 if active in marks:
4863 ui.write(' *' + active, label=activebookmarklabel)
4864 ui.write(' *' + active, label=activebookmarklabel)
4864 marks.remove(active)
4865 marks.remove(active)
4865 else:
4866 else:
4866 ui.write(' [%s]' % active, label=activebookmarklabel)
4867 ui.write(' [%s]' % active, label=activebookmarklabel)
4867 for m in marks:
4868 for m in marks:
4868 ui.write(' ' + m, label='log.bookmark')
4869 ui.write(' ' + m, label='log.bookmark')
4869 ui.write('\n', label='log.bookmark')
4870 ui.write('\n', label='log.bookmark')
4870
4871
4871 status = repo.status(unknown=True)
4872 status = repo.status(unknown=True)
4872
4873
4873 c = repo.dirstate.copies()
4874 c = repo.dirstate.copies()
4874 copied, renamed = [], []
4875 copied, renamed = [], []
4875 for d, s in c.iteritems():
4876 for d, s in c.iteritems():
4876 if s in status.removed:
4877 if s in status.removed:
4877 status.removed.remove(s)
4878 status.removed.remove(s)
4878 renamed.append(d)
4879 renamed.append(d)
4879 else:
4880 else:
4880 copied.append(d)
4881 copied.append(d)
4881 if d in status.added:
4882 if d in status.added:
4882 status.added.remove(d)
4883 status.added.remove(d)
4883
4884
4884 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
4885 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
4885
4886
4886 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
4887 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
4887 (ui.label(_('%d added'), 'status.added'), status.added),
4888 (ui.label(_('%d added'), 'status.added'), status.added),
4888 (ui.label(_('%d removed'), 'status.removed'), status.removed),
4889 (ui.label(_('%d removed'), 'status.removed'), status.removed),
4889 (ui.label(_('%d renamed'), 'status.copied'), renamed),
4890 (ui.label(_('%d renamed'), 'status.copied'), renamed),
4890 (ui.label(_('%d copied'), 'status.copied'), copied),
4891 (ui.label(_('%d copied'), 'status.copied'), copied),
4891 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
4892 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
4892 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
4893 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
4893 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
4894 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
4894 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
4895 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
4895 t = []
4896 t = []
4896 for l, s in labels:
4897 for l, s in labels:
4897 if s:
4898 if s:
4898 t.append(l % len(s))
4899 t.append(l % len(s))
4899
4900
4900 t = ', '.join(t)
4901 t = ', '.join(t)
4901 cleanworkdir = False
4902 cleanworkdir = False
4902
4903
4903 if repo.vfs.exists('graftstate'):
4904 if repo.vfs.exists('graftstate'):
4904 t += _(' (graft in progress)')
4905 t += _(' (graft in progress)')
4905 if repo.vfs.exists('updatestate'):
4906 if repo.vfs.exists('updatestate'):
4906 t += _(' (interrupted update)')
4907 t += _(' (interrupted update)')
4907 elif len(parents) > 1:
4908 elif len(parents) > 1:
4908 t += _(' (merge)')
4909 t += _(' (merge)')
4909 elif branch != parents[0].branch():
4910 elif branch != parents[0].branch():
4910 t += _(' (new branch)')
4911 t += _(' (new branch)')
4911 elif (parents[0].closesbranch() and
4912 elif (parents[0].closesbranch() and
4912 pnode in repo.branchheads(branch, closed=True)):
4913 pnode in repo.branchheads(branch, closed=True)):
4913 t += _(' (head closed)')
4914 t += _(' (head closed)')
4914 elif not (status.modified or status.added or status.removed or renamed or
4915 elif not (status.modified or status.added or status.removed or renamed or
4915 copied or subs):
4916 copied or subs):
4916 t += _(' (clean)')
4917 t += _(' (clean)')
4917 cleanworkdir = True
4918 cleanworkdir = True
4918 elif pnode not in bheads:
4919 elif pnode not in bheads:
4919 t += _(' (new branch head)')
4920 t += _(' (new branch head)')
4920
4921
4921 if parents:
4922 if parents:
4922 pendingphase = max(p.phase() for p in parents)
4923 pendingphase = max(p.phase() for p in parents)
4923 else:
4924 else:
4924 pendingphase = phases.public
4925 pendingphase = phases.public
4925
4926
4926 if pendingphase > phases.newcommitphase(ui):
4927 if pendingphase > phases.newcommitphase(ui):
4927 t += ' (%s)' % phases.phasenames[pendingphase]
4928 t += ' (%s)' % phases.phasenames[pendingphase]
4928
4929
4929 if cleanworkdir:
4930 if cleanworkdir:
4930 # i18n: column positioning for "hg summary"
4931 # i18n: column positioning for "hg summary"
4931 ui.status(_('commit: %s\n') % t.strip())
4932 ui.status(_('commit: %s\n') % t.strip())
4932 else:
4933 else:
4933 # i18n: column positioning for "hg summary"
4934 # i18n: column positioning for "hg summary"
4934 ui.write(_('commit: %s\n') % t.strip())
4935 ui.write(_('commit: %s\n') % t.strip())
4935
4936
4936 # all ancestors of branch heads - all ancestors of parent = new csets
4937 # all ancestors of branch heads - all ancestors of parent = new csets
4937 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
4938 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
4938 bheads))
4939 bheads))
4939
4940
4940 if new == 0:
4941 if new == 0:
4941 # i18n: column positioning for "hg summary"
4942 # i18n: column positioning for "hg summary"
4942 ui.status(_('update: (current)\n'))
4943 ui.status(_('update: (current)\n'))
4943 elif pnode not in bheads:
4944 elif pnode not in bheads:
4944 # i18n: column positioning for "hg summary"
4945 # i18n: column positioning for "hg summary"
4945 ui.write(_('update: %d new changesets (update)\n') % new)
4946 ui.write(_('update: %d new changesets (update)\n') % new)
4946 else:
4947 else:
4947 # i18n: column positioning for "hg summary"
4948 # i18n: column positioning for "hg summary"
4948 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
4949 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
4949 (new, len(bheads)))
4950 (new, len(bheads)))
4950
4951
4951 t = []
4952 t = []
4952 draft = len(repo.revs('draft()'))
4953 draft = len(repo.revs('draft()'))
4953 if draft:
4954 if draft:
4954 t.append(_('%d draft') % draft)
4955 t.append(_('%d draft') % draft)
4955 secret = len(repo.revs('secret()'))
4956 secret = len(repo.revs('secret()'))
4956 if secret:
4957 if secret:
4957 t.append(_('%d secret') % secret)
4958 t.append(_('%d secret') % secret)
4958
4959
4959 if draft or secret:
4960 if draft or secret:
4960 ui.status(_('phases: %s\n') % ', '.join(t))
4961 ui.status(_('phases: %s\n') % ', '.join(t))
4961
4962
4962 if obsolete.isenabled(repo, obsolete.createmarkersopt):
4963 if obsolete.isenabled(repo, obsolete.createmarkersopt):
4963 for trouble in ("unstable", "divergent", "bumped"):
4964 for trouble in ("unstable", "divergent", "bumped"):
4964 numtrouble = len(repo.revs(trouble + "()"))
4965 numtrouble = len(repo.revs(trouble + "()"))
4965 # We write all the possibilities to ease translation
4966 # We write all the possibilities to ease translation
4966 troublemsg = {
4967 troublemsg = {
4967 "unstable": _("unstable: %d changesets"),
4968 "unstable": _("unstable: %d changesets"),
4968 "divergent": _("divergent: %d changesets"),
4969 "divergent": _("divergent: %d changesets"),
4969 "bumped": _("bumped: %d changesets"),
4970 "bumped": _("bumped: %d changesets"),
4970 }
4971 }
4971 if numtrouble > 0:
4972 if numtrouble > 0:
4972 ui.status(troublemsg[trouble] % numtrouble + "\n")
4973 ui.status(troublemsg[trouble] % numtrouble + "\n")
4973
4974
4974 cmdutil.summaryhooks(ui, repo)
4975 cmdutil.summaryhooks(ui, repo)
4975
4976
4976 if opts.get('remote'):
4977 if opts.get('remote'):
4977 needsincoming, needsoutgoing = True, True
4978 needsincoming, needsoutgoing = True, True
4978 else:
4979 else:
4979 needsincoming, needsoutgoing = False, False
4980 needsincoming, needsoutgoing = False, False
4980 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
4981 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
4981 if i:
4982 if i:
4982 needsincoming = True
4983 needsincoming = True
4983 if o:
4984 if o:
4984 needsoutgoing = True
4985 needsoutgoing = True
4985 if not needsincoming and not needsoutgoing:
4986 if not needsincoming and not needsoutgoing:
4986 return
4987 return
4987
4988
4988 def getincoming():
4989 def getincoming():
4989 source, branches = hg.parseurl(ui.expandpath('default'))
4990 source, branches = hg.parseurl(ui.expandpath('default'))
4990 sbranch = branches[0]
4991 sbranch = branches[0]
4991 try:
4992 try:
4992 other = hg.peer(repo, {}, source)
4993 other = hg.peer(repo, {}, source)
4993 except error.RepoError:
4994 except error.RepoError:
4994 if opts.get('remote'):
4995 if opts.get('remote'):
4995 raise
4996 raise
4996 return source, sbranch, None, None, None
4997 return source, sbranch, None, None, None
4997 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
4998 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
4998 if revs:
4999 if revs:
4999 revs = [other.lookup(rev) for rev in revs]
5000 revs = [other.lookup(rev) for rev in revs]
5000 ui.debug('comparing with %s\n' % util.hidepassword(source))
5001 ui.debug('comparing with %s\n' % util.hidepassword(source))
5001 repo.ui.pushbuffer()
5002 repo.ui.pushbuffer()
5002 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5003 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5003 repo.ui.popbuffer()
5004 repo.ui.popbuffer()
5004 return source, sbranch, other, commoninc, commoninc[1]
5005 return source, sbranch, other, commoninc, commoninc[1]
5005
5006
5006 if needsincoming:
5007 if needsincoming:
5007 source, sbranch, sother, commoninc, incoming = getincoming()
5008 source, sbranch, sother, commoninc, incoming = getincoming()
5008 else:
5009 else:
5009 source = sbranch = sother = commoninc = incoming = None
5010 source = sbranch = sother = commoninc = incoming = None
5010
5011
5011 def getoutgoing():
5012 def getoutgoing():
5012 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5013 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5013 dbranch = branches[0]
5014 dbranch = branches[0]
5014 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5015 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5015 if source != dest:
5016 if source != dest:
5016 try:
5017 try:
5017 dother = hg.peer(repo, {}, dest)
5018 dother = hg.peer(repo, {}, dest)
5018 except error.RepoError:
5019 except error.RepoError:
5019 if opts.get('remote'):
5020 if opts.get('remote'):
5020 raise
5021 raise
5021 return dest, dbranch, None, None
5022 return dest, dbranch, None, None
5022 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5023 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5023 elif sother is None:
5024 elif sother is None:
5024 # there is no explicit destination peer, but source one is invalid
5025 # there is no explicit destination peer, but source one is invalid
5025 return dest, dbranch, None, None
5026 return dest, dbranch, None, None
5026 else:
5027 else:
5027 dother = sother
5028 dother = sother
5028 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5029 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5029 common = None
5030 common = None
5030 else:
5031 else:
5031 common = commoninc
5032 common = commoninc
5032 if revs:
5033 if revs:
5033 revs = [repo.lookup(rev) for rev in revs]
5034 revs = [repo.lookup(rev) for rev in revs]
5034 repo.ui.pushbuffer()
5035 repo.ui.pushbuffer()
5035 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5036 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5036 commoninc=common)
5037 commoninc=common)
5037 repo.ui.popbuffer()
5038 repo.ui.popbuffer()
5038 return dest, dbranch, dother, outgoing
5039 return dest, dbranch, dother, outgoing
5039
5040
5040 if needsoutgoing:
5041 if needsoutgoing:
5041 dest, dbranch, dother, outgoing = getoutgoing()
5042 dest, dbranch, dother, outgoing = getoutgoing()
5042 else:
5043 else:
5043 dest = dbranch = dother = outgoing = None
5044 dest = dbranch = dother = outgoing = None
5044
5045
5045 if opts.get('remote'):
5046 if opts.get('remote'):
5046 t = []
5047 t = []
5047 if incoming:
5048 if incoming:
5048 t.append(_('1 or more incoming'))
5049 t.append(_('1 or more incoming'))
5049 o = outgoing.missing
5050 o = outgoing.missing
5050 if o:
5051 if o:
5051 t.append(_('%d outgoing') % len(o))
5052 t.append(_('%d outgoing') % len(o))
5052 other = dother or sother
5053 other = dother or sother
5053 if 'bookmarks' in other.listkeys('namespaces'):
5054 if 'bookmarks' in other.listkeys('namespaces'):
5054 counts = bookmarks.summary(repo, other)
5055 counts = bookmarks.summary(repo, other)
5055 if counts[0] > 0:
5056 if counts[0] > 0:
5056 t.append(_('%d incoming bookmarks') % counts[0])
5057 t.append(_('%d incoming bookmarks') % counts[0])
5057 if counts[1] > 0:
5058 if counts[1] > 0:
5058 t.append(_('%d outgoing bookmarks') % counts[1])
5059 t.append(_('%d outgoing bookmarks') % counts[1])
5059
5060
5060 if t:
5061 if t:
5061 # i18n: column positioning for "hg summary"
5062 # i18n: column positioning for "hg summary"
5062 ui.write(_('remote: %s\n') % (', '.join(t)))
5063 ui.write(_('remote: %s\n') % (', '.join(t)))
5063 else:
5064 else:
5064 # i18n: column positioning for "hg summary"
5065 # i18n: column positioning for "hg summary"
5065 ui.status(_('remote: (synced)\n'))
5066 ui.status(_('remote: (synced)\n'))
5066
5067
5067 cmdutil.summaryremotehooks(ui, repo, opts,
5068 cmdutil.summaryremotehooks(ui, repo, opts,
5068 ((source, sbranch, sother, commoninc),
5069 ((source, sbranch, sother, commoninc),
5069 (dest, dbranch, dother, outgoing)))
5070 (dest, dbranch, dother, outgoing)))
5070
5071
5071 @command('tag',
5072 @command('tag',
5072 [('f', 'force', None, _('force tag')),
5073 [('f', 'force', None, _('force tag')),
5073 ('l', 'local', None, _('make the tag local')),
5074 ('l', 'local', None, _('make the tag local')),
5074 ('r', 'rev', '', _('revision to tag'), _('REV')),
5075 ('r', 'rev', '', _('revision to tag'), _('REV')),
5075 ('', 'remove', None, _('remove a tag')),
5076 ('', 'remove', None, _('remove a tag')),
5076 # -l/--local is already there, commitopts cannot be used
5077 # -l/--local is already there, commitopts cannot be used
5077 ('e', 'edit', None, _('invoke editor on commit messages')),
5078 ('e', 'edit', None, _('invoke editor on commit messages')),
5078 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5079 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5079 ] + commitopts2,
5080 ] + commitopts2,
5080 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5081 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5081 def tag(ui, repo, name1, *names, **opts):
5082 def tag(ui, repo, name1, *names, **opts):
5082 """add one or more tags for the current or given revision
5083 """add one or more tags for the current or given revision
5083
5084
5084 Name a particular revision using <name>.
5085 Name a particular revision using <name>.
5085
5086
5086 Tags are used to name particular revisions of the repository and are
5087 Tags are used to name particular revisions of the repository and are
5087 very useful to compare different revisions, to go back to significant
5088 very useful to compare different revisions, to go back to significant
5088 earlier versions or to mark branch points as releases, etc. Changing
5089 earlier versions or to mark branch points as releases, etc. Changing
5089 an existing tag is normally disallowed; use -f/--force to override.
5090 an existing tag is normally disallowed; use -f/--force to override.
5090
5091
5091 If no revision is given, the parent of the working directory is
5092 If no revision is given, the parent of the working directory is
5092 used.
5093 used.
5093
5094
5094 To facilitate version control, distribution, and merging of tags,
5095 To facilitate version control, distribution, and merging of tags,
5095 they are stored as a file named ".hgtags" which is managed similarly
5096 they are stored as a file named ".hgtags" which is managed similarly
5096 to other project files and can be hand-edited if necessary. This
5097 to other project files and can be hand-edited if necessary. This
5097 also means that tagging creates a new commit. The file
5098 also means that tagging creates a new commit. The file
5098 ".hg/localtags" is used for local tags (not shared among
5099 ".hg/localtags" is used for local tags (not shared among
5099 repositories).
5100 repositories).
5100
5101
5101 Tag commits are usually made at the head of a branch. If the parent
5102 Tag commits are usually made at the head of a branch. If the parent
5102 of the working directory is not a branch head, :hg:`tag` aborts; use
5103 of the working directory is not a branch head, :hg:`tag` aborts; use
5103 -f/--force to force the tag commit to be based on a non-head
5104 -f/--force to force the tag commit to be based on a non-head
5104 changeset.
5105 changeset.
5105
5106
5106 See :hg:`help dates` for a list of formats valid for -d/--date.
5107 See :hg:`help dates` for a list of formats valid for -d/--date.
5107
5108
5108 Since tag names have priority over branch names during revision
5109 Since tag names have priority over branch names during revision
5109 lookup, using an existing branch name as a tag name is discouraged.
5110 lookup, using an existing branch name as a tag name is discouraged.
5110
5111
5111 Returns 0 on success.
5112 Returns 0 on success.
5112 """
5113 """
5113 wlock = lock = None
5114 wlock = lock = None
5114 try:
5115 try:
5115 wlock = repo.wlock()
5116 wlock = repo.wlock()
5116 lock = repo.lock()
5117 lock = repo.lock()
5117 rev_ = "."
5118 rev_ = "."
5118 names = [t.strip() for t in (name1,) + names]
5119 names = [t.strip() for t in (name1,) + names]
5119 if len(names) != len(set(names)):
5120 if len(names) != len(set(names)):
5120 raise error.Abort(_('tag names must be unique'))
5121 raise error.Abort(_('tag names must be unique'))
5121 for n in names:
5122 for n in names:
5122 scmutil.checknewlabel(repo, n, 'tag')
5123 scmutil.checknewlabel(repo, n, 'tag')
5123 if not n:
5124 if not n:
5124 raise error.Abort(_('tag names cannot consist entirely of '
5125 raise error.Abort(_('tag names cannot consist entirely of '
5125 'whitespace'))
5126 'whitespace'))
5126 if opts.get('rev') and opts.get('remove'):
5127 if opts.get('rev') and opts.get('remove'):
5127 raise error.Abort(_("--rev and --remove are incompatible"))
5128 raise error.Abort(_("--rev and --remove are incompatible"))
5128 if opts.get('rev'):
5129 if opts.get('rev'):
5129 rev_ = opts['rev']
5130 rev_ = opts['rev']
5130 message = opts.get('message')
5131 message = opts.get('message')
5131 if opts.get('remove'):
5132 if opts.get('remove'):
5132 if opts.get('local'):
5133 if opts.get('local'):
5133 expectedtype = 'local'
5134 expectedtype = 'local'
5134 else:
5135 else:
5135 expectedtype = 'global'
5136 expectedtype = 'global'
5136
5137
5137 for n in names:
5138 for n in names:
5138 if not repo.tagtype(n):
5139 if not repo.tagtype(n):
5139 raise error.Abort(_("tag '%s' does not exist") % n)
5140 raise error.Abort(_("tag '%s' does not exist") % n)
5140 if repo.tagtype(n) != expectedtype:
5141 if repo.tagtype(n) != expectedtype:
5141 if expectedtype == 'global':
5142 if expectedtype == 'global':
5142 raise error.Abort(_("tag '%s' is not a global tag") % n)
5143 raise error.Abort(_("tag '%s' is not a global tag") % n)
5143 else:
5144 else:
5144 raise error.Abort(_("tag '%s' is not a local tag") % n)
5145 raise error.Abort(_("tag '%s' is not a local tag") % n)
5145 rev_ = 'null'
5146 rev_ = 'null'
5146 if not message:
5147 if not message:
5147 # we don't translate commit messages
5148 # we don't translate commit messages
5148 message = 'Removed tag %s' % ', '.join(names)
5149 message = 'Removed tag %s' % ', '.join(names)
5149 elif not opts.get('force'):
5150 elif not opts.get('force'):
5150 for n in names:
5151 for n in names:
5151 if n in repo.tags():
5152 if n in repo.tags():
5152 raise error.Abort(_("tag '%s' already exists "
5153 raise error.Abort(_("tag '%s' already exists "
5153 "(use -f to force)") % n)
5154 "(use -f to force)") % n)
5154 if not opts.get('local'):
5155 if not opts.get('local'):
5155 p1, p2 = repo.dirstate.parents()
5156 p1, p2 = repo.dirstate.parents()
5156 if p2 != nullid:
5157 if p2 != nullid:
5157 raise error.Abort(_('uncommitted merge'))
5158 raise error.Abort(_('uncommitted merge'))
5158 bheads = repo.branchheads()
5159 bheads = repo.branchheads()
5159 if not opts.get('force') and bheads and p1 not in bheads:
5160 if not opts.get('force') and bheads and p1 not in bheads:
5160 raise error.Abort(_('working directory is not at a branch head '
5161 raise error.Abort(_('working directory is not at a branch head '
5161 '(use -f to force)'))
5162 '(use -f to force)'))
5162 r = scmutil.revsingle(repo, rev_).node()
5163 r = scmutil.revsingle(repo, rev_).node()
5163
5164
5164 if not message:
5165 if not message:
5165 # we don't translate commit messages
5166 # we don't translate commit messages
5166 message = ('Added tag %s for changeset %s' %
5167 message = ('Added tag %s for changeset %s' %
5167 (', '.join(names), short(r)))
5168 (', '.join(names), short(r)))
5168
5169
5169 date = opts.get('date')
5170 date = opts.get('date')
5170 if date:
5171 if date:
5171 date = util.parsedate(date)
5172 date = util.parsedate(date)
5172
5173
5173 if opts.get('remove'):
5174 if opts.get('remove'):
5174 editform = 'tag.remove'
5175 editform = 'tag.remove'
5175 else:
5176 else:
5176 editform = 'tag.add'
5177 editform = 'tag.add'
5177 editor = cmdutil.getcommiteditor(editform=editform, **opts)
5178 editor = cmdutil.getcommiteditor(editform=editform, **opts)
5178
5179
5179 # don't allow tagging the null rev
5180 # don't allow tagging the null rev
5180 if (not opts.get('remove') and
5181 if (not opts.get('remove') and
5181 scmutil.revsingle(repo, rev_).rev() == nullrev):
5182 scmutil.revsingle(repo, rev_).rev() == nullrev):
5182 raise error.Abort(_("cannot tag null revision"))
5183 raise error.Abort(_("cannot tag null revision"))
5183
5184
5184 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
5185 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
5185 editor=editor)
5186 editor=editor)
5186 finally:
5187 finally:
5187 release(lock, wlock)
5188 release(lock, wlock)
5188
5189
5189 @command('tags', formatteropts, '')
5190 @command('tags', formatteropts, '')
5190 def tags(ui, repo, **opts):
5191 def tags(ui, repo, **opts):
5191 """list repository tags
5192 """list repository tags
5192
5193
5193 This lists both regular and local tags. When the -v/--verbose
5194 This lists both regular and local tags. When the -v/--verbose
5194 switch is used, a third column "local" is printed for local tags.
5195 switch is used, a third column "local" is printed for local tags.
5195 When the -q/--quiet switch is used, only the tag name is printed.
5196 When the -q/--quiet switch is used, only the tag name is printed.
5196
5197
5197 Returns 0 on success.
5198 Returns 0 on success.
5198 """
5199 """
5199
5200
5200 fm = ui.formatter('tags', opts)
5201 fm = ui.formatter('tags', opts)
5201 hexfunc = fm.hexfunc
5202 hexfunc = fm.hexfunc
5202 tagtype = ""
5203 tagtype = ""
5203
5204
5204 for t, n in reversed(repo.tagslist()):
5205 for t, n in reversed(repo.tagslist()):
5205 hn = hexfunc(n)
5206 hn = hexfunc(n)
5206 label = 'tags.normal'
5207 label = 'tags.normal'
5207 tagtype = ''
5208 tagtype = ''
5208 if repo.tagtype(t) == 'local':
5209 if repo.tagtype(t) == 'local':
5209 label = 'tags.local'
5210 label = 'tags.local'
5210 tagtype = 'local'
5211 tagtype = 'local'
5211
5212
5212 fm.startitem()
5213 fm.startitem()
5213 fm.write('tag', '%s', t, label=label)
5214 fm.write('tag', '%s', t, label=label)
5214 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5215 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5215 fm.condwrite(not ui.quiet, 'rev node', fmt,
5216 fm.condwrite(not ui.quiet, 'rev node', fmt,
5216 repo.changelog.rev(n), hn, label=label)
5217 repo.changelog.rev(n), hn, label=label)
5217 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5218 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5218 tagtype, label=label)
5219 tagtype, label=label)
5219 fm.plain('\n')
5220 fm.plain('\n')
5220 fm.end()
5221 fm.end()
5221
5222
5222 @command('tip',
5223 @command('tip',
5223 [('p', 'patch', None, _('show patch')),
5224 [('p', 'patch', None, _('show patch')),
5224 ('g', 'git', None, _('use git extended diff format')),
5225 ('g', 'git', None, _('use git extended diff format')),
5225 ] + templateopts,
5226 ] + templateopts,
5226 _('[-p] [-g]'))
5227 _('[-p] [-g]'))
5227 def tip(ui, repo, **opts):
5228 def tip(ui, repo, **opts):
5228 """show the tip revision (DEPRECATED)
5229 """show the tip revision (DEPRECATED)
5229
5230
5230 The tip revision (usually just called the tip) is the changeset
5231 The tip revision (usually just called the tip) is the changeset
5231 most recently added to the repository (and therefore the most
5232 most recently added to the repository (and therefore the most
5232 recently changed head).
5233 recently changed head).
5233
5234
5234 If you have just made a commit, that commit will be the tip. If
5235 If you have just made a commit, that commit will be the tip. If
5235 you have just pulled changes from another repository, the tip of
5236 you have just pulled changes from another repository, the tip of
5236 that repository becomes the current tip. The "tip" tag is special
5237 that repository becomes the current tip. The "tip" tag is special
5237 and cannot be renamed or assigned to a different changeset.
5238 and cannot be renamed or assigned to a different changeset.
5238
5239
5239 This command is deprecated, please use :hg:`heads` instead.
5240 This command is deprecated, please use :hg:`heads` instead.
5240
5241
5241 Returns 0 on success.
5242 Returns 0 on success.
5242 """
5243 """
5243 displayer = cmdutil.show_changeset(ui, repo, opts)
5244 displayer = cmdutil.show_changeset(ui, repo, opts)
5244 displayer.show(repo['tip'])
5245 displayer.show(repo['tip'])
5245 displayer.close()
5246 displayer.close()
5246
5247
5247 @command('unbundle',
5248 @command('unbundle',
5248 [('u', 'update', None,
5249 [('u', 'update', None,
5249 _('update to new branch head if changesets were unbundled'))],
5250 _('update to new branch head if changesets were unbundled'))],
5250 _('[-u] FILE...'))
5251 _('[-u] FILE...'))
5251 def unbundle(ui, repo, fname1, *fnames, **opts):
5252 def unbundle(ui, repo, fname1, *fnames, **opts):
5252 """apply one or more changegroup files
5253 """apply one or more changegroup files
5253
5254
5254 Apply one or more compressed changegroup files generated by the
5255 Apply one or more compressed changegroup files generated by the
5255 bundle command.
5256 bundle command.
5256
5257
5257 Returns 0 on success, 1 if an update has unresolved files.
5258 Returns 0 on success, 1 if an update has unresolved files.
5258 """
5259 """
5259 fnames = (fname1,) + fnames
5260 fnames = (fname1,) + fnames
5260
5261
5261 with repo.lock():
5262 with repo.lock():
5262 for fname in fnames:
5263 for fname in fnames:
5263 f = hg.openpath(ui, fname)
5264 f = hg.openpath(ui, fname)
5264 gen = exchange.readbundle(ui, f, fname)
5265 gen = exchange.readbundle(ui, f, fname)
5265 if isinstance(gen, bundle2.unbundle20):
5266 if isinstance(gen, bundle2.unbundle20):
5266 tr = repo.transaction('unbundle')
5267 tr = repo.transaction('unbundle')
5267 try:
5268 try:
5268 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
5269 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
5269 url='bundle:' + fname)
5270 url='bundle:' + fname)
5270 tr.close()
5271 tr.close()
5271 except error.BundleUnknownFeatureError as exc:
5272 except error.BundleUnknownFeatureError as exc:
5272 raise error.Abort(_('%s: unknown bundle feature, %s')
5273 raise error.Abort(_('%s: unknown bundle feature, %s')
5273 % (fname, exc),
5274 % (fname, exc),
5274 hint=_("see https://mercurial-scm.org/"
5275 hint=_("see https://mercurial-scm.org/"
5275 "wiki/BundleFeature for more "
5276 "wiki/BundleFeature for more "
5276 "information"))
5277 "information"))
5277 finally:
5278 finally:
5278 if tr:
5279 if tr:
5279 tr.release()
5280 tr.release()
5280 changes = [r.get('return', 0)
5281 changes = [r.get('return', 0)
5281 for r in op.records['changegroup']]
5282 for r in op.records['changegroup']]
5282 modheads = changegroup.combineresults(changes)
5283 modheads = changegroup.combineresults(changes)
5283 elif isinstance(gen, streamclone.streamcloneapplier):
5284 elif isinstance(gen, streamclone.streamcloneapplier):
5284 raise error.Abort(
5285 raise error.Abort(
5285 _('packed bundles cannot be applied with '
5286 _('packed bundles cannot be applied with '
5286 '"hg unbundle"'),
5287 '"hg unbundle"'),
5287 hint=_('use "hg debugapplystreamclonebundle"'))
5288 hint=_('use "hg debugapplystreamclonebundle"'))
5288 else:
5289 else:
5289 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
5290 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
5290
5291
5291 return postincoming(ui, repo, modheads, opts.get('update'), None, None)
5292 return postincoming(ui, repo, modheads, opts.get('update'), None, None)
5292
5293
5293 @command('^update|up|checkout|co',
5294 @command('^update|up|checkout|co',
5294 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5295 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5295 ('c', 'check', None, _('require clean working directory')),
5296 ('c', 'check', None, _('require clean working directory')),
5296 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5297 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5297 ('r', 'rev', '', _('revision'), _('REV'))
5298 ('r', 'rev', '', _('revision'), _('REV'))
5298 ] + mergetoolopts,
5299 ] + mergetoolopts,
5299 _('[-C|-c] [-d DATE] [[-r] REV]'))
5300 _('[-C|-c] [-d DATE] [[-r] REV]'))
5300 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
5301 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
5301 tool=None):
5302 tool=None):
5302 """update working directory (or switch revisions)
5303 """update working directory (or switch revisions)
5303
5304
5304 Update the repository's working directory to the specified
5305 Update the repository's working directory to the specified
5305 changeset. If no changeset is specified, update to the tip of the
5306 changeset. If no changeset is specified, update to the tip of the
5306 current named branch and move the active bookmark (see :hg:`help
5307 current named branch and move the active bookmark (see :hg:`help
5307 bookmarks`).
5308 bookmarks`).
5308
5309
5309 Update sets the working directory's parent revision to the specified
5310 Update sets the working directory's parent revision to the specified
5310 changeset (see :hg:`help parents`).
5311 changeset (see :hg:`help parents`).
5311
5312
5312 If the changeset is not a descendant or ancestor of the working
5313 If the changeset is not a descendant or ancestor of the working
5313 directory's parent and there are uncommitted changes, the update is
5314 directory's parent and there are uncommitted changes, the update is
5314 aborted. With the -c/--check option, the working directory is checked
5315 aborted. With the -c/--check option, the working directory is checked
5315 for uncommitted changes; if none are found, the working directory is
5316 for uncommitted changes; if none are found, the working directory is
5316 updated to the specified changeset.
5317 updated to the specified changeset.
5317
5318
5318 .. container:: verbose
5319 .. container:: verbose
5319
5320
5320 The -C/--clean and -c/--check options control what happens if the
5321 The -C/--clean and -c/--check options control what happens if the
5321 working directory contains uncommitted changes.
5322 working directory contains uncommitted changes.
5322 At most of one of them can be specified.
5323 At most of one of them can be specified.
5323
5324
5324 1. If no option is specified, and if
5325 1. If no option is specified, and if
5325 the requested changeset is an ancestor or descendant of
5326 the requested changeset is an ancestor or descendant of
5326 the working directory's parent, the uncommitted changes
5327 the working directory's parent, the uncommitted changes
5327 are merged into the requested changeset and the merged
5328 are merged into the requested changeset and the merged
5328 result is left uncommitted. If the requested changeset is
5329 result is left uncommitted. If the requested changeset is
5329 not an ancestor or descendant (that is, it is on another
5330 not an ancestor or descendant (that is, it is on another
5330 branch), the update is aborted and the uncommitted changes
5331 branch), the update is aborted and the uncommitted changes
5331 are preserved.
5332 are preserved.
5332
5333
5333 2. With the -c/--check option, the update is aborted and the
5334 2. With the -c/--check option, the update is aborted and the
5334 uncommitted changes are preserved.
5335 uncommitted changes are preserved.
5335
5336
5336 3. With the -C/--clean option, uncommitted changes are discarded and
5337 3. With the -C/--clean option, uncommitted changes are discarded and
5337 the working directory is updated to the requested changeset.
5338 the working directory is updated to the requested changeset.
5338
5339
5339 To cancel an uncommitted merge (and lose your changes), use
5340 To cancel an uncommitted merge (and lose your changes), use
5340 :hg:`update --clean .`.
5341 :hg:`update --clean .`.
5341
5342
5342 Use null as the changeset to remove the working directory (like
5343 Use null as the changeset to remove the working directory (like
5343 :hg:`clone -U`).
5344 :hg:`clone -U`).
5344
5345
5345 If you want to revert just one file to an older revision, use
5346 If you want to revert just one file to an older revision, use
5346 :hg:`revert [-r REV] NAME`.
5347 :hg:`revert [-r REV] NAME`.
5347
5348
5348 See :hg:`help dates` for a list of formats valid for -d/--date.
5349 See :hg:`help dates` for a list of formats valid for -d/--date.
5349
5350
5350 Returns 0 on success, 1 if there are unresolved files.
5351 Returns 0 on success, 1 if there are unresolved files.
5351 """
5352 """
5352 if rev and node:
5353 if rev and node:
5353 raise error.Abort(_("please specify just one revision"))
5354 raise error.Abort(_("please specify just one revision"))
5354
5355
5355 if rev is None or rev == '':
5356 if rev is None or rev == '':
5356 rev = node
5357 rev = node
5357
5358
5358 if date and rev is not None:
5359 if date and rev is not None:
5359 raise error.Abort(_("you can't specify a revision and a date"))
5360 raise error.Abort(_("you can't specify a revision and a date"))
5360
5361
5361 if check and clean:
5362 if check and clean:
5362 raise error.Abort(_("cannot specify both -c/--check and -C/--clean"))
5363 raise error.Abort(_("cannot specify both -c/--check and -C/--clean"))
5363
5364
5364 with repo.wlock():
5365 with repo.wlock():
5365 cmdutil.clearunfinished(repo)
5366 cmdutil.clearunfinished(repo)
5366
5367
5367 if date:
5368 if date:
5368 rev = cmdutil.finddate(ui, repo, date)
5369 rev = cmdutil.finddate(ui, repo, date)
5369
5370
5370 # if we defined a bookmark, we have to remember the original name
5371 # if we defined a bookmark, we have to remember the original name
5371 brev = rev
5372 brev = rev
5372 rev = scmutil.revsingle(repo, rev, rev).rev()
5373 rev = scmutil.revsingle(repo, rev, rev).rev()
5373
5374
5374 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
5375 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
5375
5376
5376 return hg.updatetotally(ui, repo, rev, brev, clean=clean, check=check)
5377 return hg.updatetotally(ui, repo, rev, brev, clean=clean, check=check)
5377
5378
5378 @command('verify', [])
5379 @command('verify', [])
5379 def verify(ui, repo):
5380 def verify(ui, repo):
5380 """verify the integrity of the repository
5381 """verify the integrity of the repository
5381
5382
5382 Verify the integrity of the current repository.
5383 Verify the integrity of the current repository.
5383
5384
5384 This will perform an extensive check of the repository's
5385 This will perform an extensive check of the repository's
5385 integrity, validating the hashes and checksums of each entry in
5386 integrity, validating the hashes and checksums of each entry in
5386 the changelog, manifest, and tracked files, as well as the
5387 the changelog, manifest, and tracked files, as well as the
5387 integrity of their crosslinks and indices.
5388 integrity of their crosslinks and indices.
5388
5389
5389 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
5390 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
5390 for more information about recovery from corruption of the
5391 for more information about recovery from corruption of the
5391 repository.
5392 repository.
5392
5393
5393 Returns 0 on success, 1 if errors are encountered.
5394 Returns 0 on success, 1 if errors are encountered.
5394 """
5395 """
5395 return hg.verify(repo)
5396 return hg.verify(repo)
5396
5397
5397 @command('version', [] + formatteropts, norepo=True)
5398 @command('version', [] + formatteropts, norepo=True)
5398 def version_(ui, **opts):
5399 def version_(ui, **opts):
5399 """output version and copyright information"""
5400 """output version and copyright information"""
5400 fm = ui.formatter("version", opts)
5401 fm = ui.formatter("version", opts)
5401 fm.startitem()
5402 fm.startitem()
5402 fm.write("ver", _("Mercurial Distributed SCM (version %s)\n"),
5403 fm.write("ver", _("Mercurial Distributed SCM (version %s)\n"),
5403 util.version())
5404 util.version())
5404 license = _(
5405 license = _(
5405 "(see https://mercurial-scm.org for more information)\n"
5406 "(see https://mercurial-scm.org for more information)\n"
5406 "\nCopyright (C) 2005-2017 Matt Mackall and others\n"
5407 "\nCopyright (C) 2005-2017 Matt Mackall and others\n"
5407 "This is free software; see the source for copying conditions. "
5408 "This is free software; see the source for copying conditions. "
5408 "There is NO\nwarranty; "
5409 "There is NO\nwarranty; "
5409 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5410 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5410 )
5411 )
5411 if not ui.quiet:
5412 if not ui.quiet:
5412 fm.plain(license)
5413 fm.plain(license)
5413
5414
5414 if ui.verbose:
5415 if ui.verbose:
5415 fm.plain(_("\nEnabled extensions:\n\n"))
5416 fm.plain(_("\nEnabled extensions:\n\n"))
5416 # format names and versions into columns
5417 # format names and versions into columns
5417 names = []
5418 names = []
5418 vers = []
5419 vers = []
5419 isinternals = []
5420 isinternals = []
5420 for name, module in extensions.extensions():
5421 for name, module in extensions.extensions():
5421 names.append(name)
5422 names.append(name)
5422 vers.append(extensions.moduleversion(module) or None)
5423 vers.append(extensions.moduleversion(module) or None)
5423 isinternals.append(extensions.ismoduleinternal(module))
5424 isinternals.append(extensions.ismoduleinternal(module))
5424 fn = fm.nested("extensions")
5425 fn = fm.nested("extensions")
5425 if names:
5426 if names:
5426 namefmt = " %%-%ds " % max(len(n) for n in names)
5427 namefmt = " %%-%ds " % max(len(n) for n in names)
5427 places = [_("external"), _("internal")]
5428 places = [_("external"), _("internal")]
5428 for n, v, p in zip(names, vers, isinternals):
5429 for n, v, p in zip(names, vers, isinternals):
5429 fn.startitem()
5430 fn.startitem()
5430 fn.condwrite(ui.verbose, "name", namefmt, n)
5431 fn.condwrite(ui.verbose, "name", namefmt, n)
5431 if ui.verbose:
5432 if ui.verbose:
5432 fn.plain("%s " % places[p])
5433 fn.plain("%s " % places[p])
5433 fn.data(bundled=p)
5434 fn.data(bundled=p)
5434 fn.condwrite(ui.verbose and v, "ver", "%s", v)
5435 fn.condwrite(ui.verbose and v, "ver", "%s", v)
5435 if ui.verbose:
5436 if ui.verbose:
5436 fn.plain("\n")
5437 fn.plain("\n")
5437 fn.end()
5438 fn.end()
5438 fm.end()
5439 fm.end()
5439
5440
5440 def loadcmdtable(ui, name, cmdtable):
5441 def loadcmdtable(ui, name, cmdtable):
5441 """Load command functions from specified cmdtable
5442 """Load command functions from specified cmdtable
5442 """
5443 """
5443 overrides = [cmd for cmd in cmdtable if cmd in table]
5444 overrides = [cmd for cmd in cmdtable if cmd in table]
5444 if overrides:
5445 if overrides:
5445 ui.warn(_("extension '%s' overrides commands: %s\n")
5446 ui.warn(_("extension '%s' overrides commands: %s\n")
5446 % (name, " ".join(overrides)))
5447 % (name, " ".join(overrides)))
5447 table.update(cmdtable)
5448 table.update(cmdtable)
General Comments 0
You need to be logged in to leave comments. Login now