##// END OF EJS Templates
cat: migrate to modern pager API
Augie Fackler -
r31029:d6a703af 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 = ['cat', 'diff', 'export', 'glog', 'log', 'qdiff']
113 attended = ['diff', 'export', 'glog', 'log', 'qdiff']
@@ -1,5446 +1,5447 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 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1421 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1421
1422
1422 @command('^clone',
1423 @command('^clone',
1423 [('U', 'noupdate', None, _('the clone will include an empty working '
1424 [('U', 'noupdate', None, _('the clone will include an empty working '
1424 'directory (only a repository)')),
1425 'directory (only a repository)')),
1425 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1426 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1426 _('REV')),
1427 _('REV')),
1427 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1428 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1428 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1429 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1429 ('', 'pull', None, _('use pull protocol to copy metadata')),
1430 ('', 'pull', None, _('use pull protocol to copy metadata')),
1430 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1431 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1431 ] + remoteopts,
1432 ] + remoteopts,
1432 _('[OPTION]... SOURCE [DEST]'),
1433 _('[OPTION]... SOURCE [DEST]'),
1433 norepo=True)
1434 norepo=True)
1434 def clone(ui, source, dest=None, **opts):
1435 def clone(ui, source, dest=None, **opts):
1435 """make a copy of an existing repository
1436 """make a copy of an existing repository
1436
1437
1437 Create a copy of an existing repository in a new directory.
1438 Create a copy of an existing repository in a new directory.
1438
1439
1439 If no destination directory name is specified, it defaults to the
1440 If no destination directory name is specified, it defaults to the
1440 basename of the source.
1441 basename of the source.
1441
1442
1442 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
1443 ``.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.
1444
1445
1445 Only local paths and ``ssh://`` URLs are supported as
1446 Only local paths and ``ssh://`` URLs are supported as
1446 destinations. For ``ssh://`` destinations, no working directory or
1447 destinations. For ``ssh://`` destinations, no working directory or
1447 ``.hg/hgrc`` will be created on the remote side.
1448 ``.hg/hgrc`` will be created on the remote side.
1448
1449
1449 If the source repository has a bookmark called '@' set, that
1450 If the source repository has a bookmark called '@' set, that
1450 revision will be checked out in the new repository by default.
1451 revision will be checked out in the new repository by default.
1451
1452
1452 To check out a particular version, use -u/--update, or
1453 To check out a particular version, use -u/--update, or
1453 -U/--noupdate to create a clone with no working directory.
1454 -U/--noupdate to create a clone with no working directory.
1454
1455
1455 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
1456 identifiers with -r/--rev or branches with -b/--branch. The
1457 identifiers with -r/--rev or branches with -b/--branch. The
1457 resulting clone will contain only the specified changesets and
1458 resulting clone will contain only the specified changesets and
1458 their ancestors. These options (or 'clone src#rev dest') imply
1459 their ancestors. These options (or 'clone src#rev dest') imply
1459 --pull, even for local source repositories.
1460 --pull, even for local source repositories.
1460
1461
1461 .. note::
1462 .. note::
1462
1463
1463 Specifying a tag will include the tagged changeset but not the
1464 Specifying a tag will include the tagged changeset but not the
1464 changeset containing the tag.
1465 changeset containing the tag.
1465
1466
1466 .. container:: verbose
1467 .. container:: verbose
1467
1468
1468 For efficiency, hardlinks are used for cloning whenever the
1469 For efficiency, hardlinks are used for cloning whenever the
1469 source and destination are on the same filesystem (note this
1470 source and destination are on the same filesystem (note this
1470 applies only to the repository data, not to the working
1471 applies only to the repository data, not to the working
1471 directory). Some filesystems, such as AFS, implement hardlinking
1472 directory). Some filesystems, such as AFS, implement hardlinking
1472 incorrectly, but do not report errors. In these cases, use the
1473 incorrectly, but do not report errors. In these cases, use the
1473 --pull option to avoid hardlinking.
1474 --pull option to avoid hardlinking.
1474
1475
1475 In some cases, you can clone repositories and the working
1476 In some cases, you can clone repositories and the working
1476 directory using full hardlinks with ::
1477 directory using full hardlinks with ::
1477
1478
1478 $ cp -al REPO REPOCLONE
1479 $ cp -al REPO REPOCLONE
1479
1480
1480 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
1481 operation is not atomic (making sure REPO is not modified during
1482 operation is not atomic (making sure REPO is not modified during
1482 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
1483 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1484 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1484 so). Also, this is not compatible with certain extensions that
1485 so). Also, this is not compatible with certain extensions that
1485 place their metadata under the .hg directory, such as mq.
1486 place their metadata under the .hg directory, such as mq.
1486
1487
1487 Mercurial will update the working directory to the first applicable
1488 Mercurial will update the working directory to the first applicable
1488 revision from this list:
1489 revision from this list:
1489
1490
1490 a) null if -U or the source repository has no changesets
1491 a) null if -U or the source repository has no changesets
1491 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
1492 the source repository's working directory
1493 the source repository's working directory
1493 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
1494 latest head of that branch)
1495 latest head of that branch)
1495 d) the changeset specified with -r
1496 d) the changeset specified with -r
1496 e) the tipmost head specified with -b
1497 e) the tipmost head specified with -b
1497 f) the tipmost head specified with the url#branch source syntax
1498 f) the tipmost head specified with the url#branch source syntax
1498 g) the revision marked with the '@' bookmark, if present
1499 g) the revision marked with the '@' bookmark, if present
1499 h) the tipmost head of the default branch
1500 h) the tipmost head of the default branch
1500 i) tip
1501 i) tip
1501
1502
1502 When cloning from servers that support it, Mercurial may fetch
1503 When cloning from servers that support it, Mercurial may fetch
1503 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,
1504 hooks operating on incoming changesets and changegroups may fire twice,
1505 hooks operating on incoming changesets and changegroups may fire twice,
1505 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
1506 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
1507 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
1508 change in future releases. See :hg:`help -e clonebundles` for more.
1509 change in future releases. See :hg:`help -e clonebundles` for more.
1509
1510
1510 Examples:
1511 Examples:
1511
1512
1512 - clone a remote repository to a new directory named hg/::
1513 - clone a remote repository to a new directory named hg/::
1513
1514
1514 hg clone https://www.mercurial-scm.org/repo/hg/
1515 hg clone https://www.mercurial-scm.org/repo/hg/
1515
1516
1516 - create a lightweight local clone::
1517 - create a lightweight local clone::
1517
1518
1518 hg clone project/ project-feature/
1519 hg clone project/ project-feature/
1519
1520
1520 - 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)::
1521
1522
1522 hg clone ssh://user@server//home/projects/alpha/
1523 hg clone ssh://user@server//home/projects/alpha/
1523
1524
1524 - 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
1525 specified version::
1526 specified version::
1526
1527
1527 hg clone --uncompressed http://server/repo -u 1.5
1528 hg clone --uncompressed http://server/repo -u 1.5
1528
1529
1529 - create a repository without changesets after a particular revision::
1530 - create a repository without changesets after a particular revision::
1530
1531
1531 hg clone -r 04e544 experimental/ good/
1532 hg clone -r 04e544 experimental/ good/
1532
1533
1533 - clone (and track) a particular named branch::
1534 - clone (and track) a particular named branch::
1534
1535
1535 hg clone https://www.mercurial-scm.org/repo/hg/#stable
1536 hg clone https://www.mercurial-scm.org/repo/hg/#stable
1536
1537
1537 See :hg:`help urls` for details on specifying URLs.
1538 See :hg:`help urls` for details on specifying URLs.
1538
1539
1539 Returns 0 on success.
1540 Returns 0 on success.
1540 """
1541 """
1541 if opts.get('noupdate') and opts.get('updaterev'):
1542 if opts.get('noupdate') and opts.get('updaterev'):
1542 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1543 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1543
1544
1544 r = hg.clone(ui, opts, source, dest,
1545 r = hg.clone(ui, opts, source, dest,
1545 pull=opts.get('pull'),
1546 pull=opts.get('pull'),
1546 stream=opts.get('uncompressed'),
1547 stream=opts.get('uncompressed'),
1547 rev=opts.get('rev'),
1548 rev=opts.get('rev'),
1548 update=opts.get('updaterev') or not opts.get('noupdate'),
1549 update=opts.get('updaterev') or not opts.get('noupdate'),
1549 branch=opts.get('branch'),
1550 branch=opts.get('branch'),
1550 shareopts=opts.get('shareopts'))
1551 shareopts=opts.get('shareopts'))
1551
1552
1552 return r is None
1553 return r is None
1553
1554
1554 @command('^commit|ci',
1555 @command('^commit|ci',
1555 [('A', 'addremove', None,
1556 [('A', 'addremove', None,
1556 _('mark new/missing files as added/removed before committing')),
1557 _('mark new/missing files as added/removed before committing')),
1557 ('', 'close-branch', None,
1558 ('', 'close-branch', None,
1558 _('mark a branch head as closed')),
1559 _('mark a branch head as closed')),
1559 ('', 'amend', None, _('amend the parent of the working directory')),
1560 ('', 'amend', None, _('amend the parent of the working directory')),
1560 ('s', 'secret', None, _('use the secret phase for committing')),
1561 ('s', 'secret', None, _('use the secret phase for committing')),
1561 ('e', 'edit', None, _('invoke editor on commit messages')),
1562 ('e', 'edit', None, _('invoke editor on commit messages')),
1562 ('i', 'interactive', None, _('use interactive mode')),
1563 ('i', 'interactive', None, _('use interactive mode')),
1563 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1564 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1564 _('[OPTION]... [FILE]...'),
1565 _('[OPTION]... [FILE]...'),
1565 inferrepo=True)
1566 inferrepo=True)
1566 def commit(ui, repo, *pats, **opts):
1567 def commit(ui, repo, *pats, **opts):
1567 """commit the specified files or all outstanding changes
1568 """commit the specified files or all outstanding changes
1568
1569
1569 Commit changes to the given files into the repository. Unlike a
1570 Commit changes to the given files into the repository. Unlike a
1570 centralized SCM, this operation is a local operation. See
1571 centralized SCM, this operation is a local operation. See
1571 :hg:`push` for a way to actively distribute your changes.
1572 :hg:`push` for a way to actively distribute your changes.
1572
1573
1573 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`
1574 will be committed.
1575 will be committed.
1575
1576
1576 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
1577 filenames or -I/-X filters.
1578 filenames or -I/-X filters.
1578
1579
1579 If no commit message is specified, Mercurial starts your
1580 If no commit message is specified, Mercurial starts your
1580 configured editor where you can enter a message. In case your
1581 configured editor where you can enter a message. In case your
1581 commit fails, you will find a backup of your message in
1582 commit fails, you will find a backup of your message in
1582 ``.hg/last-message.txt``.
1583 ``.hg/last-message.txt``.
1583
1584
1584 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
1585 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
1586 will be considered closed and no longer listed.
1587 will be considered closed and no longer listed.
1587
1588
1588 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
1589 working directory with a new commit that contains the changes
1590 working directory with a new commit that contains the changes
1590 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`,
1591 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
1592 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1593 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1593 on how to restore it).
1594 on how to restore it).
1594
1595
1595 Message, user and date are taken from the amended commit unless
1596 Message, user and date are taken from the amended commit unless
1596 specified. When a message isn't specified on the command line,
1597 specified. When a message isn't specified on the command line,
1597 the editor will open with the message of the amended commit.
1598 the editor will open with the message of the amended commit.
1598
1599
1599 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`)
1600 or changesets that have children.
1601 or changesets that have children.
1601
1602
1602 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.
1603
1604
1604 Returns 0 on success, 1 if nothing changed.
1605 Returns 0 on success, 1 if nothing changed.
1605
1606
1606 .. container:: verbose
1607 .. container:: verbose
1607
1608
1608 Examples:
1609 Examples:
1609
1610
1610 - commit all files ending in .py::
1611 - commit all files ending in .py::
1611
1612
1612 hg commit --include "set:**.py"
1613 hg commit --include "set:**.py"
1613
1614
1614 - commit all non-binary files::
1615 - commit all non-binary files::
1615
1616
1616 hg commit --exclude "set:binary()"
1617 hg commit --exclude "set:binary()"
1617
1618
1618 - amend the current commit and set the date to now::
1619 - amend the current commit and set the date to now::
1619
1620
1620 hg commit --amend --date now
1621 hg commit --amend --date now
1621 """
1622 """
1622 wlock = lock = None
1623 wlock = lock = None
1623 try:
1624 try:
1624 wlock = repo.wlock()
1625 wlock = repo.wlock()
1625 lock = repo.lock()
1626 lock = repo.lock()
1626 return _docommit(ui, repo, *pats, **opts)
1627 return _docommit(ui, repo, *pats, **opts)
1627 finally:
1628 finally:
1628 release(lock, wlock)
1629 release(lock, wlock)
1629
1630
1630 def _docommit(ui, repo, *pats, **opts):
1631 def _docommit(ui, repo, *pats, **opts):
1631 if opts.get('interactive'):
1632 if opts.get('interactive'):
1632 opts.pop('interactive')
1633 opts.pop('interactive')
1633 ret = cmdutil.dorecord(ui, repo, commit, None, False,
1634 ret = cmdutil.dorecord(ui, repo, commit, None, False,
1634 cmdutil.recordfilter, *pats, **opts)
1635 cmdutil.recordfilter, *pats, **opts)
1635 # 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
1636 # commit(), 1 if nothing changed or None on success.
1637 # commit(), 1 if nothing changed or None on success.
1637 return 1 if ret == 0 else ret
1638 return 1 if ret == 0 else ret
1638
1639
1639 if opts.get('subrepos'):
1640 if opts.get('subrepos'):
1640 if opts.get('amend'):
1641 if opts.get('amend'):
1641 raise error.Abort(_('cannot amend with --subrepos'))
1642 raise error.Abort(_('cannot amend with --subrepos'))
1642 # Let --subrepos on the command line override config setting.
1643 # Let --subrepos on the command line override config setting.
1643 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1644 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1644
1645
1645 cmdutil.checkunfinished(repo, commit=True)
1646 cmdutil.checkunfinished(repo, commit=True)
1646
1647
1647 branch = repo[None].branch()
1648 branch = repo[None].branch()
1648 bheads = repo.branchheads(branch)
1649 bheads = repo.branchheads(branch)
1649
1650
1650 extra = {}
1651 extra = {}
1651 if opts.get('close_branch'):
1652 if opts.get('close_branch'):
1652 extra['close'] = 1
1653 extra['close'] = 1
1653
1654
1654 if not bheads:
1655 if not bheads:
1655 raise error.Abort(_('can only close branch heads'))
1656 raise error.Abort(_('can only close branch heads'))
1656 elif opts.get('amend'):
1657 elif opts.get('amend'):
1657 if repo[None].parents()[0].p1().branch() != branch and \
1658 if repo[None].parents()[0].p1().branch() != branch and \
1658 repo[None].parents()[0].p2().branch() != branch:
1659 repo[None].parents()[0].p2().branch() != branch:
1659 raise error.Abort(_('can only close branch heads'))
1660 raise error.Abort(_('can only close branch heads'))
1660
1661
1661 if opts.get('amend'):
1662 if opts.get('amend'):
1662 if ui.configbool('ui', 'commitsubrepos'):
1663 if ui.configbool('ui', 'commitsubrepos'):
1663 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1664 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1664
1665
1665 old = repo['.']
1666 old = repo['.']
1666 if not old.mutable():
1667 if not old.mutable():
1667 raise error.Abort(_('cannot amend public changesets'))
1668 raise error.Abort(_('cannot amend public changesets'))
1668 if len(repo[None].parents()) > 1:
1669 if len(repo[None].parents()) > 1:
1669 raise error.Abort(_('cannot amend while merging'))
1670 raise error.Abort(_('cannot amend while merging'))
1670 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1671 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1671 if not allowunstable and old.children():
1672 if not allowunstable and old.children():
1672 raise error.Abort(_('cannot amend changeset with children'))
1673 raise error.Abort(_('cannot amend changeset with children'))
1673
1674
1674 # Currently histedit gets confused if an amend happens while histedit
1675 # Currently histedit gets confused if an amend happens while histedit
1675 # is in progress. Since we have a checkunfinished command, we are
1676 # is in progress. Since we have a checkunfinished command, we are
1676 # temporarily honoring it.
1677 # temporarily honoring it.
1677 #
1678 #
1678 # Note: eventually this guard will be removed. Please do not expect
1679 # Note: eventually this guard will be removed. Please do not expect
1679 # this behavior to remain.
1680 # this behavior to remain.
1680 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
1681 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
1681 cmdutil.checkunfinished(repo)
1682 cmdutil.checkunfinished(repo)
1682
1683
1683 # commitfunc is used only for temporary amend commit by cmdutil.amend
1684 # commitfunc is used only for temporary amend commit by cmdutil.amend
1684 def commitfunc(ui, repo, message, match, opts):
1685 def commitfunc(ui, repo, message, match, opts):
1685 return repo.commit(message,
1686 return repo.commit(message,
1686 opts.get('user') or old.user(),
1687 opts.get('user') or old.user(),
1687 opts.get('date') or old.date(),
1688 opts.get('date') or old.date(),
1688 match,
1689 match,
1689 extra=extra)
1690 extra=extra)
1690
1691
1691 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1692 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1692 if node == old.node():
1693 if node == old.node():
1693 ui.status(_("nothing changed\n"))
1694 ui.status(_("nothing changed\n"))
1694 return 1
1695 return 1
1695 else:
1696 else:
1696 def commitfunc(ui, repo, message, match, opts):
1697 def commitfunc(ui, repo, message, match, opts):
1697 backup = ui.backupconfig('phases', 'new-commit')
1698 backup = ui.backupconfig('phases', 'new-commit')
1698 baseui = repo.baseui
1699 baseui = repo.baseui
1699 basebackup = baseui.backupconfig('phases', 'new-commit')
1700 basebackup = baseui.backupconfig('phases', 'new-commit')
1700 try:
1701 try:
1701 if opts.get('secret'):
1702 if opts.get('secret'):
1702 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1703 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1703 # Propagate to subrepos
1704 # Propagate to subrepos
1704 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1705 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1705
1706
1706 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1707 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1707 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1708 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1708 return repo.commit(message, opts.get('user'), opts.get('date'),
1709 return repo.commit(message, opts.get('user'), opts.get('date'),
1709 match,
1710 match,
1710 editor=editor,
1711 editor=editor,
1711 extra=extra)
1712 extra=extra)
1712 finally:
1713 finally:
1713 ui.restoreconfig(backup)
1714 ui.restoreconfig(backup)
1714 repo.baseui.restoreconfig(basebackup)
1715 repo.baseui.restoreconfig(basebackup)
1715
1716
1716
1717
1717 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1718 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1718
1719
1719 if not node:
1720 if not node:
1720 stat = cmdutil.postcommitstatus(repo, pats, opts)
1721 stat = cmdutil.postcommitstatus(repo, pats, opts)
1721 if stat[3]:
1722 if stat[3]:
1722 ui.status(_("nothing changed (%d missing files, see "
1723 ui.status(_("nothing changed (%d missing files, see "
1723 "'hg status')\n") % len(stat[3]))
1724 "'hg status')\n") % len(stat[3]))
1724 else:
1725 else:
1725 ui.status(_("nothing changed\n"))
1726 ui.status(_("nothing changed\n"))
1726 return 1
1727 return 1
1727
1728
1728 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1729 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1729
1730
1730 @command('config|showconfig|debugconfig',
1731 @command('config|showconfig|debugconfig',
1731 [('u', 'untrusted', None, _('show untrusted configuration options')),
1732 [('u', 'untrusted', None, _('show untrusted configuration options')),
1732 ('e', 'edit', None, _('edit user config')),
1733 ('e', 'edit', None, _('edit user config')),
1733 ('l', 'local', None, _('edit repository config')),
1734 ('l', 'local', None, _('edit repository config')),
1734 ('g', 'global', None, _('edit global config'))] + formatteropts,
1735 ('g', 'global', None, _('edit global config'))] + formatteropts,
1735 _('[-u] [NAME]...'),
1736 _('[-u] [NAME]...'),
1736 optionalrepo=True)
1737 optionalrepo=True)
1737 def config(ui, repo, *values, **opts):
1738 def config(ui, repo, *values, **opts):
1738 """show combined config settings from all hgrc files
1739 """show combined config settings from all hgrc files
1739
1740
1740 With no arguments, print names and values of all config items.
1741 With no arguments, print names and values of all config items.
1741
1742
1742 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
1743 of that config item.
1744 of that config item.
1744
1745
1745 With multiple arguments, print names and values of all config
1746 With multiple arguments, print names and values of all config
1746 items with matching section names.
1747 items with matching section names.
1747
1748
1748 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
1749 --global, edit the system-wide config file. With --local, edit the
1750 --global, edit the system-wide config file. With --local, edit the
1750 repository-level config file.
1751 repository-level config file.
1751
1752
1752 With --debug, the source (filename and line number) is printed
1753 With --debug, the source (filename and line number) is printed
1753 for each config item.
1754 for each config item.
1754
1755
1755 See :hg:`help config` for more information about config files.
1756 See :hg:`help config` for more information about config files.
1756
1757
1757 Returns 0 on success, 1 if NAME does not exist.
1758 Returns 0 on success, 1 if NAME does not exist.
1758
1759
1759 """
1760 """
1760
1761
1761 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'):
1762 if opts.get('local') and opts.get('global'):
1763 if opts.get('local') and opts.get('global'):
1763 raise error.Abort(_("can't use --local and --global together"))
1764 raise error.Abort(_("can't use --local and --global together"))
1764
1765
1765 if opts.get('local'):
1766 if opts.get('local'):
1766 if not repo:
1767 if not repo:
1767 raise error.Abort(_("can't use --local outside a repository"))
1768 raise error.Abort(_("can't use --local outside a repository"))
1768 paths = [repo.join('hgrc')]
1769 paths = [repo.join('hgrc')]
1769 elif opts.get('global'):
1770 elif opts.get('global'):
1770 paths = scmutil.systemrcpath()
1771 paths = scmutil.systemrcpath()
1771 else:
1772 else:
1772 paths = scmutil.userrcpath()
1773 paths = scmutil.userrcpath()
1773
1774
1774 for f in paths:
1775 for f in paths:
1775 if os.path.exists(f):
1776 if os.path.exists(f):
1776 break
1777 break
1777 else:
1778 else:
1778 if opts.get('global'):
1779 if opts.get('global'):
1779 samplehgrc = uimod.samplehgrcs['global']
1780 samplehgrc = uimod.samplehgrcs['global']
1780 elif opts.get('local'):
1781 elif opts.get('local'):
1781 samplehgrc = uimod.samplehgrcs['local']
1782 samplehgrc = uimod.samplehgrcs['local']
1782 else:
1783 else:
1783 samplehgrc = uimod.samplehgrcs['user']
1784 samplehgrc = uimod.samplehgrcs['user']
1784
1785
1785 f = paths[0]
1786 f = paths[0]
1786 fp = open(f, "w")
1787 fp = open(f, "w")
1787 fp.write(samplehgrc)
1788 fp.write(samplehgrc)
1788 fp.close()
1789 fp.close()
1789
1790
1790 editor = ui.geteditor()
1791 editor = ui.geteditor()
1791 ui.system("%s \"%s\"" % (editor, f),
1792 ui.system("%s \"%s\"" % (editor, f),
1792 onerr=error.Abort, errprefix=_("edit failed"))
1793 onerr=error.Abort, errprefix=_("edit failed"))
1793 return
1794 return
1794
1795
1795 fm = ui.formatter('config', opts)
1796 fm = ui.formatter('config', opts)
1796 for f in scmutil.rcpath():
1797 for f in scmutil.rcpath():
1797 ui.debug('read config from: %s\n' % f)
1798 ui.debug('read config from: %s\n' % f)
1798 untrusted = bool(opts.get('untrusted'))
1799 untrusted = bool(opts.get('untrusted'))
1799 if values:
1800 if values:
1800 sections = [v for v in values if '.' not in v]
1801 sections = [v for v in values if '.' not in v]
1801 items = [v for v in values if '.' in v]
1802 items = [v for v in values if '.' in v]
1802 if len(items) > 1 or items and sections:
1803 if len(items) > 1 or items and sections:
1803 raise error.Abort(_('only one config item permitted'))
1804 raise error.Abort(_('only one config item permitted'))
1804 matched = False
1805 matched = False
1805 for section, name, value in ui.walkconfig(untrusted=untrusted):
1806 for section, name, value in ui.walkconfig(untrusted=untrusted):
1806 source = ui.configsource(section, name, untrusted)
1807 source = ui.configsource(section, name, untrusted)
1807 value = str(value)
1808 value = str(value)
1808 if fm.isplain():
1809 if fm.isplain():
1809 source = source or 'none'
1810 source = source or 'none'
1810 value = value.replace('\n', '\\n')
1811 value = value.replace('\n', '\\n')
1811 entryname = section + '.' + name
1812 entryname = section + '.' + name
1812 if values:
1813 if values:
1813 for v in values:
1814 for v in values:
1814 if v == section:
1815 if v == section:
1815 fm.startitem()
1816 fm.startitem()
1816 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1817 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1817 fm.write('name value', '%s=%s\n', entryname, value)
1818 fm.write('name value', '%s=%s\n', entryname, value)
1818 matched = True
1819 matched = True
1819 elif v == entryname:
1820 elif v == entryname:
1820 fm.startitem()
1821 fm.startitem()
1821 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1822 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1822 fm.write('value', '%s\n', value)
1823 fm.write('value', '%s\n', value)
1823 fm.data(name=entryname)
1824 fm.data(name=entryname)
1824 matched = True
1825 matched = True
1825 else:
1826 else:
1826 fm.startitem()
1827 fm.startitem()
1827 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1828 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1828 fm.write('name value', '%s=%s\n', entryname, value)
1829 fm.write('name value', '%s=%s\n', entryname, value)
1829 matched = True
1830 matched = True
1830 fm.end()
1831 fm.end()
1831 if matched:
1832 if matched:
1832 return 0
1833 return 0
1833 return 1
1834 return 1
1834
1835
1835 @command('copy|cp',
1836 @command('copy|cp',
1836 [('A', 'after', None, _('record a copy that has already occurred')),
1837 [('A', 'after', None, _('record a copy that has already occurred')),
1837 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1838 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1838 ] + walkopts + dryrunopts,
1839 ] + walkopts + dryrunopts,
1839 _('[OPTION]... [SOURCE]... DEST'))
1840 _('[OPTION]... [SOURCE]... DEST'))
1840 def copy(ui, repo, *pats, **opts):
1841 def copy(ui, repo, *pats, **opts):
1841 """mark files as copied for the next commit
1842 """mark files as copied for the next commit
1842
1843
1843 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
1844 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,
1845 the source must be a single file.
1846 the source must be a single file.
1846
1847
1847 By default, this command copies the contents of files as they
1848 By default, this command copies the contents of files as they
1848 exist in the working directory. If invoked with -A/--after, the
1849 exist in the working directory. If invoked with -A/--after, the
1849 operation is recorded, but no copying is performed.
1850 operation is recorded, but no copying is performed.
1850
1851
1851 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
1852 before that, see :hg:`revert`.
1853 before that, see :hg:`revert`.
1853
1854
1854 Returns 0 on success, 1 if errors are encountered.
1855 Returns 0 on success, 1 if errors are encountered.
1855 """
1856 """
1856 with repo.wlock(False):
1857 with repo.wlock(False):
1857 return cmdutil.copy(ui, repo, pats, opts)
1858 return cmdutil.copy(ui, repo, pats, opts)
1858
1859
1859 @command('^diff',
1860 @command('^diff',
1860 [('r', 'rev', [], _('revision'), _('REV')),
1861 [('r', 'rev', [], _('revision'), _('REV')),
1861 ('c', 'change', '', _('change made by revision'), _('REV'))
1862 ('c', 'change', '', _('change made by revision'), _('REV'))
1862 ] + diffopts + diffopts2 + walkopts + subrepoopts,
1863 ] + diffopts + diffopts2 + walkopts + subrepoopts,
1863 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
1864 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
1864 inferrepo=True)
1865 inferrepo=True)
1865 def diff(ui, repo, *pats, **opts):
1866 def diff(ui, repo, *pats, **opts):
1866 """diff repository (or selected files)
1867 """diff repository (or selected files)
1867
1868
1868 Show differences between revisions for the specified files.
1869 Show differences between revisions for the specified files.
1869
1870
1870 Differences between files are shown using the unified diff format.
1871 Differences between files are shown using the unified diff format.
1871
1872
1872 .. note::
1873 .. note::
1873
1874
1874 :hg:`diff` may generate unexpected results for merges, as it will
1875 :hg:`diff` may generate unexpected results for merges, as it will
1875 default to comparing against the working directory's first
1876 default to comparing against the working directory's first
1876 parent changeset if no revisions are specified.
1877 parent changeset if no revisions are specified.
1877
1878
1878 When two revision arguments are given, then changes are shown
1879 When two revision arguments are given, then changes are shown
1879 between those revisions. If only one revision is specified then
1880 between those revisions. If only one revision is specified then
1880 that revision is compared to the working directory, and, when no
1881 that revision is compared to the working directory, and, when no
1881 revisions are specified, the working directory files are compared
1882 revisions are specified, the working directory files are compared
1882 to its first parent.
1883 to its first parent.
1883
1884
1884 Alternatively you can specify -c/--change with a revision to see
1885 Alternatively you can specify -c/--change with a revision to see
1885 the changes in that changeset relative to its first parent.
1886 the changes in that changeset relative to its first parent.
1886
1887
1887 Without the -a/--text option, diff will avoid generating diffs of
1888 Without the -a/--text option, diff will avoid generating diffs of
1888 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
1889 anyway, probably with undesirable results.
1890 anyway, probably with undesirable results.
1890
1891
1891 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
1892 format. For more information, read :hg:`help diffs`.
1893 format. For more information, read :hg:`help diffs`.
1893
1894
1894 .. container:: verbose
1895 .. container:: verbose
1895
1896
1896 Examples:
1897 Examples:
1897
1898
1898 - compare a file in the current working directory to its parent::
1899 - compare a file in the current working directory to its parent::
1899
1900
1900 hg diff foo.c
1901 hg diff foo.c
1901
1902
1902 - compare two historical versions of a directory, with rename info::
1903 - compare two historical versions of a directory, with rename info::
1903
1904
1904 hg diff --git -r 1.0:1.2 lib/
1905 hg diff --git -r 1.0:1.2 lib/
1905
1906
1906 - get change stats relative to the last change on some date::
1907 - get change stats relative to the last change on some date::
1907
1908
1908 hg diff --stat -r "date('may 2')"
1909 hg diff --stat -r "date('may 2')"
1909
1910
1910 - diff all newly-added files that contain a keyword::
1911 - diff all newly-added files that contain a keyword::
1911
1912
1912 hg diff "set:added() and grep(GNU)"
1913 hg diff "set:added() and grep(GNU)"
1913
1914
1914 - compare a revision and its parents::
1915 - compare a revision and its parents::
1915
1916
1916 hg diff -c 9353 # compare against first parent
1917 hg diff -c 9353 # compare against first parent
1917 hg diff -r 9353^:9353 # same using revset syntax
1918 hg diff -r 9353^:9353 # same using revset syntax
1918 hg diff -r 9353^2:9353 # compare against the second parent
1919 hg diff -r 9353^2:9353 # compare against the second parent
1919
1920
1920 Returns 0 on success.
1921 Returns 0 on success.
1921 """
1922 """
1922
1923
1923 revs = opts.get('rev')
1924 revs = opts.get('rev')
1924 change = opts.get('change')
1925 change = opts.get('change')
1925 stat = opts.get('stat')
1926 stat = opts.get('stat')
1926 reverse = opts.get('reverse')
1927 reverse = opts.get('reverse')
1927
1928
1928 if revs and change:
1929 if revs and change:
1929 msg = _('cannot specify --rev and --change at the same time')
1930 msg = _('cannot specify --rev and --change at the same time')
1930 raise error.Abort(msg)
1931 raise error.Abort(msg)
1931 elif change:
1932 elif change:
1932 node2 = scmutil.revsingle(repo, change, None).node()
1933 node2 = scmutil.revsingle(repo, change, None).node()
1933 node1 = repo[node2].p1().node()
1934 node1 = repo[node2].p1().node()
1934 else:
1935 else:
1935 node1, node2 = scmutil.revpair(repo, revs)
1936 node1, node2 = scmutil.revpair(repo, revs)
1936
1937
1937 if reverse:
1938 if reverse:
1938 node1, node2 = node2, node1
1939 node1, node2 = node2, node1
1939
1940
1940 diffopts = patch.diffallopts(ui, opts)
1941 diffopts = patch.diffallopts(ui, opts)
1941 m = scmutil.match(repo[node2], pats, opts)
1942 m = scmutil.match(repo[node2], pats, opts)
1942 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
1943 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
1943 listsubrepos=opts.get('subrepos'),
1944 listsubrepos=opts.get('subrepos'),
1944 root=opts.get('root'))
1945 root=opts.get('root'))
1945
1946
1946 @command('^export',
1947 @command('^export',
1947 [('o', 'output', '',
1948 [('o', 'output', '',
1948 _('print output to file with formatted name'), _('FORMAT')),
1949 _('print output to file with formatted name'), _('FORMAT')),
1949 ('', 'switch-parent', None, _('diff against the second parent')),
1950 ('', 'switch-parent', None, _('diff against the second parent')),
1950 ('r', 'rev', [], _('revisions to export'), _('REV')),
1951 ('r', 'rev', [], _('revisions to export'), _('REV')),
1951 ] + diffopts,
1952 ] + diffopts,
1952 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
1953 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
1953 def export(ui, repo, *changesets, **opts):
1954 def export(ui, repo, *changesets, **opts):
1954 """dump the header and diffs for one or more changesets
1955 """dump the header and diffs for one or more changesets
1955
1956
1956 Print the changeset header and diffs for one or more revisions.
1957 Print the changeset header and diffs for one or more revisions.
1957 If no revision is given, the parent of the working directory is used.
1958 If no revision is given, the parent of the working directory is used.
1958
1959
1959 The information shown in the changeset header is: author, date,
1960 The information shown in the changeset header is: author, date,
1960 branch name (if non-default), changeset hash, parent(s) and commit
1961 branch name (if non-default), changeset hash, parent(s) and commit
1961 comment.
1962 comment.
1962
1963
1963 .. note::
1964 .. note::
1964
1965
1965 :hg:`export` may generate unexpected diff output for merge
1966 :hg:`export` may generate unexpected diff output for merge
1966 changesets, as it will compare the merge changeset against its
1967 changesets, as it will compare the merge changeset against its
1967 first parent only.
1968 first parent only.
1968
1969
1969 Output may be to a file, in which case the name of the file is
1970 Output may be to a file, in which case the name of the file is
1970 given using a format string. The formatting rules are as follows:
1971 given using a format string. The formatting rules are as follows:
1971
1972
1972 :``%%``: literal "%" character
1973 :``%%``: literal "%" character
1973 :``%H``: changeset hash (40 hexadecimal digits)
1974 :``%H``: changeset hash (40 hexadecimal digits)
1974 :``%N``: number of patches being generated
1975 :``%N``: number of patches being generated
1975 :``%R``: changeset revision number
1976 :``%R``: changeset revision number
1976 :``%b``: basename of the exporting repository
1977 :``%b``: basename of the exporting repository
1977 :``%h``: short-form changeset hash (12 hexadecimal digits)
1978 :``%h``: short-form changeset hash (12 hexadecimal digits)
1978 :``%m``: first line of the commit message (only alphanumeric characters)
1979 :``%m``: first line of the commit message (only alphanumeric characters)
1979 :``%n``: zero-padded sequence number, starting at 1
1980 :``%n``: zero-padded sequence number, starting at 1
1980 :``%r``: zero-padded changeset revision number
1981 :``%r``: zero-padded changeset revision number
1981
1982
1982 Without the -a/--text option, export will avoid generating diffs
1983 Without the -a/--text option, export will avoid generating diffs
1983 of files it detects as binary. With -a, export will generate a
1984 of files it detects as binary. With -a, export will generate a
1984 diff anyway, probably with undesirable results.
1985 diff anyway, probably with undesirable results.
1985
1986
1986 Use the -g/--git option to generate diffs in the git extended diff
1987 Use the -g/--git option to generate diffs in the git extended diff
1987 format. See :hg:`help diffs` for more information.
1988 format. See :hg:`help diffs` for more information.
1988
1989
1989 With the --switch-parent option, the diff will be against the
1990 With the --switch-parent option, the diff will be against the
1990 second parent. It can be useful to review a merge.
1991 second parent. It can be useful to review a merge.
1991
1992
1992 .. container:: verbose
1993 .. container:: verbose
1993
1994
1994 Examples:
1995 Examples:
1995
1996
1996 - use export and import to transplant a bugfix to the current
1997 - use export and import to transplant a bugfix to the current
1997 branch::
1998 branch::
1998
1999
1999 hg export -r 9353 | hg import -
2000 hg export -r 9353 | hg import -
2000
2001
2001 - export all the changesets between two revisions to a file with
2002 - export all the changesets between two revisions to a file with
2002 rename information::
2003 rename information::
2003
2004
2004 hg export --git -r 123:150 > changes.txt
2005 hg export --git -r 123:150 > changes.txt
2005
2006
2006 - split outgoing changes into a series of patches with
2007 - split outgoing changes into a series of patches with
2007 descriptive names::
2008 descriptive names::
2008
2009
2009 hg export -r "outgoing()" -o "%n-%m.patch"
2010 hg export -r "outgoing()" -o "%n-%m.patch"
2010
2011
2011 Returns 0 on success.
2012 Returns 0 on success.
2012 """
2013 """
2013 changesets += tuple(opts.get('rev', []))
2014 changesets += tuple(opts.get('rev', []))
2014 if not changesets:
2015 if not changesets:
2015 changesets = ['.']
2016 changesets = ['.']
2016 revs = scmutil.revrange(repo, changesets)
2017 revs = scmutil.revrange(repo, changesets)
2017 if not revs:
2018 if not revs:
2018 raise error.Abort(_("export requires at least one changeset"))
2019 raise error.Abort(_("export requires at least one changeset"))
2019 if len(revs) > 1:
2020 if len(revs) > 1:
2020 ui.note(_('exporting patches:\n'))
2021 ui.note(_('exporting patches:\n'))
2021 else:
2022 else:
2022 ui.note(_('exporting patch:\n'))
2023 ui.note(_('exporting patch:\n'))
2023 cmdutil.export(repo, revs, template=opts.get('output'),
2024 cmdutil.export(repo, revs, template=opts.get('output'),
2024 switch_parent=opts.get('switch_parent'),
2025 switch_parent=opts.get('switch_parent'),
2025 opts=patch.diffallopts(ui, opts))
2026 opts=patch.diffallopts(ui, opts))
2026
2027
2027 @command('files',
2028 @command('files',
2028 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
2029 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
2029 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
2030 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
2030 ] + walkopts + formatteropts + subrepoopts,
2031 ] + walkopts + formatteropts + subrepoopts,
2031 _('[OPTION]... [FILE]...'))
2032 _('[OPTION]... [FILE]...'))
2032 def files(ui, repo, *pats, **opts):
2033 def files(ui, repo, *pats, **opts):
2033 """list tracked files
2034 """list tracked files
2034
2035
2035 Print files under Mercurial control in the working directory or
2036 Print files under Mercurial control in the working directory or
2036 specified revision for given files (excluding removed files).
2037 specified revision for given files (excluding removed files).
2037 Files can be specified as filenames or filesets.
2038 Files can be specified as filenames or filesets.
2038
2039
2039 If no files are given to match, this command prints the names
2040 If no files are given to match, this command prints the names
2040 of all files under Mercurial control.
2041 of all files under Mercurial control.
2041
2042
2042 .. container:: verbose
2043 .. container:: verbose
2043
2044
2044 Examples:
2045 Examples:
2045
2046
2046 - list all files under the current directory::
2047 - list all files under the current directory::
2047
2048
2048 hg files .
2049 hg files .
2049
2050
2050 - shows sizes and flags for current revision::
2051 - shows sizes and flags for current revision::
2051
2052
2052 hg files -vr .
2053 hg files -vr .
2053
2054
2054 - list all files named README::
2055 - list all files named README::
2055
2056
2056 hg files -I "**/README"
2057 hg files -I "**/README"
2057
2058
2058 - list all binary files::
2059 - list all binary files::
2059
2060
2060 hg files "set:binary()"
2061 hg files "set:binary()"
2061
2062
2062 - find files containing a regular expression::
2063 - find files containing a regular expression::
2063
2064
2064 hg files "set:grep('bob')"
2065 hg files "set:grep('bob')"
2065
2066
2066 - search tracked file contents with xargs and grep::
2067 - search tracked file contents with xargs and grep::
2067
2068
2068 hg files -0 | xargs -0 grep foo
2069 hg files -0 | xargs -0 grep foo
2069
2070
2070 See :hg:`help patterns` and :hg:`help filesets` for more information
2071 See :hg:`help patterns` and :hg:`help filesets` for more information
2071 on specifying file patterns.
2072 on specifying file patterns.
2072
2073
2073 Returns 0 if a match is found, 1 otherwise.
2074 Returns 0 if a match is found, 1 otherwise.
2074
2075
2075 """
2076 """
2076 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2077 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2077
2078
2078 end = '\n'
2079 end = '\n'
2079 if opts.get('print0'):
2080 if opts.get('print0'):
2080 end = '\0'
2081 end = '\0'
2081 fmt = '%s' + end
2082 fmt = '%s' + end
2082
2083
2083 m = scmutil.match(ctx, pats, opts)
2084 m = scmutil.match(ctx, pats, opts)
2084 with ui.formatter('files', opts) as fm:
2085 with ui.formatter('files', opts) as fm:
2085 return cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
2086 return cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
2086
2087
2087 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
2088 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
2088 def forget(ui, repo, *pats, **opts):
2089 def forget(ui, repo, *pats, **opts):
2089 """forget the specified files on the next commit
2090 """forget the specified files on the next commit
2090
2091
2091 Mark the specified files so they will no longer be tracked
2092 Mark the specified files so they will no longer be tracked
2092 after the next commit.
2093 after the next commit.
2093
2094
2094 This only removes files from the current branch, not from the
2095 This only removes files from the current branch, not from the
2095 entire project history, and it does not delete them from the
2096 entire project history, and it does not delete them from the
2096 working directory.
2097 working directory.
2097
2098
2098 To delete the file from the working directory, see :hg:`remove`.
2099 To delete the file from the working directory, see :hg:`remove`.
2099
2100
2100 To undo a forget before the next commit, see :hg:`add`.
2101 To undo a forget before the next commit, see :hg:`add`.
2101
2102
2102 .. container:: verbose
2103 .. container:: verbose
2103
2104
2104 Examples:
2105 Examples:
2105
2106
2106 - forget newly-added binary files::
2107 - forget newly-added binary files::
2107
2108
2108 hg forget "set:added() and binary()"
2109 hg forget "set:added() and binary()"
2109
2110
2110 - forget files that would be excluded by .hgignore::
2111 - forget files that would be excluded by .hgignore::
2111
2112
2112 hg forget "set:hgignore()"
2113 hg forget "set:hgignore()"
2113
2114
2114 Returns 0 on success.
2115 Returns 0 on success.
2115 """
2116 """
2116
2117
2117 if not pats:
2118 if not pats:
2118 raise error.Abort(_('no files specified'))
2119 raise error.Abort(_('no files specified'))
2119
2120
2120 m = scmutil.match(repo[None], pats, opts)
2121 m = scmutil.match(repo[None], pats, opts)
2121 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2122 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2122 return rejected and 1 or 0
2123 return rejected and 1 or 0
2123
2124
2124 @command(
2125 @command(
2125 'graft',
2126 'graft',
2126 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2127 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2127 ('c', 'continue', False, _('resume interrupted graft')),
2128 ('c', 'continue', False, _('resume interrupted graft')),
2128 ('e', 'edit', False, _('invoke editor on commit messages')),
2129 ('e', 'edit', False, _('invoke editor on commit messages')),
2129 ('', 'log', None, _('append graft info to log message')),
2130 ('', 'log', None, _('append graft info to log message')),
2130 ('f', 'force', False, _('force graft')),
2131 ('f', 'force', False, _('force graft')),
2131 ('D', 'currentdate', False,
2132 ('D', 'currentdate', False,
2132 _('record the current date as commit date')),
2133 _('record the current date as commit date')),
2133 ('U', 'currentuser', False,
2134 ('U', 'currentuser', False,
2134 _('record the current user as committer'), _('DATE'))]
2135 _('record the current user as committer'), _('DATE'))]
2135 + commitopts2 + mergetoolopts + dryrunopts,
2136 + commitopts2 + mergetoolopts + dryrunopts,
2136 _('[OPTION]... [-r REV]... REV...'))
2137 _('[OPTION]... [-r REV]... REV...'))
2137 def graft(ui, repo, *revs, **opts):
2138 def graft(ui, repo, *revs, **opts):
2138 '''copy changes from other branches onto the current branch
2139 '''copy changes from other branches onto the current branch
2139
2140
2140 This command uses Mercurial's merge logic to copy individual
2141 This command uses Mercurial's merge logic to copy individual
2141 changes from other branches without merging branches in the
2142 changes from other branches without merging branches in the
2142 history graph. This is sometimes known as 'backporting' or
2143 history graph. This is sometimes known as 'backporting' or
2143 'cherry-picking'. By default, graft will copy user, date, and
2144 'cherry-picking'. By default, graft will copy user, date, and
2144 description from the source changesets.
2145 description from the source changesets.
2145
2146
2146 Changesets that are ancestors of the current revision, that have
2147 Changesets that are ancestors of the current revision, that have
2147 already been grafted, or that are merges will be skipped.
2148 already been grafted, or that are merges will be skipped.
2148
2149
2149 If --log is specified, log messages will have a comment appended
2150 If --log is specified, log messages will have a comment appended
2150 of the form::
2151 of the form::
2151
2152
2152 (grafted from CHANGESETHASH)
2153 (grafted from CHANGESETHASH)
2153
2154
2154 If --force is specified, revisions will be grafted even if they
2155 If --force is specified, revisions will be grafted even if they
2155 are already ancestors of or have been grafted to the destination.
2156 are already ancestors of or have been grafted to the destination.
2156 This is useful when the revisions have since been backed out.
2157 This is useful when the revisions have since been backed out.
2157
2158
2158 If a graft merge results in conflicts, the graft process is
2159 If a graft merge results in conflicts, the graft process is
2159 interrupted so that the current merge can be manually resolved.
2160 interrupted so that the current merge can be manually resolved.
2160 Once all conflicts are addressed, the graft process can be
2161 Once all conflicts are addressed, the graft process can be
2161 continued with the -c/--continue option.
2162 continued with the -c/--continue option.
2162
2163
2163 .. note::
2164 .. note::
2164
2165
2165 The -c/--continue option does not reapply earlier options, except
2166 The -c/--continue option does not reapply earlier options, except
2166 for --force.
2167 for --force.
2167
2168
2168 .. container:: verbose
2169 .. container:: verbose
2169
2170
2170 Examples:
2171 Examples:
2171
2172
2172 - copy a single change to the stable branch and edit its description::
2173 - copy a single change to the stable branch and edit its description::
2173
2174
2174 hg update stable
2175 hg update stable
2175 hg graft --edit 9393
2176 hg graft --edit 9393
2176
2177
2177 - graft a range of changesets with one exception, updating dates::
2178 - graft a range of changesets with one exception, updating dates::
2178
2179
2179 hg graft -D "2085::2093 and not 2091"
2180 hg graft -D "2085::2093 and not 2091"
2180
2181
2181 - continue a graft after resolving conflicts::
2182 - continue a graft after resolving conflicts::
2182
2183
2183 hg graft -c
2184 hg graft -c
2184
2185
2185 - show the source of a grafted changeset::
2186 - show the source of a grafted changeset::
2186
2187
2187 hg log --debug -r .
2188 hg log --debug -r .
2188
2189
2189 - show revisions sorted by date::
2190 - show revisions sorted by date::
2190
2191
2191 hg log -r "sort(all(), date)"
2192 hg log -r "sort(all(), date)"
2192
2193
2193 See :hg:`help revisions` for more about specifying revisions.
2194 See :hg:`help revisions` for more about specifying revisions.
2194
2195
2195 Returns 0 on successful completion.
2196 Returns 0 on successful completion.
2196 '''
2197 '''
2197 with repo.wlock():
2198 with repo.wlock():
2198 return _dograft(ui, repo, *revs, **opts)
2199 return _dograft(ui, repo, *revs, **opts)
2199
2200
2200 def _dograft(ui, repo, *revs, **opts):
2201 def _dograft(ui, repo, *revs, **opts):
2201 if revs and opts.get('rev'):
2202 if revs and opts.get('rev'):
2202 ui.warn(_('warning: inconsistent use of --rev might give unexpected '
2203 ui.warn(_('warning: inconsistent use of --rev might give unexpected '
2203 'revision ordering!\n'))
2204 'revision ordering!\n'))
2204
2205
2205 revs = list(revs)
2206 revs = list(revs)
2206 revs.extend(opts.get('rev'))
2207 revs.extend(opts.get('rev'))
2207
2208
2208 if not opts.get('user') and opts.get('currentuser'):
2209 if not opts.get('user') and opts.get('currentuser'):
2209 opts['user'] = ui.username()
2210 opts['user'] = ui.username()
2210 if not opts.get('date') and opts.get('currentdate'):
2211 if not opts.get('date') and opts.get('currentdate'):
2211 opts['date'] = "%d %d" % util.makedate()
2212 opts['date'] = "%d %d" % util.makedate()
2212
2213
2213 editor = cmdutil.getcommiteditor(editform='graft', **opts)
2214 editor = cmdutil.getcommiteditor(editform='graft', **opts)
2214
2215
2215 cont = False
2216 cont = False
2216 if opts.get('continue'):
2217 if opts.get('continue'):
2217 cont = True
2218 cont = True
2218 if revs:
2219 if revs:
2219 raise error.Abort(_("can't specify --continue and revisions"))
2220 raise error.Abort(_("can't specify --continue and revisions"))
2220 # read in unfinished revisions
2221 # read in unfinished revisions
2221 try:
2222 try:
2222 nodes = repo.vfs.read('graftstate').splitlines()
2223 nodes = repo.vfs.read('graftstate').splitlines()
2223 revs = [repo[node].rev() for node in nodes]
2224 revs = [repo[node].rev() for node in nodes]
2224 except IOError as inst:
2225 except IOError as inst:
2225 if inst.errno != errno.ENOENT:
2226 if inst.errno != errno.ENOENT:
2226 raise
2227 raise
2227 cmdutil.wrongtooltocontinue(repo, _('graft'))
2228 cmdutil.wrongtooltocontinue(repo, _('graft'))
2228 else:
2229 else:
2229 cmdutil.checkunfinished(repo)
2230 cmdutil.checkunfinished(repo)
2230 cmdutil.bailifchanged(repo)
2231 cmdutil.bailifchanged(repo)
2231 if not revs:
2232 if not revs:
2232 raise error.Abort(_('no revisions specified'))
2233 raise error.Abort(_('no revisions specified'))
2233 revs = scmutil.revrange(repo, revs)
2234 revs = scmutil.revrange(repo, revs)
2234
2235
2235 skipped = set()
2236 skipped = set()
2236 # check for merges
2237 # check for merges
2237 for rev in repo.revs('%ld and merge()', revs):
2238 for rev in repo.revs('%ld and merge()', revs):
2238 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2239 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2239 skipped.add(rev)
2240 skipped.add(rev)
2240 revs = [r for r in revs if r not in skipped]
2241 revs = [r for r in revs if r not in skipped]
2241 if not revs:
2242 if not revs:
2242 return -1
2243 return -1
2243
2244
2244 # Don't check in the --continue case, in effect retaining --force across
2245 # Don't check in the --continue case, in effect retaining --force across
2245 # --continues. That's because without --force, any revisions we decided to
2246 # --continues. That's because without --force, any revisions we decided to
2246 # skip would have been filtered out here, so they wouldn't have made their
2247 # skip would have been filtered out here, so they wouldn't have made their
2247 # way to the graftstate. With --force, any revisions we would have otherwise
2248 # way to the graftstate. With --force, any revisions we would have otherwise
2248 # skipped would not have been filtered out, and if they hadn't been applied
2249 # skipped would not have been filtered out, and if they hadn't been applied
2249 # already, they'd have been in the graftstate.
2250 # already, they'd have been in the graftstate.
2250 if not (cont or opts.get('force')):
2251 if not (cont or opts.get('force')):
2251 # check for ancestors of dest branch
2252 # check for ancestors of dest branch
2252 crev = repo['.'].rev()
2253 crev = repo['.'].rev()
2253 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2254 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2254 # XXX make this lazy in the future
2255 # XXX make this lazy in the future
2255 # don't mutate while iterating, create a copy
2256 # don't mutate while iterating, create a copy
2256 for rev in list(revs):
2257 for rev in list(revs):
2257 if rev in ancestors:
2258 if rev in ancestors:
2258 ui.warn(_('skipping ancestor revision %d:%s\n') %
2259 ui.warn(_('skipping ancestor revision %d:%s\n') %
2259 (rev, repo[rev]))
2260 (rev, repo[rev]))
2260 # XXX remove on list is slow
2261 # XXX remove on list is slow
2261 revs.remove(rev)
2262 revs.remove(rev)
2262 if not revs:
2263 if not revs:
2263 return -1
2264 return -1
2264
2265
2265 # analyze revs for earlier grafts
2266 # analyze revs for earlier grafts
2266 ids = {}
2267 ids = {}
2267 for ctx in repo.set("%ld", revs):
2268 for ctx in repo.set("%ld", revs):
2268 ids[ctx.hex()] = ctx.rev()
2269 ids[ctx.hex()] = ctx.rev()
2269 n = ctx.extra().get('source')
2270 n = ctx.extra().get('source')
2270 if n:
2271 if n:
2271 ids[n] = ctx.rev()
2272 ids[n] = ctx.rev()
2272
2273
2273 # check ancestors for earlier grafts
2274 # check ancestors for earlier grafts
2274 ui.debug('scanning for duplicate grafts\n')
2275 ui.debug('scanning for duplicate grafts\n')
2275
2276
2276 for rev in repo.changelog.findmissingrevs(revs, [crev]):
2277 for rev in repo.changelog.findmissingrevs(revs, [crev]):
2277 ctx = repo[rev]
2278 ctx = repo[rev]
2278 n = ctx.extra().get('source')
2279 n = ctx.extra().get('source')
2279 if n in ids:
2280 if n in ids:
2280 try:
2281 try:
2281 r = repo[n].rev()
2282 r = repo[n].rev()
2282 except error.RepoLookupError:
2283 except error.RepoLookupError:
2283 r = None
2284 r = None
2284 if r in revs:
2285 if r in revs:
2285 ui.warn(_('skipping revision %d:%s '
2286 ui.warn(_('skipping revision %d:%s '
2286 '(already grafted to %d:%s)\n')
2287 '(already grafted to %d:%s)\n')
2287 % (r, repo[r], rev, ctx))
2288 % (r, repo[r], rev, ctx))
2288 revs.remove(r)
2289 revs.remove(r)
2289 elif ids[n] in revs:
2290 elif ids[n] in revs:
2290 if r is None:
2291 if r is None:
2291 ui.warn(_('skipping already grafted revision %d:%s '
2292 ui.warn(_('skipping already grafted revision %d:%s '
2292 '(%d:%s also has unknown origin %s)\n')
2293 '(%d:%s also has unknown origin %s)\n')
2293 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
2294 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
2294 else:
2295 else:
2295 ui.warn(_('skipping already grafted revision %d:%s '
2296 ui.warn(_('skipping already grafted revision %d:%s '
2296 '(%d:%s also has origin %d:%s)\n')
2297 '(%d:%s also has origin %d:%s)\n')
2297 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
2298 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
2298 revs.remove(ids[n])
2299 revs.remove(ids[n])
2299 elif ctx.hex() in ids:
2300 elif ctx.hex() in ids:
2300 r = ids[ctx.hex()]
2301 r = ids[ctx.hex()]
2301 ui.warn(_('skipping already grafted revision %d:%s '
2302 ui.warn(_('skipping already grafted revision %d:%s '
2302 '(was grafted from %d:%s)\n') %
2303 '(was grafted from %d:%s)\n') %
2303 (r, repo[r], rev, ctx))
2304 (r, repo[r], rev, ctx))
2304 revs.remove(r)
2305 revs.remove(r)
2305 if not revs:
2306 if not revs:
2306 return -1
2307 return -1
2307
2308
2308 for pos, ctx in enumerate(repo.set("%ld", revs)):
2309 for pos, ctx in enumerate(repo.set("%ld", revs)):
2309 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
2310 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
2310 ctx.description().split('\n', 1)[0])
2311 ctx.description().split('\n', 1)[0])
2311 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
2312 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
2312 if names:
2313 if names:
2313 desc += ' (%s)' % ' '.join(names)
2314 desc += ' (%s)' % ' '.join(names)
2314 ui.status(_('grafting %s\n') % desc)
2315 ui.status(_('grafting %s\n') % desc)
2315 if opts.get('dry_run'):
2316 if opts.get('dry_run'):
2316 continue
2317 continue
2317
2318
2318 source = ctx.extra().get('source')
2319 source = ctx.extra().get('source')
2319 extra = {}
2320 extra = {}
2320 if source:
2321 if source:
2321 extra['source'] = source
2322 extra['source'] = source
2322 extra['intermediate-source'] = ctx.hex()
2323 extra['intermediate-source'] = ctx.hex()
2323 else:
2324 else:
2324 extra['source'] = ctx.hex()
2325 extra['source'] = ctx.hex()
2325 user = ctx.user()
2326 user = ctx.user()
2326 if opts.get('user'):
2327 if opts.get('user'):
2327 user = opts['user']
2328 user = opts['user']
2328 date = ctx.date()
2329 date = ctx.date()
2329 if opts.get('date'):
2330 if opts.get('date'):
2330 date = opts['date']
2331 date = opts['date']
2331 message = ctx.description()
2332 message = ctx.description()
2332 if opts.get('log'):
2333 if opts.get('log'):
2333 message += '\n(grafted from %s)' % ctx.hex()
2334 message += '\n(grafted from %s)' % ctx.hex()
2334
2335
2335 # we don't merge the first commit when continuing
2336 # we don't merge the first commit when continuing
2336 if not cont:
2337 if not cont:
2337 # perform the graft merge with p1(rev) as 'ancestor'
2338 # perform the graft merge with p1(rev) as 'ancestor'
2338 try:
2339 try:
2339 # ui.forcemerge is an internal variable, do not document
2340 # ui.forcemerge is an internal variable, do not document
2340 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
2341 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
2341 'graft')
2342 'graft')
2342 stats = mergemod.graft(repo, ctx, ctx.p1(),
2343 stats = mergemod.graft(repo, ctx, ctx.p1(),
2343 ['local', 'graft'])
2344 ['local', 'graft'])
2344 finally:
2345 finally:
2345 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
2346 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
2346 # report any conflicts
2347 # report any conflicts
2347 if stats and stats[3] > 0:
2348 if stats and stats[3] > 0:
2348 # write out state for --continue
2349 # write out state for --continue
2349 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2350 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2350 repo.vfs.write('graftstate', ''.join(nodelines))
2351 repo.vfs.write('graftstate', ''.join(nodelines))
2351 extra = ''
2352 extra = ''
2352 if opts.get('user'):
2353 if opts.get('user'):
2353 extra += ' --user %s' % util.shellquote(opts['user'])
2354 extra += ' --user %s' % util.shellquote(opts['user'])
2354 if opts.get('date'):
2355 if opts.get('date'):
2355 extra += ' --date %s' % util.shellquote(opts['date'])
2356 extra += ' --date %s' % util.shellquote(opts['date'])
2356 if opts.get('log'):
2357 if opts.get('log'):
2357 extra += ' --log'
2358 extra += ' --log'
2358 hint=_("use 'hg resolve' and 'hg graft --continue%s'") % extra
2359 hint=_("use 'hg resolve' and 'hg graft --continue%s'") % extra
2359 raise error.Abort(
2360 raise error.Abort(
2360 _("unresolved conflicts, can't continue"),
2361 _("unresolved conflicts, can't continue"),
2361 hint=hint)
2362 hint=hint)
2362 else:
2363 else:
2363 cont = False
2364 cont = False
2364
2365
2365 # commit
2366 # commit
2366 node = repo.commit(text=message, user=user,
2367 node = repo.commit(text=message, user=user,
2367 date=date, extra=extra, editor=editor)
2368 date=date, extra=extra, editor=editor)
2368 if node is None:
2369 if node is None:
2369 ui.warn(
2370 ui.warn(
2370 _('note: graft of %d:%s created no changes to commit\n') %
2371 _('note: graft of %d:%s created no changes to commit\n') %
2371 (ctx.rev(), ctx))
2372 (ctx.rev(), ctx))
2372
2373
2373 # remove state when we complete successfully
2374 # remove state when we complete successfully
2374 if not opts.get('dry_run'):
2375 if not opts.get('dry_run'):
2375 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
2376 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
2376
2377
2377 return 0
2378 return 0
2378
2379
2379 @command('grep',
2380 @command('grep',
2380 [('0', 'print0', None, _('end fields with NUL')),
2381 [('0', 'print0', None, _('end fields with NUL')),
2381 ('', 'all', None, _('print all revisions that match')),
2382 ('', 'all', None, _('print all revisions that match')),
2382 ('a', 'text', None, _('treat all files as text')),
2383 ('a', 'text', None, _('treat all files as text')),
2383 ('f', 'follow', None,
2384 ('f', 'follow', None,
2384 _('follow changeset history,'
2385 _('follow changeset history,'
2385 ' or file history across copies and renames')),
2386 ' or file history across copies and renames')),
2386 ('i', 'ignore-case', None, _('ignore case when matching')),
2387 ('i', 'ignore-case', None, _('ignore case when matching')),
2387 ('l', 'files-with-matches', None,
2388 ('l', 'files-with-matches', None,
2388 _('print only filenames and revisions that match')),
2389 _('print only filenames and revisions that match')),
2389 ('n', 'line-number', None, _('print matching line numbers')),
2390 ('n', 'line-number', None, _('print matching line numbers')),
2390 ('r', 'rev', [],
2391 ('r', 'rev', [],
2391 _('only search files changed within revision range'), _('REV')),
2392 _('only search files changed within revision range'), _('REV')),
2392 ('u', 'user', None, _('list the author (long with -v)')),
2393 ('u', 'user', None, _('list the author (long with -v)')),
2393 ('d', 'date', None, _('list the date (short with -q)')),
2394 ('d', 'date', None, _('list the date (short with -q)')),
2394 ] + formatteropts + walkopts,
2395 ] + formatteropts + walkopts,
2395 _('[OPTION]... PATTERN [FILE]...'),
2396 _('[OPTION]... PATTERN [FILE]...'),
2396 inferrepo=True)
2397 inferrepo=True)
2397 def grep(ui, repo, pattern, *pats, **opts):
2398 def grep(ui, repo, pattern, *pats, **opts):
2398 """search revision history for a pattern in specified files
2399 """search revision history for a pattern in specified files
2399
2400
2400 Search revision history for a regular expression in the specified
2401 Search revision history for a regular expression in the specified
2401 files or the entire project.
2402 files or the entire project.
2402
2403
2403 By default, grep prints the most recent revision number for each
2404 By default, grep prints the most recent revision number for each
2404 file in which it finds a match. To get it to print every revision
2405 file in which it finds a match. To get it to print every revision
2405 that contains a change in match status ("-" for a match that becomes
2406 that contains a change in match status ("-" for a match that becomes
2406 a non-match, or "+" for a non-match that becomes a match), use the
2407 a non-match, or "+" for a non-match that becomes a match), use the
2407 --all flag.
2408 --all flag.
2408
2409
2409 PATTERN can be any Python (roughly Perl-compatible) regular
2410 PATTERN can be any Python (roughly Perl-compatible) regular
2410 expression.
2411 expression.
2411
2412
2412 If no FILEs are specified (and -f/--follow isn't set), all files in
2413 If no FILEs are specified (and -f/--follow isn't set), all files in
2413 the repository are searched, including those that don't exist in the
2414 the repository are searched, including those that don't exist in the
2414 current branch or have been deleted in a prior changeset.
2415 current branch or have been deleted in a prior changeset.
2415
2416
2416 Returns 0 if a match is found, 1 otherwise.
2417 Returns 0 if a match is found, 1 otherwise.
2417 """
2418 """
2418 reflags = re.M
2419 reflags = re.M
2419 if opts.get('ignore_case'):
2420 if opts.get('ignore_case'):
2420 reflags |= re.I
2421 reflags |= re.I
2421 try:
2422 try:
2422 regexp = util.re.compile(pattern, reflags)
2423 regexp = util.re.compile(pattern, reflags)
2423 except re.error as inst:
2424 except re.error as inst:
2424 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2425 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2425 return 1
2426 return 1
2426 sep, eol = ':', '\n'
2427 sep, eol = ':', '\n'
2427 if opts.get('print0'):
2428 if opts.get('print0'):
2428 sep = eol = '\0'
2429 sep = eol = '\0'
2429
2430
2430 getfile = util.lrucachefunc(repo.file)
2431 getfile = util.lrucachefunc(repo.file)
2431
2432
2432 def matchlines(body):
2433 def matchlines(body):
2433 begin = 0
2434 begin = 0
2434 linenum = 0
2435 linenum = 0
2435 while begin < len(body):
2436 while begin < len(body):
2436 match = regexp.search(body, begin)
2437 match = regexp.search(body, begin)
2437 if not match:
2438 if not match:
2438 break
2439 break
2439 mstart, mend = match.span()
2440 mstart, mend = match.span()
2440 linenum += body.count('\n', begin, mstart) + 1
2441 linenum += body.count('\n', begin, mstart) + 1
2441 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2442 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2442 begin = body.find('\n', mend) + 1 or len(body) + 1
2443 begin = body.find('\n', mend) + 1 or len(body) + 1
2443 lend = begin - 1
2444 lend = begin - 1
2444 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2445 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2445
2446
2446 class linestate(object):
2447 class linestate(object):
2447 def __init__(self, line, linenum, colstart, colend):
2448 def __init__(self, line, linenum, colstart, colend):
2448 self.line = line
2449 self.line = line
2449 self.linenum = linenum
2450 self.linenum = linenum
2450 self.colstart = colstart
2451 self.colstart = colstart
2451 self.colend = colend
2452 self.colend = colend
2452
2453
2453 def __hash__(self):
2454 def __hash__(self):
2454 return hash((self.linenum, self.line))
2455 return hash((self.linenum, self.line))
2455
2456
2456 def __eq__(self, other):
2457 def __eq__(self, other):
2457 return self.line == other.line
2458 return self.line == other.line
2458
2459
2459 def findpos(self):
2460 def findpos(self):
2460 """Iterate all (start, end) indices of matches"""
2461 """Iterate all (start, end) indices of matches"""
2461 yield self.colstart, self.colend
2462 yield self.colstart, self.colend
2462 p = self.colend
2463 p = self.colend
2463 while p < len(self.line):
2464 while p < len(self.line):
2464 m = regexp.search(self.line, p)
2465 m = regexp.search(self.line, p)
2465 if not m:
2466 if not m:
2466 break
2467 break
2467 yield m.span()
2468 yield m.span()
2468 p = m.end()
2469 p = m.end()
2469
2470
2470 matches = {}
2471 matches = {}
2471 copies = {}
2472 copies = {}
2472 def grepbody(fn, rev, body):
2473 def grepbody(fn, rev, body):
2473 matches[rev].setdefault(fn, [])
2474 matches[rev].setdefault(fn, [])
2474 m = matches[rev][fn]
2475 m = matches[rev][fn]
2475 for lnum, cstart, cend, line in matchlines(body):
2476 for lnum, cstart, cend, line in matchlines(body):
2476 s = linestate(line, lnum, cstart, cend)
2477 s = linestate(line, lnum, cstart, cend)
2477 m.append(s)
2478 m.append(s)
2478
2479
2479 def difflinestates(a, b):
2480 def difflinestates(a, b):
2480 sm = difflib.SequenceMatcher(None, a, b)
2481 sm = difflib.SequenceMatcher(None, a, b)
2481 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2482 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2482 if tag == 'insert':
2483 if tag == 'insert':
2483 for i in xrange(blo, bhi):
2484 for i in xrange(blo, bhi):
2484 yield ('+', b[i])
2485 yield ('+', b[i])
2485 elif tag == 'delete':
2486 elif tag == 'delete':
2486 for i in xrange(alo, ahi):
2487 for i in xrange(alo, ahi):
2487 yield ('-', a[i])
2488 yield ('-', a[i])
2488 elif tag == 'replace':
2489 elif tag == 'replace':
2489 for i in xrange(alo, ahi):
2490 for i in xrange(alo, ahi):
2490 yield ('-', a[i])
2491 yield ('-', a[i])
2491 for i in xrange(blo, bhi):
2492 for i in xrange(blo, bhi):
2492 yield ('+', b[i])
2493 yield ('+', b[i])
2493
2494
2494 def display(fm, fn, ctx, pstates, states):
2495 def display(fm, fn, ctx, pstates, states):
2495 rev = ctx.rev()
2496 rev = ctx.rev()
2496 if fm.isplain():
2497 if fm.isplain():
2497 formatuser = ui.shortuser
2498 formatuser = ui.shortuser
2498 else:
2499 else:
2499 formatuser = str
2500 formatuser = str
2500 if ui.quiet:
2501 if ui.quiet:
2501 datefmt = '%Y-%m-%d'
2502 datefmt = '%Y-%m-%d'
2502 else:
2503 else:
2503 datefmt = '%a %b %d %H:%M:%S %Y %1%2'
2504 datefmt = '%a %b %d %H:%M:%S %Y %1%2'
2504 found = False
2505 found = False
2505 @util.cachefunc
2506 @util.cachefunc
2506 def binary():
2507 def binary():
2507 flog = getfile(fn)
2508 flog = getfile(fn)
2508 return util.binary(flog.read(ctx.filenode(fn)))
2509 return util.binary(flog.read(ctx.filenode(fn)))
2509
2510
2510 fieldnamemap = {'filename': 'file', 'linenumber': 'line_number'}
2511 fieldnamemap = {'filename': 'file', 'linenumber': 'line_number'}
2511 if opts.get('all'):
2512 if opts.get('all'):
2512 iter = difflinestates(pstates, states)
2513 iter = difflinestates(pstates, states)
2513 else:
2514 else:
2514 iter = [('', l) for l in states]
2515 iter = [('', l) for l in states]
2515 for change, l in iter:
2516 for change, l in iter:
2516 fm.startitem()
2517 fm.startitem()
2517 fm.data(node=fm.hexfunc(ctx.node()))
2518 fm.data(node=fm.hexfunc(ctx.node()))
2518 cols = [
2519 cols = [
2519 ('filename', fn, True),
2520 ('filename', fn, True),
2520 ('rev', rev, True),
2521 ('rev', rev, True),
2521 ('linenumber', l.linenum, opts.get('line_number')),
2522 ('linenumber', l.linenum, opts.get('line_number')),
2522 ]
2523 ]
2523 if opts.get('all'):
2524 if opts.get('all'):
2524 cols.append(('change', change, True))
2525 cols.append(('change', change, True))
2525 cols.extend([
2526 cols.extend([
2526 ('user', formatuser(ctx.user()), opts.get('user')),
2527 ('user', formatuser(ctx.user()), opts.get('user')),
2527 ('date', fm.formatdate(ctx.date(), datefmt), opts.get('date')),
2528 ('date', fm.formatdate(ctx.date(), datefmt), opts.get('date')),
2528 ])
2529 ])
2529 lastcol = next(name for name, data, cond in reversed(cols) if cond)
2530 lastcol = next(name for name, data, cond in reversed(cols) if cond)
2530 for name, data, cond in cols:
2531 for name, data, cond in cols:
2531 field = fieldnamemap.get(name, name)
2532 field = fieldnamemap.get(name, name)
2532 fm.condwrite(cond, field, '%s', data, label='grep.%s' % name)
2533 fm.condwrite(cond, field, '%s', data, label='grep.%s' % name)
2533 if cond and name != lastcol:
2534 if cond and name != lastcol:
2534 fm.plain(sep, label='grep.sep')
2535 fm.plain(sep, label='grep.sep')
2535 if not opts.get('files_with_matches'):
2536 if not opts.get('files_with_matches'):
2536 fm.plain(sep, label='grep.sep')
2537 fm.plain(sep, label='grep.sep')
2537 if not opts.get('text') and binary():
2538 if not opts.get('text') and binary():
2538 fm.plain(_(" Binary file matches"))
2539 fm.plain(_(" Binary file matches"))
2539 else:
2540 else:
2540 displaymatches(fm.nested('texts'), l)
2541 displaymatches(fm.nested('texts'), l)
2541 fm.plain(eol)
2542 fm.plain(eol)
2542 found = True
2543 found = True
2543 if opts.get('files_with_matches'):
2544 if opts.get('files_with_matches'):
2544 break
2545 break
2545 return found
2546 return found
2546
2547
2547 def displaymatches(fm, l):
2548 def displaymatches(fm, l):
2548 p = 0
2549 p = 0
2549 for s, e in l.findpos():
2550 for s, e in l.findpos():
2550 if p < s:
2551 if p < s:
2551 fm.startitem()
2552 fm.startitem()
2552 fm.write('text', '%s', l.line[p:s])
2553 fm.write('text', '%s', l.line[p:s])
2553 fm.data(matched=False)
2554 fm.data(matched=False)
2554 fm.startitem()
2555 fm.startitem()
2555 fm.write('text', '%s', l.line[s:e], label='grep.match')
2556 fm.write('text', '%s', l.line[s:e], label='grep.match')
2556 fm.data(matched=True)
2557 fm.data(matched=True)
2557 p = e
2558 p = e
2558 if p < len(l.line):
2559 if p < len(l.line):
2559 fm.startitem()
2560 fm.startitem()
2560 fm.write('text', '%s', l.line[p:])
2561 fm.write('text', '%s', l.line[p:])
2561 fm.data(matched=False)
2562 fm.data(matched=False)
2562 fm.end()
2563 fm.end()
2563
2564
2564 skip = {}
2565 skip = {}
2565 revfiles = {}
2566 revfiles = {}
2566 matchfn = scmutil.match(repo[None], pats, opts)
2567 matchfn = scmutil.match(repo[None], pats, opts)
2567 found = False
2568 found = False
2568 follow = opts.get('follow')
2569 follow = opts.get('follow')
2569
2570
2570 def prep(ctx, fns):
2571 def prep(ctx, fns):
2571 rev = ctx.rev()
2572 rev = ctx.rev()
2572 pctx = ctx.p1()
2573 pctx = ctx.p1()
2573 parent = pctx.rev()
2574 parent = pctx.rev()
2574 matches.setdefault(rev, {})
2575 matches.setdefault(rev, {})
2575 matches.setdefault(parent, {})
2576 matches.setdefault(parent, {})
2576 files = revfiles.setdefault(rev, [])
2577 files = revfiles.setdefault(rev, [])
2577 for fn in fns:
2578 for fn in fns:
2578 flog = getfile(fn)
2579 flog = getfile(fn)
2579 try:
2580 try:
2580 fnode = ctx.filenode(fn)
2581 fnode = ctx.filenode(fn)
2581 except error.LookupError:
2582 except error.LookupError:
2582 continue
2583 continue
2583
2584
2584 copied = flog.renamed(fnode)
2585 copied = flog.renamed(fnode)
2585 copy = follow and copied and copied[0]
2586 copy = follow and copied and copied[0]
2586 if copy:
2587 if copy:
2587 copies.setdefault(rev, {})[fn] = copy
2588 copies.setdefault(rev, {})[fn] = copy
2588 if fn in skip:
2589 if fn in skip:
2589 if copy:
2590 if copy:
2590 skip[copy] = True
2591 skip[copy] = True
2591 continue
2592 continue
2592 files.append(fn)
2593 files.append(fn)
2593
2594
2594 if fn not in matches[rev]:
2595 if fn not in matches[rev]:
2595 grepbody(fn, rev, flog.read(fnode))
2596 grepbody(fn, rev, flog.read(fnode))
2596
2597
2597 pfn = copy or fn
2598 pfn = copy or fn
2598 if pfn not in matches[parent]:
2599 if pfn not in matches[parent]:
2599 try:
2600 try:
2600 fnode = pctx.filenode(pfn)
2601 fnode = pctx.filenode(pfn)
2601 grepbody(pfn, parent, flog.read(fnode))
2602 grepbody(pfn, parent, flog.read(fnode))
2602 except error.LookupError:
2603 except error.LookupError:
2603 pass
2604 pass
2604
2605
2605 fm = ui.formatter('grep', opts)
2606 fm = ui.formatter('grep', opts)
2606 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2607 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2607 rev = ctx.rev()
2608 rev = ctx.rev()
2608 parent = ctx.p1().rev()
2609 parent = ctx.p1().rev()
2609 for fn in sorted(revfiles.get(rev, [])):
2610 for fn in sorted(revfiles.get(rev, [])):
2610 states = matches[rev][fn]
2611 states = matches[rev][fn]
2611 copy = copies.get(rev, {}).get(fn)
2612 copy = copies.get(rev, {}).get(fn)
2612 if fn in skip:
2613 if fn in skip:
2613 if copy:
2614 if copy:
2614 skip[copy] = True
2615 skip[copy] = True
2615 continue
2616 continue
2616 pstates = matches.get(parent, {}).get(copy or fn, [])
2617 pstates = matches.get(parent, {}).get(copy or fn, [])
2617 if pstates or states:
2618 if pstates or states:
2618 r = display(fm, fn, ctx, pstates, states)
2619 r = display(fm, fn, ctx, pstates, states)
2619 found = found or r
2620 found = found or r
2620 if r and not opts.get('all'):
2621 if r and not opts.get('all'):
2621 skip[fn] = True
2622 skip[fn] = True
2622 if copy:
2623 if copy:
2623 skip[copy] = True
2624 skip[copy] = True
2624 del matches[rev]
2625 del matches[rev]
2625 del revfiles[rev]
2626 del revfiles[rev]
2626 fm.end()
2627 fm.end()
2627
2628
2628 return not found
2629 return not found
2629
2630
2630 @command('heads',
2631 @command('heads',
2631 [('r', 'rev', '',
2632 [('r', 'rev', '',
2632 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2633 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2633 ('t', 'topo', False, _('show topological heads only')),
2634 ('t', 'topo', False, _('show topological heads only')),
2634 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2635 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2635 ('c', 'closed', False, _('show normal and closed branch heads')),
2636 ('c', 'closed', False, _('show normal and closed branch heads')),
2636 ] + templateopts,
2637 ] + templateopts,
2637 _('[-ct] [-r STARTREV] [REV]...'))
2638 _('[-ct] [-r STARTREV] [REV]...'))
2638 def heads(ui, repo, *branchrevs, **opts):
2639 def heads(ui, repo, *branchrevs, **opts):
2639 """show branch heads
2640 """show branch heads
2640
2641
2641 With no arguments, show all open branch heads in the repository.
2642 With no arguments, show all open branch heads in the repository.
2642 Branch heads are changesets that have no descendants on the
2643 Branch heads are changesets that have no descendants on the
2643 same branch. They are where development generally takes place and
2644 same branch. They are where development generally takes place and
2644 are the usual targets for update and merge operations.
2645 are the usual targets for update and merge operations.
2645
2646
2646 If one or more REVs are given, only open branch heads on the
2647 If one or more REVs are given, only open branch heads on the
2647 branches associated with the specified changesets are shown. This
2648 branches associated with the specified changesets are shown. This
2648 means that you can use :hg:`heads .` to see the heads on the
2649 means that you can use :hg:`heads .` to see the heads on the
2649 currently checked-out branch.
2650 currently checked-out branch.
2650
2651
2651 If -c/--closed is specified, also show branch heads marked closed
2652 If -c/--closed is specified, also show branch heads marked closed
2652 (see :hg:`commit --close-branch`).
2653 (see :hg:`commit --close-branch`).
2653
2654
2654 If STARTREV is specified, only those heads that are descendants of
2655 If STARTREV is specified, only those heads that are descendants of
2655 STARTREV will be displayed.
2656 STARTREV will be displayed.
2656
2657
2657 If -t/--topo is specified, named branch mechanics will be ignored and only
2658 If -t/--topo is specified, named branch mechanics will be ignored and only
2658 topological heads (changesets with no children) will be shown.
2659 topological heads (changesets with no children) will be shown.
2659
2660
2660 Returns 0 if matching heads are found, 1 if not.
2661 Returns 0 if matching heads are found, 1 if not.
2661 """
2662 """
2662
2663
2663 start = None
2664 start = None
2664 if 'rev' in opts:
2665 if 'rev' in opts:
2665 start = scmutil.revsingle(repo, opts['rev'], None).node()
2666 start = scmutil.revsingle(repo, opts['rev'], None).node()
2666
2667
2667 if opts.get('topo'):
2668 if opts.get('topo'):
2668 heads = [repo[h] for h in repo.heads(start)]
2669 heads = [repo[h] for h in repo.heads(start)]
2669 else:
2670 else:
2670 heads = []
2671 heads = []
2671 for branch in repo.branchmap():
2672 for branch in repo.branchmap():
2672 heads += repo.branchheads(branch, start, opts.get('closed'))
2673 heads += repo.branchheads(branch, start, opts.get('closed'))
2673 heads = [repo[h] for h in heads]
2674 heads = [repo[h] for h in heads]
2674
2675
2675 if branchrevs:
2676 if branchrevs:
2676 branches = set(repo[br].branch() for br in branchrevs)
2677 branches = set(repo[br].branch() for br in branchrevs)
2677 heads = [h for h in heads if h.branch() in branches]
2678 heads = [h for h in heads if h.branch() in branches]
2678
2679
2679 if opts.get('active') and branchrevs:
2680 if opts.get('active') and branchrevs:
2680 dagheads = repo.heads(start)
2681 dagheads = repo.heads(start)
2681 heads = [h for h in heads if h.node() in dagheads]
2682 heads = [h for h in heads if h.node() in dagheads]
2682
2683
2683 if branchrevs:
2684 if branchrevs:
2684 haveheads = set(h.branch() for h in heads)
2685 haveheads = set(h.branch() for h in heads)
2685 if branches - haveheads:
2686 if branches - haveheads:
2686 headless = ', '.join(b for b in branches - haveheads)
2687 headless = ', '.join(b for b in branches - haveheads)
2687 msg = _('no open branch heads found on branches %s')
2688 msg = _('no open branch heads found on branches %s')
2688 if opts.get('rev'):
2689 if opts.get('rev'):
2689 msg += _(' (started at %s)') % opts['rev']
2690 msg += _(' (started at %s)') % opts['rev']
2690 ui.warn((msg + '\n') % headless)
2691 ui.warn((msg + '\n') % headless)
2691
2692
2692 if not heads:
2693 if not heads:
2693 return 1
2694 return 1
2694
2695
2695 heads = sorted(heads, key=lambda x: -x.rev())
2696 heads = sorted(heads, key=lambda x: -x.rev())
2696 displayer = cmdutil.show_changeset(ui, repo, opts)
2697 displayer = cmdutil.show_changeset(ui, repo, opts)
2697 for ctx in heads:
2698 for ctx in heads:
2698 displayer.show(ctx)
2699 displayer.show(ctx)
2699 displayer.close()
2700 displayer.close()
2700
2701
2701 @command('help',
2702 @command('help',
2702 [('e', 'extension', None, _('show only help for extensions')),
2703 [('e', 'extension', None, _('show only help for extensions')),
2703 ('c', 'command', None, _('show only help for commands')),
2704 ('c', 'command', None, _('show only help for commands')),
2704 ('k', 'keyword', None, _('show topics matching keyword')),
2705 ('k', 'keyword', None, _('show topics matching keyword')),
2705 ('s', 'system', [], _('show help for specific platform(s)')),
2706 ('s', 'system', [], _('show help for specific platform(s)')),
2706 ],
2707 ],
2707 _('[-ecks] [TOPIC]'),
2708 _('[-ecks] [TOPIC]'),
2708 norepo=True)
2709 norepo=True)
2709 def help_(ui, name=None, **opts):
2710 def help_(ui, name=None, **opts):
2710 """show help for a given topic or a help overview
2711 """show help for a given topic or a help overview
2711
2712
2712 With no arguments, print a list of commands with short help messages.
2713 With no arguments, print a list of commands with short help messages.
2713
2714
2714 Given a topic, extension, or command name, print help for that
2715 Given a topic, extension, or command name, print help for that
2715 topic.
2716 topic.
2716
2717
2717 Returns 0 if successful.
2718 Returns 0 if successful.
2718 """
2719 """
2719
2720
2720 textwidth = ui.configint('ui', 'textwidth', 78)
2721 textwidth = ui.configint('ui', 'textwidth', 78)
2721 termwidth = ui.termwidth() - 2
2722 termwidth = ui.termwidth() - 2
2722 if textwidth <= 0 or termwidth < textwidth:
2723 if textwidth <= 0 or termwidth < textwidth:
2723 textwidth = termwidth
2724 textwidth = termwidth
2724
2725
2725 keep = opts.get('system') or []
2726 keep = opts.get('system') or []
2726 if len(keep) == 0:
2727 if len(keep) == 0:
2727 if pycompat.sysplatform.startswith('win'):
2728 if pycompat.sysplatform.startswith('win'):
2728 keep.append('windows')
2729 keep.append('windows')
2729 elif pycompat.sysplatform == 'OpenVMS':
2730 elif pycompat.sysplatform == 'OpenVMS':
2730 keep.append('vms')
2731 keep.append('vms')
2731 elif pycompat.sysplatform == 'plan9':
2732 elif pycompat.sysplatform == 'plan9':
2732 keep.append('plan9')
2733 keep.append('plan9')
2733 else:
2734 else:
2734 keep.append('unix')
2735 keep.append('unix')
2735 keep.append(pycompat.sysplatform.lower())
2736 keep.append(pycompat.sysplatform.lower())
2736 if ui.verbose:
2737 if ui.verbose:
2737 keep.append('verbose')
2738 keep.append('verbose')
2738
2739
2739 fullname = name
2740 fullname = name
2740 section = None
2741 section = None
2741 subtopic = None
2742 subtopic = None
2742 if name and '.' in name:
2743 if name and '.' in name:
2743 name, remaining = name.split('.', 1)
2744 name, remaining = name.split('.', 1)
2744 remaining = encoding.lower(remaining)
2745 remaining = encoding.lower(remaining)
2745 if '.' in remaining:
2746 if '.' in remaining:
2746 subtopic, section = remaining.split('.', 1)
2747 subtopic, section = remaining.split('.', 1)
2747 else:
2748 else:
2748 if name in help.subtopics:
2749 if name in help.subtopics:
2749 subtopic = remaining
2750 subtopic = remaining
2750 else:
2751 else:
2751 section = remaining
2752 section = remaining
2752
2753
2753 text = help.help_(ui, name, subtopic=subtopic, **opts)
2754 text = help.help_(ui, name, subtopic=subtopic, **opts)
2754
2755
2755 formatted, pruned = minirst.format(text, textwidth, keep=keep,
2756 formatted, pruned = minirst.format(text, textwidth, keep=keep,
2756 section=section)
2757 section=section)
2757
2758
2758 # We could have been given a weird ".foo" section without a name
2759 # We could have been given a weird ".foo" section without a name
2759 # to look for, or we could have simply failed to found "foo.bar"
2760 # to look for, or we could have simply failed to found "foo.bar"
2760 # because bar isn't a section of foo
2761 # because bar isn't a section of foo
2761 if section and not (formatted and name):
2762 if section and not (formatted and name):
2762 raise error.Abort(_("help section not found: %s") % fullname)
2763 raise error.Abort(_("help section not found: %s") % fullname)
2763
2764
2764 if 'verbose' in pruned:
2765 if 'verbose' in pruned:
2765 keep.append('omitted')
2766 keep.append('omitted')
2766 else:
2767 else:
2767 keep.append('notomitted')
2768 keep.append('notomitted')
2768 formatted, pruned = minirst.format(text, textwidth, keep=keep,
2769 formatted, pruned = minirst.format(text, textwidth, keep=keep,
2769 section=section)
2770 section=section)
2770 ui.write(formatted)
2771 ui.write(formatted)
2771
2772
2772
2773
2773 @command('identify|id',
2774 @command('identify|id',
2774 [('r', 'rev', '',
2775 [('r', 'rev', '',
2775 _('identify the specified revision'), _('REV')),
2776 _('identify the specified revision'), _('REV')),
2776 ('n', 'num', None, _('show local revision number')),
2777 ('n', 'num', None, _('show local revision number')),
2777 ('i', 'id', None, _('show global revision id')),
2778 ('i', 'id', None, _('show global revision id')),
2778 ('b', 'branch', None, _('show branch')),
2779 ('b', 'branch', None, _('show branch')),
2779 ('t', 'tags', None, _('show tags')),
2780 ('t', 'tags', None, _('show tags')),
2780 ('B', 'bookmarks', None, _('show bookmarks')),
2781 ('B', 'bookmarks', None, _('show bookmarks')),
2781 ] + remoteopts,
2782 ] + remoteopts,
2782 _('[-nibtB] [-r REV] [SOURCE]'),
2783 _('[-nibtB] [-r REV] [SOURCE]'),
2783 optionalrepo=True)
2784 optionalrepo=True)
2784 def identify(ui, repo, source=None, rev=None,
2785 def identify(ui, repo, source=None, rev=None,
2785 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
2786 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
2786 """identify the working directory or specified revision
2787 """identify the working directory or specified revision
2787
2788
2788 Print a summary identifying the repository state at REV using one or
2789 Print a summary identifying the repository state at REV using one or
2789 two parent hash identifiers, followed by a "+" if the working
2790 two parent hash identifiers, followed by a "+" if the working
2790 directory has uncommitted changes, the branch name (if not default),
2791 directory has uncommitted changes, the branch name (if not default),
2791 a list of tags, and a list of bookmarks.
2792 a list of tags, and a list of bookmarks.
2792
2793
2793 When REV is not given, print a summary of the current state of the
2794 When REV is not given, print a summary of the current state of the
2794 repository.
2795 repository.
2795
2796
2796 Specifying a path to a repository root or Mercurial bundle will
2797 Specifying a path to a repository root or Mercurial bundle will
2797 cause lookup to operate on that repository/bundle.
2798 cause lookup to operate on that repository/bundle.
2798
2799
2799 .. container:: verbose
2800 .. container:: verbose
2800
2801
2801 Examples:
2802 Examples:
2802
2803
2803 - generate a build identifier for the working directory::
2804 - generate a build identifier for the working directory::
2804
2805
2805 hg id --id > build-id.dat
2806 hg id --id > build-id.dat
2806
2807
2807 - find the revision corresponding to a tag::
2808 - find the revision corresponding to a tag::
2808
2809
2809 hg id -n -r 1.3
2810 hg id -n -r 1.3
2810
2811
2811 - check the most recent revision of a remote repository::
2812 - check the most recent revision of a remote repository::
2812
2813
2813 hg id -r tip https://www.mercurial-scm.org/repo/hg/
2814 hg id -r tip https://www.mercurial-scm.org/repo/hg/
2814
2815
2815 See :hg:`log` for generating more information about specific revisions,
2816 See :hg:`log` for generating more information about specific revisions,
2816 including full hash identifiers.
2817 including full hash identifiers.
2817
2818
2818 Returns 0 if successful.
2819 Returns 0 if successful.
2819 """
2820 """
2820
2821
2821 if not repo and not source:
2822 if not repo and not source:
2822 raise error.Abort(_("there is no Mercurial repository here "
2823 raise error.Abort(_("there is no Mercurial repository here "
2823 "(.hg not found)"))
2824 "(.hg not found)"))
2824
2825
2825 if ui.debugflag:
2826 if ui.debugflag:
2826 hexfunc = hex
2827 hexfunc = hex
2827 else:
2828 else:
2828 hexfunc = short
2829 hexfunc = short
2829 default = not (num or id or branch or tags or bookmarks)
2830 default = not (num or id or branch or tags or bookmarks)
2830 output = []
2831 output = []
2831 revs = []
2832 revs = []
2832
2833
2833 if source:
2834 if source:
2834 source, branches = hg.parseurl(ui.expandpath(source))
2835 source, branches = hg.parseurl(ui.expandpath(source))
2835 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
2836 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
2836 repo = peer.local()
2837 repo = peer.local()
2837 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
2838 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
2838
2839
2839 if not repo:
2840 if not repo:
2840 if num or branch or tags:
2841 if num or branch or tags:
2841 raise error.Abort(
2842 raise error.Abort(
2842 _("can't query remote revision number, branch, or tags"))
2843 _("can't query remote revision number, branch, or tags"))
2843 if not rev and revs:
2844 if not rev and revs:
2844 rev = revs[0]
2845 rev = revs[0]
2845 if not rev:
2846 if not rev:
2846 rev = "tip"
2847 rev = "tip"
2847
2848
2848 remoterev = peer.lookup(rev)
2849 remoterev = peer.lookup(rev)
2849 if default or id:
2850 if default or id:
2850 output = [hexfunc(remoterev)]
2851 output = [hexfunc(remoterev)]
2851
2852
2852 def getbms():
2853 def getbms():
2853 bms = []
2854 bms = []
2854
2855
2855 if 'bookmarks' in peer.listkeys('namespaces'):
2856 if 'bookmarks' in peer.listkeys('namespaces'):
2856 hexremoterev = hex(remoterev)
2857 hexremoterev = hex(remoterev)
2857 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
2858 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
2858 if bmr == hexremoterev]
2859 if bmr == hexremoterev]
2859
2860
2860 return sorted(bms)
2861 return sorted(bms)
2861
2862
2862 if bookmarks:
2863 if bookmarks:
2863 output.extend(getbms())
2864 output.extend(getbms())
2864 elif default and not ui.quiet:
2865 elif default and not ui.quiet:
2865 # multiple bookmarks for a single parent separated by '/'
2866 # multiple bookmarks for a single parent separated by '/'
2866 bm = '/'.join(getbms())
2867 bm = '/'.join(getbms())
2867 if bm:
2868 if bm:
2868 output.append(bm)
2869 output.append(bm)
2869 else:
2870 else:
2870 ctx = scmutil.revsingle(repo, rev, None)
2871 ctx = scmutil.revsingle(repo, rev, None)
2871
2872
2872 if ctx.rev() is None:
2873 if ctx.rev() is None:
2873 ctx = repo[None]
2874 ctx = repo[None]
2874 parents = ctx.parents()
2875 parents = ctx.parents()
2875 taglist = []
2876 taglist = []
2876 for p in parents:
2877 for p in parents:
2877 taglist.extend(p.tags())
2878 taglist.extend(p.tags())
2878
2879
2879 changed = ""
2880 changed = ""
2880 if default or id or num:
2881 if default or id or num:
2881 if (any(repo.status())
2882 if (any(repo.status())
2882 or any(ctx.sub(s).dirty() for s in ctx.substate)):
2883 or any(ctx.sub(s).dirty() for s in ctx.substate)):
2883 changed = '+'
2884 changed = '+'
2884 if default or id:
2885 if default or id:
2885 output = ["%s%s" %
2886 output = ["%s%s" %
2886 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
2887 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
2887 if num:
2888 if num:
2888 output.append("%s%s" %
2889 output.append("%s%s" %
2889 ('+'.join([str(p.rev()) for p in parents]), changed))
2890 ('+'.join([str(p.rev()) for p in parents]), changed))
2890 else:
2891 else:
2891 if default or id:
2892 if default or id:
2892 output = [hexfunc(ctx.node())]
2893 output = [hexfunc(ctx.node())]
2893 if num:
2894 if num:
2894 output.append(str(ctx.rev()))
2895 output.append(str(ctx.rev()))
2895 taglist = ctx.tags()
2896 taglist = ctx.tags()
2896
2897
2897 if default and not ui.quiet:
2898 if default and not ui.quiet:
2898 b = ctx.branch()
2899 b = ctx.branch()
2899 if b != 'default':
2900 if b != 'default':
2900 output.append("(%s)" % b)
2901 output.append("(%s)" % b)
2901
2902
2902 # multiple tags for a single parent separated by '/'
2903 # multiple tags for a single parent separated by '/'
2903 t = '/'.join(taglist)
2904 t = '/'.join(taglist)
2904 if t:
2905 if t:
2905 output.append(t)
2906 output.append(t)
2906
2907
2907 # multiple bookmarks for a single parent separated by '/'
2908 # multiple bookmarks for a single parent separated by '/'
2908 bm = '/'.join(ctx.bookmarks())
2909 bm = '/'.join(ctx.bookmarks())
2909 if bm:
2910 if bm:
2910 output.append(bm)
2911 output.append(bm)
2911 else:
2912 else:
2912 if branch:
2913 if branch:
2913 output.append(ctx.branch())
2914 output.append(ctx.branch())
2914
2915
2915 if tags:
2916 if tags:
2916 output.extend(taglist)
2917 output.extend(taglist)
2917
2918
2918 if bookmarks:
2919 if bookmarks:
2919 output.extend(ctx.bookmarks())
2920 output.extend(ctx.bookmarks())
2920
2921
2921 ui.write("%s\n" % ' '.join(output))
2922 ui.write("%s\n" % ' '.join(output))
2922
2923
2923 @command('import|patch',
2924 @command('import|patch',
2924 [('p', 'strip', 1,
2925 [('p', 'strip', 1,
2925 _('directory strip option for patch. This has the same '
2926 _('directory strip option for patch. This has the same '
2926 'meaning as the corresponding patch option'), _('NUM')),
2927 'meaning as the corresponding patch option'), _('NUM')),
2927 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
2928 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
2928 ('e', 'edit', False, _('invoke editor on commit messages')),
2929 ('e', 'edit', False, _('invoke editor on commit messages')),
2929 ('f', 'force', None,
2930 ('f', 'force', None,
2930 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
2931 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
2931 ('', 'no-commit', None,
2932 ('', 'no-commit', None,
2932 _("don't commit, just update the working directory")),
2933 _("don't commit, just update the working directory")),
2933 ('', 'bypass', None,
2934 ('', 'bypass', None,
2934 _("apply patch without touching the working directory")),
2935 _("apply patch without touching the working directory")),
2935 ('', 'partial', None,
2936 ('', 'partial', None,
2936 _('commit even if some hunks fail')),
2937 _('commit even if some hunks fail')),
2937 ('', 'exact', None,
2938 ('', 'exact', None,
2938 _('abort if patch would apply lossily')),
2939 _('abort if patch would apply lossily')),
2939 ('', 'prefix', '',
2940 ('', 'prefix', '',
2940 _('apply patch to subdirectory'), _('DIR')),
2941 _('apply patch to subdirectory'), _('DIR')),
2941 ('', 'import-branch', None,
2942 ('', 'import-branch', None,
2942 _('use any branch information in patch (implied by --exact)'))] +
2943 _('use any branch information in patch (implied by --exact)'))] +
2943 commitopts + commitopts2 + similarityopts,
2944 commitopts + commitopts2 + similarityopts,
2944 _('[OPTION]... PATCH...'))
2945 _('[OPTION]... PATCH...'))
2945 def import_(ui, repo, patch1=None, *patches, **opts):
2946 def import_(ui, repo, patch1=None, *patches, **opts):
2946 """import an ordered set of patches
2947 """import an ordered set of patches
2947
2948
2948 Import a list of patches and commit them individually (unless
2949 Import a list of patches and commit them individually (unless
2949 --no-commit is specified).
2950 --no-commit is specified).
2950
2951
2951 To read a patch from standard input (stdin), use "-" as the patch
2952 To read a patch from standard input (stdin), use "-" as the patch
2952 name. If a URL is specified, the patch will be downloaded from
2953 name. If a URL is specified, the patch will be downloaded from
2953 there.
2954 there.
2954
2955
2955 Import first applies changes to the working directory (unless
2956 Import first applies changes to the working directory (unless
2956 --bypass is specified), import will abort if there are outstanding
2957 --bypass is specified), import will abort if there are outstanding
2957 changes.
2958 changes.
2958
2959
2959 Use --bypass to apply and commit patches directly to the
2960 Use --bypass to apply and commit patches directly to the
2960 repository, without affecting the working directory. Without
2961 repository, without affecting the working directory. Without
2961 --exact, patches will be applied on top of the working directory
2962 --exact, patches will be applied on top of the working directory
2962 parent revision.
2963 parent revision.
2963
2964
2964 You can import a patch straight from a mail message. Even patches
2965 You can import a patch straight from a mail message. Even patches
2965 as attachments work (to use the body part, it must have type
2966 as attachments work (to use the body part, it must have type
2966 text/plain or text/x-patch). From and Subject headers of email
2967 text/plain or text/x-patch). From and Subject headers of email
2967 message are used as default committer and commit message. All
2968 message are used as default committer and commit message. All
2968 text/plain body parts before first diff are added to the commit
2969 text/plain body parts before first diff are added to the commit
2969 message.
2970 message.
2970
2971
2971 If the imported patch was generated by :hg:`export`, user and
2972 If the imported patch was generated by :hg:`export`, user and
2972 description from patch override values from message headers and
2973 description from patch override values from message headers and
2973 body. Values given on command line with -m/--message and -u/--user
2974 body. Values given on command line with -m/--message and -u/--user
2974 override these.
2975 override these.
2975
2976
2976 If --exact is specified, import will set the working directory to
2977 If --exact is specified, import will set the working directory to
2977 the parent of each patch before applying it, and will abort if the
2978 the parent of each patch before applying it, and will abort if the
2978 resulting changeset has a different ID than the one recorded in
2979 resulting changeset has a different ID than the one recorded in
2979 the patch. This will guard against various ways that portable
2980 the patch. This will guard against various ways that portable
2980 patch formats and mail systems might fail to transfer Mercurial
2981 patch formats and mail systems might fail to transfer Mercurial
2981 data or metadata. See :hg:`bundle` for lossless transmission.
2982 data or metadata. See :hg:`bundle` for lossless transmission.
2982
2983
2983 Use --partial to ensure a changeset will be created from the patch
2984 Use --partial to ensure a changeset will be created from the patch
2984 even if some hunks fail to apply. Hunks that fail to apply will be
2985 even if some hunks fail to apply. Hunks that fail to apply will be
2985 written to a <target-file>.rej file. Conflicts can then be resolved
2986 written to a <target-file>.rej file. Conflicts can then be resolved
2986 by hand before :hg:`commit --amend` is run to update the created
2987 by hand before :hg:`commit --amend` is run to update the created
2987 changeset. This flag exists to let people import patches that
2988 changeset. This flag exists to let people import patches that
2988 partially apply without losing the associated metadata (author,
2989 partially apply without losing the associated metadata (author,
2989 date, description, ...).
2990 date, description, ...).
2990
2991
2991 .. note::
2992 .. note::
2992
2993
2993 When no hunks apply cleanly, :hg:`import --partial` will create
2994 When no hunks apply cleanly, :hg:`import --partial` will create
2994 an empty changeset, importing only the patch metadata.
2995 an empty changeset, importing only the patch metadata.
2995
2996
2996 With -s/--similarity, hg will attempt to discover renames and
2997 With -s/--similarity, hg will attempt to discover renames and
2997 copies in the patch in the same way as :hg:`addremove`.
2998 copies in the patch in the same way as :hg:`addremove`.
2998
2999
2999 It is possible to use external patch programs to perform the patch
3000 It is possible to use external patch programs to perform the patch
3000 by setting the ``ui.patch`` configuration option. For the default
3001 by setting the ``ui.patch`` configuration option. For the default
3001 internal tool, the fuzz can also be configured via ``patch.fuzz``.
3002 internal tool, the fuzz can also be configured via ``patch.fuzz``.
3002 See :hg:`help config` for more information about configuration
3003 See :hg:`help config` for more information about configuration
3003 files and how to use these options.
3004 files and how to use these options.
3004
3005
3005 See :hg:`help dates` for a list of formats valid for -d/--date.
3006 See :hg:`help dates` for a list of formats valid for -d/--date.
3006
3007
3007 .. container:: verbose
3008 .. container:: verbose
3008
3009
3009 Examples:
3010 Examples:
3010
3011
3011 - import a traditional patch from a website and detect renames::
3012 - import a traditional patch from a website and detect renames::
3012
3013
3013 hg import -s 80 http://example.com/bugfix.patch
3014 hg import -s 80 http://example.com/bugfix.patch
3014
3015
3015 - import a changeset from an hgweb server::
3016 - import a changeset from an hgweb server::
3016
3017
3017 hg import https://www.mercurial-scm.org/repo/hg/rev/5ca8c111e9aa
3018 hg import https://www.mercurial-scm.org/repo/hg/rev/5ca8c111e9aa
3018
3019
3019 - import all the patches in an Unix-style mbox::
3020 - import all the patches in an Unix-style mbox::
3020
3021
3021 hg import incoming-patches.mbox
3022 hg import incoming-patches.mbox
3022
3023
3023 - import patches from stdin::
3024 - import patches from stdin::
3024
3025
3025 hg import -
3026 hg import -
3026
3027
3027 - attempt to exactly restore an exported changeset (not always
3028 - attempt to exactly restore an exported changeset (not always
3028 possible)::
3029 possible)::
3029
3030
3030 hg import --exact proposed-fix.patch
3031 hg import --exact proposed-fix.patch
3031
3032
3032 - use an external tool to apply a patch which is too fuzzy for
3033 - use an external tool to apply a patch which is too fuzzy for
3033 the default internal tool.
3034 the default internal tool.
3034
3035
3035 hg import --config ui.patch="patch --merge" fuzzy.patch
3036 hg import --config ui.patch="patch --merge" fuzzy.patch
3036
3037
3037 - change the default fuzzing from 2 to a less strict 7
3038 - change the default fuzzing from 2 to a less strict 7
3038
3039
3039 hg import --config ui.fuzz=7 fuzz.patch
3040 hg import --config ui.fuzz=7 fuzz.patch
3040
3041
3041 Returns 0 on success, 1 on partial success (see --partial).
3042 Returns 0 on success, 1 on partial success (see --partial).
3042 """
3043 """
3043
3044
3044 if not patch1:
3045 if not patch1:
3045 raise error.Abort(_('need at least one patch to import'))
3046 raise error.Abort(_('need at least one patch to import'))
3046
3047
3047 patches = (patch1,) + patches
3048 patches = (patch1,) + patches
3048
3049
3049 date = opts.get('date')
3050 date = opts.get('date')
3050 if date:
3051 if date:
3051 opts['date'] = util.parsedate(date)
3052 opts['date'] = util.parsedate(date)
3052
3053
3053 exact = opts.get('exact')
3054 exact = opts.get('exact')
3054 update = not opts.get('bypass')
3055 update = not opts.get('bypass')
3055 if not update and opts.get('no_commit'):
3056 if not update and opts.get('no_commit'):
3056 raise error.Abort(_('cannot use --no-commit with --bypass'))
3057 raise error.Abort(_('cannot use --no-commit with --bypass'))
3057 try:
3058 try:
3058 sim = float(opts.get('similarity') or 0)
3059 sim = float(opts.get('similarity') or 0)
3059 except ValueError:
3060 except ValueError:
3060 raise error.Abort(_('similarity must be a number'))
3061 raise error.Abort(_('similarity must be a number'))
3061 if sim < 0 or sim > 100:
3062 if sim < 0 or sim > 100:
3062 raise error.Abort(_('similarity must be between 0 and 100'))
3063 raise error.Abort(_('similarity must be between 0 and 100'))
3063 if sim and not update:
3064 if sim and not update:
3064 raise error.Abort(_('cannot use --similarity with --bypass'))
3065 raise error.Abort(_('cannot use --similarity with --bypass'))
3065 if exact:
3066 if exact:
3066 if opts.get('edit'):
3067 if opts.get('edit'):
3067 raise error.Abort(_('cannot use --exact with --edit'))
3068 raise error.Abort(_('cannot use --exact with --edit'))
3068 if opts.get('prefix'):
3069 if opts.get('prefix'):
3069 raise error.Abort(_('cannot use --exact with --prefix'))
3070 raise error.Abort(_('cannot use --exact with --prefix'))
3070
3071
3071 base = opts["base"]
3072 base = opts["base"]
3072 wlock = dsguard = lock = tr = None
3073 wlock = dsguard = lock = tr = None
3073 msgs = []
3074 msgs = []
3074 ret = 0
3075 ret = 0
3075
3076
3076
3077
3077 try:
3078 try:
3078 wlock = repo.wlock()
3079 wlock = repo.wlock()
3079
3080
3080 if update:
3081 if update:
3081 cmdutil.checkunfinished(repo)
3082 cmdutil.checkunfinished(repo)
3082 if (exact or not opts.get('force')):
3083 if (exact or not opts.get('force')):
3083 cmdutil.bailifchanged(repo)
3084 cmdutil.bailifchanged(repo)
3084
3085
3085 if not opts.get('no_commit'):
3086 if not opts.get('no_commit'):
3086 lock = repo.lock()
3087 lock = repo.lock()
3087 tr = repo.transaction('import')
3088 tr = repo.transaction('import')
3088 else:
3089 else:
3089 dsguard = dirstateguard.dirstateguard(repo, 'import')
3090 dsguard = dirstateguard.dirstateguard(repo, 'import')
3090 parents = repo[None].parents()
3091 parents = repo[None].parents()
3091 for patchurl in patches:
3092 for patchurl in patches:
3092 if patchurl == '-':
3093 if patchurl == '-':
3093 ui.status(_('applying patch from stdin\n'))
3094 ui.status(_('applying patch from stdin\n'))
3094 patchfile = ui.fin
3095 patchfile = ui.fin
3095 patchurl = 'stdin' # for error message
3096 patchurl = 'stdin' # for error message
3096 else:
3097 else:
3097 patchurl = os.path.join(base, patchurl)
3098 patchurl = os.path.join(base, patchurl)
3098 ui.status(_('applying %s\n') % patchurl)
3099 ui.status(_('applying %s\n') % patchurl)
3099 patchfile = hg.openpath(ui, patchurl)
3100 patchfile = hg.openpath(ui, patchurl)
3100
3101
3101 haspatch = False
3102 haspatch = False
3102 for hunk in patch.split(patchfile):
3103 for hunk in patch.split(patchfile):
3103 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
3104 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
3104 parents, opts,
3105 parents, opts,
3105 msgs, hg.clean)
3106 msgs, hg.clean)
3106 if msg:
3107 if msg:
3107 haspatch = True
3108 haspatch = True
3108 ui.note(msg + '\n')
3109 ui.note(msg + '\n')
3109 if update or exact:
3110 if update or exact:
3110 parents = repo[None].parents()
3111 parents = repo[None].parents()
3111 else:
3112 else:
3112 parents = [repo[node]]
3113 parents = [repo[node]]
3113 if rej:
3114 if rej:
3114 ui.write_err(_("patch applied partially\n"))
3115 ui.write_err(_("patch applied partially\n"))
3115 ui.write_err(_("(fix the .rej files and run "
3116 ui.write_err(_("(fix the .rej files and run "
3116 "`hg commit --amend`)\n"))
3117 "`hg commit --amend`)\n"))
3117 ret = 1
3118 ret = 1
3118 break
3119 break
3119
3120
3120 if not haspatch:
3121 if not haspatch:
3121 raise error.Abort(_('%s: no diffs found') % patchurl)
3122 raise error.Abort(_('%s: no diffs found') % patchurl)
3122
3123
3123 if tr:
3124 if tr:
3124 tr.close()
3125 tr.close()
3125 if msgs:
3126 if msgs:
3126 repo.savecommitmessage('\n* * *\n'.join(msgs))
3127 repo.savecommitmessage('\n* * *\n'.join(msgs))
3127 if dsguard:
3128 if dsguard:
3128 dsguard.close()
3129 dsguard.close()
3129 return ret
3130 return ret
3130 finally:
3131 finally:
3131 if tr:
3132 if tr:
3132 tr.release()
3133 tr.release()
3133 release(lock, dsguard, wlock)
3134 release(lock, dsguard, wlock)
3134
3135
3135 @command('incoming|in',
3136 @command('incoming|in',
3136 [('f', 'force', None,
3137 [('f', 'force', None,
3137 _('run even if remote repository is unrelated')),
3138 _('run even if remote repository is unrelated')),
3138 ('n', 'newest-first', None, _('show newest record first')),
3139 ('n', 'newest-first', None, _('show newest record first')),
3139 ('', 'bundle', '',
3140 ('', 'bundle', '',
3140 _('file to store the bundles into'), _('FILE')),
3141 _('file to store the bundles into'), _('FILE')),
3141 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3142 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3142 ('B', 'bookmarks', False, _("compare bookmarks")),
3143 ('B', 'bookmarks', False, _("compare bookmarks")),
3143 ('b', 'branch', [],
3144 ('b', 'branch', [],
3144 _('a specific branch you would like to pull'), _('BRANCH')),
3145 _('a specific branch you would like to pull'), _('BRANCH')),
3145 ] + logopts + remoteopts + subrepoopts,
3146 ] + logopts + remoteopts + subrepoopts,
3146 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3147 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3147 def incoming(ui, repo, source="default", **opts):
3148 def incoming(ui, repo, source="default", **opts):
3148 """show new changesets found in source
3149 """show new changesets found in source
3149
3150
3150 Show new changesets found in the specified path/URL or the default
3151 Show new changesets found in the specified path/URL or the default
3151 pull location. These are the changesets that would have been pulled
3152 pull location. These are the changesets that would have been pulled
3152 if a pull at the time you issued this command.
3153 if a pull at the time you issued this command.
3153
3154
3154 See pull for valid source format details.
3155 See pull for valid source format details.
3155
3156
3156 .. container:: verbose
3157 .. container:: verbose
3157
3158
3158 With -B/--bookmarks, the result of bookmark comparison between
3159 With -B/--bookmarks, the result of bookmark comparison between
3159 local and remote repositories is displayed. With -v/--verbose,
3160 local and remote repositories is displayed. With -v/--verbose,
3160 status is also displayed for each bookmark like below::
3161 status is also displayed for each bookmark like below::
3161
3162
3162 BM1 01234567890a added
3163 BM1 01234567890a added
3163 BM2 1234567890ab advanced
3164 BM2 1234567890ab advanced
3164 BM3 234567890abc diverged
3165 BM3 234567890abc diverged
3165 BM4 34567890abcd changed
3166 BM4 34567890abcd changed
3166
3167
3167 The action taken locally when pulling depends on the
3168 The action taken locally when pulling depends on the
3168 status of each bookmark:
3169 status of each bookmark:
3169
3170
3170 :``added``: pull will create it
3171 :``added``: pull will create it
3171 :``advanced``: pull will update it
3172 :``advanced``: pull will update it
3172 :``diverged``: pull will create a divergent bookmark
3173 :``diverged``: pull will create a divergent bookmark
3173 :``changed``: result depends on remote changesets
3174 :``changed``: result depends on remote changesets
3174
3175
3175 From the point of view of pulling behavior, bookmark
3176 From the point of view of pulling behavior, bookmark
3176 existing only in the remote repository are treated as ``added``,
3177 existing only in the remote repository are treated as ``added``,
3177 even if it is in fact locally deleted.
3178 even if it is in fact locally deleted.
3178
3179
3179 .. container:: verbose
3180 .. container:: verbose
3180
3181
3181 For remote repository, using --bundle avoids downloading the
3182 For remote repository, using --bundle avoids downloading the
3182 changesets twice if the incoming is followed by a pull.
3183 changesets twice if the incoming is followed by a pull.
3183
3184
3184 Examples:
3185 Examples:
3185
3186
3186 - show incoming changes with patches and full description::
3187 - show incoming changes with patches and full description::
3187
3188
3188 hg incoming -vp
3189 hg incoming -vp
3189
3190
3190 - show incoming changes excluding merges, store a bundle::
3191 - show incoming changes excluding merges, store a bundle::
3191
3192
3192 hg in -vpM --bundle incoming.hg
3193 hg in -vpM --bundle incoming.hg
3193 hg pull incoming.hg
3194 hg pull incoming.hg
3194
3195
3195 - briefly list changes inside a bundle::
3196 - briefly list changes inside a bundle::
3196
3197
3197 hg in changes.hg -T "{desc|firstline}\\n"
3198 hg in changes.hg -T "{desc|firstline}\\n"
3198
3199
3199 Returns 0 if there are incoming changes, 1 otherwise.
3200 Returns 0 if there are incoming changes, 1 otherwise.
3200 """
3201 """
3201 if opts.get('graph'):
3202 if opts.get('graph'):
3202 cmdutil.checkunsupportedgraphflags([], opts)
3203 cmdutil.checkunsupportedgraphflags([], opts)
3203 def display(other, chlist, displayer):
3204 def display(other, chlist, displayer):
3204 revdag = cmdutil.graphrevs(other, chlist, opts)
3205 revdag = cmdutil.graphrevs(other, chlist, opts)
3205 cmdutil.displaygraph(ui, repo, revdag, displayer,
3206 cmdutil.displaygraph(ui, repo, revdag, displayer,
3206 graphmod.asciiedges)
3207 graphmod.asciiedges)
3207
3208
3208 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3209 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3209 return 0
3210 return 0
3210
3211
3211 if opts.get('bundle') and opts.get('subrepos'):
3212 if opts.get('bundle') and opts.get('subrepos'):
3212 raise error.Abort(_('cannot combine --bundle and --subrepos'))
3213 raise error.Abort(_('cannot combine --bundle and --subrepos'))
3213
3214
3214 if opts.get('bookmarks'):
3215 if opts.get('bookmarks'):
3215 source, branches = hg.parseurl(ui.expandpath(source),
3216 source, branches = hg.parseurl(ui.expandpath(source),
3216 opts.get('branch'))
3217 opts.get('branch'))
3217 other = hg.peer(repo, opts, source)
3218 other = hg.peer(repo, opts, source)
3218 if 'bookmarks' not in other.listkeys('namespaces'):
3219 if 'bookmarks' not in other.listkeys('namespaces'):
3219 ui.warn(_("remote doesn't support bookmarks\n"))
3220 ui.warn(_("remote doesn't support bookmarks\n"))
3220 return 0
3221 return 0
3221 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3222 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3222 return bookmarks.incoming(ui, repo, other)
3223 return bookmarks.incoming(ui, repo, other)
3223
3224
3224 repo._subtoppath = ui.expandpath(source)
3225 repo._subtoppath = ui.expandpath(source)
3225 try:
3226 try:
3226 return hg.incoming(ui, repo, source, opts)
3227 return hg.incoming(ui, repo, source, opts)
3227 finally:
3228 finally:
3228 del repo._subtoppath
3229 del repo._subtoppath
3229
3230
3230
3231
3231 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
3232 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
3232 norepo=True)
3233 norepo=True)
3233 def init(ui, dest=".", **opts):
3234 def init(ui, dest=".", **opts):
3234 """create a new repository in the given directory
3235 """create a new repository in the given directory
3235
3236
3236 Initialize a new repository in the given directory. If the given
3237 Initialize a new repository in the given directory. If the given
3237 directory does not exist, it will be created.
3238 directory does not exist, it will be created.
3238
3239
3239 If no directory is given, the current directory is used.
3240 If no directory is given, the current directory is used.
3240
3241
3241 It is possible to specify an ``ssh://`` URL as the destination.
3242 It is possible to specify an ``ssh://`` URL as the destination.
3242 See :hg:`help urls` for more information.
3243 See :hg:`help urls` for more information.
3243
3244
3244 Returns 0 on success.
3245 Returns 0 on success.
3245 """
3246 """
3246 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3247 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3247
3248
3248 @command('locate',
3249 @command('locate',
3249 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3250 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3250 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3251 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3251 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3252 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3252 ] + walkopts,
3253 ] + walkopts,
3253 _('[OPTION]... [PATTERN]...'))
3254 _('[OPTION]... [PATTERN]...'))
3254 def locate(ui, repo, *pats, **opts):
3255 def locate(ui, repo, *pats, **opts):
3255 """locate files matching specific patterns (DEPRECATED)
3256 """locate files matching specific patterns (DEPRECATED)
3256
3257
3257 Print files under Mercurial control in the working directory whose
3258 Print files under Mercurial control in the working directory whose
3258 names match the given patterns.
3259 names match the given patterns.
3259
3260
3260 By default, this command searches all directories in the working
3261 By default, this command searches all directories in the working
3261 directory. To search just the current directory and its
3262 directory. To search just the current directory and its
3262 subdirectories, use "--include .".
3263 subdirectories, use "--include .".
3263
3264
3264 If no patterns are given to match, this command prints the names
3265 If no patterns are given to match, this command prints the names
3265 of all files under Mercurial control in the working directory.
3266 of all files under Mercurial control in the working directory.
3266
3267
3267 If you want to feed the output of this command into the "xargs"
3268 If you want to feed the output of this command into the "xargs"
3268 command, use the -0 option to both this command and "xargs". This
3269 command, use the -0 option to both this command and "xargs". This
3269 will avoid the problem of "xargs" treating single filenames that
3270 will avoid the problem of "xargs" treating single filenames that
3270 contain whitespace as multiple filenames.
3271 contain whitespace as multiple filenames.
3271
3272
3272 See :hg:`help files` for a more versatile command.
3273 See :hg:`help files` for a more versatile command.
3273
3274
3274 Returns 0 if a match is found, 1 otherwise.
3275 Returns 0 if a match is found, 1 otherwise.
3275 """
3276 """
3276 if opts.get('print0'):
3277 if opts.get('print0'):
3277 end = '\0'
3278 end = '\0'
3278 else:
3279 else:
3279 end = '\n'
3280 end = '\n'
3280 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3281 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3281
3282
3282 ret = 1
3283 ret = 1
3283 ctx = repo[rev]
3284 ctx = repo[rev]
3284 m = scmutil.match(ctx, pats, opts, default='relglob',
3285 m = scmutil.match(ctx, pats, opts, default='relglob',
3285 badfn=lambda x, y: False)
3286 badfn=lambda x, y: False)
3286
3287
3287 for abs in ctx.matches(m):
3288 for abs in ctx.matches(m):
3288 if opts.get('fullpath'):
3289 if opts.get('fullpath'):
3289 ui.write(repo.wjoin(abs), end)
3290 ui.write(repo.wjoin(abs), end)
3290 else:
3291 else:
3291 ui.write(((pats and m.rel(abs)) or abs), end)
3292 ui.write(((pats and m.rel(abs)) or abs), end)
3292 ret = 0
3293 ret = 0
3293
3294
3294 return ret
3295 return ret
3295
3296
3296 @command('^log|history',
3297 @command('^log|history',
3297 [('f', 'follow', None,
3298 [('f', 'follow', None,
3298 _('follow changeset history, or file history across copies and renames')),
3299 _('follow changeset history, or file history across copies and renames')),
3299 ('', 'follow-first', None,
3300 ('', 'follow-first', None,
3300 _('only follow the first parent of merge changesets (DEPRECATED)')),
3301 _('only follow the first parent of merge changesets (DEPRECATED)')),
3301 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3302 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3302 ('C', 'copies', None, _('show copied files')),
3303 ('C', 'copies', None, _('show copied files')),
3303 ('k', 'keyword', [],
3304 ('k', 'keyword', [],
3304 _('do case-insensitive search for a given text'), _('TEXT')),
3305 _('do case-insensitive search for a given text'), _('TEXT')),
3305 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
3306 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
3306 ('', 'removed', None, _('include revisions where files were removed')),
3307 ('', 'removed', None, _('include revisions where files were removed')),
3307 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3308 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3308 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3309 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3309 ('', 'only-branch', [],
3310 ('', 'only-branch', [],
3310 _('show only changesets within the given named branch (DEPRECATED)'),
3311 _('show only changesets within the given named branch (DEPRECATED)'),
3311 _('BRANCH')),
3312 _('BRANCH')),
3312 ('b', 'branch', [],
3313 ('b', 'branch', [],
3313 _('show changesets within the given named branch'), _('BRANCH')),
3314 _('show changesets within the given named branch'), _('BRANCH')),
3314 ('P', 'prune', [],
3315 ('P', 'prune', [],
3315 _('do not display revision or any of its ancestors'), _('REV')),
3316 _('do not display revision or any of its ancestors'), _('REV')),
3316 ] + logopts + walkopts,
3317 ] + logopts + walkopts,
3317 _('[OPTION]... [FILE]'),
3318 _('[OPTION]... [FILE]'),
3318 inferrepo=True)
3319 inferrepo=True)
3319 def log(ui, repo, *pats, **opts):
3320 def log(ui, repo, *pats, **opts):
3320 """show revision history of entire repository or files
3321 """show revision history of entire repository or files
3321
3322
3322 Print the revision history of the specified files or the entire
3323 Print the revision history of the specified files or the entire
3323 project.
3324 project.
3324
3325
3325 If no revision range is specified, the default is ``tip:0`` unless
3326 If no revision range is specified, the default is ``tip:0`` unless
3326 --follow is set, in which case the working directory parent is
3327 --follow is set, in which case the working directory parent is
3327 used as the starting revision.
3328 used as the starting revision.
3328
3329
3329 File history is shown without following rename or copy history of
3330 File history is shown without following rename or copy history of
3330 files. Use -f/--follow with a filename to follow history across
3331 files. Use -f/--follow with a filename to follow history across
3331 renames and copies. --follow without a filename will only show
3332 renames and copies. --follow without a filename will only show
3332 ancestors or descendants of the starting revision.
3333 ancestors or descendants of the starting revision.
3333
3334
3334 By default this command prints revision number and changeset id,
3335 By default this command prints revision number and changeset id,
3335 tags, non-trivial parents, user, date and time, and a summary for
3336 tags, non-trivial parents, user, date and time, and a summary for
3336 each commit. When the -v/--verbose switch is used, the list of
3337 each commit. When the -v/--verbose switch is used, the list of
3337 changed files and full commit message are shown.
3338 changed files and full commit message are shown.
3338
3339
3339 With --graph the revisions are shown as an ASCII art DAG with the most
3340 With --graph the revisions are shown as an ASCII art DAG with the most
3340 recent changeset at the top.
3341 recent changeset at the top.
3341 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
3342 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
3342 and '+' represents a fork where the changeset from the lines below is a
3343 and '+' represents a fork where the changeset from the lines below is a
3343 parent of the 'o' merge on the same line.
3344 parent of the 'o' merge on the same line.
3344
3345
3345 .. note::
3346 .. note::
3346
3347
3347 :hg:`log --patch` may generate unexpected diff output for merge
3348 :hg:`log --patch` may generate unexpected diff output for merge
3348 changesets, as it will only compare the merge changeset against
3349 changesets, as it will only compare the merge changeset against
3349 its first parent. Also, only files different from BOTH parents
3350 its first parent. Also, only files different from BOTH parents
3350 will appear in files:.
3351 will appear in files:.
3351
3352
3352 .. note::
3353 .. note::
3353
3354
3354 For performance reasons, :hg:`log FILE` may omit duplicate changes
3355 For performance reasons, :hg:`log FILE` may omit duplicate changes
3355 made on branches and will not show removals or mode changes. To
3356 made on branches and will not show removals or mode changes. To
3356 see all such changes, use the --removed switch.
3357 see all such changes, use the --removed switch.
3357
3358
3358 .. container:: verbose
3359 .. container:: verbose
3359
3360
3360 Some examples:
3361 Some examples:
3361
3362
3362 - changesets with full descriptions and file lists::
3363 - changesets with full descriptions and file lists::
3363
3364
3364 hg log -v
3365 hg log -v
3365
3366
3366 - changesets ancestral to the working directory::
3367 - changesets ancestral to the working directory::
3367
3368
3368 hg log -f
3369 hg log -f
3369
3370
3370 - last 10 commits on the current branch::
3371 - last 10 commits on the current branch::
3371
3372
3372 hg log -l 10 -b .
3373 hg log -l 10 -b .
3373
3374
3374 - changesets showing all modifications of a file, including removals::
3375 - changesets showing all modifications of a file, including removals::
3375
3376
3376 hg log --removed file.c
3377 hg log --removed file.c
3377
3378
3378 - all changesets that touch a directory, with diffs, excluding merges::
3379 - all changesets that touch a directory, with diffs, excluding merges::
3379
3380
3380 hg log -Mp lib/
3381 hg log -Mp lib/
3381
3382
3382 - all revision numbers that match a keyword::
3383 - all revision numbers that match a keyword::
3383
3384
3384 hg log -k bug --template "{rev}\\n"
3385 hg log -k bug --template "{rev}\\n"
3385
3386
3386 - the full hash identifier of the working directory parent::
3387 - the full hash identifier of the working directory parent::
3387
3388
3388 hg log -r . --template "{node}\\n"
3389 hg log -r . --template "{node}\\n"
3389
3390
3390 - list available log templates::
3391 - list available log templates::
3391
3392
3392 hg log -T list
3393 hg log -T list
3393
3394
3394 - check if a given changeset is included in a tagged release::
3395 - check if a given changeset is included in a tagged release::
3395
3396
3396 hg log -r "a21ccf and ancestor(1.9)"
3397 hg log -r "a21ccf and ancestor(1.9)"
3397
3398
3398 - find all changesets by some user in a date range::
3399 - find all changesets by some user in a date range::
3399
3400
3400 hg log -k alice -d "may 2008 to jul 2008"
3401 hg log -k alice -d "may 2008 to jul 2008"
3401
3402
3402 - summary of all changesets after the last tag::
3403 - summary of all changesets after the last tag::
3403
3404
3404 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3405 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3405
3406
3406 See :hg:`help dates` for a list of formats valid for -d/--date.
3407 See :hg:`help dates` for a list of formats valid for -d/--date.
3407
3408
3408 See :hg:`help revisions` for more about specifying and ordering
3409 See :hg:`help revisions` for more about specifying and ordering
3409 revisions.
3410 revisions.
3410
3411
3411 See :hg:`help templates` for more about pre-packaged styles and
3412 See :hg:`help templates` for more about pre-packaged styles and
3412 specifying custom templates.
3413 specifying custom templates.
3413
3414
3414 Returns 0 on success.
3415 Returns 0 on success.
3415
3416
3416 """
3417 """
3417 if opts.get('follow') and opts.get('rev'):
3418 if opts.get('follow') and opts.get('rev'):
3418 opts['rev'] = [revsetlang.formatspec('reverse(::%lr)', opts.get('rev'))]
3419 opts['rev'] = [revsetlang.formatspec('reverse(::%lr)', opts.get('rev'))]
3419 del opts['follow']
3420 del opts['follow']
3420
3421
3421 if opts.get('graph'):
3422 if opts.get('graph'):
3422 return cmdutil.graphlog(ui, repo, *pats, **opts)
3423 return cmdutil.graphlog(ui, repo, *pats, **opts)
3423
3424
3424 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
3425 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
3425 limit = cmdutil.loglimit(opts)
3426 limit = cmdutil.loglimit(opts)
3426 count = 0
3427 count = 0
3427
3428
3428 getrenamed = None
3429 getrenamed = None
3429 if opts.get('copies'):
3430 if opts.get('copies'):
3430 endrev = None
3431 endrev = None
3431 if opts.get('rev'):
3432 if opts.get('rev'):
3432 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
3433 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
3433 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3434 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3434
3435
3435 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
3436 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
3436 for rev in revs:
3437 for rev in revs:
3437 if count == limit:
3438 if count == limit:
3438 break
3439 break
3439 ctx = repo[rev]
3440 ctx = repo[rev]
3440 copies = None
3441 copies = None
3441 if getrenamed is not None and rev:
3442 if getrenamed is not None and rev:
3442 copies = []
3443 copies = []
3443 for fn in ctx.files():
3444 for fn in ctx.files():
3444 rename = getrenamed(fn, rev)
3445 rename = getrenamed(fn, rev)
3445 if rename:
3446 if rename:
3446 copies.append((fn, rename[0]))
3447 copies.append((fn, rename[0]))
3447 if filematcher:
3448 if filematcher:
3448 revmatchfn = filematcher(ctx.rev())
3449 revmatchfn = filematcher(ctx.rev())
3449 else:
3450 else:
3450 revmatchfn = None
3451 revmatchfn = None
3451 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
3452 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
3452 if displayer.flush(ctx):
3453 if displayer.flush(ctx):
3453 count += 1
3454 count += 1
3454
3455
3455 displayer.close()
3456 displayer.close()
3456
3457
3457 @command('manifest',
3458 @command('manifest',
3458 [('r', 'rev', '', _('revision to display'), _('REV')),
3459 [('r', 'rev', '', _('revision to display'), _('REV')),
3459 ('', 'all', False, _("list files from all revisions"))]
3460 ('', 'all', False, _("list files from all revisions"))]
3460 + formatteropts,
3461 + formatteropts,
3461 _('[-r REV]'))
3462 _('[-r REV]'))
3462 def manifest(ui, repo, node=None, rev=None, **opts):
3463 def manifest(ui, repo, node=None, rev=None, **opts):
3463 """output the current or given revision of the project manifest
3464 """output the current or given revision of the project manifest
3464
3465
3465 Print a list of version controlled files for the given revision.
3466 Print a list of version controlled files for the given revision.
3466 If no revision is given, the first parent of the working directory
3467 If no revision is given, the first parent of the working directory
3467 is used, or the null revision if no revision is checked out.
3468 is used, or the null revision if no revision is checked out.
3468
3469
3469 With -v, print file permissions, symlink and executable bits.
3470 With -v, print file permissions, symlink and executable bits.
3470 With --debug, print file revision hashes.
3471 With --debug, print file revision hashes.
3471
3472
3472 If option --all is specified, the list of all files from all revisions
3473 If option --all is specified, the list of all files from all revisions
3473 is printed. This includes deleted and renamed files.
3474 is printed. This includes deleted and renamed files.
3474
3475
3475 Returns 0 on success.
3476 Returns 0 on success.
3476 """
3477 """
3477
3478
3478 fm = ui.formatter('manifest', opts)
3479 fm = ui.formatter('manifest', opts)
3479
3480
3480 if opts.get('all'):
3481 if opts.get('all'):
3481 if rev or node:
3482 if rev or node:
3482 raise error.Abort(_("can't specify a revision with --all"))
3483 raise error.Abort(_("can't specify a revision with --all"))
3483
3484
3484 res = []
3485 res = []
3485 prefix = "data/"
3486 prefix = "data/"
3486 suffix = ".i"
3487 suffix = ".i"
3487 plen = len(prefix)
3488 plen = len(prefix)
3488 slen = len(suffix)
3489 slen = len(suffix)
3489 with repo.lock():
3490 with repo.lock():
3490 for fn, b, size in repo.store.datafiles():
3491 for fn, b, size in repo.store.datafiles():
3491 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
3492 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
3492 res.append(fn[plen:-slen])
3493 res.append(fn[plen:-slen])
3493 for f in res:
3494 for f in res:
3494 fm.startitem()
3495 fm.startitem()
3495 fm.write("path", '%s\n', f)
3496 fm.write("path", '%s\n', f)
3496 fm.end()
3497 fm.end()
3497 return
3498 return
3498
3499
3499 if rev and node:
3500 if rev and node:
3500 raise error.Abort(_("please specify just one revision"))
3501 raise error.Abort(_("please specify just one revision"))
3501
3502
3502 if not node:
3503 if not node:
3503 node = rev
3504 node = rev
3504
3505
3505 char = {'l': '@', 'x': '*', '': ''}
3506 char = {'l': '@', 'x': '*', '': ''}
3506 mode = {'l': '644', 'x': '755', '': '644'}
3507 mode = {'l': '644', 'x': '755', '': '644'}
3507 ctx = scmutil.revsingle(repo, node)
3508 ctx = scmutil.revsingle(repo, node)
3508 mf = ctx.manifest()
3509 mf = ctx.manifest()
3509 for f in ctx:
3510 for f in ctx:
3510 fm.startitem()
3511 fm.startitem()
3511 fl = ctx[f].flags()
3512 fl = ctx[f].flags()
3512 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
3513 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
3513 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
3514 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
3514 fm.write('path', '%s\n', f)
3515 fm.write('path', '%s\n', f)
3515 fm.end()
3516 fm.end()
3516
3517
3517 @command('^merge',
3518 @command('^merge',
3518 [('f', 'force', None,
3519 [('f', 'force', None,
3519 _('force a merge including outstanding changes (DEPRECATED)')),
3520 _('force a merge including outstanding changes (DEPRECATED)')),
3520 ('r', 'rev', '', _('revision to merge'), _('REV')),
3521 ('r', 'rev', '', _('revision to merge'), _('REV')),
3521 ('P', 'preview', None,
3522 ('P', 'preview', None,
3522 _('review revisions to merge (no merge is performed)'))
3523 _('review revisions to merge (no merge is performed)'))
3523 ] + mergetoolopts,
3524 ] + mergetoolopts,
3524 _('[-P] [[-r] REV]'))
3525 _('[-P] [[-r] REV]'))
3525 def merge(ui, repo, node=None, **opts):
3526 def merge(ui, repo, node=None, **opts):
3526 """merge another revision into working directory
3527 """merge another revision into working directory
3527
3528
3528 The current working directory is updated with all changes made in
3529 The current working directory is updated with all changes made in
3529 the requested revision since the last common predecessor revision.
3530 the requested revision since the last common predecessor revision.
3530
3531
3531 Files that changed between either parent are marked as changed for
3532 Files that changed between either parent are marked as changed for
3532 the next commit and a commit must be performed before any further
3533 the next commit and a commit must be performed before any further
3533 updates to the repository are allowed. The next commit will have
3534 updates to the repository are allowed. The next commit will have
3534 two parents.
3535 two parents.
3535
3536
3536 ``--tool`` can be used to specify the merge tool used for file
3537 ``--tool`` can be used to specify the merge tool used for file
3537 merges. It overrides the HGMERGE environment variable and your
3538 merges. It overrides the HGMERGE environment variable and your
3538 configuration files. See :hg:`help merge-tools` for options.
3539 configuration files. See :hg:`help merge-tools` for options.
3539
3540
3540 If no revision is specified, the working directory's parent is a
3541 If no revision is specified, the working directory's parent is a
3541 head revision, and the current branch contains exactly one other
3542 head revision, and the current branch contains exactly one other
3542 head, the other head is merged with by default. Otherwise, an
3543 head, the other head is merged with by default. Otherwise, an
3543 explicit revision with which to merge with must be provided.
3544 explicit revision with which to merge with must be provided.
3544
3545
3545 See :hg:`help resolve` for information on handling file conflicts.
3546 See :hg:`help resolve` for information on handling file conflicts.
3546
3547
3547 To undo an uncommitted merge, use :hg:`update --clean .` which
3548 To undo an uncommitted merge, use :hg:`update --clean .` which
3548 will check out a clean copy of the original merge parent, losing
3549 will check out a clean copy of the original merge parent, losing
3549 all changes.
3550 all changes.
3550
3551
3551 Returns 0 on success, 1 if there are unresolved files.
3552 Returns 0 on success, 1 if there are unresolved files.
3552 """
3553 """
3553
3554
3554 if opts.get('rev') and node:
3555 if opts.get('rev') and node:
3555 raise error.Abort(_("please specify just one revision"))
3556 raise error.Abort(_("please specify just one revision"))
3556 if not node:
3557 if not node:
3557 node = opts.get('rev')
3558 node = opts.get('rev')
3558
3559
3559 if node:
3560 if node:
3560 node = scmutil.revsingle(repo, node).node()
3561 node = scmutil.revsingle(repo, node).node()
3561
3562
3562 if not node:
3563 if not node:
3563 node = repo[destutil.destmerge(repo)].node()
3564 node = repo[destutil.destmerge(repo)].node()
3564
3565
3565 if opts.get('preview'):
3566 if opts.get('preview'):
3566 # find nodes that are ancestors of p2 but not of p1
3567 # find nodes that are ancestors of p2 but not of p1
3567 p1 = repo.lookup('.')
3568 p1 = repo.lookup('.')
3568 p2 = repo.lookup(node)
3569 p2 = repo.lookup(node)
3569 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
3570 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
3570
3571
3571 displayer = cmdutil.show_changeset(ui, repo, opts)
3572 displayer = cmdutil.show_changeset(ui, repo, opts)
3572 for node in nodes:
3573 for node in nodes:
3573 displayer.show(repo[node])
3574 displayer.show(repo[node])
3574 displayer.close()
3575 displayer.close()
3575 return 0
3576 return 0
3576
3577
3577 try:
3578 try:
3578 # ui.forcemerge is an internal variable, do not document
3579 # ui.forcemerge is an internal variable, do not document
3579 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
3580 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
3580 force = opts.get('force')
3581 force = opts.get('force')
3581 labels = ['working copy', 'merge rev']
3582 labels = ['working copy', 'merge rev']
3582 return hg.merge(repo, node, force=force, mergeforce=force,
3583 return hg.merge(repo, node, force=force, mergeforce=force,
3583 labels=labels)
3584 labels=labels)
3584 finally:
3585 finally:
3585 ui.setconfig('ui', 'forcemerge', '', 'merge')
3586 ui.setconfig('ui', 'forcemerge', '', 'merge')
3586
3587
3587 @command('outgoing|out',
3588 @command('outgoing|out',
3588 [('f', 'force', None, _('run even when the destination is unrelated')),
3589 [('f', 'force', None, _('run even when the destination is unrelated')),
3589 ('r', 'rev', [],
3590 ('r', 'rev', [],
3590 _('a changeset intended to be included in the destination'), _('REV')),
3591 _('a changeset intended to be included in the destination'), _('REV')),
3591 ('n', 'newest-first', None, _('show newest record first')),
3592 ('n', 'newest-first', None, _('show newest record first')),
3592 ('B', 'bookmarks', False, _('compare bookmarks')),
3593 ('B', 'bookmarks', False, _('compare bookmarks')),
3593 ('b', 'branch', [], _('a specific branch you would like to push'),
3594 ('b', 'branch', [], _('a specific branch you would like to push'),
3594 _('BRANCH')),
3595 _('BRANCH')),
3595 ] + logopts + remoteopts + subrepoopts,
3596 ] + logopts + remoteopts + subrepoopts,
3596 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
3597 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
3597 def outgoing(ui, repo, dest=None, **opts):
3598 def outgoing(ui, repo, dest=None, **opts):
3598 """show changesets not found in the destination
3599 """show changesets not found in the destination
3599
3600
3600 Show changesets not found in the specified destination repository
3601 Show changesets not found in the specified destination repository
3601 or the default push location. These are the changesets that would
3602 or the default push location. These are the changesets that would
3602 be pushed if a push was requested.
3603 be pushed if a push was requested.
3603
3604
3604 See pull for details of valid destination formats.
3605 See pull for details of valid destination formats.
3605
3606
3606 .. container:: verbose
3607 .. container:: verbose
3607
3608
3608 With -B/--bookmarks, the result of bookmark comparison between
3609 With -B/--bookmarks, the result of bookmark comparison between
3609 local and remote repositories is displayed. With -v/--verbose,
3610 local and remote repositories is displayed. With -v/--verbose,
3610 status is also displayed for each bookmark like below::
3611 status is also displayed for each bookmark like below::
3611
3612
3612 BM1 01234567890a added
3613 BM1 01234567890a added
3613 BM2 deleted
3614 BM2 deleted
3614 BM3 234567890abc advanced
3615 BM3 234567890abc advanced
3615 BM4 34567890abcd diverged
3616 BM4 34567890abcd diverged
3616 BM5 4567890abcde changed
3617 BM5 4567890abcde changed
3617
3618
3618 The action taken when pushing depends on the
3619 The action taken when pushing depends on the
3619 status of each bookmark:
3620 status of each bookmark:
3620
3621
3621 :``added``: push with ``-B`` will create it
3622 :``added``: push with ``-B`` will create it
3622 :``deleted``: push with ``-B`` will delete it
3623 :``deleted``: push with ``-B`` will delete it
3623 :``advanced``: push will update it
3624 :``advanced``: push will update it
3624 :``diverged``: push with ``-B`` will update it
3625 :``diverged``: push with ``-B`` will update it
3625 :``changed``: push with ``-B`` will update it
3626 :``changed``: push with ``-B`` will update it
3626
3627
3627 From the point of view of pushing behavior, bookmarks
3628 From the point of view of pushing behavior, bookmarks
3628 existing only in the remote repository are treated as
3629 existing only in the remote repository are treated as
3629 ``deleted``, even if it is in fact added remotely.
3630 ``deleted``, even if it is in fact added remotely.
3630
3631
3631 Returns 0 if there are outgoing changes, 1 otherwise.
3632 Returns 0 if there are outgoing changes, 1 otherwise.
3632 """
3633 """
3633 if opts.get('graph'):
3634 if opts.get('graph'):
3634 cmdutil.checkunsupportedgraphflags([], opts)
3635 cmdutil.checkunsupportedgraphflags([], opts)
3635 o, other = hg._outgoing(ui, repo, dest, opts)
3636 o, other = hg._outgoing(ui, repo, dest, opts)
3636 if not o:
3637 if not o:
3637 cmdutil.outgoinghooks(ui, repo, other, opts, o)
3638 cmdutil.outgoinghooks(ui, repo, other, opts, o)
3638 return
3639 return
3639
3640
3640 revdag = cmdutil.graphrevs(repo, o, opts)
3641 revdag = cmdutil.graphrevs(repo, o, opts)
3641 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
3642 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
3642 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
3643 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
3643 cmdutil.outgoinghooks(ui, repo, other, opts, o)
3644 cmdutil.outgoinghooks(ui, repo, other, opts, o)
3644 return 0
3645 return 0
3645
3646
3646 if opts.get('bookmarks'):
3647 if opts.get('bookmarks'):
3647 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3648 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3648 dest, branches = hg.parseurl(dest, opts.get('branch'))
3649 dest, branches = hg.parseurl(dest, opts.get('branch'))
3649 other = hg.peer(repo, opts, dest)
3650 other = hg.peer(repo, opts, dest)
3650 if 'bookmarks' not in other.listkeys('namespaces'):
3651 if 'bookmarks' not in other.listkeys('namespaces'):
3651 ui.warn(_("remote doesn't support bookmarks\n"))
3652 ui.warn(_("remote doesn't support bookmarks\n"))
3652 return 0
3653 return 0
3653 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
3654 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
3654 return bookmarks.outgoing(ui, repo, other)
3655 return bookmarks.outgoing(ui, repo, other)
3655
3656
3656 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
3657 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
3657 try:
3658 try:
3658 return hg.outgoing(ui, repo, dest, opts)
3659 return hg.outgoing(ui, repo, dest, opts)
3659 finally:
3660 finally:
3660 del repo._subtoppath
3661 del repo._subtoppath
3661
3662
3662 @command('parents',
3663 @command('parents',
3663 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
3664 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
3664 ] + templateopts,
3665 ] + templateopts,
3665 _('[-r REV] [FILE]'),
3666 _('[-r REV] [FILE]'),
3666 inferrepo=True)
3667 inferrepo=True)
3667 def parents(ui, repo, file_=None, **opts):
3668 def parents(ui, repo, file_=None, **opts):
3668 """show the parents of the working directory or revision (DEPRECATED)
3669 """show the parents of the working directory or revision (DEPRECATED)
3669
3670
3670 Print the working directory's parent revisions. If a revision is
3671 Print the working directory's parent revisions. If a revision is
3671 given via -r/--rev, the parent of that revision will be printed.
3672 given via -r/--rev, the parent of that revision will be printed.
3672 If a file argument is given, the revision in which the file was
3673 If a file argument is given, the revision in which the file was
3673 last changed (before the working directory revision or the
3674 last changed (before the working directory revision or the
3674 argument to --rev if given) is printed.
3675 argument to --rev if given) is printed.
3675
3676
3676 This command is equivalent to::
3677 This command is equivalent to::
3677
3678
3678 hg log -r "p1()+p2()" or
3679 hg log -r "p1()+p2()" or
3679 hg log -r "p1(REV)+p2(REV)" or
3680 hg log -r "p1(REV)+p2(REV)" or
3680 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
3681 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
3681 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
3682 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
3682
3683
3683 See :hg:`summary` and :hg:`help revsets` for related information.
3684 See :hg:`summary` and :hg:`help revsets` for related information.
3684
3685
3685 Returns 0 on success.
3686 Returns 0 on success.
3686 """
3687 """
3687
3688
3688 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3689 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3689
3690
3690 if file_:
3691 if file_:
3691 m = scmutil.match(ctx, (file_,), opts)
3692 m = scmutil.match(ctx, (file_,), opts)
3692 if m.anypats() or len(m.files()) != 1:
3693 if m.anypats() or len(m.files()) != 1:
3693 raise error.Abort(_('can only specify an explicit filename'))
3694 raise error.Abort(_('can only specify an explicit filename'))
3694 file_ = m.files()[0]
3695 file_ = m.files()[0]
3695 filenodes = []
3696 filenodes = []
3696 for cp in ctx.parents():
3697 for cp in ctx.parents():
3697 if not cp:
3698 if not cp:
3698 continue
3699 continue
3699 try:
3700 try:
3700 filenodes.append(cp.filenode(file_))
3701 filenodes.append(cp.filenode(file_))
3701 except error.LookupError:
3702 except error.LookupError:
3702 pass
3703 pass
3703 if not filenodes:
3704 if not filenodes:
3704 raise error.Abort(_("'%s' not found in manifest!") % file_)
3705 raise error.Abort(_("'%s' not found in manifest!") % file_)
3705 p = []
3706 p = []
3706 for fn in filenodes:
3707 for fn in filenodes:
3707 fctx = repo.filectx(file_, fileid=fn)
3708 fctx = repo.filectx(file_, fileid=fn)
3708 p.append(fctx.node())
3709 p.append(fctx.node())
3709 else:
3710 else:
3710 p = [cp.node() for cp in ctx.parents()]
3711 p = [cp.node() for cp in ctx.parents()]
3711
3712
3712 displayer = cmdutil.show_changeset(ui, repo, opts)
3713 displayer = cmdutil.show_changeset(ui, repo, opts)
3713 for n in p:
3714 for n in p:
3714 if n != nullid:
3715 if n != nullid:
3715 displayer.show(repo[n])
3716 displayer.show(repo[n])
3716 displayer.close()
3717 displayer.close()
3717
3718
3718 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True)
3719 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True)
3719 def paths(ui, repo, search=None, **opts):
3720 def paths(ui, repo, search=None, **opts):
3720 """show aliases for remote repositories
3721 """show aliases for remote repositories
3721
3722
3722 Show definition of symbolic path name NAME. If no name is given,
3723 Show definition of symbolic path name NAME. If no name is given,
3723 show definition of all available names.
3724 show definition of all available names.
3724
3725
3725 Option -q/--quiet suppresses all output when searching for NAME
3726 Option -q/--quiet suppresses all output when searching for NAME
3726 and shows only the path names when listing all definitions.
3727 and shows only the path names when listing all definitions.
3727
3728
3728 Path names are defined in the [paths] section of your
3729 Path names are defined in the [paths] section of your
3729 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
3730 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
3730 repository, ``.hg/hgrc`` is used, too.
3731 repository, ``.hg/hgrc`` is used, too.
3731
3732
3732 The path names ``default`` and ``default-push`` have a special
3733 The path names ``default`` and ``default-push`` have a special
3733 meaning. When performing a push or pull operation, they are used
3734 meaning. When performing a push or pull operation, they are used
3734 as fallbacks if no location is specified on the command-line.
3735 as fallbacks if no location is specified on the command-line.
3735 When ``default-push`` is set, it will be used for push and
3736 When ``default-push`` is set, it will be used for push and
3736 ``default`` will be used for pull; otherwise ``default`` is used
3737 ``default`` will be used for pull; otherwise ``default`` is used
3737 as the fallback for both. When cloning a repository, the clone
3738 as the fallback for both. When cloning a repository, the clone
3738 source is written as ``default`` in ``.hg/hgrc``.
3739 source is written as ``default`` in ``.hg/hgrc``.
3739
3740
3740 .. note::
3741 .. note::
3741
3742
3742 ``default`` and ``default-push`` apply to all inbound (e.g.
3743 ``default`` and ``default-push`` apply to all inbound (e.g.
3743 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
3744 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
3744 and :hg:`bundle`) operations.
3745 and :hg:`bundle`) operations.
3745
3746
3746 See :hg:`help urls` for more information.
3747 See :hg:`help urls` for more information.
3747
3748
3748 Returns 0 on success.
3749 Returns 0 on success.
3749 """
3750 """
3750 if search:
3751 if search:
3751 pathitems = [(name, path) for name, path in ui.paths.iteritems()
3752 pathitems = [(name, path) for name, path in ui.paths.iteritems()
3752 if name == search]
3753 if name == search]
3753 else:
3754 else:
3754 pathitems = sorted(ui.paths.iteritems())
3755 pathitems = sorted(ui.paths.iteritems())
3755
3756
3756 fm = ui.formatter('paths', opts)
3757 fm = ui.formatter('paths', opts)
3757 if fm.isplain():
3758 if fm.isplain():
3758 hidepassword = util.hidepassword
3759 hidepassword = util.hidepassword
3759 else:
3760 else:
3760 hidepassword = str
3761 hidepassword = str
3761 if ui.quiet:
3762 if ui.quiet:
3762 namefmt = '%s\n'
3763 namefmt = '%s\n'
3763 else:
3764 else:
3764 namefmt = '%s = '
3765 namefmt = '%s = '
3765 showsubopts = not search and not ui.quiet
3766 showsubopts = not search and not ui.quiet
3766
3767
3767 for name, path in pathitems:
3768 for name, path in pathitems:
3768 fm.startitem()
3769 fm.startitem()
3769 fm.condwrite(not search, 'name', namefmt, name)
3770 fm.condwrite(not search, 'name', namefmt, name)
3770 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
3771 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
3771 for subopt, value in sorted(path.suboptions.items()):
3772 for subopt, value in sorted(path.suboptions.items()):
3772 assert subopt not in ('name', 'url')
3773 assert subopt not in ('name', 'url')
3773 if showsubopts:
3774 if showsubopts:
3774 fm.plain('%s:%s = ' % (name, subopt))
3775 fm.plain('%s:%s = ' % (name, subopt))
3775 fm.condwrite(showsubopts, subopt, '%s\n', value)
3776 fm.condwrite(showsubopts, subopt, '%s\n', value)
3776
3777
3777 fm.end()
3778 fm.end()
3778
3779
3779 if search and not pathitems:
3780 if search and not pathitems:
3780 if not ui.quiet:
3781 if not ui.quiet:
3781 ui.warn(_("not found!\n"))
3782 ui.warn(_("not found!\n"))
3782 return 1
3783 return 1
3783 else:
3784 else:
3784 return 0
3785 return 0
3785
3786
3786 @command('phase',
3787 @command('phase',
3787 [('p', 'public', False, _('set changeset phase to public')),
3788 [('p', 'public', False, _('set changeset phase to public')),
3788 ('d', 'draft', False, _('set changeset phase to draft')),
3789 ('d', 'draft', False, _('set changeset phase to draft')),
3789 ('s', 'secret', False, _('set changeset phase to secret')),
3790 ('s', 'secret', False, _('set changeset phase to secret')),
3790 ('f', 'force', False, _('allow to move boundary backward')),
3791 ('f', 'force', False, _('allow to move boundary backward')),
3791 ('r', 'rev', [], _('target revision'), _('REV')),
3792 ('r', 'rev', [], _('target revision'), _('REV')),
3792 ],
3793 ],
3793 _('[-p|-d|-s] [-f] [-r] [REV...]'))
3794 _('[-p|-d|-s] [-f] [-r] [REV...]'))
3794 def phase(ui, repo, *revs, **opts):
3795 def phase(ui, repo, *revs, **opts):
3795 """set or show the current phase name
3796 """set or show the current phase name
3796
3797
3797 With no argument, show the phase name of the current revision(s).
3798 With no argument, show the phase name of the current revision(s).
3798
3799
3799 With one of -p/--public, -d/--draft or -s/--secret, change the
3800 With one of -p/--public, -d/--draft or -s/--secret, change the
3800 phase value of the specified revisions.
3801 phase value of the specified revisions.
3801
3802
3802 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
3803 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
3803 lower phase to an higher phase. Phases are ordered as follows::
3804 lower phase to an higher phase. Phases are ordered as follows::
3804
3805
3805 public < draft < secret
3806 public < draft < secret
3806
3807
3807 Returns 0 on success, 1 if some phases could not be changed.
3808 Returns 0 on success, 1 if some phases could not be changed.
3808
3809
3809 (For more information about the phases concept, see :hg:`help phases`.)
3810 (For more information about the phases concept, see :hg:`help phases`.)
3810 """
3811 """
3811 # search for a unique phase argument
3812 # search for a unique phase argument
3812 targetphase = None
3813 targetphase = None
3813 for idx, name in enumerate(phases.phasenames):
3814 for idx, name in enumerate(phases.phasenames):
3814 if opts[name]:
3815 if opts[name]:
3815 if targetphase is not None:
3816 if targetphase is not None:
3816 raise error.Abort(_('only one phase can be specified'))
3817 raise error.Abort(_('only one phase can be specified'))
3817 targetphase = idx
3818 targetphase = idx
3818
3819
3819 # look for specified revision
3820 # look for specified revision
3820 revs = list(revs)
3821 revs = list(revs)
3821 revs.extend(opts['rev'])
3822 revs.extend(opts['rev'])
3822 if not revs:
3823 if not revs:
3823 # display both parents as the second parent phase can influence
3824 # display both parents as the second parent phase can influence
3824 # the phase of a merge commit
3825 # the phase of a merge commit
3825 revs = [c.rev() for c in repo[None].parents()]
3826 revs = [c.rev() for c in repo[None].parents()]
3826
3827
3827 revs = scmutil.revrange(repo, revs)
3828 revs = scmutil.revrange(repo, revs)
3828
3829
3829 lock = None
3830 lock = None
3830 ret = 0
3831 ret = 0
3831 if targetphase is None:
3832 if targetphase is None:
3832 # display
3833 # display
3833 for r in revs:
3834 for r in revs:
3834 ctx = repo[r]
3835 ctx = repo[r]
3835 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
3836 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
3836 else:
3837 else:
3837 tr = None
3838 tr = None
3838 lock = repo.lock()
3839 lock = repo.lock()
3839 try:
3840 try:
3840 tr = repo.transaction("phase")
3841 tr = repo.transaction("phase")
3841 # set phase
3842 # set phase
3842 if not revs:
3843 if not revs:
3843 raise error.Abort(_('empty revision set'))
3844 raise error.Abort(_('empty revision set'))
3844 nodes = [repo[r].node() for r in revs]
3845 nodes = [repo[r].node() for r in revs]
3845 # moving revision from public to draft may hide them
3846 # moving revision from public to draft may hide them
3846 # We have to check result on an unfiltered repository
3847 # We have to check result on an unfiltered repository
3847 unfi = repo.unfiltered()
3848 unfi = repo.unfiltered()
3848 getphase = unfi._phasecache.phase
3849 getphase = unfi._phasecache.phase
3849 olddata = [getphase(unfi, r) for r in unfi]
3850 olddata = [getphase(unfi, r) for r in unfi]
3850 phases.advanceboundary(repo, tr, targetphase, nodes)
3851 phases.advanceboundary(repo, tr, targetphase, nodes)
3851 if opts['force']:
3852 if opts['force']:
3852 phases.retractboundary(repo, tr, targetphase, nodes)
3853 phases.retractboundary(repo, tr, targetphase, nodes)
3853 tr.close()
3854 tr.close()
3854 finally:
3855 finally:
3855 if tr is not None:
3856 if tr is not None:
3856 tr.release()
3857 tr.release()
3857 lock.release()
3858 lock.release()
3858 getphase = unfi._phasecache.phase
3859 getphase = unfi._phasecache.phase
3859 newdata = [getphase(unfi, r) for r in unfi]
3860 newdata = [getphase(unfi, r) for r in unfi]
3860 changes = sum(newdata[r] != olddata[r] for r in unfi)
3861 changes = sum(newdata[r] != olddata[r] for r in unfi)
3861 cl = unfi.changelog
3862 cl = unfi.changelog
3862 rejected = [n for n in nodes
3863 rejected = [n for n in nodes
3863 if newdata[cl.rev(n)] < targetphase]
3864 if newdata[cl.rev(n)] < targetphase]
3864 if rejected:
3865 if rejected:
3865 ui.warn(_('cannot move %i changesets to a higher '
3866 ui.warn(_('cannot move %i changesets to a higher '
3866 'phase, use --force\n') % len(rejected))
3867 'phase, use --force\n') % len(rejected))
3867 ret = 1
3868 ret = 1
3868 if changes:
3869 if changes:
3869 msg = _('phase changed for %i changesets\n') % changes
3870 msg = _('phase changed for %i changesets\n') % changes
3870 if ret:
3871 if ret:
3871 ui.status(msg)
3872 ui.status(msg)
3872 else:
3873 else:
3873 ui.note(msg)
3874 ui.note(msg)
3874 else:
3875 else:
3875 ui.warn(_('no phases changed\n'))
3876 ui.warn(_('no phases changed\n'))
3876 return ret
3877 return ret
3877
3878
3878 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
3879 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
3879 """Run after a changegroup has been added via pull/unbundle
3880 """Run after a changegroup has been added via pull/unbundle
3880
3881
3881 This takes arguments below:
3882 This takes arguments below:
3882
3883
3883 :modheads: change of heads by pull/unbundle
3884 :modheads: change of heads by pull/unbundle
3884 :optupdate: updating working directory is needed or not
3885 :optupdate: updating working directory is needed or not
3885 :checkout: update destination revision (or None to default destination)
3886 :checkout: update destination revision (or None to default destination)
3886 :brev: a name, which might be a bookmark to be activated after updating
3887 :brev: a name, which might be a bookmark to be activated after updating
3887 """
3888 """
3888 if modheads == 0:
3889 if modheads == 0:
3889 return
3890 return
3890 if optupdate:
3891 if optupdate:
3891 try:
3892 try:
3892 return hg.updatetotally(ui, repo, checkout, brev)
3893 return hg.updatetotally(ui, repo, checkout, brev)
3893 except error.UpdateAbort as inst:
3894 except error.UpdateAbort as inst:
3894 msg = _("not updating: %s") % str(inst)
3895 msg = _("not updating: %s") % str(inst)
3895 hint = inst.hint
3896 hint = inst.hint
3896 raise error.UpdateAbort(msg, hint=hint)
3897 raise error.UpdateAbort(msg, hint=hint)
3897 if modheads > 1:
3898 if modheads > 1:
3898 currentbranchheads = len(repo.branchheads())
3899 currentbranchheads = len(repo.branchheads())
3899 if currentbranchheads == modheads:
3900 if currentbranchheads == modheads:
3900 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
3901 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
3901 elif currentbranchheads > 1:
3902 elif currentbranchheads > 1:
3902 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
3903 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
3903 "merge)\n"))
3904 "merge)\n"))
3904 else:
3905 else:
3905 ui.status(_("(run 'hg heads' to see heads)\n"))
3906 ui.status(_("(run 'hg heads' to see heads)\n"))
3906 else:
3907 else:
3907 ui.status(_("(run 'hg update' to get a working copy)\n"))
3908 ui.status(_("(run 'hg update' to get a working copy)\n"))
3908
3909
3909 @command('^pull',
3910 @command('^pull',
3910 [('u', 'update', None,
3911 [('u', 'update', None,
3911 _('update to new branch head if changesets were pulled')),
3912 _('update to new branch head if changesets were pulled')),
3912 ('f', 'force', None, _('run even when remote repository is unrelated')),
3913 ('f', 'force', None, _('run even when remote repository is unrelated')),
3913 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3914 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3914 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
3915 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
3915 ('b', 'branch', [], _('a specific branch you would like to pull'),
3916 ('b', 'branch', [], _('a specific branch you would like to pull'),
3916 _('BRANCH')),
3917 _('BRANCH')),
3917 ] + remoteopts,
3918 ] + remoteopts,
3918 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
3919 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
3919 def pull(ui, repo, source="default", **opts):
3920 def pull(ui, repo, source="default", **opts):
3920 """pull changes from the specified source
3921 """pull changes from the specified source
3921
3922
3922 Pull changes from a remote repository to a local one.
3923 Pull changes from a remote repository to a local one.
3923
3924
3924 This finds all changes from the repository at the specified path
3925 This finds all changes from the repository at the specified path
3925 or URL and adds them to a local repository (the current one unless
3926 or URL and adds them to a local repository (the current one unless
3926 -R is specified). By default, this does not update the copy of the
3927 -R is specified). By default, this does not update the copy of the
3927 project in the working directory.
3928 project in the working directory.
3928
3929
3929 Use :hg:`incoming` if you want to see what would have been added
3930 Use :hg:`incoming` if you want to see what would have been added
3930 by a pull at the time you issued this command. If you then decide
3931 by a pull at the time you issued this command. If you then decide
3931 to add those changes to the repository, you should use :hg:`pull
3932 to add those changes to the repository, you should use :hg:`pull
3932 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
3933 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
3933
3934
3934 If SOURCE is omitted, the 'default' path will be used.
3935 If SOURCE is omitted, the 'default' path will be used.
3935 See :hg:`help urls` for more information.
3936 See :hg:`help urls` for more information.
3936
3937
3937 Specifying bookmark as ``.`` is equivalent to specifying the active
3938 Specifying bookmark as ``.`` is equivalent to specifying the active
3938 bookmark's name.
3939 bookmark's name.
3939
3940
3940 Returns 0 on success, 1 if an update had unresolved files.
3941 Returns 0 on success, 1 if an update had unresolved files.
3941 """
3942 """
3942 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
3943 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
3943 ui.status(_('pulling from %s\n') % util.hidepassword(source))
3944 ui.status(_('pulling from %s\n') % util.hidepassword(source))
3944 other = hg.peer(repo, opts, source)
3945 other = hg.peer(repo, opts, source)
3945 try:
3946 try:
3946 revs, checkout = hg.addbranchrevs(repo, other, branches,
3947 revs, checkout = hg.addbranchrevs(repo, other, branches,
3947 opts.get('rev'))
3948 opts.get('rev'))
3948
3949
3949
3950
3950 pullopargs = {}
3951 pullopargs = {}
3951 if opts.get('bookmark'):
3952 if opts.get('bookmark'):
3952 if not revs:
3953 if not revs:
3953 revs = []
3954 revs = []
3954 # The list of bookmark used here is not the one used to actually
3955 # The list of bookmark used here is not the one used to actually
3955 # update the bookmark name. This can result in the revision pulled
3956 # update the bookmark name. This can result in the revision pulled
3956 # not ending up with the name of the bookmark because of a race
3957 # not ending up with the name of the bookmark because of a race
3957 # condition on the server. (See issue 4689 for details)
3958 # condition on the server. (See issue 4689 for details)
3958 remotebookmarks = other.listkeys('bookmarks')
3959 remotebookmarks = other.listkeys('bookmarks')
3959 pullopargs['remotebookmarks'] = remotebookmarks
3960 pullopargs['remotebookmarks'] = remotebookmarks
3960 for b in opts['bookmark']:
3961 for b in opts['bookmark']:
3961 b = repo._bookmarks.expandname(b)
3962 b = repo._bookmarks.expandname(b)
3962 if b not in remotebookmarks:
3963 if b not in remotebookmarks:
3963 raise error.Abort(_('remote bookmark %s not found!') % b)
3964 raise error.Abort(_('remote bookmark %s not found!') % b)
3964 revs.append(remotebookmarks[b])
3965 revs.append(remotebookmarks[b])
3965
3966
3966 if revs:
3967 if revs:
3967 try:
3968 try:
3968 # When 'rev' is a bookmark name, we cannot guarantee that it
3969 # When 'rev' is a bookmark name, we cannot guarantee that it
3969 # will be updated with that name because of a race condition
3970 # will be updated with that name because of a race condition
3970 # server side. (See issue 4689 for details)
3971 # server side. (See issue 4689 for details)
3971 oldrevs = revs
3972 oldrevs = revs
3972 revs = [] # actually, nodes
3973 revs = [] # actually, nodes
3973 for r in oldrevs:
3974 for r in oldrevs:
3974 node = other.lookup(r)
3975 node = other.lookup(r)
3975 revs.append(node)
3976 revs.append(node)
3976 if r == checkout:
3977 if r == checkout:
3977 checkout = node
3978 checkout = node
3978 except error.CapabilityError:
3979 except error.CapabilityError:
3979 err = _("other repository doesn't support revision lookup, "
3980 err = _("other repository doesn't support revision lookup, "
3980 "so a rev cannot be specified.")
3981 "so a rev cannot be specified.")
3981 raise error.Abort(err)
3982 raise error.Abort(err)
3982
3983
3983 pullopargs.update(opts.get('opargs', {}))
3984 pullopargs.update(opts.get('opargs', {}))
3984 modheads = exchange.pull(repo, other, heads=revs,
3985 modheads = exchange.pull(repo, other, heads=revs,
3985 force=opts.get('force'),
3986 force=opts.get('force'),
3986 bookmarks=opts.get('bookmark', ()),
3987 bookmarks=opts.get('bookmark', ()),
3987 opargs=pullopargs).cgresult
3988 opargs=pullopargs).cgresult
3988
3989
3989 # brev is a name, which might be a bookmark to be activated at
3990 # brev is a name, which might be a bookmark to be activated at
3990 # the end of the update. In other words, it is an explicit
3991 # the end of the update. In other words, it is an explicit
3991 # destination of the update
3992 # destination of the update
3992 brev = None
3993 brev = None
3993
3994
3994 if checkout:
3995 if checkout:
3995 checkout = str(repo.changelog.rev(checkout))
3996 checkout = str(repo.changelog.rev(checkout))
3996
3997
3997 # order below depends on implementation of
3998 # order below depends on implementation of
3998 # hg.addbranchrevs(). opts['bookmark'] is ignored,
3999 # hg.addbranchrevs(). opts['bookmark'] is ignored,
3999 # because 'checkout' is determined without it.
4000 # because 'checkout' is determined without it.
4000 if opts.get('rev'):
4001 if opts.get('rev'):
4001 brev = opts['rev'][0]
4002 brev = opts['rev'][0]
4002 elif opts.get('branch'):
4003 elif opts.get('branch'):
4003 brev = opts['branch'][0]
4004 brev = opts['branch'][0]
4004 else:
4005 else:
4005 brev = branches[0]
4006 brev = branches[0]
4006 repo._subtoppath = source
4007 repo._subtoppath = source
4007 try:
4008 try:
4008 ret = postincoming(ui, repo, modheads, opts.get('update'),
4009 ret = postincoming(ui, repo, modheads, opts.get('update'),
4009 checkout, brev)
4010 checkout, brev)
4010
4011
4011 finally:
4012 finally:
4012 del repo._subtoppath
4013 del repo._subtoppath
4013
4014
4014 finally:
4015 finally:
4015 other.close()
4016 other.close()
4016 return ret
4017 return ret
4017
4018
4018 @command('^push',
4019 @command('^push',
4019 [('f', 'force', None, _('force push')),
4020 [('f', 'force', None, _('force push')),
4020 ('r', 'rev', [],
4021 ('r', 'rev', [],
4021 _('a changeset intended to be included in the destination'),
4022 _('a changeset intended to be included in the destination'),
4022 _('REV')),
4023 _('REV')),
4023 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4024 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4024 ('b', 'branch', [],
4025 ('b', 'branch', [],
4025 _('a specific branch you would like to push'), _('BRANCH')),
4026 _('a specific branch you would like to push'), _('BRANCH')),
4026 ('', 'new-branch', False, _('allow pushing a new branch')),
4027 ('', 'new-branch', False, _('allow pushing a new branch')),
4027 ] + remoteopts,
4028 ] + remoteopts,
4028 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4029 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4029 def push(ui, repo, dest=None, **opts):
4030 def push(ui, repo, dest=None, **opts):
4030 """push changes to the specified destination
4031 """push changes to the specified destination
4031
4032
4032 Push changesets from the local repository to the specified
4033 Push changesets from the local repository to the specified
4033 destination.
4034 destination.
4034
4035
4035 This operation is symmetrical to pull: it is identical to a pull
4036 This operation is symmetrical to pull: it is identical to a pull
4036 in the destination repository from the current one.
4037 in the destination repository from the current one.
4037
4038
4038 By default, push will not allow creation of new heads at the
4039 By default, push will not allow creation of new heads at the
4039 destination, since multiple heads would make it unclear which head
4040 destination, since multiple heads would make it unclear which head
4040 to use. In this situation, it is recommended to pull and merge
4041 to use. In this situation, it is recommended to pull and merge
4041 before pushing.
4042 before pushing.
4042
4043
4043 Use --new-branch if you want to allow push to create a new named
4044 Use --new-branch if you want to allow push to create a new named
4044 branch that is not present at the destination. This allows you to
4045 branch that is not present at the destination. This allows you to
4045 only create a new branch without forcing other changes.
4046 only create a new branch without forcing other changes.
4046
4047
4047 .. note::
4048 .. note::
4048
4049
4049 Extra care should be taken with the -f/--force option,
4050 Extra care should be taken with the -f/--force option,
4050 which will push all new heads on all branches, an action which will
4051 which will push all new heads on all branches, an action which will
4051 almost always cause confusion for collaborators.
4052 almost always cause confusion for collaborators.
4052
4053
4053 If -r/--rev is used, the specified revision and all its ancestors
4054 If -r/--rev is used, the specified revision and all its ancestors
4054 will be pushed to the remote repository.
4055 will be pushed to the remote repository.
4055
4056
4056 If -B/--bookmark is used, the specified bookmarked revision, its
4057 If -B/--bookmark is used, the specified bookmarked revision, its
4057 ancestors, and the bookmark will be pushed to the remote
4058 ancestors, and the bookmark will be pushed to the remote
4058 repository. Specifying ``.`` is equivalent to specifying the active
4059 repository. Specifying ``.`` is equivalent to specifying the active
4059 bookmark's name.
4060 bookmark's name.
4060
4061
4061 Please see :hg:`help urls` for important details about ``ssh://``
4062 Please see :hg:`help urls` for important details about ``ssh://``
4062 URLs. If DESTINATION is omitted, a default path will be used.
4063 URLs. If DESTINATION is omitted, a default path will be used.
4063
4064
4064 Returns 0 if push was successful, 1 if nothing to push.
4065 Returns 0 if push was successful, 1 if nothing to push.
4065 """
4066 """
4066
4067
4067 if opts.get('bookmark'):
4068 if opts.get('bookmark'):
4068 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
4069 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
4069 for b in opts['bookmark']:
4070 for b in opts['bookmark']:
4070 # translate -B options to -r so changesets get pushed
4071 # translate -B options to -r so changesets get pushed
4071 b = repo._bookmarks.expandname(b)
4072 b = repo._bookmarks.expandname(b)
4072 if b in repo._bookmarks:
4073 if b in repo._bookmarks:
4073 opts.setdefault('rev', []).append(b)
4074 opts.setdefault('rev', []).append(b)
4074 else:
4075 else:
4075 # if we try to push a deleted bookmark, translate it to null
4076 # if we try to push a deleted bookmark, translate it to null
4076 # this lets simultaneous -r, -b options continue working
4077 # this lets simultaneous -r, -b options continue working
4077 opts.setdefault('rev', []).append("null")
4078 opts.setdefault('rev', []).append("null")
4078
4079
4079 path = ui.paths.getpath(dest, default=('default-push', 'default'))
4080 path = ui.paths.getpath(dest, default=('default-push', 'default'))
4080 if not path:
4081 if not path:
4081 raise error.Abort(_('default repository not configured!'),
4082 raise error.Abort(_('default repository not configured!'),
4082 hint=_("see 'hg help config.paths'"))
4083 hint=_("see 'hg help config.paths'"))
4083 dest = path.pushloc or path.loc
4084 dest = path.pushloc or path.loc
4084 branches = (path.branch, opts.get('branch') or [])
4085 branches = (path.branch, opts.get('branch') or [])
4085 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4086 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4086 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4087 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4087 other = hg.peer(repo, opts, dest)
4088 other = hg.peer(repo, opts, dest)
4088
4089
4089 if revs:
4090 if revs:
4090 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4091 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4091 if not revs:
4092 if not revs:
4092 raise error.Abort(_("specified revisions evaluate to an empty set"),
4093 raise error.Abort(_("specified revisions evaluate to an empty set"),
4093 hint=_("use different revision arguments"))
4094 hint=_("use different revision arguments"))
4094 elif path.pushrev:
4095 elif path.pushrev:
4095 # It doesn't make any sense to specify ancestor revisions. So limit
4096 # It doesn't make any sense to specify ancestor revisions. So limit
4096 # to DAG heads to make discovery simpler.
4097 # to DAG heads to make discovery simpler.
4097 expr = revsetlang.formatspec('heads(%r)', path.pushrev)
4098 expr = revsetlang.formatspec('heads(%r)', path.pushrev)
4098 revs = scmutil.revrange(repo, [expr])
4099 revs = scmutil.revrange(repo, [expr])
4099 revs = [repo[rev].node() for rev in revs]
4100 revs = [repo[rev].node() for rev in revs]
4100 if not revs:
4101 if not revs:
4101 raise error.Abort(_('default push revset for path evaluates to an '
4102 raise error.Abort(_('default push revset for path evaluates to an '
4102 'empty set'))
4103 'empty set'))
4103
4104
4104 repo._subtoppath = dest
4105 repo._subtoppath = dest
4105 try:
4106 try:
4106 # push subrepos depth-first for coherent ordering
4107 # push subrepos depth-first for coherent ordering
4107 c = repo['']
4108 c = repo['']
4108 subs = c.substate # only repos that are committed
4109 subs = c.substate # only repos that are committed
4109 for s in sorted(subs):
4110 for s in sorted(subs):
4110 result = c.sub(s).push(opts)
4111 result = c.sub(s).push(opts)
4111 if result == 0:
4112 if result == 0:
4112 return not result
4113 return not result
4113 finally:
4114 finally:
4114 del repo._subtoppath
4115 del repo._subtoppath
4115 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
4116 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
4116 newbranch=opts.get('new_branch'),
4117 newbranch=opts.get('new_branch'),
4117 bookmarks=opts.get('bookmark', ()),
4118 bookmarks=opts.get('bookmark', ()),
4118 opargs=opts.get('opargs'))
4119 opargs=opts.get('opargs'))
4119
4120
4120 result = not pushop.cgresult
4121 result = not pushop.cgresult
4121
4122
4122 if pushop.bkresult is not None:
4123 if pushop.bkresult is not None:
4123 if pushop.bkresult == 2:
4124 if pushop.bkresult == 2:
4124 result = 2
4125 result = 2
4125 elif not result and pushop.bkresult:
4126 elif not result and pushop.bkresult:
4126 result = 2
4127 result = 2
4127
4128
4128 return result
4129 return result
4129
4130
4130 @command('recover', [])
4131 @command('recover', [])
4131 def recover(ui, repo):
4132 def recover(ui, repo):
4132 """roll back an interrupted transaction
4133 """roll back an interrupted transaction
4133
4134
4134 Recover from an interrupted commit or pull.
4135 Recover from an interrupted commit or pull.
4135
4136
4136 This command tries to fix the repository status after an
4137 This command tries to fix the repository status after an
4137 interrupted operation. It should only be necessary when Mercurial
4138 interrupted operation. It should only be necessary when Mercurial
4138 suggests it.
4139 suggests it.
4139
4140
4140 Returns 0 if successful, 1 if nothing to recover or verify fails.
4141 Returns 0 if successful, 1 if nothing to recover or verify fails.
4141 """
4142 """
4142 if repo.recover():
4143 if repo.recover():
4143 return hg.verify(repo)
4144 return hg.verify(repo)
4144 return 1
4145 return 1
4145
4146
4146 @command('^remove|rm',
4147 @command('^remove|rm',
4147 [('A', 'after', None, _('record delete for missing files')),
4148 [('A', 'after', None, _('record delete for missing files')),
4148 ('f', 'force', None,
4149 ('f', 'force', None,
4149 _('forget added files, delete modified files')),
4150 _('forget added files, delete modified files')),
4150 ] + subrepoopts + walkopts,
4151 ] + subrepoopts + walkopts,
4151 _('[OPTION]... FILE...'),
4152 _('[OPTION]... FILE...'),
4152 inferrepo=True)
4153 inferrepo=True)
4153 def remove(ui, repo, *pats, **opts):
4154 def remove(ui, repo, *pats, **opts):
4154 """remove the specified files on the next commit
4155 """remove the specified files on the next commit
4155
4156
4156 Schedule the indicated files for removal from the current branch.
4157 Schedule the indicated files for removal from the current branch.
4157
4158
4158 This command schedules the files to be removed at the next commit.
4159 This command schedules the files to be removed at the next commit.
4159 To undo a remove before that, see :hg:`revert`. To undo added
4160 To undo a remove before that, see :hg:`revert`. To undo added
4160 files, see :hg:`forget`.
4161 files, see :hg:`forget`.
4161
4162
4162 .. container:: verbose
4163 .. container:: verbose
4163
4164
4164 -A/--after can be used to remove only files that have already
4165 -A/--after can be used to remove only files that have already
4165 been deleted, -f/--force can be used to force deletion, and -Af
4166 been deleted, -f/--force can be used to force deletion, and -Af
4166 can be used to remove files from the next revision without
4167 can be used to remove files from the next revision without
4167 deleting them from the working directory.
4168 deleting them from the working directory.
4168
4169
4169 The following table details the behavior of remove for different
4170 The following table details the behavior of remove for different
4170 file states (columns) and option combinations (rows). The file
4171 file states (columns) and option combinations (rows). The file
4171 states are Added [A], Clean [C], Modified [M] and Missing [!]
4172 states are Added [A], Clean [C], Modified [M] and Missing [!]
4172 (as reported by :hg:`status`). The actions are Warn, Remove
4173 (as reported by :hg:`status`). The actions are Warn, Remove
4173 (from branch) and Delete (from disk):
4174 (from branch) and Delete (from disk):
4174
4175
4175 ========= == == == ==
4176 ========= == == == ==
4176 opt/state A C M !
4177 opt/state A C M !
4177 ========= == == == ==
4178 ========= == == == ==
4178 none W RD W R
4179 none W RD W R
4179 -f R RD RD R
4180 -f R RD RD R
4180 -A W W W R
4181 -A W W W R
4181 -Af R R R R
4182 -Af R R R R
4182 ========= == == == ==
4183 ========= == == == ==
4183
4184
4184 .. note::
4185 .. note::
4185
4186
4186 :hg:`remove` never deletes files in Added [A] state from the
4187 :hg:`remove` never deletes files in Added [A] state from the
4187 working directory, not even if ``--force`` is specified.
4188 working directory, not even if ``--force`` is specified.
4188
4189
4189 Returns 0 on success, 1 if any warnings encountered.
4190 Returns 0 on success, 1 if any warnings encountered.
4190 """
4191 """
4191
4192
4192 after, force = opts.get('after'), opts.get('force')
4193 after, force = opts.get('after'), opts.get('force')
4193 if not pats and not after:
4194 if not pats and not after:
4194 raise error.Abort(_('no files specified'))
4195 raise error.Abort(_('no files specified'))
4195
4196
4196 m = scmutil.match(repo[None], pats, opts)
4197 m = scmutil.match(repo[None], pats, opts)
4197 subrepos = opts.get('subrepos')
4198 subrepos = opts.get('subrepos')
4198 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
4199 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
4199
4200
4200 @command('rename|move|mv',
4201 @command('rename|move|mv',
4201 [('A', 'after', None, _('record a rename that has already occurred')),
4202 [('A', 'after', None, _('record a rename that has already occurred')),
4202 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4203 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4203 ] + walkopts + dryrunopts,
4204 ] + walkopts + dryrunopts,
4204 _('[OPTION]... SOURCE... DEST'))
4205 _('[OPTION]... SOURCE... DEST'))
4205 def rename(ui, repo, *pats, **opts):
4206 def rename(ui, repo, *pats, **opts):
4206 """rename files; equivalent of copy + remove
4207 """rename files; equivalent of copy + remove
4207
4208
4208 Mark dest as copies of sources; mark sources for deletion. If dest
4209 Mark dest as copies of sources; mark sources for deletion. If dest
4209 is a directory, copies are put in that directory. If dest is a
4210 is a directory, copies are put in that directory. If dest is a
4210 file, there can only be one source.
4211 file, there can only be one source.
4211
4212
4212 By default, this command copies the contents of files as they
4213 By default, this command copies the contents of files as they
4213 exist in the working directory. If invoked with -A/--after, the
4214 exist in the working directory. If invoked with -A/--after, the
4214 operation is recorded, but no copying is performed.
4215 operation is recorded, but no copying is performed.
4215
4216
4216 This command takes effect at the next commit. To undo a rename
4217 This command takes effect at the next commit. To undo a rename
4217 before that, see :hg:`revert`.
4218 before that, see :hg:`revert`.
4218
4219
4219 Returns 0 on success, 1 if errors are encountered.
4220 Returns 0 on success, 1 if errors are encountered.
4220 """
4221 """
4221 with repo.wlock(False):
4222 with repo.wlock(False):
4222 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4223 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4223
4224
4224 @command('resolve',
4225 @command('resolve',
4225 [('a', 'all', None, _('select all unresolved files')),
4226 [('a', 'all', None, _('select all unresolved files')),
4226 ('l', 'list', None, _('list state of files needing merge')),
4227 ('l', 'list', None, _('list state of files needing merge')),
4227 ('m', 'mark', None, _('mark files as resolved')),
4228 ('m', 'mark', None, _('mark files as resolved')),
4228 ('u', 'unmark', None, _('mark files as unresolved')),
4229 ('u', 'unmark', None, _('mark files as unresolved')),
4229 ('n', 'no-status', None, _('hide status prefix'))]
4230 ('n', 'no-status', None, _('hide status prefix'))]
4230 + mergetoolopts + walkopts + formatteropts,
4231 + mergetoolopts + walkopts + formatteropts,
4231 _('[OPTION]... [FILE]...'),
4232 _('[OPTION]... [FILE]...'),
4232 inferrepo=True)
4233 inferrepo=True)
4233 def resolve(ui, repo, *pats, **opts):
4234 def resolve(ui, repo, *pats, **opts):
4234 """redo merges or set/view the merge status of files
4235 """redo merges or set/view the merge status of files
4235
4236
4236 Merges with unresolved conflicts are often the result of
4237 Merges with unresolved conflicts are often the result of
4237 non-interactive merging using the ``internal:merge`` configuration
4238 non-interactive merging using the ``internal:merge`` configuration
4238 setting, or a command-line merge tool like ``diff3``. The resolve
4239 setting, or a command-line merge tool like ``diff3``. The resolve
4239 command is used to manage the files involved in a merge, after
4240 command is used to manage the files involved in a merge, after
4240 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4241 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4241 working directory must have two parents). See :hg:`help
4242 working directory must have two parents). See :hg:`help
4242 merge-tools` for information on configuring merge tools.
4243 merge-tools` for information on configuring merge tools.
4243
4244
4244 The resolve command can be used in the following ways:
4245 The resolve command can be used in the following ways:
4245
4246
4246 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4247 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4247 files, discarding any previous merge attempts. Re-merging is not
4248 files, discarding any previous merge attempts. Re-merging is not
4248 performed for files already marked as resolved. Use ``--all/-a``
4249 performed for files already marked as resolved. Use ``--all/-a``
4249 to select all unresolved files. ``--tool`` can be used to specify
4250 to select all unresolved files. ``--tool`` can be used to specify
4250 the merge tool used for the given files. It overrides the HGMERGE
4251 the merge tool used for the given files. It overrides the HGMERGE
4251 environment variable and your configuration files. Previous file
4252 environment variable and your configuration files. Previous file
4252 contents are saved with a ``.orig`` suffix.
4253 contents are saved with a ``.orig`` suffix.
4253
4254
4254 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4255 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4255 (e.g. after having manually fixed-up the files). The default is
4256 (e.g. after having manually fixed-up the files). The default is
4256 to mark all unresolved files.
4257 to mark all unresolved files.
4257
4258
4258 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4259 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4259 default is to mark all resolved files.
4260 default is to mark all resolved files.
4260
4261
4261 - :hg:`resolve -l`: list files which had or still have conflicts.
4262 - :hg:`resolve -l`: list files which had or still have conflicts.
4262 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4263 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4263 You can use ``set:unresolved()`` or ``set:resolved()`` to filter
4264 You can use ``set:unresolved()`` or ``set:resolved()`` to filter
4264 the list. See :hg:`help filesets` for details.
4265 the list. See :hg:`help filesets` for details.
4265
4266
4266 .. note::
4267 .. note::
4267
4268
4268 Mercurial will not let you commit files with unresolved merge
4269 Mercurial will not let you commit files with unresolved merge
4269 conflicts. You must use :hg:`resolve -m ...` before you can
4270 conflicts. You must use :hg:`resolve -m ...` before you can
4270 commit after a conflicting merge.
4271 commit after a conflicting merge.
4271
4272
4272 Returns 0 on success, 1 if any files fail a resolve attempt.
4273 Returns 0 on success, 1 if any files fail a resolve attempt.
4273 """
4274 """
4274
4275
4275 flaglist = 'all mark unmark list no_status'.split()
4276 flaglist = 'all mark unmark list no_status'.split()
4276 all, mark, unmark, show, nostatus = \
4277 all, mark, unmark, show, nostatus = \
4277 [opts.get(o) for o in flaglist]
4278 [opts.get(o) for o in flaglist]
4278
4279
4279 if (show and (mark or unmark)) or (mark and unmark):
4280 if (show and (mark or unmark)) or (mark and unmark):
4280 raise error.Abort(_("too many options specified"))
4281 raise error.Abort(_("too many options specified"))
4281 if pats and all:
4282 if pats and all:
4282 raise error.Abort(_("can't specify --all and patterns"))
4283 raise error.Abort(_("can't specify --all and patterns"))
4283 if not (all or pats or show or mark or unmark):
4284 if not (all or pats or show or mark or unmark):
4284 raise error.Abort(_('no files or directories specified'),
4285 raise error.Abort(_('no files or directories specified'),
4285 hint=('use --all to re-merge all unresolved files'))
4286 hint=('use --all to re-merge all unresolved files'))
4286
4287
4287 if show:
4288 if show:
4288 fm = ui.formatter('resolve', opts)
4289 fm = ui.formatter('resolve', opts)
4289 ms = mergemod.mergestate.read(repo)
4290 ms = mergemod.mergestate.read(repo)
4290 m = scmutil.match(repo[None], pats, opts)
4291 m = scmutil.match(repo[None], pats, opts)
4291 for f in ms:
4292 for f in ms:
4292 if not m(f):
4293 if not m(f):
4293 continue
4294 continue
4294 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
4295 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
4295 'd': 'driverresolved'}[ms[f]]
4296 'd': 'driverresolved'}[ms[f]]
4296 fm.startitem()
4297 fm.startitem()
4297 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
4298 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
4298 fm.write('path', '%s\n', f, label=l)
4299 fm.write('path', '%s\n', f, label=l)
4299 fm.end()
4300 fm.end()
4300 return 0
4301 return 0
4301
4302
4302 with repo.wlock():
4303 with repo.wlock():
4303 ms = mergemod.mergestate.read(repo)
4304 ms = mergemod.mergestate.read(repo)
4304
4305
4305 if not (ms.active() or repo.dirstate.p2() != nullid):
4306 if not (ms.active() or repo.dirstate.p2() != nullid):
4306 raise error.Abort(
4307 raise error.Abort(
4307 _('resolve command not applicable when not merging'))
4308 _('resolve command not applicable when not merging'))
4308
4309
4309 wctx = repo[None]
4310 wctx = repo[None]
4310
4311
4311 if ms.mergedriver and ms.mdstate() == 'u':
4312 if ms.mergedriver and ms.mdstate() == 'u':
4312 proceed = mergemod.driverpreprocess(repo, ms, wctx)
4313 proceed = mergemod.driverpreprocess(repo, ms, wctx)
4313 ms.commit()
4314 ms.commit()
4314 # allow mark and unmark to go through
4315 # allow mark and unmark to go through
4315 if not mark and not unmark and not proceed:
4316 if not mark and not unmark and not proceed:
4316 return 1
4317 return 1
4317
4318
4318 m = scmutil.match(wctx, pats, opts)
4319 m = scmutil.match(wctx, pats, opts)
4319 ret = 0
4320 ret = 0
4320 didwork = False
4321 didwork = False
4321 runconclude = False
4322 runconclude = False
4322
4323
4323 tocomplete = []
4324 tocomplete = []
4324 for f in ms:
4325 for f in ms:
4325 if not m(f):
4326 if not m(f):
4326 continue
4327 continue
4327
4328
4328 didwork = True
4329 didwork = True
4329
4330
4330 # don't let driver-resolved files be marked, and run the conclude
4331 # don't let driver-resolved files be marked, and run the conclude
4331 # step if asked to resolve
4332 # step if asked to resolve
4332 if ms[f] == "d":
4333 if ms[f] == "d":
4333 exact = m.exact(f)
4334 exact = m.exact(f)
4334 if mark:
4335 if mark:
4335 if exact:
4336 if exact:
4336 ui.warn(_('not marking %s as it is driver-resolved\n')
4337 ui.warn(_('not marking %s as it is driver-resolved\n')
4337 % f)
4338 % f)
4338 elif unmark:
4339 elif unmark:
4339 if exact:
4340 if exact:
4340 ui.warn(_('not unmarking %s as it is driver-resolved\n')
4341 ui.warn(_('not unmarking %s as it is driver-resolved\n')
4341 % f)
4342 % f)
4342 else:
4343 else:
4343 runconclude = True
4344 runconclude = True
4344 continue
4345 continue
4345
4346
4346 if mark:
4347 if mark:
4347 ms.mark(f, "r")
4348 ms.mark(f, "r")
4348 elif unmark:
4349 elif unmark:
4349 ms.mark(f, "u")
4350 ms.mark(f, "u")
4350 else:
4351 else:
4351 # backup pre-resolve (merge uses .orig for its own purposes)
4352 # backup pre-resolve (merge uses .orig for its own purposes)
4352 a = repo.wjoin(f)
4353 a = repo.wjoin(f)
4353 try:
4354 try:
4354 util.copyfile(a, a + ".resolve")
4355 util.copyfile(a, a + ".resolve")
4355 except (IOError, OSError) as inst:
4356 except (IOError, OSError) as inst:
4356 if inst.errno != errno.ENOENT:
4357 if inst.errno != errno.ENOENT:
4357 raise
4358 raise
4358
4359
4359 try:
4360 try:
4360 # preresolve file
4361 # preresolve file
4361 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4362 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4362 'resolve')
4363 'resolve')
4363 complete, r = ms.preresolve(f, wctx)
4364 complete, r = ms.preresolve(f, wctx)
4364 if not complete:
4365 if not complete:
4365 tocomplete.append(f)
4366 tocomplete.append(f)
4366 elif r:
4367 elif r:
4367 ret = 1
4368 ret = 1
4368 finally:
4369 finally:
4369 ui.setconfig('ui', 'forcemerge', '', 'resolve')
4370 ui.setconfig('ui', 'forcemerge', '', 'resolve')
4370 ms.commit()
4371 ms.commit()
4371
4372
4372 # replace filemerge's .orig file with our resolve file, but only
4373 # replace filemerge's .orig file with our resolve file, but only
4373 # for merges that are complete
4374 # for merges that are complete
4374 if complete:
4375 if complete:
4375 try:
4376 try:
4376 util.rename(a + ".resolve",
4377 util.rename(a + ".resolve",
4377 scmutil.origpath(ui, repo, a))
4378 scmutil.origpath(ui, repo, a))
4378 except OSError as inst:
4379 except OSError as inst:
4379 if inst.errno != errno.ENOENT:
4380 if inst.errno != errno.ENOENT:
4380 raise
4381 raise
4381
4382
4382 for f in tocomplete:
4383 for f in tocomplete:
4383 try:
4384 try:
4384 # resolve file
4385 # resolve file
4385 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4386 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4386 'resolve')
4387 'resolve')
4387 r = ms.resolve(f, wctx)
4388 r = ms.resolve(f, wctx)
4388 if r:
4389 if r:
4389 ret = 1
4390 ret = 1
4390 finally:
4391 finally:
4391 ui.setconfig('ui', 'forcemerge', '', 'resolve')
4392 ui.setconfig('ui', 'forcemerge', '', 'resolve')
4392 ms.commit()
4393 ms.commit()
4393
4394
4394 # replace filemerge's .orig file with our resolve file
4395 # replace filemerge's .orig file with our resolve file
4395 a = repo.wjoin(f)
4396 a = repo.wjoin(f)
4396 try:
4397 try:
4397 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
4398 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
4398 except OSError as inst:
4399 except OSError as inst:
4399 if inst.errno != errno.ENOENT:
4400 if inst.errno != errno.ENOENT:
4400 raise
4401 raise
4401
4402
4402 ms.commit()
4403 ms.commit()
4403 ms.recordactions()
4404 ms.recordactions()
4404
4405
4405 if not didwork and pats:
4406 if not didwork and pats:
4406 hint = None
4407 hint = None
4407 if not any([p for p in pats if p.find(':') >= 0]):
4408 if not any([p for p in pats if p.find(':') >= 0]):
4408 pats = ['path:%s' % p for p in pats]
4409 pats = ['path:%s' % p for p in pats]
4409 m = scmutil.match(wctx, pats, opts)
4410 m = scmutil.match(wctx, pats, opts)
4410 for f in ms:
4411 for f in ms:
4411 if not m(f):
4412 if not m(f):
4412 continue
4413 continue
4413 flags = ''.join(['-%s ' % o[0] for o in flaglist
4414 flags = ''.join(['-%s ' % o[0] for o in flaglist
4414 if opts.get(o)])
4415 if opts.get(o)])
4415 hint = _("(try: hg resolve %s%s)\n") % (
4416 hint = _("(try: hg resolve %s%s)\n") % (
4416 flags,
4417 flags,
4417 ' '.join(pats))
4418 ' '.join(pats))
4418 break
4419 break
4419 ui.warn(_("arguments do not match paths that need resolving\n"))
4420 ui.warn(_("arguments do not match paths that need resolving\n"))
4420 if hint:
4421 if hint:
4421 ui.warn(hint)
4422 ui.warn(hint)
4422 elif ms.mergedriver and ms.mdstate() != 's':
4423 elif ms.mergedriver and ms.mdstate() != 's':
4423 # run conclude step when either a driver-resolved file is requested
4424 # run conclude step when either a driver-resolved file is requested
4424 # or there are no driver-resolved files
4425 # or there are no driver-resolved files
4425 # we can't use 'ret' to determine whether any files are unresolved
4426 # we can't use 'ret' to determine whether any files are unresolved
4426 # because we might not have tried to resolve some
4427 # because we might not have tried to resolve some
4427 if ((runconclude or not list(ms.driverresolved()))
4428 if ((runconclude or not list(ms.driverresolved()))
4428 and not list(ms.unresolved())):
4429 and not list(ms.unresolved())):
4429 proceed = mergemod.driverconclude(repo, ms, wctx)
4430 proceed = mergemod.driverconclude(repo, ms, wctx)
4430 ms.commit()
4431 ms.commit()
4431 if not proceed:
4432 if not proceed:
4432 return 1
4433 return 1
4433
4434
4434 # Nudge users into finishing an unfinished operation
4435 # Nudge users into finishing an unfinished operation
4435 unresolvedf = list(ms.unresolved())
4436 unresolvedf = list(ms.unresolved())
4436 driverresolvedf = list(ms.driverresolved())
4437 driverresolvedf = list(ms.driverresolved())
4437 if not unresolvedf and not driverresolvedf:
4438 if not unresolvedf and not driverresolvedf:
4438 ui.status(_('(no more unresolved files)\n'))
4439 ui.status(_('(no more unresolved files)\n'))
4439 cmdutil.checkafterresolved(repo)
4440 cmdutil.checkafterresolved(repo)
4440 elif not unresolvedf:
4441 elif not unresolvedf:
4441 ui.status(_('(no more unresolved files -- '
4442 ui.status(_('(no more unresolved files -- '
4442 'run "hg resolve --all" to conclude)\n'))
4443 'run "hg resolve --all" to conclude)\n'))
4443
4444
4444 return ret
4445 return ret
4445
4446
4446 @command('revert',
4447 @command('revert',
4447 [('a', 'all', None, _('revert all changes when no arguments given')),
4448 [('a', 'all', None, _('revert all changes when no arguments given')),
4448 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4449 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4449 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4450 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4450 ('C', 'no-backup', None, _('do not save backup copies of files')),
4451 ('C', 'no-backup', None, _('do not save backup copies of files')),
4451 ('i', 'interactive', None,
4452 ('i', 'interactive', None,
4452 _('interactively select the changes (EXPERIMENTAL)')),
4453 _('interactively select the changes (EXPERIMENTAL)')),
4453 ] + walkopts + dryrunopts,
4454 ] + walkopts + dryrunopts,
4454 _('[OPTION]... [-r REV] [NAME]...'))
4455 _('[OPTION]... [-r REV] [NAME]...'))
4455 def revert(ui, repo, *pats, **opts):
4456 def revert(ui, repo, *pats, **opts):
4456 """restore files to their checkout state
4457 """restore files to their checkout state
4457
4458
4458 .. note::
4459 .. note::
4459
4460
4460 To check out earlier revisions, you should use :hg:`update REV`.
4461 To check out earlier revisions, you should use :hg:`update REV`.
4461 To cancel an uncommitted merge (and lose your changes),
4462 To cancel an uncommitted merge (and lose your changes),
4462 use :hg:`update --clean .`.
4463 use :hg:`update --clean .`.
4463
4464
4464 With no revision specified, revert the specified files or directories
4465 With no revision specified, revert the specified files or directories
4465 to the contents they had in the parent of the working directory.
4466 to the contents they had in the parent of the working directory.
4466 This restores the contents of files to an unmodified
4467 This restores the contents of files to an unmodified
4467 state and unschedules adds, removes, copies, and renames. If the
4468 state and unschedules adds, removes, copies, and renames. If the
4468 working directory has two parents, you must explicitly specify a
4469 working directory has two parents, you must explicitly specify a
4469 revision.
4470 revision.
4470
4471
4471 Using the -r/--rev or -d/--date options, revert the given files or
4472 Using the -r/--rev or -d/--date options, revert the given files or
4472 directories to their states as of a specific revision. Because
4473 directories to their states as of a specific revision. Because
4473 revert does not change the working directory parents, this will
4474 revert does not change the working directory parents, this will
4474 cause these files to appear modified. This can be helpful to "back
4475 cause these files to appear modified. This can be helpful to "back
4475 out" some or all of an earlier change. See :hg:`backout` for a
4476 out" some or all of an earlier change. See :hg:`backout` for a
4476 related method.
4477 related method.
4477
4478
4478 Modified files are saved with a .orig suffix before reverting.
4479 Modified files are saved with a .orig suffix before reverting.
4479 To disable these backups, use --no-backup. It is possible to store
4480 To disable these backups, use --no-backup. It is possible to store
4480 the backup files in a custom directory relative to the root of the
4481 the backup files in a custom directory relative to the root of the
4481 repository by setting the ``ui.origbackuppath`` configuration
4482 repository by setting the ``ui.origbackuppath`` configuration
4482 option.
4483 option.
4483
4484
4484 See :hg:`help dates` for a list of formats valid for -d/--date.
4485 See :hg:`help dates` for a list of formats valid for -d/--date.
4485
4486
4486 See :hg:`help backout` for a way to reverse the effect of an
4487 See :hg:`help backout` for a way to reverse the effect of an
4487 earlier changeset.
4488 earlier changeset.
4488
4489
4489 Returns 0 on success.
4490 Returns 0 on success.
4490 """
4491 """
4491
4492
4492 if opts.get("date"):
4493 if opts.get("date"):
4493 if opts.get("rev"):
4494 if opts.get("rev"):
4494 raise error.Abort(_("you can't specify a revision and a date"))
4495 raise error.Abort(_("you can't specify a revision and a date"))
4495 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4496 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4496
4497
4497 parent, p2 = repo.dirstate.parents()
4498 parent, p2 = repo.dirstate.parents()
4498 if not opts.get('rev') and p2 != nullid:
4499 if not opts.get('rev') and p2 != nullid:
4499 # revert after merge is a trap for new users (issue2915)
4500 # revert after merge is a trap for new users (issue2915)
4500 raise error.Abort(_('uncommitted merge with no revision specified'),
4501 raise error.Abort(_('uncommitted merge with no revision specified'),
4501 hint=_("use 'hg update' or see 'hg help revert'"))
4502 hint=_("use 'hg update' or see 'hg help revert'"))
4502
4503
4503 ctx = scmutil.revsingle(repo, opts.get('rev'))
4504 ctx = scmutil.revsingle(repo, opts.get('rev'))
4504
4505
4505 if (not (pats or opts.get('include') or opts.get('exclude') or
4506 if (not (pats or opts.get('include') or opts.get('exclude') or
4506 opts.get('all') or opts.get('interactive'))):
4507 opts.get('all') or opts.get('interactive'))):
4507 msg = _("no files or directories specified")
4508 msg = _("no files or directories specified")
4508 if p2 != nullid:
4509 if p2 != nullid:
4509 hint = _("uncommitted merge, use --all to discard all changes,"
4510 hint = _("uncommitted merge, use --all to discard all changes,"
4510 " or 'hg update -C .' to abort the merge")
4511 " or 'hg update -C .' to abort the merge")
4511 raise error.Abort(msg, hint=hint)
4512 raise error.Abort(msg, hint=hint)
4512 dirty = any(repo.status())
4513 dirty = any(repo.status())
4513 node = ctx.node()
4514 node = ctx.node()
4514 if node != parent:
4515 if node != parent:
4515 if dirty:
4516 if dirty:
4516 hint = _("uncommitted changes, use --all to discard all"
4517 hint = _("uncommitted changes, use --all to discard all"
4517 " changes, or 'hg update %s' to update") % ctx.rev()
4518 " changes, or 'hg update %s' to update") % ctx.rev()
4518 else:
4519 else:
4519 hint = _("use --all to revert all files,"
4520 hint = _("use --all to revert all files,"
4520 " or 'hg update %s' to update") % ctx.rev()
4521 " or 'hg update %s' to update") % ctx.rev()
4521 elif dirty:
4522 elif dirty:
4522 hint = _("uncommitted changes, use --all to discard all changes")
4523 hint = _("uncommitted changes, use --all to discard all changes")
4523 else:
4524 else:
4524 hint = _("use --all to revert all files")
4525 hint = _("use --all to revert all files")
4525 raise error.Abort(msg, hint=hint)
4526 raise error.Abort(msg, hint=hint)
4526
4527
4527 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
4528 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
4528
4529
4529 @command('rollback', dryrunopts +
4530 @command('rollback', dryrunopts +
4530 [('f', 'force', False, _('ignore safety measures'))])
4531 [('f', 'force', False, _('ignore safety measures'))])
4531 def rollback(ui, repo, **opts):
4532 def rollback(ui, repo, **opts):
4532 """roll back the last transaction (DANGEROUS) (DEPRECATED)
4533 """roll back the last transaction (DANGEROUS) (DEPRECATED)
4533
4534
4534 Please use :hg:`commit --amend` instead of rollback to correct
4535 Please use :hg:`commit --amend` instead of rollback to correct
4535 mistakes in the last commit.
4536 mistakes in the last commit.
4536
4537
4537 This command should be used with care. There is only one level of
4538 This command should be used with care. There is only one level of
4538 rollback, and there is no way to undo a rollback. It will also
4539 rollback, and there is no way to undo a rollback. It will also
4539 restore the dirstate at the time of the last transaction, losing
4540 restore the dirstate at the time of the last transaction, losing
4540 any dirstate changes since that time. This command does not alter
4541 any dirstate changes since that time. This command does not alter
4541 the working directory.
4542 the working directory.
4542
4543
4543 Transactions are used to encapsulate the effects of all commands
4544 Transactions are used to encapsulate the effects of all commands
4544 that create new changesets or propagate existing changesets into a
4545 that create new changesets or propagate existing changesets into a
4545 repository.
4546 repository.
4546
4547
4547 .. container:: verbose
4548 .. container:: verbose
4548
4549
4549 For example, the following commands are transactional, and their
4550 For example, the following commands are transactional, and their
4550 effects can be rolled back:
4551 effects can be rolled back:
4551
4552
4552 - commit
4553 - commit
4553 - import
4554 - import
4554 - pull
4555 - pull
4555 - push (with this repository as the destination)
4556 - push (with this repository as the destination)
4556 - unbundle
4557 - unbundle
4557
4558
4558 To avoid permanent data loss, rollback will refuse to rollback a
4559 To avoid permanent data loss, rollback will refuse to rollback a
4559 commit transaction if it isn't checked out. Use --force to
4560 commit transaction if it isn't checked out. Use --force to
4560 override this protection.
4561 override this protection.
4561
4562
4562 The rollback command can be entirely disabled by setting the
4563 The rollback command can be entirely disabled by setting the
4563 ``ui.rollback`` configuration setting to false. If you're here
4564 ``ui.rollback`` configuration setting to false. If you're here
4564 because you want to use rollback and it's disabled, you can
4565 because you want to use rollback and it's disabled, you can
4565 re-enable the command by setting ``ui.rollback`` to true.
4566 re-enable the command by setting ``ui.rollback`` to true.
4566
4567
4567 This command is not intended for use on public repositories. Once
4568 This command is not intended for use on public repositories. Once
4568 changes are visible for pull by other users, rolling a transaction
4569 changes are visible for pull by other users, rolling a transaction
4569 back locally is ineffective (someone else may already have pulled
4570 back locally is ineffective (someone else may already have pulled
4570 the changes). Furthermore, a race is possible with readers of the
4571 the changes). Furthermore, a race is possible with readers of the
4571 repository; for example an in-progress pull from the repository
4572 repository; for example an in-progress pull from the repository
4572 may fail if a rollback is performed.
4573 may fail if a rollback is performed.
4573
4574
4574 Returns 0 on success, 1 if no rollback data is available.
4575 Returns 0 on success, 1 if no rollback data is available.
4575 """
4576 """
4576 if not ui.configbool('ui', 'rollback', True):
4577 if not ui.configbool('ui', 'rollback', True):
4577 raise error.Abort(_('rollback is disabled because it is unsafe'),
4578 raise error.Abort(_('rollback is disabled because it is unsafe'),
4578 hint=('see `hg help -v rollback` for information'))
4579 hint=('see `hg help -v rollback` for information'))
4579 return repo.rollback(dryrun=opts.get('dry_run'),
4580 return repo.rollback(dryrun=opts.get('dry_run'),
4580 force=opts.get('force'))
4581 force=opts.get('force'))
4581
4582
4582 @command('root', [])
4583 @command('root', [])
4583 def root(ui, repo):
4584 def root(ui, repo):
4584 """print the root (top) of the current working directory
4585 """print the root (top) of the current working directory
4585
4586
4586 Print the root directory of the current repository.
4587 Print the root directory of the current repository.
4587
4588
4588 Returns 0 on success.
4589 Returns 0 on success.
4589 """
4590 """
4590 ui.write(repo.root + "\n")
4591 ui.write(repo.root + "\n")
4591
4592
4592 @command('^serve',
4593 @command('^serve',
4593 [('A', 'accesslog', '', _('name of access log file to write to'),
4594 [('A', 'accesslog', '', _('name of access log file to write to'),
4594 _('FILE')),
4595 _('FILE')),
4595 ('d', 'daemon', None, _('run server in background')),
4596 ('d', 'daemon', None, _('run server in background')),
4596 ('', 'daemon-postexec', [], _('used internally by daemon mode')),
4597 ('', 'daemon-postexec', [], _('used internally by daemon mode')),
4597 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4598 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4598 # use string type, then we can check if something was passed
4599 # use string type, then we can check if something was passed
4599 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4600 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4600 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4601 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4601 _('ADDR')),
4602 _('ADDR')),
4602 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4603 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4603 _('PREFIX')),
4604 _('PREFIX')),
4604 ('n', 'name', '',
4605 ('n', 'name', '',
4605 _('name to show in web pages (default: working directory)'), _('NAME')),
4606 _('name to show in web pages (default: working directory)'), _('NAME')),
4606 ('', 'web-conf', '',
4607 ('', 'web-conf', '',
4607 _("name of the hgweb config file (see 'hg help hgweb')"), _('FILE')),
4608 _("name of the hgweb config file (see 'hg help hgweb')"), _('FILE')),
4608 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4609 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4609 _('FILE')),
4610 _('FILE')),
4610 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4611 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4611 ('', 'stdio', None, _('for remote clients')),
4612 ('', 'stdio', None, _('for remote clients')),
4612 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
4613 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
4613 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4614 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4614 ('', 'style', '', _('template style to use'), _('STYLE')),
4615 ('', 'style', '', _('template style to use'), _('STYLE')),
4615 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4616 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4616 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
4617 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
4617 _('[OPTION]...'),
4618 _('[OPTION]...'),
4618 optionalrepo=True)
4619 optionalrepo=True)
4619 def serve(ui, repo, **opts):
4620 def serve(ui, repo, **opts):
4620 """start stand-alone webserver
4621 """start stand-alone webserver
4621
4622
4622 Start a local HTTP repository browser and pull server. You can use
4623 Start a local HTTP repository browser and pull server. You can use
4623 this for ad-hoc sharing and browsing of repositories. It is
4624 this for ad-hoc sharing and browsing of repositories. It is
4624 recommended to use a real web server to serve a repository for
4625 recommended to use a real web server to serve a repository for
4625 longer periods of time.
4626 longer periods of time.
4626
4627
4627 Please note that the server does not implement access control.
4628 Please note that the server does not implement access control.
4628 This means that, by default, anybody can read from the server and
4629 This means that, by default, anybody can read from the server and
4629 nobody can write to it by default. Set the ``web.allow_push``
4630 nobody can write to it by default. Set the ``web.allow_push``
4630 option to ``*`` to allow everybody to push to the server. You
4631 option to ``*`` to allow everybody to push to the server. You
4631 should use a real web server if you need to authenticate users.
4632 should use a real web server if you need to authenticate users.
4632
4633
4633 By default, the server logs accesses to stdout and errors to
4634 By default, the server logs accesses to stdout and errors to
4634 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
4635 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
4635 files.
4636 files.
4636
4637
4637 To have the server choose a free port number to listen on, specify
4638 To have the server choose a free port number to listen on, specify
4638 a port number of 0; in this case, the server will print the port
4639 a port number of 0; in this case, the server will print the port
4639 number it uses.
4640 number it uses.
4640
4641
4641 Returns 0 on success.
4642 Returns 0 on success.
4642 """
4643 """
4643
4644
4644 if opts["stdio"] and opts["cmdserver"]:
4645 if opts["stdio"] and opts["cmdserver"]:
4645 raise error.Abort(_("cannot use --stdio with --cmdserver"))
4646 raise error.Abort(_("cannot use --stdio with --cmdserver"))
4646
4647
4647 if opts["stdio"]:
4648 if opts["stdio"]:
4648 if repo is None:
4649 if repo is None:
4649 raise error.RepoError(_("there is no Mercurial repository here"
4650 raise error.RepoError(_("there is no Mercurial repository here"
4650 " (.hg not found)"))
4651 " (.hg not found)"))
4651 s = sshserver.sshserver(ui, repo)
4652 s = sshserver.sshserver(ui, repo)
4652 s.serve_forever()
4653 s.serve_forever()
4653
4654
4654 service = server.createservice(ui, repo, opts)
4655 service = server.createservice(ui, repo, opts)
4655 return server.runservice(opts, initfn=service.init, runfn=service.run)
4656 return server.runservice(opts, initfn=service.init, runfn=service.run)
4656
4657
4657 @command('^status|st',
4658 @command('^status|st',
4658 [('A', 'all', None, _('show status of all files')),
4659 [('A', 'all', None, _('show status of all files')),
4659 ('m', 'modified', None, _('show only modified files')),
4660 ('m', 'modified', None, _('show only modified files')),
4660 ('a', 'added', None, _('show only added files')),
4661 ('a', 'added', None, _('show only added files')),
4661 ('r', 'removed', None, _('show only removed files')),
4662 ('r', 'removed', None, _('show only removed files')),
4662 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4663 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4663 ('c', 'clean', None, _('show only files without changes')),
4664 ('c', 'clean', None, _('show only files without changes')),
4664 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4665 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4665 ('i', 'ignored', None, _('show only ignored files')),
4666 ('i', 'ignored', None, _('show only ignored files')),
4666 ('n', 'no-status', None, _('hide status prefix')),
4667 ('n', 'no-status', None, _('hide status prefix')),
4667 ('C', 'copies', None, _('show source of copied files')),
4668 ('C', 'copies', None, _('show source of copied files')),
4668 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4669 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4669 ('', 'rev', [], _('show difference from revision'), _('REV')),
4670 ('', 'rev', [], _('show difference from revision'), _('REV')),
4670 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
4671 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
4671 ] + walkopts + subrepoopts + formatteropts,
4672 ] + walkopts + subrepoopts + formatteropts,
4672 _('[OPTION]... [FILE]...'),
4673 _('[OPTION]... [FILE]...'),
4673 inferrepo=True)
4674 inferrepo=True)
4674 def status(ui, repo, *pats, **opts):
4675 def status(ui, repo, *pats, **opts):
4675 """show changed files in the working directory
4676 """show changed files in the working directory
4676
4677
4677 Show status of files in the repository. If names are given, only
4678 Show status of files in the repository. If names are given, only
4678 files that match are shown. Files that are clean or ignored or
4679 files that match are shown. Files that are clean or ignored or
4679 the source of a copy/move operation, are not listed unless
4680 the source of a copy/move operation, are not listed unless
4680 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
4681 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
4681 Unless options described with "show only ..." are given, the
4682 Unless options described with "show only ..." are given, the
4682 options -mardu are used.
4683 options -mardu are used.
4683
4684
4684 Option -q/--quiet hides untracked (unknown and ignored) files
4685 Option -q/--quiet hides untracked (unknown and ignored) files
4685 unless explicitly requested with -u/--unknown or -i/--ignored.
4686 unless explicitly requested with -u/--unknown or -i/--ignored.
4686
4687
4687 .. note::
4688 .. note::
4688
4689
4689 :hg:`status` may appear to disagree with diff if permissions have
4690 :hg:`status` may appear to disagree with diff if permissions have
4690 changed or a merge has occurred. The standard diff format does
4691 changed or a merge has occurred. The standard diff format does
4691 not report permission changes and diff only reports changes
4692 not report permission changes and diff only reports changes
4692 relative to one merge parent.
4693 relative to one merge parent.
4693
4694
4694 If one revision is given, it is used as the base revision.
4695 If one revision is given, it is used as the base revision.
4695 If two revisions are given, the differences between them are
4696 If two revisions are given, the differences between them are
4696 shown. The --change option can also be used as a shortcut to list
4697 shown. The --change option can also be used as a shortcut to list
4697 the changed files of a revision from its first parent.
4698 the changed files of a revision from its first parent.
4698
4699
4699 The codes used to show the status of files are::
4700 The codes used to show the status of files are::
4700
4701
4701 M = modified
4702 M = modified
4702 A = added
4703 A = added
4703 R = removed
4704 R = removed
4704 C = clean
4705 C = clean
4705 ! = missing (deleted by non-hg command, but still tracked)
4706 ! = missing (deleted by non-hg command, but still tracked)
4706 ? = not tracked
4707 ? = not tracked
4707 I = ignored
4708 I = ignored
4708 = origin of the previous file (with --copies)
4709 = origin of the previous file (with --copies)
4709
4710
4710 .. container:: verbose
4711 .. container:: verbose
4711
4712
4712 Examples:
4713 Examples:
4713
4714
4714 - show changes in the working directory relative to a
4715 - show changes in the working directory relative to a
4715 changeset::
4716 changeset::
4716
4717
4717 hg status --rev 9353
4718 hg status --rev 9353
4718
4719
4719 - show changes in the working directory relative to the
4720 - show changes in the working directory relative to the
4720 current directory (see :hg:`help patterns` for more information)::
4721 current directory (see :hg:`help patterns` for more information)::
4721
4722
4722 hg status re:
4723 hg status re:
4723
4724
4724 - show all changes including copies in an existing changeset::
4725 - show all changes including copies in an existing changeset::
4725
4726
4726 hg status --copies --change 9353
4727 hg status --copies --change 9353
4727
4728
4728 - get a NUL separated list of added files, suitable for xargs::
4729 - get a NUL separated list of added files, suitable for xargs::
4729
4730
4730 hg status -an0
4731 hg status -an0
4731
4732
4732 Returns 0 on success.
4733 Returns 0 on success.
4733 """
4734 """
4734
4735
4735 revs = opts.get('rev')
4736 revs = opts.get('rev')
4736 change = opts.get('change')
4737 change = opts.get('change')
4737
4738
4738 if revs and change:
4739 if revs and change:
4739 msg = _('cannot specify --rev and --change at the same time')
4740 msg = _('cannot specify --rev and --change at the same time')
4740 raise error.Abort(msg)
4741 raise error.Abort(msg)
4741 elif change:
4742 elif change:
4742 node2 = scmutil.revsingle(repo, change, None).node()
4743 node2 = scmutil.revsingle(repo, change, None).node()
4743 node1 = repo[node2].p1().node()
4744 node1 = repo[node2].p1().node()
4744 else:
4745 else:
4745 node1, node2 = scmutil.revpair(repo, revs)
4746 node1, node2 = scmutil.revpair(repo, revs)
4746
4747
4747 if pats:
4748 if pats:
4748 cwd = repo.getcwd()
4749 cwd = repo.getcwd()
4749 else:
4750 else:
4750 cwd = ''
4751 cwd = ''
4751
4752
4752 if opts.get('print0'):
4753 if opts.get('print0'):
4753 end = '\0'
4754 end = '\0'
4754 else:
4755 else:
4755 end = '\n'
4756 end = '\n'
4756 copy = {}
4757 copy = {}
4757 states = 'modified added removed deleted unknown ignored clean'.split()
4758 states = 'modified added removed deleted unknown ignored clean'.split()
4758 show = [k for k in states if opts.get(k)]
4759 show = [k for k in states if opts.get(k)]
4759 if opts.get('all'):
4760 if opts.get('all'):
4760 show += ui.quiet and (states[:4] + ['clean']) or states
4761 show += ui.quiet and (states[:4] + ['clean']) or states
4761 if not show:
4762 if not show:
4762 if ui.quiet:
4763 if ui.quiet:
4763 show = states[:4]
4764 show = states[:4]
4764 else:
4765 else:
4765 show = states[:5]
4766 show = states[:5]
4766
4767
4767 m = scmutil.match(repo[node2], pats, opts)
4768 m = scmutil.match(repo[node2], pats, opts)
4768 stat = repo.status(node1, node2, m,
4769 stat = repo.status(node1, node2, m,
4769 'ignored' in show, 'clean' in show, 'unknown' in show,
4770 'ignored' in show, 'clean' in show, 'unknown' in show,
4770 opts.get('subrepos'))
4771 opts.get('subrepos'))
4771 changestates = zip(states, 'MAR!?IC', stat)
4772 changestates = zip(states, 'MAR!?IC', stat)
4772
4773
4773 if (opts.get('all') or opts.get('copies')
4774 if (opts.get('all') or opts.get('copies')
4774 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
4775 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
4775 copy = copies.pathcopies(repo[node1], repo[node2], m)
4776 copy = copies.pathcopies(repo[node1], repo[node2], m)
4776
4777
4777 fm = ui.formatter('status', opts)
4778 fm = ui.formatter('status', opts)
4778 fmt = '%s' + end
4779 fmt = '%s' + end
4779 showchar = not opts.get('no_status')
4780 showchar = not opts.get('no_status')
4780
4781
4781 for state, char, files in changestates:
4782 for state, char, files in changestates:
4782 if state in show:
4783 if state in show:
4783 label = 'status.' + state
4784 label = 'status.' + state
4784 for f in files:
4785 for f in files:
4785 fm.startitem()
4786 fm.startitem()
4786 fm.condwrite(showchar, 'status', '%s ', char, label=label)
4787 fm.condwrite(showchar, 'status', '%s ', char, label=label)
4787 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
4788 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
4788 if f in copy:
4789 if f in copy:
4789 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
4790 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
4790 label='status.copied')
4791 label='status.copied')
4791 fm.end()
4792 fm.end()
4792
4793
4793 @command('^summary|sum',
4794 @command('^summary|sum',
4794 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
4795 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
4795 def summary(ui, repo, **opts):
4796 def summary(ui, repo, **opts):
4796 """summarize working directory state
4797 """summarize working directory state
4797
4798
4798 This generates a brief summary of the working directory state,
4799 This generates a brief summary of the working directory state,
4799 including parents, branch, commit status, phase and available updates.
4800 including parents, branch, commit status, phase and available updates.
4800
4801
4801 With the --remote option, this will check the default paths for
4802 With the --remote option, this will check the default paths for
4802 incoming and outgoing changes. This can be time-consuming.
4803 incoming and outgoing changes. This can be time-consuming.
4803
4804
4804 Returns 0 on success.
4805 Returns 0 on success.
4805 """
4806 """
4806
4807
4807 ctx = repo[None]
4808 ctx = repo[None]
4808 parents = ctx.parents()
4809 parents = ctx.parents()
4809 pnode = parents[0].node()
4810 pnode = parents[0].node()
4810 marks = []
4811 marks = []
4811
4812
4812 ms = None
4813 ms = None
4813 try:
4814 try:
4814 ms = mergemod.mergestate.read(repo)
4815 ms = mergemod.mergestate.read(repo)
4815 except error.UnsupportedMergeRecords as e:
4816 except error.UnsupportedMergeRecords as e:
4816 s = ' '.join(e.recordtypes)
4817 s = ' '.join(e.recordtypes)
4817 ui.warn(
4818 ui.warn(
4818 _('warning: merge state has unsupported record types: %s\n') % s)
4819 _('warning: merge state has unsupported record types: %s\n') % s)
4819 unresolved = 0
4820 unresolved = 0
4820 else:
4821 else:
4821 unresolved = [f for f in ms if ms[f] == 'u']
4822 unresolved = [f for f in ms if ms[f] == 'u']
4822
4823
4823 for p in parents:
4824 for p in parents:
4824 # label with log.changeset (instead of log.parent) since this
4825 # label with log.changeset (instead of log.parent) since this
4825 # shows a working directory parent *changeset*:
4826 # shows a working directory parent *changeset*:
4826 # i18n: column positioning for "hg summary"
4827 # i18n: column positioning for "hg summary"
4827 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
4828 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
4828 label=cmdutil._changesetlabels(p))
4829 label=cmdutil._changesetlabels(p))
4829 ui.write(' '.join(p.tags()), label='log.tag')
4830 ui.write(' '.join(p.tags()), label='log.tag')
4830 if p.bookmarks():
4831 if p.bookmarks():
4831 marks.extend(p.bookmarks())
4832 marks.extend(p.bookmarks())
4832 if p.rev() == -1:
4833 if p.rev() == -1:
4833 if not len(repo):
4834 if not len(repo):
4834 ui.write(_(' (empty repository)'))
4835 ui.write(_(' (empty repository)'))
4835 else:
4836 else:
4836 ui.write(_(' (no revision checked out)'))
4837 ui.write(_(' (no revision checked out)'))
4837 if p.troubled():
4838 if p.troubled():
4838 ui.write(' ('
4839 ui.write(' ('
4839 + ', '.join(ui.label(trouble, 'trouble.%s' % trouble)
4840 + ', '.join(ui.label(trouble, 'trouble.%s' % trouble)
4840 for trouble in p.troubles())
4841 for trouble in p.troubles())
4841 + ')')
4842 + ')')
4842 ui.write('\n')
4843 ui.write('\n')
4843 if p.description():
4844 if p.description():
4844 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
4845 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
4845 label='log.summary')
4846 label='log.summary')
4846
4847
4847 branch = ctx.branch()
4848 branch = ctx.branch()
4848 bheads = repo.branchheads(branch)
4849 bheads = repo.branchheads(branch)
4849 # i18n: column positioning for "hg summary"
4850 # i18n: column positioning for "hg summary"
4850 m = _('branch: %s\n') % branch
4851 m = _('branch: %s\n') % branch
4851 if branch != 'default':
4852 if branch != 'default':
4852 ui.write(m, label='log.branch')
4853 ui.write(m, label='log.branch')
4853 else:
4854 else:
4854 ui.status(m, label='log.branch')
4855 ui.status(m, label='log.branch')
4855
4856
4856 if marks:
4857 if marks:
4857 active = repo._activebookmark
4858 active = repo._activebookmark
4858 # i18n: column positioning for "hg summary"
4859 # i18n: column positioning for "hg summary"
4859 ui.write(_('bookmarks:'), label='log.bookmark')
4860 ui.write(_('bookmarks:'), label='log.bookmark')
4860 if active is not None:
4861 if active is not None:
4861 if active in marks:
4862 if active in marks:
4862 ui.write(' *' + active, label=activebookmarklabel)
4863 ui.write(' *' + active, label=activebookmarklabel)
4863 marks.remove(active)
4864 marks.remove(active)
4864 else:
4865 else:
4865 ui.write(' [%s]' % active, label=activebookmarklabel)
4866 ui.write(' [%s]' % active, label=activebookmarklabel)
4866 for m in marks:
4867 for m in marks:
4867 ui.write(' ' + m, label='log.bookmark')
4868 ui.write(' ' + m, label='log.bookmark')
4868 ui.write('\n', label='log.bookmark')
4869 ui.write('\n', label='log.bookmark')
4869
4870
4870 status = repo.status(unknown=True)
4871 status = repo.status(unknown=True)
4871
4872
4872 c = repo.dirstate.copies()
4873 c = repo.dirstate.copies()
4873 copied, renamed = [], []
4874 copied, renamed = [], []
4874 for d, s in c.iteritems():
4875 for d, s in c.iteritems():
4875 if s in status.removed:
4876 if s in status.removed:
4876 status.removed.remove(s)
4877 status.removed.remove(s)
4877 renamed.append(d)
4878 renamed.append(d)
4878 else:
4879 else:
4879 copied.append(d)
4880 copied.append(d)
4880 if d in status.added:
4881 if d in status.added:
4881 status.added.remove(d)
4882 status.added.remove(d)
4882
4883
4883 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
4884 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
4884
4885
4885 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
4886 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
4886 (ui.label(_('%d added'), 'status.added'), status.added),
4887 (ui.label(_('%d added'), 'status.added'), status.added),
4887 (ui.label(_('%d removed'), 'status.removed'), status.removed),
4888 (ui.label(_('%d removed'), 'status.removed'), status.removed),
4888 (ui.label(_('%d renamed'), 'status.copied'), renamed),
4889 (ui.label(_('%d renamed'), 'status.copied'), renamed),
4889 (ui.label(_('%d copied'), 'status.copied'), copied),
4890 (ui.label(_('%d copied'), 'status.copied'), copied),
4890 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
4891 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
4891 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
4892 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
4892 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
4893 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
4893 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
4894 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
4894 t = []
4895 t = []
4895 for l, s in labels:
4896 for l, s in labels:
4896 if s:
4897 if s:
4897 t.append(l % len(s))
4898 t.append(l % len(s))
4898
4899
4899 t = ', '.join(t)
4900 t = ', '.join(t)
4900 cleanworkdir = False
4901 cleanworkdir = False
4901
4902
4902 if repo.vfs.exists('graftstate'):
4903 if repo.vfs.exists('graftstate'):
4903 t += _(' (graft in progress)')
4904 t += _(' (graft in progress)')
4904 if repo.vfs.exists('updatestate'):
4905 if repo.vfs.exists('updatestate'):
4905 t += _(' (interrupted update)')
4906 t += _(' (interrupted update)')
4906 elif len(parents) > 1:
4907 elif len(parents) > 1:
4907 t += _(' (merge)')
4908 t += _(' (merge)')
4908 elif branch != parents[0].branch():
4909 elif branch != parents[0].branch():
4909 t += _(' (new branch)')
4910 t += _(' (new branch)')
4910 elif (parents[0].closesbranch() and
4911 elif (parents[0].closesbranch() and
4911 pnode in repo.branchheads(branch, closed=True)):
4912 pnode in repo.branchheads(branch, closed=True)):
4912 t += _(' (head closed)')
4913 t += _(' (head closed)')
4913 elif not (status.modified or status.added or status.removed or renamed or
4914 elif not (status.modified or status.added or status.removed or renamed or
4914 copied or subs):
4915 copied or subs):
4915 t += _(' (clean)')
4916 t += _(' (clean)')
4916 cleanworkdir = True
4917 cleanworkdir = True
4917 elif pnode not in bheads:
4918 elif pnode not in bheads:
4918 t += _(' (new branch head)')
4919 t += _(' (new branch head)')
4919
4920
4920 if parents:
4921 if parents:
4921 pendingphase = max(p.phase() for p in parents)
4922 pendingphase = max(p.phase() for p in parents)
4922 else:
4923 else:
4923 pendingphase = phases.public
4924 pendingphase = phases.public
4924
4925
4925 if pendingphase > phases.newcommitphase(ui):
4926 if pendingphase > phases.newcommitphase(ui):
4926 t += ' (%s)' % phases.phasenames[pendingphase]
4927 t += ' (%s)' % phases.phasenames[pendingphase]
4927
4928
4928 if cleanworkdir:
4929 if cleanworkdir:
4929 # i18n: column positioning for "hg summary"
4930 # i18n: column positioning for "hg summary"
4930 ui.status(_('commit: %s\n') % t.strip())
4931 ui.status(_('commit: %s\n') % t.strip())
4931 else:
4932 else:
4932 # i18n: column positioning for "hg summary"
4933 # i18n: column positioning for "hg summary"
4933 ui.write(_('commit: %s\n') % t.strip())
4934 ui.write(_('commit: %s\n') % t.strip())
4934
4935
4935 # all ancestors of branch heads - all ancestors of parent = new csets
4936 # all ancestors of branch heads - all ancestors of parent = new csets
4936 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
4937 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
4937 bheads))
4938 bheads))
4938
4939
4939 if new == 0:
4940 if new == 0:
4940 # i18n: column positioning for "hg summary"
4941 # i18n: column positioning for "hg summary"
4941 ui.status(_('update: (current)\n'))
4942 ui.status(_('update: (current)\n'))
4942 elif pnode not in bheads:
4943 elif pnode not in bheads:
4943 # i18n: column positioning for "hg summary"
4944 # i18n: column positioning for "hg summary"
4944 ui.write(_('update: %d new changesets (update)\n') % new)
4945 ui.write(_('update: %d new changesets (update)\n') % new)
4945 else:
4946 else:
4946 # i18n: column positioning for "hg summary"
4947 # i18n: column positioning for "hg summary"
4947 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
4948 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
4948 (new, len(bheads)))
4949 (new, len(bheads)))
4949
4950
4950 t = []
4951 t = []
4951 draft = len(repo.revs('draft()'))
4952 draft = len(repo.revs('draft()'))
4952 if draft:
4953 if draft:
4953 t.append(_('%d draft') % draft)
4954 t.append(_('%d draft') % draft)
4954 secret = len(repo.revs('secret()'))
4955 secret = len(repo.revs('secret()'))
4955 if secret:
4956 if secret:
4956 t.append(_('%d secret') % secret)
4957 t.append(_('%d secret') % secret)
4957
4958
4958 if draft or secret:
4959 if draft or secret:
4959 ui.status(_('phases: %s\n') % ', '.join(t))
4960 ui.status(_('phases: %s\n') % ', '.join(t))
4960
4961
4961 if obsolete.isenabled(repo, obsolete.createmarkersopt):
4962 if obsolete.isenabled(repo, obsolete.createmarkersopt):
4962 for trouble in ("unstable", "divergent", "bumped"):
4963 for trouble in ("unstable", "divergent", "bumped"):
4963 numtrouble = len(repo.revs(trouble + "()"))
4964 numtrouble = len(repo.revs(trouble + "()"))
4964 # We write all the possibilities to ease translation
4965 # We write all the possibilities to ease translation
4965 troublemsg = {
4966 troublemsg = {
4966 "unstable": _("unstable: %d changesets"),
4967 "unstable": _("unstable: %d changesets"),
4967 "divergent": _("divergent: %d changesets"),
4968 "divergent": _("divergent: %d changesets"),
4968 "bumped": _("bumped: %d changesets"),
4969 "bumped": _("bumped: %d changesets"),
4969 }
4970 }
4970 if numtrouble > 0:
4971 if numtrouble > 0:
4971 ui.status(troublemsg[trouble] % numtrouble + "\n")
4972 ui.status(troublemsg[trouble] % numtrouble + "\n")
4972
4973
4973 cmdutil.summaryhooks(ui, repo)
4974 cmdutil.summaryhooks(ui, repo)
4974
4975
4975 if opts.get('remote'):
4976 if opts.get('remote'):
4976 needsincoming, needsoutgoing = True, True
4977 needsincoming, needsoutgoing = True, True
4977 else:
4978 else:
4978 needsincoming, needsoutgoing = False, False
4979 needsincoming, needsoutgoing = False, False
4979 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
4980 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
4980 if i:
4981 if i:
4981 needsincoming = True
4982 needsincoming = True
4982 if o:
4983 if o:
4983 needsoutgoing = True
4984 needsoutgoing = True
4984 if not needsincoming and not needsoutgoing:
4985 if not needsincoming and not needsoutgoing:
4985 return
4986 return
4986
4987
4987 def getincoming():
4988 def getincoming():
4988 source, branches = hg.parseurl(ui.expandpath('default'))
4989 source, branches = hg.parseurl(ui.expandpath('default'))
4989 sbranch = branches[0]
4990 sbranch = branches[0]
4990 try:
4991 try:
4991 other = hg.peer(repo, {}, source)
4992 other = hg.peer(repo, {}, source)
4992 except error.RepoError:
4993 except error.RepoError:
4993 if opts.get('remote'):
4994 if opts.get('remote'):
4994 raise
4995 raise
4995 return source, sbranch, None, None, None
4996 return source, sbranch, None, None, None
4996 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
4997 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
4997 if revs:
4998 if revs:
4998 revs = [other.lookup(rev) for rev in revs]
4999 revs = [other.lookup(rev) for rev in revs]
4999 ui.debug('comparing with %s\n' % util.hidepassword(source))
5000 ui.debug('comparing with %s\n' % util.hidepassword(source))
5000 repo.ui.pushbuffer()
5001 repo.ui.pushbuffer()
5001 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5002 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5002 repo.ui.popbuffer()
5003 repo.ui.popbuffer()
5003 return source, sbranch, other, commoninc, commoninc[1]
5004 return source, sbranch, other, commoninc, commoninc[1]
5004
5005
5005 if needsincoming:
5006 if needsincoming:
5006 source, sbranch, sother, commoninc, incoming = getincoming()
5007 source, sbranch, sother, commoninc, incoming = getincoming()
5007 else:
5008 else:
5008 source = sbranch = sother = commoninc = incoming = None
5009 source = sbranch = sother = commoninc = incoming = None
5009
5010
5010 def getoutgoing():
5011 def getoutgoing():
5011 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5012 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5012 dbranch = branches[0]
5013 dbranch = branches[0]
5013 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5014 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5014 if source != dest:
5015 if source != dest:
5015 try:
5016 try:
5016 dother = hg.peer(repo, {}, dest)
5017 dother = hg.peer(repo, {}, dest)
5017 except error.RepoError:
5018 except error.RepoError:
5018 if opts.get('remote'):
5019 if opts.get('remote'):
5019 raise
5020 raise
5020 return dest, dbranch, None, None
5021 return dest, dbranch, None, None
5021 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5022 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5022 elif sother is None:
5023 elif sother is None:
5023 # there is no explicit destination peer, but source one is invalid
5024 # there is no explicit destination peer, but source one is invalid
5024 return dest, dbranch, None, None
5025 return dest, dbranch, None, None
5025 else:
5026 else:
5026 dother = sother
5027 dother = sother
5027 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5028 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5028 common = None
5029 common = None
5029 else:
5030 else:
5030 common = commoninc
5031 common = commoninc
5031 if revs:
5032 if revs:
5032 revs = [repo.lookup(rev) for rev in revs]
5033 revs = [repo.lookup(rev) for rev in revs]
5033 repo.ui.pushbuffer()
5034 repo.ui.pushbuffer()
5034 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5035 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5035 commoninc=common)
5036 commoninc=common)
5036 repo.ui.popbuffer()
5037 repo.ui.popbuffer()
5037 return dest, dbranch, dother, outgoing
5038 return dest, dbranch, dother, outgoing
5038
5039
5039 if needsoutgoing:
5040 if needsoutgoing:
5040 dest, dbranch, dother, outgoing = getoutgoing()
5041 dest, dbranch, dother, outgoing = getoutgoing()
5041 else:
5042 else:
5042 dest = dbranch = dother = outgoing = None
5043 dest = dbranch = dother = outgoing = None
5043
5044
5044 if opts.get('remote'):
5045 if opts.get('remote'):
5045 t = []
5046 t = []
5046 if incoming:
5047 if incoming:
5047 t.append(_('1 or more incoming'))
5048 t.append(_('1 or more incoming'))
5048 o = outgoing.missing
5049 o = outgoing.missing
5049 if o:
5050 if o:
5050 t.append(_('%d outgoing') % len(o))
5051 t.append(_('%d outgoing') % len(o))
5051 other = dother or sother
5052 other = dother or sother
5052 if 'bookmarks' in other.listkeys('namespaces'):
5053 if 'bookmarks' in other.listkeys('namespaces'):
5053 counts = bookmarks.summary(repo, other)
5054 counts = bookmarks.summary(repo, other)
5054 if counts[0] > 0:
5055 if counts[0] > 0:
5055 t.append(_('%d incoming bookmarks') % counts[0])
5056 t.append(_('%d incoming bookmarks') % counts[0])
5056 if counts[1] > 0:
5057 if counts[1] > 0:
5057 t.append(_('%d outgoing bookmarks') % counts[1])
5058 t.append(_('%d outgoing bookmarks') % counts[1])
5058
5059
5059 if t:
5060 if t:
5060 # i18n: column positioning for "hg summary"
5061 # i18n: column positioning for "hg summary"
5061 ui.write(_('remote: %s\n') % (', '.join(t)))
5062 ui.write(_('remote: %s\n') % (', '.join(t)))
5062 else:
5063 else:
5063 # i18n: column positioning for "hg summary"
5064 # i18n: column positioning for "hg summary"
5064 ui.status(_('remote: (synced)\n'))
5065 ui.status(_('remote: (synced)\n'))
5065
5066
5066 cmdutil.summaryremotehooks(ui, repo, opts,
5067 cmdutil.summaryremotehooks(ui, repo, opts,
5067 ((source, sbranch, sother, commoninc),
5068 ((source, sbranch, sother, commoninc),
5068 (dest, dbranch, dother, outgoing)))
5069 (dest, dbranch, dother, outgoing)))
5069
5070
5070 @command('tag',
5071 @command('tag',
5071 [('f', 'force', None, _('force tag')),
5072 [('f', 'force', None, _('force tag')),
5072 ('l', 'local', None, _('make the tag local')),
5073 ('l', 'local', None, _('make the tag local')),
5073 ('r', 'rev', '', _('revision to tag'), _('REV')),
5074 ('r', 'rev', '', _('revision to tag'), _('REV')),
5074 ('', 'remove', None, _('remove a tag')),
5075 ('', 'remove', None, _('remove a tag')),
5075 # -l/--local is already there, commitopts cannot be used
5076 # -l/--local is already there, commitopts cannot be used
5076 ('e', 'edit', None, _('invoke editor on commit messages')),
5077 ('e', 'edit', None, _('invoke editor on commit messages')),
5077 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5078 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5078 ] + commitopts2,
5079 ] + commitopts2,
5079 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5080 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5080 def tag(ui, repo, name1, *names, **opts):
5081 def tag(ui, repo, name1, *names, **opts):
5081 """add one or more tags for the current or given revision
5082 """add one or more tags for the current or given revision
5082
5083
5083 Name a particular revision using <name>.
5084 Name a particular revision using <name>.
5084
5085
5085 Tags are used to name particular revisions of the repository and are
5086 Tags are used to name particular revisions of the repository and are
5086 very useful to compare different revisions, to go back to significant
5087 very useful to compare different revisions, to go back to significant
5087 earlier versions or to mark branch points as releases, etc. Changing
5088 earlier versions or to mark branch points as releases, etc. Changing
5088 an existing tag is normally disallowed; use -f/--force to override.
5089 an existing tag is normally disallowed; use -f/--force to override.
5089
5090
5090 If no revision is given, the parent of the working directory is
5091 If no revision is given, the parent of the working directory is
5091 used.
5092 used.
5092
5093
5093 To facilitate version control, distribution, and merging of tags,
5094 To facilitate version control, distribution, and merging of tags,
5094 they are stored as a file named ".hgtags" which is managed similarly
5095 they are stored as a file named ".hgtags" which is managed similarly
5095 to other project files and can be hand-edited if necessary. This
5096 to other project files and can be hand-edited if necessary. This
5096 also means that tagging creates a new commit. The file
5097 also means that tagging creates a new commit. The file
5097 ".hg/localtags" is used for local tags (not shared among
5098 ".hg/localtags" is used for local tags (not shared among
5098 repositories).
5099 repositories).
5099
5100
5100 Tag commits are usually made at the head of a branch. If the parent
5101 Tag commits are usually made at the head of a branch. If the parent
5101 of the working directory is not a branch head, :hg:`tag` aborts; use
5102 of the working directory is not a branch head, :hg:`tag` aborts; use
5102 -f/--force to force the tag commit to be based on a non-head
5103 -f/--force to force the tag commit to be based on a non-head
5103 changeset.
5104 changeset.
5104
5105
5105 See :hg:`help dates` for a list of formats valid for -d/--date.
5106 See :hg:`help dates` for a list of formats valid for -d/--date.
5106
5107
5107 Since tag names have priority over branch names during revision
5108 Since tag names have priority over branch names during revision
5108 lookup, using an existing branch name as a tag name is discouraged.
5109 lookup, using an existing branch name as a tag name is discouraged.
5109
5110
5110 Returns 0 on success.
5111 Returns 0 on success.
5111 """
5112 """
5112 wlock = lock = None
5113 wlock = lock = None
5113 try:
5114 try:
5114 wlock = repo.wlock()
5115 wlock = repo.wlock()
5115 lock = repo.lock()
5116 lock = repo.lock()
5116 rev_ = "."
5117 rev_ = "."
5117 names = [t.strip() for t in (name1,) + names]
5118 names = [t.strip() for t in (name1,) + names]
5118 if len(names) != len(set(names)):
5119 if len(names) != len(set(names)):
5119 raise error.Abort(_('tag names must be unique'))
5120 raise error.Abort(_('tag names must be unique'))
5120 for n in names:
5121 for n in names:
5121 scmutil.checknewlabel(repo, n, 'tag')
5122 scmutil.checknewlabel(repo, n, 'tag')
5122 if not n:
5123 if not n:
5123 raise error.Abort(_('tag names cannot consist entirely of '
5124 raise error.Abort(_('tag names cannot consist entirely of '
5124 'whitespace'))
5125 'whitespace'))
5125 if opts.get('rev') and opts.get('remove'):
5126 if opts.get('rev') and opts.get('remove'):
5126 raise error.Abort(_("--rev and --remove are incompatible"))
5127 raise error.Abort(_("--rev and --remove are incompatible"))
5127 if opts.get('rev'):
5128 if opts.get('rev'):
5128 rev_ = opts['rev']
5129 rev_ = opts['rev']
5129 message = opts.get('message')
5130 message = opts.get('message')
5130 if opts.get('remove'):
5131 if opts.get('remove'):
5131 if opts.get('local'):
5132 if opts.get('local'):
5132 expectedtype = 'local'
5133 expectedtype = 'local'
5133 else:
5134 else:
5134 expectedtype = 'global'
5135 expectedtype = 'global'
5135
5136
5136 for n in names:
5137 for n in names:
5137 if not repo.tagtype(n):
5138 if not repo.tagtype(n):
5138 raise error.Abort(_("tag '%s' does not exist") % n)
5139 raise error.Abort(_("tag '%s' does not exist") % n)
5139 if repo.tagtype(n) != expectedtype:
5140 if repo.tagtype(n) != expectedtype:
5140 if expectedtype == 'global':
5141 if expectedtype == 'global':
5141 raise error.Abort(_("tag '%s' is not a global tag") % n)
5142 raise error.Abort(_("tag '%s' is not a global tag") % n)
5142 else:
5143 else:
5143 raise error.Abort(_("tag '%s' is not a local tag") % n)
5144 raise error.Abort(_("tag '%s' is not a local tag") % n)
5144 rev_ = 'null'
5145 rev_ = 'null'
5145 if not message:
5146 if not message:
5146 # we don't translate commit messages
5147 # we don't translate commit messages
5147 message = 'Removed tag %s' % ', '.join(names)
5148 message = 'Removed tag %s' % ', '.join(names)
5148 elif not opts.get('force'):
5149 elif not opts.get('force'):
5149 for n in names:
5150 for n in names:
5150 if n in repo.tags():
5151 if n in repo.tags():
5151 raise error.Abort(_("tag '%s' already exists "
5152 raise error.Abort(_("tag '%s' already exists "
5152 "(use -f to force)") % n)
5153 "(use -f to force)") % n)
5153 if not opts.get('local'):
5154 if not opts.get('local'):
5154 p1, p2 = repo.dirstate.parents()
5155 p1, p2 = repo.dirstate.parents()
5155 if p2 != nullid:
5156 if p2 != nullid:
5156 raise error.Abort(_('uncommitted merge'))
5157 raise error.Abort(_('uncommitted merge'))
5157 bheads = repo.branchheads()
5158 bheads = repo.branchheads()
5158 if not opts.get('force') and bheads and p1 not in bheads:
5159 if not opts.get('force') and bheads and p1 not in bheads:
5159 raise error.Abort(_('working directory is not at a branch head '
5160 raise error.Abort(_('working directory is not at a branch head '
5160 '(use -f to force)'))
5161 '(use -f to force)'))
5161 r = scmutil.revsingle(repo, rev_).node()
5162 r = scmutil.revsingle(repo, rev_).node()
5162
5163
5163 if not message:
5164 if not message:
5164 # we don't translate commit messages
5165 # we don't translate commit messages
5165 message = ('Added tag %s for changeset %s' %
5166 message = ('Added tag %s for changeset %s' %
5166 (', '.join(names), short(r)))
5167 (', '.join(names), short(r)))
5167
5168
5168 date = opts.get('date')
5169 date = opts.get('date')
5169 if date:
5170 if date:
5170 date = util.parsedate(date)
5171 date = util.parsedate(date)
5171
5172
5172 if opts.get('remove'):
5173 if opts.get('remove'):
5173 editform = 'tag.remove'
5174 editform = 'tag.remove'
5174 else:
5175 else:
5175 editform = 'tag.add'
5176 editform = 'tag.add'
5176 editor = cmdutil.getcommiteditor(editform=editform, **opts)
5177 editor = cmdutil.getcommiteditor(editform=editform, **opts)
5177
5178
5178 # don't allow tagging the null rev
5179 # don't allow tagging the null rev
5179 if (not opts.get('remove') and
5180 if (not opts.get('remove') and
5180 scmutil.revsingle(repo, rev_).rev() == nullrev):
5181 scmutil.revsingle(repo, rev_).rev() == nullrev):
5181 raise error.Abort(_("cannot tag null revision"))
5182 raise error.Abort(_("cannot tag null revision"))
5182
5183
5183 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
5184 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
5184 editor=editor)
5185 editor=editor)
5185 finally:
5186 finally:
5186 release(lock, wlock)
5187 release(lock, wlock)
5187
5188
5188 @command('tags', formatteropts, '')
5189 @command('tags', formatteropts, '')
5189 def tags(ui, repo, **opts):
5190 def tags(ui, repo, **opts):
5190 """list repository tags
5191 """list repository tags
5191
5192
5192 This lists both regular and local tags. When the -v/--verbose
5193 This lists both regular and local tags. When the -v/--verbose
5193 switch is used, a third column "local" is printed for local tags.
5194 switch is used, a third column "local" is printed for local tags.
5194 When the -q/--quiet switch is used, only the tag name is printed.
5195 When the -q/--quiet switch is used, only the tag name is printed.
5195
5196
5196 Returns 0 on success.
5197 Returns 0 on success.
5197 """
5198 """
5198
5199
5199 fm = ui.formatter('tags', opts)
5200 fm = ui.formatter('tags', opts)
5200 hexfunc = fm.hexfunc
5201 hexfunc = fm.hexfunc
5201 tagtype = ""
5202 tagtype = ""
5202
5203
5203 for t, n in reversed(repo.tagslist()):
5204 for t, n in reversed(repo.tagslist()):
5204 hn = hexfunc(n)
5205 hn = hexfunc(n)
5205 label = 'tags.normal'
5206 label = 'tags.normal'
5206 tagtype = ''
5207 tagtype = ''
5207 if repo.tagtype(t) == 'local':
5208 if repo.tagtype(t) == 'local':
5208 label = 'tags.local'
5209 label = 'tags.local'
5209 tagtype = 'local'
5210 tagtype = 'local'
5210
5211
5211 fm.startitem()
5212 fm.startitem()
5212 fm.write('tag', '%s', t, label=label)
5213 fm.write('tag', '%s', t, label=label)
5213 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5214 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5214 fm.condwrite(not ui.quiet, 'rev node', fmt,
5215 fm.condwrite(not ui.quiet, 'rev node', fmt,
5215 repo.changelog.rev(n), hn, label=label)
5216 repo.changelog.rev(n), hn, label=label)
5216 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5217 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5217 tagtype, label=label)
5218 tagtype, label=label)
5218 fm.plain('\n')
5219 fm.plain('\n')
5219 fm.end()
5220 fm.end()
5220
5221
5221 @command('tip',
5222 @command('tip',
5222 [('p', 'patch', None, _('show patch')),
5223 [('p', 'patch', None, _('show patch')),
5223 ('g', 'git', None, _('use git extended diff format')),
5224 ('g', 'git', None, _('use git extended diff format')),
5224 ] + templateopts,
5225 ] + templateopts,
5225 _('[-p] [-g]'))
5226 _('[-p] [-g]'))
5226 def tip(ui, repo, **opts):
5227 def tip(ui, repo, **opts):
5227 """show the tip revision (DEPRECATED)
5228 """show the tip revision (DEPRECATED)
5228
5229
5229 The tip revision (usually just called the tip) is the changeset
5230 The tip revision (usually just called the tip) is the changeset
5230 most recently added to the repository (and therefore the most
5231 most recently added to the repository (and therefore the most
5231 recently changed head).
5232 recently changed head).
5232
5233
5233 If you have just made a commit, that commit will be the tip. If
5234 If you have just made a commit, that commit will be the tip. If
5234 you have just pulled changes from another repository, the tip of
5235 you have just pulled changes from another repository, the tip of
5235 that repository becomes the current tip. The "tip" tag is special
5236 that repository becomes the current tip. The "tip" tag is special
5236 and cannot be renamed or assigned to a different changeset.
5237 and cannot be renamed or assigned to a different changeset.
5237
5238
5238 This command is deprecated, please use :hg:`heads` instead.
5239 This command is deprecated, please use :hg:`heads` instead.
5239
5240
5240 Returns 0 on success.
5241 Returns 0 on success.
5241 """
5242 """
5242 displayer = cmdutil.show_changeset(ui, repo, opts)
5243 displayer = cmdutil.show_changeset(ui, repo, opts)
5243 displayer.show(repo['tip'])
5244 displayer.show(repo['tip'])
5244 displayer.close()
5245 displayer.close()
5245
5246
5246 @command('unbundle',
5247 @command('unbundle',
5247 [('u', 'update', None,
5248 [('u', 'update', None,
5248 _('update to new branch head if changesets were unbundled'))],
5249 _('update to new branch head if changesets were unbundled'))],
5249 _('[-u] FILE...'))
5250 _('[-u] FILE...'))
5250 def unbundle(ui, repo, fname1, *fnames, **opts):
5251 def unbundle(ui, repo, fname1, *fnames, **opts):
5251 """apply one or more changegroup files
5252 """apply one or more changegroup files
5252
5253
5253 Apply one or more compressed changegroup files generated by the
5254 Apply one or more compressed changegroup files generated by the
5254 bundle command.
5255 bundle command.
5255
5256
5256 Returns 0 on success, 1 if an update has unresolved files.
5257 Returns 0 on success, 1 if an update has unresolved files.
5257 """
5258 """
5258 fnames = (fname1,) + fnames
5259 fnames = (fname1,) + fnames
5259
5260
5260 with repo.lock():
5261 with repo.lock():
5261 for fname in fnames:
5262 for fname in fnames:
5262 f = hg.openpath(ui, fname)
5263 f = hg.openpath(ui, fname)
5263 gen = exchange.readbundle(ui, f, fname)
5264 gen = exchange.readbundle(ui, f, fname)
5264 if isinstance(gen, bundle2.unbundle20):
5265 if isinstance(gen, bundle2.unbundle20):
5265 tr = repo.transaction('unbundle')
5266 tr = repo.transaction('unbundle')
5266 try:
5267 try:
5267 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
5268 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
5268 url='bundle:' + fname)
5269 url='bundle:' + fname)
5269 tr.close()
5270 tr.close()
5270 except error.BundleUnknownFeatureError as exc:
5271 except error.BundleUnknownFeatureError as exc:
5271 raise error.Abort(_('%s: unknown bundle feature, %s')
5272 raise error.Abort(_('%s: unknown bundle feature, %s')
5272 % (fname, exc),
5273 % (fname, exc),
5273 hint=_("see https://mercurial-scm.org/"
5274 hint=_("see https://mercurial-scm.org/"
5274 "wiki/BundleFeature for more "
5275 "wiki/BundleFeature for more "
5275 "information"))
5276 "information"))
5276 finally:
5277 finally:
5277 if tr:
5278 if tr:
5278 tr.release()
5279 tr.release()
5279 changes = [r.get('return', 0)
5280 changes = [r.get('return', 0)
5280 for r in op.records['changegroup']]
5281 for r in op.records['changegroup']]
5281 modheads = changegroup.combineresults(changes)
5282 modheads = changegroup.combineresults(changes)
5282 elif isinstance(gen, streamclone.streamcloneapplier):
5283 elif isinstance(gen, streamclone.streamcloneapplier):
5283 raise error.Abort(
5284 raise error.Abort(
5284 _('packed bundles cannot be applied with '
5285 _('packed bundles cannot be applied with '
5285 '"hg unbundle"'),
5286 '"hg unbundle"'),
5286 hint=_('use "hg debugapplystreamclonebundle"'))
5287 hint=_('use "hg debugapplystreamclonebundle"'))
5287 else:
5288 else:
5288 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
5289 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
5289
5290
5290 return postincoming(ui, repo, modheads, opts.get('update'), None, None)
5291 return postincoming(ui, repo, modheads, opts.get('update'), None, None)
5291
5292
5292 @command('^update|up|checkout|co',
5293 @command('^update|up|checkout|co',
5293 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5294 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5294 ('c', 'check', None, _('require clean working directory')),
5295 ('c', 'check', None, _('require clean working directory')),
5295 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5296 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5296 ('r', 'rev', '', _('revision'), _('REV'))
5297 ('r', 'rev', '', _('revision'), _('REV'))
5297 ] + mergetoolopts,
5298 ] + mergetoolopts,
5298 _('[-C|-c] [-d DATE] [[-r] REV]'))
5299 _('[-C|-c] [-d DATE] [[-r] REV]'))
5299 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
5300 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
5300 tool=None):
5301 tool=None):
5301 """update working directory (or switch revisions)
5302 """update working directory (or switch revisions)
5302
5303
5303 Update the repository's working directory to the specified
5304 Update the repository's working directory to the specified
5304 changeset. If no changeset is specified, update to the tip of the
5305 changeset. If no changeset is specified, update to the tip of the
5305 current named branch and move the active bookmark (see :hg:`help
5306 current named branch and move the active bookmark (see :hg:`help
5306 bookmarks`).
5307 bookmarks`).
5307
5308
5308 Update sets the working directory's parent revision to the specified
5309 Update sets the working directory's parent revision to the specified
5309 changeset (see :hg:`help parents`).
5310 changeset (see :hg:`help parents`).
5310
5311
5311 If the changeset is not a descendant or ancestor of the working
5312 If the changeset is not a descendant or ancestor of the working
5312 directory's parent and there are uncommitted changes, the update is
5313 directory's parent and there are uncommitted changes, the update is
5313 aborted. With the -c/--check option, the working directory is checked
5314 aborted. With the -c/--check option, the working directory is checked
5314 for uncommitted changes; if none are found, the working directory is
5315 for uncommitted changes; if none are found, the working directory is
5315 updated to the specified changeset.
5316 updated to the specified changeset.
5316
5317
5317 .. container:: verbose
5318 .. container:: verbose
5318
5319
5319 The -C/--clean and -c/--check options control what happens if the
5320 The -C/--clean and -c/--check options control what happens if the
5320 working directory contains uncommitted changes.
5321 working directory contains uncommitted changes.
5321 At most of one of them can be specified.
5322 At most of one of them can be specified.
5322
5323
5323 1. If no option is specified, and if
5324 1. If no option is specified, and if
5324 the requested changeset is an ancestor or descendant of
5325 the requested changeset is an ancestor or descendant of
5325 the working directory's parent, the uncommitted changes
5326 the working directory's parent, the uncommitted changes
5326 are merged into the requested changeset and the merged
5327 are merged into the requested changeset and the merged
5327 result is left uncommitted. If the requested changeset is
5328 result is left uncommitted. If the requested changeset is
5328 not an ancestor or descendant (that is, it is on another
5329 not an ancestor or descendant (that is, it is on another
5329 branch), the update is aborted and the uncommitted changes
5330 branch), the update is aborted and the uncommitted changes
5330 are preserved.
5331 are preserved.
5331
5332
5332 2. With the -c/--check option, the update is aborted and the
5333 2. With the -c/--check option, the update is aborted and the
5333 uncommitted changes are preserved.
5334 uncommitted changes are preserved.
5334
5335
5335 3. With the -C/--clean option, uncommitted changes are discarded and
5336 3. With the -C/--clean option, uncommitted changes are discarded and
5336 the working directory is updated to the requested changeset.
5337 the working directory is updated to the requested changeset.
5337
5338
5338 To cancel an uncommitted merge (and lose your changes), use
5339 To cancel an uncommitted merge (and lose your changes), use
5339 :hg:`update --clean .`.
5340 :hg:`update --clean .`.
5340
5341
5341 Use null as the changeset to remove the working directory (like
5342 Use null as the changeset to remove the working directory (like
5342 :hg:`clone -U`).
5343 :hg:`clone -U`).
5343
5344
5344 If you want to revert just one file to an older revision, use
5345 If you want to revert just one file to an older revision, use
5345 :hg:`revert [-r REV] NAME`.
5346 :hg:`revert [-r REV] NAME`.
5346
5347
5347 See :hg:`help dates` for a list of formats valid for -d/--date.
5348 See :hg:`help dates` for a list of formats valid for -d/--date.
5348
5349
5349 Returns 0 on success, 1 if there are unresolved files.
5350 Returns 0 on success, 1 if there are unresolved files.
5350 """
5351 """
5351 if rev and node:
5352 if rev and node:
5352 raise error.Abort(_("please specify just one revision"))
5353 raise error.Abort(_("please specify just one revision"))
5353
5354
5354 if rev is None or rev == '':
5355 if rev is None or rev == '':
5355 rev = node
5356 rev = node
5356
5357
5357 if date and rev is not None:
5358 if date and rev is not None:
5358 raise error.Abort(_("you can't specify a revision and a date"))
5359 raise error.Abort(_("you can't specify a revision and a date"))
5359
5360
5360 if check and clean:
5361 if check and clean:
5361 raise error.Abort(_("cannot specify both -c/--check and -C/--clean"))
5362 raise error.Abort(_("cannot specify both -c/--check and -C/--clean"))
5362
5363
5363 with repo.wlock():
5364 with repo.wlock():
5364 cmdutil.clearunfinished(repo)
5365 cmdutil.clearunfinished(repo)
5365
5366
5366 if date:
5367 if date:
5367 rev = cmdutil.finddate(ui, repo, date)
5368 rev = cmdutil.finddate(ui, repo, date)
5368
5369
5369 # if we defined a bookmark, we have to remember the original name
5370 # if we defined a bookmark, we have to remember the original name
5370 brev = rev
5371 brev = rev
5371 rev = scmutil.revsingle(repo, rev, rev).rev()
5372 rev = scmutil.revsingle(repo, rev, rev).rev()
5372
5373
5373 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
5374 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
5374
5375
5375 return hg.updatetotally(ui, repo, rev, brev, clean=clean, check=check)
5376 return hg.updatetotally(ui, repo, rev, brev, clean=clean, check=check)
5376
5377
5377 @command('verify', [])
5378 @command('verify', [])
5378 def verify(ui, repo):
5379 def verify(ui, repo):
5379 """verify the integrity of the repository
5380 """verify the integrity of the repository
5380
5381
5381 Verify the integrity of the current repository.
5382 Verify the integrity of the current repository.
5382
5383
5383 This will perform an extensive check of the repository's
5384 This will perform an extensive check of the repository's
5384 integrity, validating the hashes and checksums of each entry in
5385 integrity, validating the hashes and checksums of each entry in
5385 the changelog, manifest, and tracked files, as well as the
5386 the changelog, manifest, and tracked files, as well as the
5386 integrity of their crosslinks and indices.
5387 integrity of their crosslinks and indices.
5387
5388
5388 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
5389 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
5389 for more information about recovery from corruption of the
5390 for more information about recovery from corruption of the
5390 repository.
5391 repository.
5391
5392
5392 Returns 0 on success, 1 if errors are encountered.
5393 Returns 0 on success, 1 if errors are encountered.
5393 """
5394 """
5394 return hg.verify(repo)
5395 return hg.verify(repo)
5395
5396
5396 @command('version', [] + formatteropts, norepo=True)
5397 @command('version', [] + formatteropts, norepo=True)
5397 def version_(ui, **opts):
5398 def version_(ui, **opts):
5398 """output version and copyright information"""
5399 """output version and copyright information"""
5399 fm = ui.formatter("version", opts)
5400 fm = ui.formatter("version", opts)
5400 fm.startitem()
5401 fm.startitem()
5401 fm.write("ver", _("Mercurial Distributed SCM (version %s)\n"),
5402 fm.write("ver", _("Mercurial Distributed SCM (version %s)\n"),
5402 util.version())
5403 util.version())
5403 license = _(
5404 license = _(
5404 "(see https://mercurial-scm.org for more information)\n"
5405 "(see https://mercurial-scm.org for more information)\n"
5405 "\nCopyright (C) 2005-2017 Matt Mackall and others\n"
5406 "\nCopyright (C) 2005-2017 Matt Mackall and others\n"
5406 "This is free software; see the source for copying conditions. "
5407 "This is free software; see the source for copying conditions. "
5407 "There is NO\nwarranty; "
5408 "There is NO\nwarranty; "
5408 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5409 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5409 )
5410 )
5410 if not ui.quiet:
5411 if not ui.quiet:
5411 fm.plain(license)
5412 fm.plain(license)
5412
5413
5413 if ui.verbose:
5414 if ui.verbose:
5414 fm.plain(_("\nEnabled extensions:\n\n"))
5415 fm.plain(_("\nEnabled extensions:\n\n"))
5415 # format names and versions into columns
5416 # format names and versions into columns
5416 names = []
5417 names = []
5417 vers = []
5418 vers = []
5418 isinternals = []
5419 isinternals = []
5419 for name, module in extensions.extensions():
5420 for name, module in extensions.extensions():
5420 names.append(name)
5421 names.append(name)
5421 vers.append(extensions.moduleversion(module) or None)
5422 vers.append(extensions.moduleversion(module) or None)
5422 isinternals.append(extensions.ismoduleinternal(module))
5423 isinternals.append(extensions.ismoduleinternal(module))
5423 fn = fm.nested("extensions")
5424 fn = fm.nested("extensions")
5424 if names:
5425 if names:
5425 namefmt = " %%-%ds " % max(len(n) for n in names)
5426 namefmt = " %%-%ds " % max(len(n) for n in names)
5426 places = [_("external"), _("internal")]
5427 places = [_("external"), _("internal")]
5427 for n, v, p in zip(names, vers, isinternals):
5428 for n, v, p in zip(names, vers, isinternals):
5428 fn.startitem()
5429 fn.startitem()
5429 fn.condwrite(ui.verbose, "name", namefmt, n)
5430 fn.condwrite(ui.verbose, "name", namefmt, n)
5430 if ui.verbose:
5431 if ui.verbose:
5431 fn.plain("%s " % places[p])
5432 fn.plain("%s " % places[p])
5432 fn.data(bundled=p)
5433 fn.data(bundled=p)
5433 fn.condwrite(ui.verbose and v, "ver", "%s", v)
5434 fn.condwrite(ui.verbose and v, "ver", "%s", v)
5434 if ui.verbose:
5435 if ui.verbose:
5435 fn.plain("\n")
5436 fn.plain("\n")
5436 fn.end()
5437 fn.end()
5437 fm.end()
5438 fm.end()
5438
5439
5439 def loadcmdtable(ui, name, cmdtable):
5440 def loadcmdtable(ui, name, cmdtable):
5440 """Load command functions from specified cmdtable
5441 """Load command functions from specified cmdtable
5441 """
5442 """
5442 overrides = [cmd for cmd in cmdtable if cmd in table]
5443 overrides = [cmd for cmd in cmdtable if cmd in table]
5443 if overrides:
5444 if overrides:
5444 ui.warn(_("extension '%s' overrides commands: %s\n")
5445 ui.warn(_("extension '%s' overrides commands: %s\n")
5445 % (name, " ".join(overrides)))
5446 % (name, " ".join(overrides)))
5446 table.update(cmdtable)
5447 table.update(cmdtable)
General Comments 0
You need to be logged in to leave comments. Login now