##// END OF EJS Templates
annotate: migrate to modern pager API
Augie Fackler -
r30999:334cf948 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 = ['annotate', 'cat', 'diff', 'export', 'glog', 'log', 'qdiff']
113 attended = ['cat', 'diff', 'export', 'glog', 'log', 'qdiff']
@@ -1,5442 +1,5443 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 revset,
47 revset,
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 ui.pager('annotate')
364 if not pats:
365 if not pats:
365 raise error.Abort(_('at least one filename or pattern is required'))
366 raise error.Abort(_('at least one filename or pattern is required'))
366
367
367 if opts.get('follow'):
368 if opts.get('follow'):
368 # --follow is deprecated and now just an alias for -f/--file
369 # --follow is deprecated and now just an alias for -f/--file
369 # to mimic the behavior of Mercurial before version 1.5
370 # to mimic the behavior of Mercurial before version 1.5
370 opts['file'] = True
371 opts['file'] = True
371
372
372 ctx = scmutil.revsingle(repo, opts.get('rev'))
373 ctx = scmutil.revsingle(repo, opts.get('rev'))
373
374
374 fm = ui.formatter('annotate', opts)
375 fm = ui.formatter('annotate', opts)
375 if ui.quiet:
376 if ui.quiet:
376 datefunc = util.shortdate
377 datefunc = util.shortdate
377 else:
378 else:
378 datefunc = util.datestr
379 datefunc = util.datestr
379 if ctx.rev() is None:
380 if ctx.rev() is None:
380 def hexfn(node):
381 def hexfn(node):
381 if node is None:
382 if node is None:
382 return None
383 return None
383 else:
384 else:
384 return fm.hexfunc(node)
385 return fm.hexfunc(node)
385 if opts.get('changeset'):
386 if opts.get('changeset'):
386 # omit "+" suffix which is appended to node hex
387 # omit "+" suffix which is appended to node hex
387 def formatrev(rev):
388 def formatrev(rev):
388 if rev is None:
389 if rev is None:
389 return '%d' % ctx.p1().rev()
390 return '%d' % ctx.p1().rev()
390 else:
391 else:
391 return '%d' % rev
392 return '%d' % rev
392 else:
393 else:
393 def formatrev(rev):
394 def formatrev(rev):
394 if rev is None:
395 if rev is None:
395 return '%d+' % ctx.p1().rev()
396 return '%d+' % ctx.p1().rev()
396 else:
397 else:
397 return '%d ' % rev
398 return '%d ' % rev
398 def formathex(hex):
399 def formathex(hex):
399 if hex is None:
400 if hex is None:
400 return '%s+' % fm.hexfunc(ctx.p1().node())
401 return '%s+' % fm.hexfunc(ctx.p1().node())
401 else:
402 else:
402 return '%s ' % hex
403 return '%s ' % hex
403 else:
404 else:
404 hexfn = fm.hexfunc
405 hexfn = fm.hexfunc
405 formatrev = formathex = str
406 formatrev = formathex = str
406
407
407 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
408 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
408 ('number', ' ', lambda x: x[0].rev(), formatrev),
409 ('number', ' ', lambda x: x[0].rev(), formatrev),
409 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
410 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
410 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
411 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
411 ('file', ' ', lambda x: x[0].path(), str),
412 ('file', ' ', lambda x: x[0].path(), str),
412 ('line_number', ':', lambda x: x[1], str),
413 ('line_number', ':', lambda x: x[1], str),
413 ]
414 ]
414 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
415 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
415
416
416 if (not opts.get('user') and not opts.get('changeset')
417 if (not opts.get('user') and not opts.get('changeset')
417 and not opts.get('date') and not opts.get('file')):
418 and not opts.get('date') and not opts.get('file')):
418 opts['number'] = True
419 opts['number'] = True
419
420
420 linenumber = opts.get('line_number') is not None
421 linenumber = opts.get('line_number') is not None
421 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
422 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'))
423 raise error.Abort(_('at least one of -n/-c is required for -l'))
423
424
424 if fm.isplain():
425 if fm.isplain():
425 def makefunc(get, fmt):
426 def makefunc(get, fmt):
426 return lambda x: fmt(get(x))
427 return lambda x: fmt(get(x))
427 else:
428 else:
428 def makefunc(get, fmt):
429 def makefunc(get, fmt):
429 return get
430 return get
430 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
431 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
431 if opts.get(op)]
432 if opts.get(op)]
432 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
433 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
433 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
434 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
434 if opts.get(op))
435 if opts.get(op))
435
436
436 def bad(x, y):
437 def bad(x, y):
437 raise error.Abort("%s: %s" % (x, y))
438 raise error.Abort("%s: %s" % (x, y))
438
439
439 m = scmutil.match(ctx, pats, opts, badfn=bad)
440 m = scmutil.match(ctx, pats, opts, badfn=bad)
440
441
441 follow = not opts.get('no_follow')
442 follow = not opts.get('no_follow')
442 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
443 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
443 whitespace=True)
444 whitespace=True)
444 for abs in ctx.walk(m):
445 for abs in ctx.walk(m):
445 fctx = ctx[abs]
446 fctx = ctx[abs]
446 if not opts.get('text') and util.binary(fctx.data()):
447 if not opts.get('text') and util.binary(fctx.data()):
447 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
448 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
448 continue
449 continue
449
450
450 lines = fctx.annotate(follow=follow, linenumber=linenumber,
451 lines = fctx.annotate(follow=follow, linenumber=linenumber,
451 diffopts=diffopts)
452 diffopts=diffopts)
452 if not lines:
453 if not lines:
453 continue
454 continue
454 formats = []
455 formats = []
455 pieces = []
456 pieces = []
456
457
457 for f, sep in funcmap:
458 for f, sep in funcmap:
458 l = [f(n) for n, dummy in lines]
459 l = [f(n) for n, dummy in lines]
459 if fm.isplain():
460 if fm.isplain():
460 sizes = [encoding.colwidth(x) for x in l]
461 sizes = [encoding.colwidth(x) for x in l]
461 ml = max(sizes)
462 ml = max(sizes)
462 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
463 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
463 else:
464 else:
464 formats.append(['%s' for x in l])
465 formats.append(['%s' for x in l])
465 pieces.append(l)
466 pieces.append(l)
466
467
467 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
468 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
468 fm.startitem()
469 fm.startitem()
469 fm.write(fields, "".join(f), *p)
470 fm.write(fields, "".join(f), *p)
470 fm.write('line', ": %s", l[1])
471 fm.write('line', ": %s", l[1])
471
472
472 if not lines[-1][1].endswith('\n'):
473 if not lines[-1][1].endswith('\n'):
473 fm.plain('\n')
474 fm.plain('\n')
474
475
475 fm.end()
476 fm.end()
476
477
477 @command('archive',
478 @command('archive',
478 [('', 'no-decode', None, _('do not pass files through decoders')),
479 [('', 'no-decode', None, _('do not pass files through decoders')),
479 ('p', 'prefix', '', _('directory prefix for files in archive'),
480 ('p', 'prefix', '', _('directory prefix for files in archive'),
480 _('PREFIX')),
481 _('PREFIX')),
481 ('r', 'rev', '', _('revision to distribute'), _('REV')),
482 ('r', 'rev', '', _('revision to distribute'), _('REV')),
482 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
483 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
483 ] + subrepoopts + walkopts,
484 ] + subrepoopts + walkopts,
484 _('[OPTION]... DEST'))
485 _('[OPTION]... DEST'))
485 def archive(ui, repo, dest, **opts):
486 def archive(ui, repo, dest, **opts):
486 '''create an unversioned archive of a repository revision
487 '''create an unversioned archive of a repository revision
487
488
488 By default, the revision used is the parent of the working
489 By default, the revision used is the parent of the working
489 directory; use -r/--rev to specify a different revision.
490 directory; use -r/--rev to specify a different revision.
490
491
491 The archive type is automatically detected based on file
492 The archive type is automatically detected based on file
492 extension (to override, use -t/--type).
493 extension (to override, use -t/--type).
493
494
494 .. container:: verbose
495 .. container:: verbose
495
496
496 Examples:
497 Examples:
497
498
498 - create a zip file containing the 1.0 release::
499 - create a zip file containing the 1.0 release::
499
500
500 hg archive -r 1.0 project-1.0.zip
501 hg archive -r 1.0 project-1.0.zip
501
502
502 - create a tarball excluding .hg files::
503 - create a tarball excluding .hg files::
503
504
504 hg archive project.tar.gz -X ".hg*"
505 hg archive project.tar.gz -X ".hg*"
505
506
506 Valid types are:
507 Valid types are:
507
508
508 :``files``: a directory full of files (default)
509 :``files``: a directory full of files (default)
509 :``tar``: tar archive, uncompressed
510 :``tar``: tar archive, uncompressed
510 :``tbz2``: tar archive, compressed using bzip2
511 :``tbz2``: tar archive, compressed using bzip2
511 :``tgz``: tar archive, compressed using gzip
512 :``tgz``: tar archive, compressed using gzip
512 :``uzip``: zip archive, uncompressed
513 :``uzip``: zip archive, uncompressed
513 :``zip``: zip archive, compressed using deflate
514 :``zip``: zip archive, compressed using deflate
514
515
515 The exact name of the destination archive or directory is given
516 The exact name of the destination archive or directory is given
516 using a format string; see :hg:`help export` for details.
517 using a format string; see :hg:`help export` for details.
517
518
518 Each member added to an archive file has a directory prefix
519 Each member added to an archive file has a directory prefix
519 prepended. Use -p/--prefix to specify a format string for the
520 prepended. Use -p/--prefix to specify a format string for the
520 prefix. The default is the basename of the archive, with suffixes
521 prefix. The default is the basename of the archive, with suffixes
521 removed.
522 removed.
522
523
523 Returns 0 on success.
524 Returns 0 on success.
524 '''
525 '''
525
526
526 ctx = scmutil.revsingle(repo, opts.get('rev'))
527 ctx = scmutil.revsingle(repo, opts.get('rev'))
527 if not ctx:
528 if not ctx:
528 raise error.Abort(_('no working directory: please specify a revision'))
529 raise error.Abort(_('no working directory: please specify a revision'))
529 node = ctx.node()
530 node = ctx.node()
530 dest = cmdutil.makefilename(repo, dest, node)
531 dest = cmdutil.makefilename(repo, dest, node)
531 if os.path.realpath(dest) == repo.root:
532 if os.path.realpath(dest) == repo.root:
532 raise error.Abort(_('repository root cannot be destination'))
533 raise error.Abort(_('repository root cannot be destination'))
533
534
534 kind = opts.get('type') or archival.guesskind(dest) or 'files'
535 kind = opts.get('type') or archival.guesskind(dest) or 'files'
535 prefix = opts.get('prefix')
536 prefix = opts.get('prefix')
536
537
537 if dest == '-':
538 if dest == '-':
538 if kind == 'files':
539 if kind == 'files':
539 raise error.Abort(_('cannot archive plain files to stdout'))
540 raise error.Abort(_('cannot archive plain files to stdout'))
540 dest = cmdutil.makefileobj(repo, dest)
541 dest = cmdutil.makefileobj(repo, dest)
541 if not prefix:
542 if not prefix:
542 prefix = os.path.basename(repo.root) + '-%h'
543 prefix = os.path.basename(repo.root) + '-%h'
543
544
544 prefix = cmdutil.makefilename(repo, prefix, node)
545 prefix = cmdutil.makefilename(repo, prefix, node)
545 matchfn = scmutil.match(ctx, [], opts)
546 matchfn = scmutil.match(ctx, [], opts)
546 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
547 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
547 matchfn, prefix, subrepos=opts.get('subrepos'))
548 matchfn, prefix, subrepos=opts.get('subrepos'))
548
549
549 @command('backout',
550 @command('backout',
550 [('', 'merge', None, _('merge with old dirstate parent after backout')),
551 [('', 'merge', None, _('merge with old dirstate parent after backout')),
551 ('', 'commit', None,
552 ('', 'commit', None,
552 _('commit if no conflicts were encountered (DEPRECATED)')),
553 _('commit if no conflicts were encountered (DEPRECATED)')),
553 ('', 'no-commit', None, _('do not commit')),
554 ('', 'no-commit', None, _('do not commit')),
554 ('', 'parent', '',
555 ('', 'parent', '',
555 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
556 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
556 ('r', 'rev', '', _('revision to backout'), _('REV')),
557 ('r', 'rev', '', _('revision to backout'), _('REV')),
557 ('e', 'edit', False, _('invoke editor on commit messages')),
558 ('e', 'edit', False, _('invoke editor on commit messages')),
558 ] + mergetoolopts + walkopts + commitopts + commitopts2,
559 ] + mergetoolopts + walkopts + commitopts + commitopts2,
559 _('[OPTION]... [-r] REV'))
560 _('[OPTION]... [-r] REV'))
560 def backout(ui, repo, node=None, rev=None, **opts):
561 def backout(ui, repo, node=None, rev=None, **opts):
561 '''reverse effect of earlier changeset
562 '''reverse effect of earlier changeset
562
563
563 Prepare a new changeset with the effect of REV undone in the
564 Prepare a new changeset with the effect of REV undone in the
564 current working directory. If no conflicts were encountered,
565 current working directory. If no conflicts were encountered,
565 it will be committed immediately.
566 it will be committed immediately.
566
567
567 If REV is the parent of the working directory, then this new changeset
568 If REV is the parent of the working directory, then this new changeset
568 is committed automatically (unless --no-commit is specified).
569 is committed automatically (unless --no-commit is specified).
569
570
570 .. note::
571 .. note::
571
572
572 :hg:`backout` cannot be used to fix either an unwanted or
573 :hg:`backout` cannot be used to fix either an unwanted or
573 incorrect merge.
574 incorrect merge.
574
575
575 .. container:: verbose
576 .. container:: verbose
576
577
577 Examples:
578 Examples:
578
579
579 - Reverse the effect of the parent of the working directory.
580 - Reverse the effect of the parent of the working directory.
580 This backout will be committed immediately::
581 This backout will be committed immediately::
581
582
582 hg backout -r .
583 hg backout -r .
583
584
584 - Reverse the effect of previous bad revision 23::
585 - Reverse the effect of previous bad revision 23::
585
586
586 hg backout -r 23
587 hg backout -r 23
587
588
588 - Reverse the effect of previous bad revision 23 and
589 - Reverse the effect of previous bad revision 23 and
589 leave changes uncommitted::
590 leave changes uncommitted::
590
591
591 hg backout -r 23 --no-commit
592 hg backout -r 23 --no-commit
592 hg commit -m "Backout revision 23"
593 hg commit -m "Backout revision 23"
593
594
594 By default, the pending changeset will have one parent,
595 By default, the pending changeset will have one parent,
595 maintaining a linear history. With --merge, the pending
596 maintaining a linear history. With --merge, the pending
596 changeset will instead have two parents: the old parent of the
597 changeset will instead have two parents: the old parent of the
597 working directory and a new child of REV that simply undoes REV.
598 working directory and a new child of REV that simply undoes REV.
598
599
599 Before version 1.7, the behavior without --merge was equivalent
600 Before version 1.7, the behavior without --merge was equivalent
600 to specifying --merge followed by :hg:`update --clean .` to
601 to specifying --merge followed by :hg:`update --clean .` to
601 cancel the merge and leave the child of REV as a head to be
602 cancel the merge and leave the child of REV as a head to be
602 merged separately.
603 merged separately.
603
604
604 See :hg:`help dates` for a list of formats valid for -d/--date.
605 See :hg:`help dates` for a list of formats valid for -d/--date.
605
606
606 See :hg:`help revert` for a way to restore files to the state
607 See :hg:`help revert` for a way to restore files to the state
607 of another revision.
608 of another revision.
608
609
609 Returns 0 on success, 1 if nothing to backout or there are unresolved
610 Returns 0 on success, 1 if nothing to backout or there are unresolved
610 files.
611 files.
611 '''
612 '''
612 wlock = lock = None
613 wlock = lock = None
613 try:
614 try:
614 wlock = repo.wlock()
615 wlock = repo.wlock()
615 lock = repo.lock()
616 lock = repo.lock()
616 return _dobackout(ui, repo, node, rev, **opts)
617 return _dobackout(ui, repo, node, rev, **opts)
617 finally:
618 finally:
618 release(lock, wlock)
619 release(lock, wlock)
619
620
620 def _dobackout(ui, repo, node=None, rev=None, **opts):
621 def _dobackout(ui, repo, node=None, rev=None, **opts):
621 if opts.get('commit') and opts.get('no_commit'):
622 if opts.get('commit') and opts.get('no_commit'):
622 raise error.Abort(_("cannot use --commit with --no-commit"))
623 raise error.Abort(_("cannot use --commit with --no-commit"))
623 if opts.get('merge') and opts.get('no_commit'):
624 if opts.get('merge') and opts.get('no_commit'):
624 raise error.Abort(_("cannot use --merge with --no-commit"))
625 raise error.Abort(_("cannot use --merge with --no-commit"))
625
626
626 if rev and node:
627 if rev and node:
627 raise error.Abort(_("please specify just one revision"))
628 raise error.Abort(_("please specify just one revision"))
628
629
629 if not rev:
630 if not rev:
630 rev = node
631 rev = node
631
632
632 if not rev:
633 if not rev:
633 raise error.Abort(_("please specify a revision to backout"))
634 raise error.Abort(_("please specify a revision to backout"))
634
635
635 date = opts.get('date')
636 date = opts.get('date')
636 if date:
637 if date:
637 opts['date'] = util.parsedate(date)
638 opts['date'] = util.parsedate(date)
638
639
639 cmdutil.checkunfinished(repo)
640 cmdutil.checkunfinished(repo)
640 cmdutil.bailifchanged(repo)
641 cmdutil.bailifchanged(repo)
641 node = scmutil.revsingle(repo, rev).node()
642 node = scmutil.revsingle(repo, rev).node()
642
643
643 op1, op2 = repo.dirstate.parents()
644 op1, op2 = repo.dirstate.parents()
644 if not repo.changelog.isancestor(node, op1):
645 if not repo.changelog.isancestor(node, op1):
645 raise error.Abort(_('cannot backout change that is not an ancestor'))
646 raise error.Abort(_('cannot backout change that is not an ancestor'))
646
647
647 p1, p2 = repo.changelog.parents(node)
648 p1, p2 = repo.changelog.parents(node)
648 if p1 == nullid:
649 if p1 == nullid:
649 raise error.Abort(_('cannot backout a change with no parents'))
650 raise error.Abort(_('cannot backout a change with no parents'))
650 if p2 != nullid:
651 if p2 != nullid:
651 if not opts.get('parent'):
652 if not opts.get('parent'):
652 raise error.Abort(_('cannot backout a merge changeset'))
653 raise error.Abort(_('cannot backout a merge changeset'))
653 p = repo.lookup(opts['parent'])
654 p = repo.lookup(opts['parent'])
654 if p not in (p1, p2):
655 if p not in (p1, p2):
655 raise error.Abort(_('%s is not a parent of %s') %
656 raise error.Abort(_('%s is not a parent of %s') %
656 (short(p), short(node)))
657 (short(p), short(node)))
657 parent = p
658 parent = p
658 else:
659 else:
659 if opts.get('parent'):
660 if opts.get('parent'):
660 raise error.Abort(_('cannot use --parent on non-merge changeset'))
661 raise error.Abort(_('cannot use --parent on non-merge changeset'))
661 parent = p1
662 parent = p1
662
663
663 # the backout should appear on the same branch
664 # the backout should appear on the same branch
664 branch = repo.dirstate.branch()
665 branch = repo.dirstate.branch()
665 bheads = repo.branchheads(branch)
666 bheads = repo.branchheads(branch)
666 rctx = scmutil.revsingle(repo, hex(parent))
667 rctx = scmutil.revsingle(repo, hex(parent))
667 if not opts.get('merge') and op1 != node:
668 if not opts.get('merge') and op1 != node:
668 dsguard = dirstateguard.dirstateguard(repo, 'backout')
669 dsguard = dirstateguard.dirstateguard(repo, 'backout')
669 try:
670 try:
670 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
671 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
671 'backout')
672 'backout')
672 stats = mergemod.update(repo, parent, True, True, node, False)
673 stats = mergemod.update(repo, parent, True, True, node, False)
673 repo.setparents(op1, op2)
674 repo.setparents(op1, op2)
674 dsguard.close()
675 dsguard.close()
675 hg._showstats(repo, stats)
676 hg._showstats(repo, stats)
676 if stats[3]:
677 if stats[3]:
677 repo.ui.status(_("use 'hg resolve' to retry unresolved "
678 repo.ui.status(_("use 'hg resolve' to retry unresolved "
678 "file merges\n"))
679 "file merges\n"))
679 return 1
680 return 1
680 finally:
681 finally:
681 ui.setconfig('ui', 'forcemerge', '', '')
682 ui.setconfig('ui', 'forcemerge', '', '')
682 lockmod.release(dsguard)
683 lockmod.release(dsguard)
683 else:
684 else:
684 hg.clean(repo, node, show_stats=False)
685 hg.clean(repo, node, show_stats=False)
685 repo.dirstate.setbranch(branch)
686 repo.dirstate.setbranch(branch)
686 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
687 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
687
688
688 if opts.get('no_commit'):
689 if opts.get('no_commit'):
689 msg = _("changeset %s backed out, "
690 msg = _("changeset %s backed out, "
690 "don't forget to commit.\n")
691 "don't forget to commit.\n")
691 ui.status(msg % short(node))
692 ui.status(msg % short(node))
692 return 0
693 return 0
693
694
694 def commitfunc(ui, repo, message, match, opts):
695 def commitfunc(ui, repo, message, match, opts):
695 editform = 'backout'
696 editform = 'backout'
696 e = cmdutil.getcommiteditor(editform=editform, **opts)
697 e = cmdutil.getcommiteditor(editform=editform, **opts)
697 if not message:
698 if not message:
698 # we don't translate commit messages
699 # we don't translate commit messages
699 message = "Backed out changeset %s" % short(node)
700 message = "Backed out changeset %s" % short(node)
700 e = cmdutil.getcommiteditor(edit=True, editform=editform)
701 e = cmdutil.getcommiteditor(edit=True, editform=editform)
701 return repo.commit(message, opts.get('user'), opts.get('date'),
702 return repo.commit(message, opts.get('user'), opts.get('date'),
702 match, editor=e)
703 match, editor=e)
703 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
704 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
704 if not newnode:
705 if not newnode:
705 ui.status(_("nothing changed\n"))
706 ui.status(_("nothing changed\n"))
706 return 1
707 return 1
707 cmdutil.commitstatus(repo, newnode, branch, bheads)
708 cmdutil.commitstatus(repo, newnode, branch, bheads)
708
709
709 def nice(node):
710 def nice(node):
710 return '%d:%s' % (repo.changelog.rev(node), short(node))
711 return '%d:%s' % (repo.changelog.rev(node), short(node))
711 ui.status(_('changeset %s backs out changeset %s\n') %
712 ui.status(_('changeset %s backs out changeset %s\n') %
712 (nice(repo.changelog.tip()), nice(node)))
713 (nice(repo.changelog.tip()), nice(node)))
713 if opts.get('merge') and op1 != node:
714 if opts.get('merge') and op1 != node:
714 hg.clean(repo, op1, show_stats=False)
715 hg.clean(repo, op1, show_stats=False)
715 ui.status(_('merging with changeset %s\n')
716 ui.status(_('merging with changeset %s\n')
716 % nice(repo.changelog.tip()))
717 % nice(repo.changelog.tip()))
717 try:
718 try:
718 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
719 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
719 'backout')
720 'backout')
720 return hg.merge(repo, hex(repo.changelog.tip()))
721 return hg.merge(repo, hex(repo.changelog.tip()))
721 finally:
722 finally:
722 ui.setconfig('ui', 'forcemerge', '', '')
723 ui.setconfig('ui', 'forcemerge', '', '')
723 return 0
724 return 0
724
725
725 @command('bisect',
726 @command('bisect',
726 [('r', 'reset', False, _('reset bisect state')),
727 [('r', 'reset', False, _('reset bisect state')),
727 ('g', 'good', False, _('mark changeset good')),
728 ('g', 'good', False, _('mark changeset good')),
728 ('b', 'bad', False, _('mark changeset bad')),
729 ('b', 'bad', False, _('mark changeset bad')),
729 ('s', 'skip', False, _('skip testing changeset')),
730 ('s', 'skip', False, _('skip testing changeset')),
730 ('e', 'extend', False, _('extend the bisect range')),
731 ('e', 'extend', False, _('extend the bisect range')),
731 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
732 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
732 ('U', 'noupdate', False, _('do not update to target'))],
733 ('U', 'noupdate', False, _('do not update to target'))],
733 _("[-gbsr] [-U] [-c CMD] [REV]"))
734 _("[-gbsr] [-U] [-c CMD] [REV]"))
734 def bisect(ui, repo, rev=None, extra=None, command=None,
735 def bisect(ui, repo, rev=None, extra=None, command=None,
735 reset=None, good=None, bad=None, skip=None, extend=None,
736 reset=None, good=None, bad=None, skip=None, extend=None,
736 noupdate=None):
737 noupdate=None):
737 """subdivision search of changesets
738 """subdivision search of changesets
738
739
739 This command helps to find changesets which introduce problems. To
740 This command helps to find changesets which introduce problems. To
740 use, mark the earliest changeset you know exhibits the problem as
741 use, mark the earliest changeset you know exhibits the problem as
741 bad, then mark the latest changeset which is free from the problem
742 bad, then mark the latest changeset which is free from the problem
742 as good. Bisect will update your working directory to a revision
743 as good. Bisect will update your working directory to a revision
743 for testing (unless the -U/--noupdate option is specified). Once
744 for testing (unless the -U/--noupdate option is specified). Once
744 you have performed tests, mark the working directory as good or
745 you have performed tests, mark the working directory as good or
745 bad, and bisect will either update to another candidate changeset
746 bad, and bisect will either update to another candidate changeset
746 or announce that it has found the bad revision.
747 or announce that it has found the bad revision.
747
748
748 As a shortcut, you can also use the revision argument to mark a
749 As a shortcut, you can also use the revision argument to mark a
749 revision as good or bad without checking it out first.
750 revision as good or bad without checking it out first.
750
751
751 If you supply a command, it will be used for automatic bisection.
752 If you supply a command, it will be used for automatic bisection.
752 The environment variable HG_NODE will contain the ID of the
753 The environment variable HG_NODE will contain the ID of the
753 changeset being tested. The exit status of the command will be
754 changeset being tested. The exit status of the command will be
754 used to mark revisions as good or bad: status 0 means good, 125
755 used to mark revisions as good or bad: status 0 means good, 125
755 means to skip the revision, 127 (command not found) will abort the
756 means to skip the revision, 127 (command not found) will abort the
756 bisection, and any other non-zero exit status means the revision
757 bisection, and any other non-zero exit status means the revision
757 is bad.
758 is bad.
758
759
759 .. container:: verbose
760 .. container:: verbose
760
761
761 Some examples:
762 Some examples:
762
763
763 - start a bisection with known bad revision 34, and good revision 12::
764 - start a bisection with known bad revision 34, and good revision 12::
764
765
765 hg bisect --bad 34
766 hg bisect --bad 34
766 hg bisect --good 12
767 hg bisect --good 12
767
768
768 - advance the current bisection by marking current revision as good or
769 - advance the current bisection by marking current revision as good or
769 bad::
770 bad::
770
771
771 hg bisect --good
772 hg bisect --good
772 hg bisect --bad
773 hg bisect --bad
773
774
774 - mark the current revision, or a known revision, to be skipped (e.g. if
775 - mark the current revision, or a known revision, to be skipped (e.g. if
775 that revision is not usable because of another issue)::
776 that revision is not usable because of another issue)::
776
777
777 hg bisect --skip
778 hg bisect --skip
778 hg bisect --skip 23
779 hg bisect --skip 23
779
780
780 - skip all revisions that do not touch directories ``foo`` or ``bar``::
781 - skip all revisions that do not touch directories ``foo`` or ``bar``::
781
782
782 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
783 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
783
784
784 - forget the current bisection::
785 - forget the current bisection::
785
786
786 hg bisect --reset
787 hg bisect --reset
787
788
788 - use 'make && make tests' to automatically find the first broken
789 - use 'make && make tests' to automatically find the first broken
789 revision::
790 revision::
790
791
791 hg bisect --reset
792 hg bisect --reset
792 hg bisect --bad 34
793 hg bisect --bad 34
793 hg bisect --good 12
794 hg bisect --good 12
794 hg bisect --command "make && make tests"
795 hg bisect --command "make && make tests"
795
796
796 - see all changesets whose states are already known in the current
797 - see all changesets whose states are already known in the current
797 bisection::
798 bisection::
798
799
799 hg log -r "bisect(pruned)"
800 hg log -r "bisect(pruned)"
800
801
801 - see the changeset currently being bisected (especially useful
802 - see the changeset currently being bisected (especially useful
802 if running with -U/--noupdate)::
803 if running with -U/--noupdate)::
803
804
804 hg log -r "bisect(current)"
805 hg log -r "bisect(current)"
805
806
806 - see all changesets that took part in the current bisection::
807 - see all changesets that took part in the current bisection::
807
808
808 hg log -r "bisect(range)"
809 hg log -r "bisect(range)"
809
810
810 - you can even get a nice graph::
811 - you can even get a nice graph::
811
812
812 hg log --graph -r "bisect(range)"
813 hg log --graph -r "bisect(range)"
813
814
814 See :hg:`help revisions.bisect` for more about the `bisect()` predicate.
815 See :hg:`help revisions.bisect` for more about the `bisect()` predicate.
815
816
816 Returns 0 on success.
817 Returns 0 on success.
817 """
818 """
818 # backward compatibility
819 # backward compatibility
819 if rev in "good bad reset init".split():
820 if rev in "good bad reset init".split():
820 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
821 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
821 cmd, rev, extra = rev, extra, None
822 cmd, rev, extra = rev, extra, None
822 if cmd == "good":
823 if cmd == "good":
823 good = True
824 good = True
824 elif cmd == "bad":
825 elif cmd == "bad":
825 bad = True
826 bad = True
826 else:
827 else:
827 reset = True
828 reset = True
828 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
829 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
829 raise error.Abort(_('incompatible arguments'))
830 raise error.Abort(_('incompatible arguments'))
830
831
831 cmdutil.checkunfinished(repo)
832 cmdutil.checkunfinished(repo)
832
833
833 if reset:
834 if reset:
834 hbisect.resetstate(repo)
835 hbisect.resetstate(repo)
835 return
836 return
836
837
837 state = hbisect.load_state(repo)
838 state = hbisect.load_state(repo)
838
839
839 # update state
840 # update state
840 if good or bad or skip:
841 if good or bad or skip:
841 if rev:
842 if rev:
842 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
843 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
843 else:
844 else:
844 nodes = [repo.lookup('.')]
845 nodes = [repo.lookup('.')]
845 if good:
846 if good:
846 state['good'] += nodes
847 state['good'] += nodes
847 elif bad:
848 elif bad:
848 state['bad'] += nodes
849 state['bad'] += nodes
849 elif skip:
850 elif skip:
850 state['skip'] += nodes
851 state['skip'] += nodes
851 hbisect.save_state(repo, state)
852 hbisect.save_state(repo, state)
852 if not (state['good'] and state['bad']):
853 if not (state['good'] and state['bad']):
853 return
854 return
854
855
855 def mayupdate(repo, node, show_stats=True):
856 def mayupdate(repo, node, show_stats=True):
856 """common used update sequence"""
857 """common used update sequence"""
857 if noupdate:
858 if noupdate:
858 return
859 return
859 cmdutil.bailifchanged(repo)
860 cmdutil.bailifchanged(repo)
860 return hg.clean(repo, node, show_stats=show_stats)
861 return hg.clean(repo, node, show_stats=show_stats)
861
862
862 displayer = cmdutil.show_changeset(ui, repo, {})
863 displayer = cmdutil.show_changeset(ui, repo, {})
863
864
864 if command:
865 if command:
865 changesets = 1
866 changesets = 1
866 if noupdate:
867 if noupdate:
867 try:
868 try:
868 node = state['current'][0]
869 node = state['current'][0]
869 except LookupError:
870 except LookupError:
870 raise error.Abort(_('current bisect revision is unknown - '
871 raise error.Abort(_('current bisect revision is unknown - '
871 'start a new bisect to fix'))
872 'start a new bisect to fix'))
872 else:
873 else:
873 node, p2 = repo.dirstate.parents()
874 node, p2 = repo.dirstate.parents()
874 if p2 != nullid:
875 if p2 != nullid:
875 raise error.Abort(_('current bisect revision is a merge'))
876 raise error.Abort(_('current bisect revision is a merge'))
876 if rev:
877 if rev:
877 node = repo[scmutil.revsingle(repo, rev, node)].node()
878 node = repo[scmutil.revsingle(repo, rev, node)].node()
878 try:
879 try:
879 while changesets:
880 while changesets:
880 # update state
881 # update state
881 state['current'] = [node]
882 state['current'] = [node]
882 hbisect.save_state(repo, state)
883 hbisect.save_state(repo, state)
883 status = ui.system(command, environ={'HG_NODE': hex(node)})
884 status = ui.system(command, environ={'HG_NODE': hex(node)})
884 if status == 125:
885 if status == 125:
885 transition = "skip"
886 transition = "skip"
886 elif status == 0:
887 elif status == 0:
887 transition = "good"
888 transition = "good"
888 # status < 0 means process was killed
889 # status < 0 means process was killed
889 elif status == 127:
890 elif status == 127:
890 raise error.Abort(_("failed to execute %s") % command)
891 raise error.Abort(_("failed to execute %s") % command)
891 elif status < 0:
892 elif status < 0:
892 raise error.Abort(_("%s killed") % command)
893 raise error.Abort(_("%s killed") % command)
893 else:
894 else:
894 transition = "bad"
895 transition = "bad"
895 state[transition].append(node)
896 state[transition].append(node)
896 ctx = repo[node]
897 ctx = repo[node]
897 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
898 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
898 hbisect.checkstate(state)
899 hbisect.checkstate(state)
899 # bisect
900 # bisect
900 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
901 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
901 # update to next check
902 # update to next check
902 node = nodes[0]
903 node = nodes[0]
903 mayupdate(repo, node, show_stats=False)
904 mayupdate(repo, node, show_stats=False)
904 finally:
905 finally:
905 state['current'] = [node]
906 state['current'] = [node]
906 hbisect.save_state(repo, state)
907 hbisect.save_state(repo, state)
907 hbisect.printresult(ui, repo, state, displayer, nodes, bgood)
908 hbisect.printresult(ui, repo, state, displayer, nodes, bgood)
908 return
909 return
909
910
910 hbisect.checkstate(state)
911 hbisect.checkstate(state)
911
912
912 # actually bisect
913 # actually bisect
913 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
914 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
914 if extend:
915 if extend:
915 if not changesets:
916 if not changesets:
916 extendnode = hbisect.extendrange(repo, state, nodes, good)
917 extendnode = hbisect.extendrange(repo, state, nodes, good)
917 if extendnode is not None:
918 if extendnode is not None:
918 ui.write(_("Extending search to changeset %d:%s\n")
919 ui.write(_("Extending search to changeset %d:%s\n")
919 % (extendnode.rev(), extendnode))
920 % (extendnode.rev(), extendnode))
920 state['current'] = [extendnode.node()]
921 state['current'] = [extendnode.node()]
921 hbisect.save_state(repo, state)
922 hbisect.save_state(repo, state)
922 return mayupdate(repo, extendnode.node())
923 return mayupdate(repo, extendnode.node())
923 raise error.Abort(_("nothing to extend"))
924 raise error.Abort(_("nothing to extend"))
924
925
925 if changesets == 0:
926 if changesets == 0:
926 hbisect.printresult(ui, repo, state, displayer, nodes, good)
927 hbisect.printresult(ui, repo, state, displayer, nodes, good)
927 else:
928 else:
928 assert len(nodes) == 1 # only a single node can be tested next
929 assert len(nodes) == 1 # only a single node can be tested next
929 node = nodes[0]
930 node = nodes[0]
930 # compute the approximate number of remaining tests
931 # compute the approximate number of remaining tests
931 tests, size = 0, 2
932 tests, size = 0, 2
932 while size <= changesets:
933 while size <= changesets:
933 tests, size = tests + 1, size * 2
934 tests, size = tests + 1, size * 2
934 rev = repo.changelog.rev(node)
935 rev = repo.changelog.rev(node)
935 ui.write(_("Testing changeset %d:%s "
936 ui.write(_("Testing changeset %d:%s "
936 "(%d changesets remaining, ~%d tests)\n")
937 "(%d changesets remaining, ~%d tests)\n")
937 % (rev, short(node), changesets, tests))
938 % (rev, short(node), changesets, tests))
938 state['current'] = [node]
939 state['current'] = [node]
939 hbisect.save_state(repo, state)
940 hbisect.save_state(repo, state)
940 return mayupdate(repo, node)
941 return mayupdate(repo, node)
941
942
942 @command('bookmarks|bookmark',
943 @command('bookmarks|bookmark',
943 [('f', 'force', False, _('force')),
944 [('f', 'force', False, _('force')),
944 ('r', 'rev', '', _('revision for bookmark action'), _('REV')),
945 ('r', 'rev', '', _('revision for bookmark action'), _('REV')),
945 ('d', 'delete', False, _('delete a given bookmark')),
946 ('d', 'delete', False, _('delete a given bookmark')),
946 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
947 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
947 ('i', 'inactive', False, _('mark a bookmark inactive')),
948 ('i', 'inactive', False, _('mark a bookmark inactive')),
948 ] + formatteropts,
949 ] + formatteropts,
949 _('hg bookmarks [OPTIONS]... [NAME]...'))
950 _('hg bookmarks [OPTIONS]... [NAME]...'))
950 def bookmark(ui, repo, *names, **opts):
951 def bookmark(ui, repo, *names, **opts):
951 '''create a new bookmark or list existing bookmarks
952 '''create a new bookmark or list existing bookmarks
952
953
953 Bookmarks are labels on changesets to help track lines of development.
954 Bookmarks are labels on changesets to help track lines of development.
954 Bookmarks are unversioned and can be moved, renamed and deleted.
955 Bookmarks are unversioned and can be moved, renamed and deleted.
955 Deleting or moving a bookmark has no effect on the associated changesets.
956 Deleting or moving a bookmark has no effect on the associated changesets.
956
957
957 Creating or updating to a bookmark causes it to be marked as 'active'.
958 Creating or updating to a bookmark causes it to be marked as 'active'.
958 The active bookmark is indicated with a '*'.
959 The active bookmark is indicated with a '*'.
959 When a commit is made, the active bookmark will advance to the new commit.
960 When a commit is made, the active bookmark will advance to the new commit.
960 A plain :hg:`update` will also advance an active bookmark, if possible.
961 A plain :hg:`update` will also advance an active bookmark, if possible.
961 Updating away from a bookmark will cause it to be deactivated.
962 Updating away from a bookmark will cause it to be deactivated.
962
963
963 Bookmarks can be pushed and pulled between repositories (see
964 Bookmarks can be pushed and pulled between repositories (see
964 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
965 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
965 diverged, a new 'divergent bookmark' of the form 'name@path' will
966 diverged, a new 'divergent bookmark' of the form 'name@path' will
966 be created. Using :hg:`merge` will resolve the divergence.
967 be created. Using :hg:`merge` will resolve the divergence.
967
968
968 A bookmark named '@' has the special property that :hg:`clone` will
969 A bookmark named '@' has the special property that :hg:`clone` will
969 check it out by default if it exists.
970 check it out by default if it exists.
970
971
971 .. container:: verbose
972 .. container:: verbose
972
973
973 Examples:
974 Examples:
974
975
975 - create an active bookmark for a new line of development::
976 - create an active bookmark for a new line of development::
976
977
977 hg book new-feature
978 hg book new-feature
978
979
979 - create an inactive bookmark as a place marker::
980 - create an inactive bookmark as a place marker::
980
981
981 hg book -i reviewed
982 hg book -i reviewed
982
983
983 - create an inactive bookmark on another changeset::
984 - create an inactive bookmark on another changeset::
984
985
985 hg book -r .^ tested
986 hg book -r .^ tested
986
987
987 - rename bookmark turkey to dinner::
988 - rename bookmark turkey to dinner::
988
989
989 hg book -m turkey dinner
990 hg book -m turkey dinner
990
991
991 - move the '@' bookmark from another branch::
992 - move the '@' bookmark from another branch::
992
993
993 hg book -f @
994 hg book -f @
994 '''
995 '''
995 force = opts.get('force')
996 force = opts.get('force')
996 rev = opts.get('rev')
997 rev = opts.get('rev')
997 delete = opts.get('delete')
998 delete = opts.get('delete')
998 rename = opts.get('rename')
999 rename = opts.get('rename')
999 inactive = opts.get('inactive')
1000 inactive = opts.get('inactive')
1000
1001
1001 def checkformat(mark):
1002 def checkformat(mark):
1002 mark = mark.strip()
1003 mark = mark.strip()
1003 if not mark:
1004 if not mark:
1004 raise error.Abort(_("bookmark names cannot consist entirely of "
1005 raise error.Abort(_("bookmark names cannot consist entirely of "
1005 "whitespace"))
1006 "whitespace"))
1006 scmutil.checknewlabel(repo, mark, 'bookmark')
1007 scmutil.checknewlabel(repo, mark, 'bookmark')
1007 return mark
1008 return mark
1008
1009
1009 def checkconflict(repo, mark, cur, force=False, target=None):
1010 def checkconflict(repo, mark, cur, force=False, target=None):
1010 if mark in marks and not force:
1011 if mark in marks and not force:
1011 if target:
1012 if target:
1012 if marks[mark] == target and target == cur:
1013 if marks[mark] == target and target == cur:
1013 # re-activating a bookmark
1014 # re-activating a bookmark
1014 return
1015 return
1015 anc = repo.changelog.ancestors([repo[target].rev()])
1016 anc = repo.changelog.ancestors([repo[target].rev()])
1016 bmctx = repo[marks[mark]]
1017 bmctx = repo[marks[mark]]
1017 divs = [repo[b].node() for b in marks
1018 divs = [repo[b].node() for b in marks
1018 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
1019 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
1019
1020
1020 # allow resolving a single divergent bookmark even if moving
1021 # allow resolving a single divergent bookmark even if moving
1021 # the bookmark across branches when a revision is specified
1022 # the bookmark across branches when a revision is specified
1022 # that contains a divergent bookmark
1023 # that contains a divergent bookmark
1023 if bmctx.rev() not in anc and target in divs:
1024 if bmctx.rev() not in anc and target in divs:
1024 bookmarks.deletedivergent(repo, [target], mark)
1025 bookmarks.deletedivergent(repo, [target], mark)
1025 return
1026 return
1026
1027
1027 deletefrom = [b for b in divs
1028 deletefrom = [b for b in divs
1028 if repo[b].rev() in anc or b == target]
1029 if repo[b].rev() in anc or b == target]
1029 bookmarks.deletedivergent(repo, deletefrom, mark)
1030 bookmarks.deletedivergent(repo, deletefrom, mark)
1030 if bookmarks.validdest(repo, bmctx, repo[target]):
1031 if bookmarks.validdest(repo, bmctx, repo[target]):
1031 ui.status(_("moving bookmark '%s' forward from %s\n") %
1032 ui.status(_("moving bookmark '%s' forward from %s\n") %
1032 (mark, short(bmctx.node())))
1033 (mark, short(bmctx.node())))
1033 return
1034 return
1034 raise error.Abort(_("bookmark '%s' already exists "
1035 raise error.Abort(_("bookmark '%s' already exists "
1035 "(use -f to force)") % mark)
1036 "(use -f to force)") % mark)
1036 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
1037 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
1037 and not force):
1038 and not force):
1038 raise error.Abort(
1039 raise error.Abort(
1039 _("a bookmark cannot have the name of an existing branch"))
1040 _("a bookmark cannot have the name of an existing branch"))
1040
1041
1041 if delete and rename:
1042 if delete and rename:
1042 raise error.Abort(_("--delete and --rename are incompatible"))
1043 raise error.Abort(_("--delete and --rename are incompatible"))
1043 if delete and rev:
1044 if delete and rev:
1044 raise error.Abort(_("--rev is incompatible with --delete"))
1045 raise error.Abort(_("--rev is incompatible with --delete"))
1045 if rename and rev:
1046 if rename and rev:
1046 raise error.Abort(_("--rev is incompatible with --rename"))
1047 raise error.Abort(_("--rev is incompatible with --rename"))
1047 if not names and (delete or rev):
1048 if not names and (delete or rev):
1048 raise error.Abort(_("bookmark name required"))
1049 raise error.Abort(_("bookmark name required"))
1049
1050
1050 if delete or rename or names or inactive:
1051 if delete or rename or names or inactive:
1051 wlock = lock = tr = None
1052 wlock = lock = tr = None
1052 try:
1053 try:
1053 wlock = repo.wlock()
1054 wlock = repo.wlock()
1054 lock = repo.lock()
1055 lock = repo.lock()
1055 cur = repo.changectx('.').node()
1056 cur = repo.changectx('.').node()
1056 marks = repo._bookmarks
1057 marks = repo._bookmarks
1057 if delete:
1058 if delete:
1058 tr = repo.transaction('bookmark')
1059 tr = repo.transaction('bookmark')
1059 for mark in names:
1060 for mark in names:
1060 if mark not in marks:
1061 if mark not in marks:
1061 raise error.Abort(_("bookmark '%s' does not exist") %
1062 raise error.Abort(_("bookmark '%s' does not exist") %
1062 mark)
1063 mark)
1063 if mark == repo._activebookmark:
1064 if mark == repo._activebookmark:
1064 bookmarks.deactivate(repo)
1065 bookmarks.deactivate(repo)
1065 del marks[mark]
1066 del marks[mark]
1066
1067
1067 elif rename:
1068 elif rename:
1068 tr = repo.transaction('bookmark')
1069 tr = repo.transaction('bookmark')
1069 if not names:
1070 if not names:
1070 raise error.Abort(_("new bookmark name required"))
1071 raise error.Abort(_("new bookmark name required"))
1071 elif len(names) > 1:
1072 elif len(names) > 1:
1072 raise error.Abort(_("only one new bookmark name allowed"))
1073 raise error.Abort(_("only one new bookmark name allowed"))
1073 mark = checkformat(names[0])
1074 mark = checkformat(names[0])
1074 if rename not in marks:
1075 if rename not in marks:
1075 raise error.Abort(_("bookmark '%s' does not exist")
1076 raise error.Abort(_("bookmark '%s' does not exist")
1076 % rename)
1077 % rename)
1077 checkconflict(repo, mark, cur, force)
1078 checkconflict(repo, mark, cur, force)
1078 marks[mark] = marks[rename]
1079 marks[mark] = marks[rename]
1079 if repo._activebookmark == rename and not inactive:
1080 if repo._activebookmark == rename and not inactive:
1080 bookmarks.activate(repo, mark)
1081 bookmarks.activate(repo, mark)
1081 del marks[rename]
1082 del marks[rename]
1082 elif names:
1083 elif names:
1083 tr = repo.transaction('bookmark')
1084 tr = repo.transaction('bookmark')
1084 newact = None
1085 newact = None
1085 for mark in names:
1086 for mark in names:
1086 mark = checkformat(mark)
1087 mark = checkformat(mark)
1087 if newact is None:
1088 if newact is None:
1088 newact = mark
1089 newact = mark
1089 if inactive and mark == repo._activebookmark:
1090 if inactive and mark == repo._activebookmark:
1090 bookmarks.deactivate(repo)
1091 bookmarks.deactivate(repo)
1091 return
1092 return
1092 tgt = cur
1093 tgt = cur
1093 if rev:
1094 if rev:
1094 tgt = scmutil.revsingle(repo, rev).node()
1095 tgt = scmutil.revsingle(repo, rev).node()
1095 checkconflict(repo, mark, cur, force, tgt)
1096 checkconflict(repo, mark, cur, force, tgt)
1096 marks[mark] = tgt
1097 marks[mark] = tgt
1097 if not inactive and cur == marks[newact] and not rev:
1098 if not inactive and cur == marks[newact] and not rev:
1098 bookmarks.activate(repo, newact)
1099 bookmarks.activate(repo, newact)
1099 elif cur != tgt and newact == repo._activebookmark:
1100 elif cur != tgt and newact == repo._activebookmark:
1100 bookmarks.deactivate(repo)
1101 bookmarks.deactivate(repo)
1101 elif inactive:
1102 elif inactive:
1102 if len(marks) == 0:
1103 if len(marks) == 0:
1103 ui.status(_("no bookmarks set\n"))
1104 ui.status(_("no bookmarks set\n"))
1104 elif not repo._activebookmark:
1105 elif not repo._activebookmark:
1105 ui.status(_("no active bookmark\n"))
1106 ui.status(_("no active bookmark\n"))
1106 else:
1107 else:
1107 bookmarks.deactivate(repo)
1108 bookmarks.deactivate(repo)
1108 if tr is not None:
1109 if tr is not None:
1109 marks.recordchange(tr)
1110 marks.recordchange(tr)
1110 tr.close()
1111 tr.close()
1111 finally:
1112 finally:
1112 lockmod.release(tr, lock, wlock)
1113 lockmod.release(tr, lock, wlock)
1113 else: # show bookmarks
1114 else: # show bookmarks
1114 fm = ui.formatter('bookmarks', opts)
1115 fm = ui.formatter('bookmarks', opts)
1115 hexfn = fm.hexfunc
1116 hexfn = fm.hexfunc
1116 marks = repo._bookmarks
1117 marks = repo._bookmarks
1117 if len(marks) == 0 and fm.isplain():
1118 if len(marks) == 0 and fm.isplain():
1118 ui.status(_("no bookmarks set\n"))
1119 ui.status(_("no bookmarks set\n"))
1119 for bmark, n in sorted(marks.iteritems()):
1120 for bmark, n in sorted(marks.iteritems()):
1120 active = repo._activebookmark
1121 active = repo._activebookmark
1121 if bmark == active:
1122 if bmark == active:
1122 prefix, label = '*', activebookmarklabel
1123 prefix, label = '*', activebookmarklabel
1123 else:
1124 else:
1124 prefix, label = ' ', ''
1125 prefix, label = ' ', ''
1125
1126
1126 fm.startitem()
1127 fm.startitem()
1127 if not ui.quiet:
1128 if not ui.quiet:
1128 fm.plain(' %s ' % prefix, label=label)
1129 fm.plain(' %s ' % prefix, label=label)
1129 fm.write('bookmark', '%s', bmark, label=label)
1130 fm.write('bookmark', '%s', bmark, label=label)
1130 pad = " " * (25 - encoding.colwidth(bmark))
1131 pad = " " * (25 - encoding.colwidth(bmark))
1131 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1132 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1132 repo.changelog.rev(n), hexfn(n), label=label)
1133 repo.changelog.rev(n), hexfn(n), label=label)
1133 fm.data(active=(bmark == active))
1134 fm.data(active=(bmark == active))
1134 fm.plain('\n')
1135 fm.plain('\n')
1135 fm.end()
1136 fm.end()
1136
1137
1137 @command('branch',
1138 @command('branch',
1138 [('f', 'force', None,
1139 [('f', 'force', None,
1139 _('set branch name even if it shadows an existing branch')),
1140 _('set branch name even if it shadows an existing branch')),
1140 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1141 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1141 _('[-fC] [NAME]'))
1142 _('[-fC] [NAME]'))
1142 def branch(ui, repo, label=None, **opts):
1143 def branch(ui, repo, label=None, **opts):
1143 """set or show the current branch name
1144 """set or show the current branch name
1144
1145
1145 .. note::
1146 .. note::
1146
1147
1147 Branch names are permanent and global. Use :hg:`bookmark` to create a
1148 Branch names are permanent and global. Use :hg:`bookmark` to create a
1148 light-weight bookmark instead. See :hg:`help glossary` for more
1149 light-weight bookmark instead. See :hg:`help glossary` for more
1149 information about named branches and bookmarks.
1150 information about named branches and bookmarks.
1150
1151
1151 With no argument, show the current branch name. With one argument,
1152 With no argument, show the current branch name. With one argument,
1152 set the working directory branch name (the branch will not exist
1153 set the working directory branch name (the branch will not exist
1153 in the repository until the next commit). Standard practice
1154 in the repository until the next commit). Standard practice
1154 recommends that primary development take place on the 'default'
1155 recommends that primary development take place on the 'default'
1155 branch.
1156 branch.
1156
1157
1157 Unless -f/--force is specified, branch will not let you set a
1158 Unless -f/--force is specified, branch will not let you set a
1158 branch name that already exists.
1159 branch name that already exists.
1159
1160
1160 Use -C/--clean to reset the working directory branch to that of
1161 Use -C/--clean to reset the working directory branch to that of
1161 the parent of the working directory, negating a previous branch
1162 the parent of the working directory, negating a previous branch
1162 change.
1163 change.
1163
1164
1164 Use the command :hg:`update` to switch to an existing branch. Use
1165 Use the command :hg:`update` to switch to an existing branch. Use
1165 :hg:`commit --close-branch` to mark this branch head as closed.
1166 :hg:`commit --close-branch` to mark this branch head as closed.
1166 When all heads of a branch are closed, the branch will be
1167 When all heads of a branch are closed, the branch will be
1167 considered closed.
1168 considered closed.
1168
1169
1169 Returns 0 on success.
1170 Returns 0 on success.
1170 """
1171 """
1171 if label:
1172 if label:
1172 label = label.strip()
1173 label = label.strip()
1173
1174
1174 if not opts.get('clean') and not label:
1175 if not opts.get('clean') and not label:
1175 ui.write("%s\n" % repo.dirstate.branch())
1176 ui.write("%s\n" % repo.dirstate.branch())
1176 return
1177 return
1177
1178
1178 with repo.wlock():
1179 with repo.wlock():
1179 if opts.get('clean'):
1180 if opts.get('clean'):
1180 label = repo[None].p1().branch()
1181 label = repo[None].p1().branch()
1181 repo.dirstate.setbranch(label)
1182 repo.dirstate.setbranch(label)
1182 ui.status(_('reset working directory to branch %s\n') % label)
1183 ui.status(_('reset working directory to branch %s\n') % label)
1183 elif label:
1184 elif label:
1184 if not opts.get('force') and label in repo.branchmap():
1185 if not opts.get('force') and label in repo.branchmap():
1185 if label not in [p.branch() for p in repo[None].parents()]:
1186 if label not in [p.branch() for p in repo[None].parents()]:
1186 raise error.Abort(_('a branch of the same name already'
1187 raise error.Abort(_('a branch of the same name already'
1187 ' exists'),
1188 ' exists'),
1188 # i18n: "it" refers to an existing branch
1189 # i18n: "it" refers to an existing branch
1189 hint=_("use 'hg update' to switch to it"))
1190 hint=_("use 'hg update' to switch to it"))
1190 scmutil.checknewlabel(repo, label, 'branch')
1191 scmutil.checknewlabel(repo, label, 'branch')
1191 repo.dirstate.setbranch(label)
1192 repo.dirstate.setbranch(label)
1192 ui.status(_('marked working directory as branch %s\n') % label)
1193 ui.status(_('marked working directory as branch %s\n') % label)
1193
1194
1194 # find any open named branches aside from default
1195 # find any open named branches aside from default
1195 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1196 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1196 if n != "default" and not c]
1197 if n != "default" and not c]
1197 if not others:
1198 if not others:
1198 ui.status(_('(branches are permanent and global, '
1199 ui.status(_('(branches are permanent and global, '
1199 'did you want a bookmark?)\n'))
1200 'did you want a bookmark?)\n'))
1200
1201
1201 @command('branches',
1202 @command('branches',
1202 [('a', 'active', False,
1203 [('a', 'active', False,
1203 _('show only branches that have unmerged heads (DEPRECATED)')),
1204 _('show only branches that have unmerged heads (DEPRECATED)')),
1204 ('c', 'closed', False, _('show normal and closed branches')),
1205 ('c', 'closed', False, _('show normal and closed branches')),
1205 ] + formatteropts,
1206 ] + formatteropts,
1206 _('[-c]'))
1207 _('[-c]'))
1207 def branches(ui, repo, active=False, closed=False, **opts):
1208 def branches(ui, repo, active=False, closed=False, **opts):
1208 """list repository named branches
1209 """list repository named branches
1209
1210
1210 List the repository's named branches, indicating which ones are
1211 List the repository's named branches, indicating which ones are
1211 inactive. If -c/--closed is specified, also list branches which have
1212 inactive. If -c/--closed is specified, also list branches which have
1212 been marked closed (see :hg:`commit --close-branch`).
1213 been marked closed (see :hg:`commit --close-branch`).
1213
1214
1214 Use the command :hg:`update` to switch to an existing branch.
1215 Use the command :hg:`update` to switch to an existing branch.
1215
1216
1216 Returns 0.
1217 Returns 0.
1217 """
1218 """
1218
1219
1219 fm = ui.formatter('branches', opts)
1220 fm = ui.formatter('branches', opts)
1220 hexfunc = fm.hexfunc
1221 hexfunc = fm.hexfunc
1221
1222
1222 allheads = set(repo.heads())
1223 allheads = set(repo.heads())
1223 branches = []
1224 branches = []
1224 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1225 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1225 isactive = not isclosed and bool(set(heads) & allheads)
1226 isactive = not isclosed and bool(set(heads) & allheads)
1226 branches.append((tag, repo[tip], isactive, not isclosed))
1227 branches.append((tag, repo[tip], isactive, not isclosed))
1227 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1228 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1228 reverse=True)
1229 reverse=True)
1229
1230
1230 for tag, ctx, isactive, isopen in branches:
1231 for tag, ctx, isactive, isopen in branches:
1231 if active and not isactive:
1232 if active and not isactive:
1232 continue
1233 continue
1233 if isactive:
1234 if isactive:
1234 label = 'branches.active'
1235 label = 'branches.active'
1235 notice = ''
1236 notice = ''
1236 elif not isopen:
1237 elif not isopen:
1237 if not closed:
1238 if not closed:
1238 continue
1239 continue
1239 label = 'branches.closed'
1240 label = 'branches.closed'
1240 notice = _(' (closed)')
1241 notice = _(' (closed)')
1241 else:
1242 else:
1242 label = 'branches.inactive'
1243 label = 'branches.inactive'
1243 notice = _(' (inactive)')
1244 notice = _(' (inactive)')
1244 current = (tag == repo.dirstate.branch())
1245 current = (tag == repo.dirstate.branch())
1245 if current:
1246 if current:
1246 label = 'branches.current'
1247 label = 'branches.current'
1247
1248
1248 fm.startitem()
1249 fm.startitem()
1249 fm.write('branch', '%s', tag, label=label)
1250 fm.write('branch', '%s', tag, label=label)
1250 rev = ctx.rev()
1251 rev = ctx.rev()
1251 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1252 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1252 fmt = ' ' * padsize + ' %d:%s'
1253 fmt = ' ' * padsize + ' %d:%s'
1253 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1254 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1254 label='log.changeset changeset.%s' % ctx.phasestr())
1255 label='log.changeset changeset.%s' % ctx.phasestr())
1255 fm.data(active=isactive, closed=not isopen, current=current)
1256 fm.data(active=isactive, closed=not isopen, current=current)
1256 if not ui.quiet:
1257 if not ui.quiet:
1257 fm.plain(notice)
1258 fm.plain(notice)
1258 fm.plain('\n')
1259 fm.plain('\n')
1259 fm.end()
1260 fm.end()
1260
1261
1261 @command('bundle',
1262 @command('bundle',
1262 [('f', 'force', None, _('run even when the destination is unrelated')),
1263 [('f', 'force', None, _('run even when the destination is unrelated')),
1263 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1264 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1264 _('REV')),
1265 _('REV')),
1265 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1266 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1266 _('BRANCH')),
1267 _('BRANCH')),
1267 ('', 'base', [],
1268 ('', 'base', [],
1268 _('a base changeset assumed to be available at the destination'),
1269 _('a base changeset assumed to be available at the destination'),
1269 _('REV')),
1270 _('REV')),
1270 ('a', 'all', None, _('bundle all changesets in the repository')),
1271 ('a', 'all', None, _('bundle all changesets in the repository')),
1271 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1272 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1272 ] + remoteopts,
1273 ] + remoteopts,
1273 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1274 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1274 def bundle(ui, repo, fname, dest=None, **opts):
1275 def bundle(ui, repo, fname, dest=None, **opts):
1275 """create a changegroup file
1276 """create a changegroup file
1276
1277
1277 Generate a changegroup file collecting changesets to be added
1278 Generate a changegroup file collecting changesets to be added
1278 to a repository.
1279 to a repository.
1279
1280
1280 To create a bundle containing all changesets, use -a/--all
1281 To create a bundle containing all changesets, use -a/--all
1281 (or --base null). Otherwise, hg assumes the destination will have
1282 (or --base null). Otherwise, hg assumes the destination will have
1282 all the nodes you specify with --base parameters. Otherwise, hg
1283 all the nodes you specify with --base parameters. Otherwise, hg
1283 will assume the repository has all the nodes in destination, or
1284 will assume the repository has all the nodes in destination, or
1284 default-push/default if no destination is specified.
1285 default-push/default if no destination is specified.
1285
1286
1286 You can change bundle format with the -t/--type option. You can
1287 You can change bundle format with the -t/--type option. You can
1287 specify a compression, a bundle version or both using a dash
1288 specify a compression, a bundle version or both using a dash
1288 (comp-version). The available compression methods are: none, bzip2,
1289 (comp-version). The available compression methods are: none, bzip2,
1289 and gzip (by default, bundles are compressed using bzip2). The
1290 and gzip (by default, bundles are compressed using bzip2). The
1290 available formats are: v1, v2 (default to most suitable).
1291 available formats are: v1, v2 (default to most suitable).
1291
1292
1292 The bundle file can then be transferred using conventional means
1293 The bundle file can then be transferred using conventional means
1293 and applied to another repository with the unbundle or pull
1294 and applied to another repository with the unbundle or pull
1294 command. This is useful when direct push and pull are not
1295 command. This is useful when direct push and pull are not
1295 available or when exporting an entire repository is undesirable.
1296 available or when exporting an entire repository is undesirable.
1296
1297
1297 Applying bundles preserves all changeset contents including
1298 Applying bundles preserves all changeset contents including
1298 permissions, copy/rename information, and revision history.
1299 permissions, copy/rename information, and revision history.
1299
1300
1300 Returns 0 on success, 1 if no changes found.
1301 Returns 0 on success, 1 if no changes found.
1301 """
1302 """
1302 revs = None
1303 revs = None
1303 if 'rev' in opts:
1304 if 'rev' in opts:
1304 revstrings = opts['rev']
1305 revstrings = opts['rev']
1305 revs = scmutil.revrange(repo, revstrings)
1306 revs = scmutil.revrange(repo, revstrings)
1306 if revstrings and not revs:
1307 if revstrings and not revs:
1307 raise error.Abort(_('no commits to bundle'))
1308 raise error.Abort(_('no commits to bundle'))
1308
1309
1309 bundletype = opts.get('type', 'bzip2').lower()
1310 bundletype = opts.get('type', 'bzip2').lower()
1310 try:
1311 try:
1311 bcompression, cgversion, params = exchange.parsebundlespec(
1312 bcompression, cgversion, params = exchange.parsebundlespec(
1312 repo, bundletype, strict=False)
1313 repo, bundletype, strict=False)
1313 except error.UnsupportedBundleSpecification as e:
1314 except error.UnsupportedBundleSpecification as e:
1314 raise error.Abort(str(e),
1315 raise error.Abort(str(e),
1315 hint=_("see 'hg help bundle' for supported "
1316 hint=_("see 'hg help bundle' for supported "
1316 "values for --type"))
1317 "values for --type"))
1317
1318
1318 # Packed bundles are a pseudo bundle format for now.
1319 # Packed bundles are a pseudo bundle format for now.
1319 if cgversion == 's1':
1320 if cgversion == 's1':
1320 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1321 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1321 hint=_("use 'hg debugcreatestreamclonebundle'"))
1322 hint=_("use 'hg debugcreatestreamclonebundle'"))
1322
1323
1323 if opts.get('all'):
1324 if opts.get('all'):
1324 if dest:
1325 if dest:
1325 raise error.Abort(_("--all is incompatible with specifying "
1326 raise error.Abort(_("--all is incompatible with specifying "
1326 "a destination"))
1327 "a destination"))
1327 if opts.get('base'):
1328 if opts.get('base'):
1328 ui.warn(_("ignoring --base because --all was specified\n"))
1329 ui.warn(_("ignoring --base because --all was specified\n"))
1329 base = ['null']
1330 base = ['null']
1330 else:
1331 else:
1331 base = scmutil.revrange(repo, opts.get('base'))
1332 base = scmutil.revrange(repo, opts.get('base'))
1332 # TODO: get desired bundlecaps from command line.
1333 # TODO: get desired bundlecaps from command line.
1333 bundlecaps = None
1334 bundlecaps = None
1334 if cgversion not in changegroup.supportedoutgoingversions(repo):
1335 if cgversion not in changegroup.supportedoutgoingversions(repo):
1335 raise error.Abort(_("repository does not support bundle version %s") %
1336 raise error.Abort(_("repository does not support bundle version %s") %
1336 cgversion)
1337 cgversion)
1337
1338
1338 if base:
1339 if base:
1339 if dest:
1340 if dest:
1340 raise error.Abort(_("--base is incompatible with specifying "
1341 raise error.Abort(_("--base is incompatible with specifying "
1341 "a destination"))
1342 "a destination"))
1342 common = [repo.lookup(rev) for rev in base]
1343 common = [repo.lookup(rev) for rev in base]
1343 heads = revs and map(repo.lookup, revs) or None
1344 heads = revs and map(repo.lookup, revs) or None
1344 outgoing = discovery.outgoing(repo, common, heads)
1345 outgoing = discovery.outgoing(repo, common, heads)
1345 cg = changegroup.getchangegroup(repo, 'bundle', outgoing,
1346 cg = changegroup.getchangegroup(repo, 'bundle', outgoing,
1346 bundlecaps=bundlecaps,
1347 bundlecaps=bundlecaps,
1347 version=cgversion)
1348 version=cgversion)
1348 outgoing = None
1349 outgoing = None
1349 else:
1350 else:
1350 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1351 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1351 dest, branches = hg.parseurl(dest, opts.get('branch'))
1352 dest, branches = hg.parseurl(dest, opts.get('branch'))
1352 other = hg.peer(repo, opts, dest)
1353 other = hg.peer(repo, opts, dest)
1353 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1354 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1354 heads = revs and map(repo.lookup, revs) or revs
1355 heads = revs and map(repo.lookup, revs) or revs
1355 outgoing = discovery.findcommonoutgoing(repo, other,
1356 outgoing = discovery.findcommonoutgoing(repo, other,
1356 onlyheads=heads,
1357 onlyheads=heads,
1357 force=opts.get('force'),
1358 force=opts.get('force'),
1358 portable=True)
1359 portable=True)
1359 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1360 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1360 bundlecaps, version=cgversion)
1361 bundlecaps, version=cgversion)
1361 if not cg:
1362 if not cg:
1362 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1363 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1363 return 1
1364 return 1
1364
1365
1365 if cgversion == '01': #bundle1
1366 if cgversion == '01': #bundle1
1366 if bcompression is None:
1367 if bcompression is None:
1367 bcompression = 'UN'
1368 bcompression = 'UN'
1368 bversion = 'HG10' + bcompression
1369 bversion = 'HG10' + bcompression
1369 bcompression = None
1370 bcompression = None
1370 else:
1371 else:
1371 assert cgversion == '02'
1372 assert cgversion == '02'
1372 bversion = 'HG20'
1373 bversion = 'HG20'
1373
1374
1374 # TODO compression options should be derived from bundlespec parsing.
1375 # TODO compression options should be derived from bundlespec parsing.
1375 # This is a temporary hack to allow adjusting bundle compression
1376 # This is a temporary hack to allow adjusting bundle compression
1376 # level without a) formalizing the bundlespec changes to declare it
1377 # level without a) formalizing the bundlespec changes to declare it
1377 # b) introducing a command flag.
1378 # b) introducing a command flag.
1378 compopts = {}
1379 compopts = {}
1379 complevel = ui.configint('experimental', 'bundlecomplevel')
1380 complevel = ui.configint('experimental', 'bundlecomplevel')
1380 if complevel is not None:
1381 if complevel is not None:
1381 compopts['level'] = complevel
1382 compopts['level'] = complevel
1382
1383
1383 bundle2.writebundle(ui, cg, fname, bversion, compression=bcompression,
1384 bundle2.writebundle(ui, cg, fname, bversion, compression=bcompression,
1384 compopts=compopts)
1385 compopts=compopts)
1385
1386
1386 @command('cat',
1387 @command('cat',
1387 [('o', 'output', '',
1388 [('o', 'output', '',
1388 _('print output to file with formatted name'), _('FORMAT')),
1389 _('print output to file with formatted name'), _('FORMAT')),
1389 ('r', 'rev', '', _('print the given revision'), _('REV')),
1390 ('r', 'rev', '', _('print the given revision'), _('REV')),
1390 ('', 'decode', None, _('apply any matching decode filter')),
1391 ('', 'decode', None, _('apply any matching decode filter')),
1391 ] + walkopts,
1392 ] + walkopts,
1392 _('[OPTION]... FILE...'),
1393 _('[OPTION]... FILE...'),
1393 inferrepo=True)
1394 inferrepo=True)
1394 def cat(ui, repo, file1, *pats, **opts):
1395 def cat(ui, repo, file1, *pats, **opts):
1395 """output the current or given revision of files
1396 """output the current or given revision of files
1396
1397
1397 Print the specified files as they were at the given revision. If
1398 Print the specified files as they were at the given revision. If
1398 no revision is given, the parent of the working directory is used.
1399 no revision is given, the parent of the working directory is used.
1399
1400
1400 Output may be to a file, in which case the name of the file is
1401 Output may be to a file, in which case the name of the file is
1401 given using a format string. The formatting rules as follows:
1402 given using a format string. The formatting rules as follows:
1402
1403
1403 :``%%``: literal "%" character
1404 :``%%``: literal "%" character
1404 :``%s``: basename of file being printed
1405 :``%s``: basename of file being printed
1405 :``%d``: dirname of file being printed, or '.' if in repository root
1406 :``%d``: dirname of file being printed, or '.' if in repository root
1406 :``%p``: root-relative path name of file being printed
1407 :``%p``: root-relative path name of file being printed
1407 :``%H``: changeset hash (40 hexadecimal digits)
1408 :``%H``: changeset hash (40 hexadecimal digits)
1408 :``%R``: changeset revision number
1409 :``%R``: changeset revision number
1409 :``%h``: short-form changeset hash (12 hexadecimal digits)
1410 :``%h``: short-form changeset hash (12 hexadecimal digits)
1410 :``%r``: zero-padded changeset revision number
1411 :``%r``: zero-padded changeset revision number
1411 :``%b``: basename of the exporting repository
1412 :``%b``: basename of the exporting repository
1412
1413
1413 Returns 0 on success.
1414 Returns 0 on success.
1414 """
1415 """
1415 ctx = scmutil.revsingle(repo, opts.get('rev'))
1416 ctx = scmutil.revsingle(repo, opts.get('rev'))
1416 m = scmutil.match(ctx, (file1,) + pats, opts)
1417 m = scmutil.match(ctx, (file1,) + pats, opts)
1417
1418
1418 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1419 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1419
1420
1420 @command('^clone',
1421 @command('^clone',
1421 [('U', 'noupdate', None, _('the clone will include an empty working '
1422 [('U', 'noupdate', None, _('the clone will include an empty working '
1422 'directory (only a repository)')),
1423 'directory (only a repository)')),
1423 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1424 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1424 _('REV')),
1425 _('REV')),
1425 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1426 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1426 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1427 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1427 ('', 'pull', None, _('use pull protocol to copy metadata')),
1428 ('', 'pull', None, _('use pull protocol to copy metadata')),
1428 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1429 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1429 ] + remoteopts,
1430 ] + remoteopts,
1430 _('[OPTION]... SOURCE [DEST]'),
1431 _('[OPTION]... SOURCE [DEST]'),
1431 norepo=True)
1432 norepo=True)
1432 def clone(ui, source, dest=None, **opts):
1433 def clone(ui, source, dest=None, **opts):
1433 """make a copy of an existing repository
1434 """make a copy of an existing repository
1434
1435
1435 Create a copy of an existing repository in a new directory.
1436 Create a copy of an existing repository in a new directory.
1436
1437
1437 If no destination directory name is specified, it defaults to the
1438 If no destination directory name is specified, it defaults to the
1438 basename of the source.
1439 basename of the source.
1439
1440
1440 The location of the source is added to the new repository's
1441 The location of the source is added to the new repository's
1441 ``.hg/hgrc`` file, as the default to be used for future pulls.
1442 ``.hg/hgrc`` file, as the default to be used for future pulls.
1442
1443
1443 Only local paths and ``ssh://`` URLs are supported as
1444 Only local paths and ``ssh://`` URLs are supported as
1444 destinations. For ``ssh://`` destinations, no working directory or
1445 destinations. For ``ssh://`` destinations, no working directory or
1445 ``.hg/hgrc`` will be created on the remote side.
1446 ``.hg/hgrc`` will be created on the remote side.
1446
1447
1447 If the source repository has a bookmark called '@' set, that
1448 If the source repository has a bookmark called '@' set, that
1448 revision will be checked out in the new repository by default.
1449 revision will be checked out in the new repository by default.
1449
1450
1450 To check out a particular version, use -u/--update, or
1451 To check out a particular version, use -u/--update, or
1451 -U/--noupdate to create a clone with no working directory.
1452 -U/--noupdate to create a clone with no working directory.
1452
1453
1453 To pull only a subset of changesets, specify one or more revisions
1454 To pull only a subset of changesets, specify one or more revisions
1454 identifiers with -r/--rev or branches with -b/--branch. The
1455 identifiers with -r/--rev or branches with -b/--branch. The
1455 resulting clone will contain only the specified changesets and
1456 resulting clone will contain only the specified changesets and
1456 their ancestors. These options (or 'clone src#rev dest') imply
1457 their ancestors. These options (or 'clone src#rev dest') imply
1457 --pull, even for local source repositories.
1458 --pull, even for local source repositories.
1458
1459
1459 .. note::
1460 .. note::
1460
1461
1461 Specifying a tag will include the tagged changeset but not the
1462 Specifying a tag will include the tagged changeset but not the
1462 changeset containing the tag.
1463 changeset containing the tag.
1463
1464
1464 .. container:: verbose
1465 .. container:: verbose
1465
1466
1466 For efficiency, hardlinks are used for cloning whenever the
1467 For efficiency, hardlinks are used for cloning whenever the
1467 source and destination are on the same filesystem (note this
1468 source and destination are on the same filesystem (note this
1468 applies only to the repository data, not to the working
1469 applies only to the repository data, not to the working
1469 directory). Some filesystems, such as AFS, implement hardlinking
1470 directory). Some filesystems, such as AFS, implement hardlinking
1470 incorrectly, but do not report errors. In these cases, use the
1471 incorrectly, but do not report errors. In these cases, use the
1471 --pull option to avoid hardlinking.
1472 --pull option to avoid hardlinking.
1472
1473
1473 In some cases, you can clone repositories and the working
1474 In some cases, you can clone repositories and the working
1474 directory using full hardlinks with ::
1475 directory using full hardlinks with ::
1475
1476
1476 $ cp -al REPO REPOCLONE
1477 $ cp -al REPO REPOCLONE
1477
1478
1478 This is the fastest way to clone, but it is not always safe. The
1479 This is the fastest way to clone, but it is not always safe. The
1479 operation is not atomic (making sure REPO is not modified during
1480 operation is not atomic (making sure REPO is not modified during
1480 the operation is up to you) and you have to make sure your
1481 the operation is up to you) and you have to make sure your
1481 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1482 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1482 so). Also, this is not compatible with certain extensions that
1483 so). Also, this is not compatible with certain extensions that
1483 place their metadata under the .hg directory, such as mq.
1484 place their metadata under the .hg directory, such as mq.
1484
1485
1485 Mercurial will update the working directory to the first applicable
1486 Mercurial will update the working directory to the first applicable
1486 revision from this list:
1487 revision from this list:
1487
1488
1488 a) null if -U or the source repository has no changesets
1489 a) null if -U or the source repository has no changesets
1489 b) if -u . and the source repository is local, the first parent of
1490 b) if -u . and the source repository is local, the first parent of
1490 the source repository's working directory
1491 the source repository's working directory
1491 c) the changeset specified with -u (if a branch name, this means the
1492 c) the changeset specified with -u (if a branch name, this means the
1492 latest head of that branch)
1493 latest head of that branch)
1493 d) the changeset specified with -r
1494 d) the changeset specified with -r
1494 e) the tipmost head specified with -b
1495 e) the tipmost head specified with -b
1495 f) the tipmost head specified with the url#branch source syntax
1496 f) the tipmost head specified with the url#branch source syntax
1496 g) the revision marked with the '@' bookmark, if present
1497 g) the revision marked with the '@' bookmark, if present
1497 h) the tipmost head of the default branch
1498 h) the tipmost head of the default branch
1498 i) tip
1499 i) tip
1499
1500
1500 When cloning from servers that support it, Mercurial may fetch
1501 When cloning from servers that support it, Mercurial may fetch
1501 pre-generated data from a server-advertised URL. When this is done,
1502 pre-generated data from a server-advertised URL. When this is done,
1502 hooks operating on incoming changesets and changegroups may fire twice,
1503 hooks operating on incoming changesets and changegroups may fire twice,
1503 once for the bundle fetched from the URL and another for any additional
1504 once for the bundle fetched from the URL and another for any additional
1504 data not fetched from this URL. In addition, if an error occurs, the
1505 data not fetched from this URL. In addition, if an error occurs, the
1505 repository may be rolled back to a partial clone. This behavior may
1506 repository may be rolled back to a partial clone. This behavior may
1506 change in future releases. See :hg:`help -e clonebundles` for more.
1507 change in future releases. See :hg:`help -e clonebundles` for more.
1507
1508
1508 Examples:
1509 Examples:
1509
1510
1510 - clone a remote repository to a new directory named hg/::
1511 - clone a remote repository to a new directory named hg/::
1511
1512
1512 hg clone https://www.mercurial-scm.org/repo/hg/
1513 hg clone https://www.mercurial-scm.org/repo/hg/
1513
1514
1514 - create a lightweight local clone::
1515 - create a lightweight local clone::
1515
1516
1516 hg clone project/ project-feature/
1517 hg clone project/ project-feature/
1517
1518
1518 - clone from an absolute path on an ssh server (note double-slash)::
1519 - clone from an absolute path on an ssh server (note double-slash)::
1519
1520
1520 hg clone ssh://user@server//home/projects/alpha/
1521 hg clone ssh://user@server//home/projects/alpha/
1521
1522
1522 - do a high-speed clone over a LAN while checking out a
1523 - do a high-speed clone over a LAN while checking out a
1523 specified version::
1524 specified version::
1524
1525
1525 hg clone --uncompressed http://server/repo -u 1.5
1526 hg clone --uncompressed http://server/repo -u 1.5
1526
1527
1527 - create a repository without changesets after a particular revision::
1528 - create a repository without changesets after a particular revision::
1528
1529
1529 hg clone -r 04e544 experimental/ good/
1530 hg clone -r 04e544 experimental/ good/
1530
1531
1531 - clone (and track) a particular named branch::
1532 - clone (and track) a particular named branch::
1532
1533
1533 hg clone https://www.mercurial-scm.org/repo/hg/#stable
1534 hg clone https://www.mercurial-scm.org/repo/hg/#stable
1534
1535
1535 See :hg:`help urls` for details on specifying URLs.
1536 See :hg:`help urls` for details on specifying URLs.
1536
1537
1537 Returns 0 on success.
1538 Returns 0 on success.
1538 """
1539 """
1539 if opts.get('noupdate') and opts.get('updaterev'):
1540 if opts.get('noupdate') and opts.get('updaterev'):
1540 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1541 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1541
1542
1542 r = hg.clone(ui, opts, source, dest,
1543 r = hg.clone(ui, opts, source, dest,
1543 pull=opts.get('pull'),
1544 pull=opts.get('pull'),
1544 stream=opts.get('uncompressed'),
1545 stream=opts.get('uncompressed'),
1545 rev=opts.get('rev'),
1546 rev=opts.get('rev'),
1546 update=opts.get('updaterev') or not opts.get('noupdate'),
1547 update=opts.get('updaterev') or not opts.get('noupdate'),
1547 branch=opts.get('branch'),
1548 branch=opts.get('branch'),
1548 shareopts=opts.get('shareopts'))
1549 shareopts=opts.get('shareopts'))
1549
1550
1550 return r is None
1551 return r is None
1551
1552
1552 @command('^commit|ci',
1553 @command('^commit|ci',
1553 [('A', 'addremove', None,
1554 [('A', 'addremove', None,
1554 _('mark new/missing files as added/removed before committing')),
1555 _('mark new/missing files as added/removed before committing')),
1555 ('', 'close-branch', None,
1556 ('', 'close-branch', None,
1556 _('mark a branch head as closed')),
1557 _('mark a branch head as closed')),
1557 ('', 'amend', None, _('amend the parent of the working directory')),
1558 ('', 'amend', None, _('amend the parent of the working directory')),
1558 ('s', 'secret', None, _('use the secret phase for committing')),
1559 ('s', 'secret', None, _('use the secret phase for committing')),
1559 ('e', 'edit', None, _('invoke editor on commit messages')),
1560 ('e', 'edit', None, _('invoke editor on commit messages')),
1560 ('i', 'interactive', None, _('use interactive mode')),
1561 ('i', 'interactive', None, _('use interactive mode')),
1561 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1562 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1562 _('[OPTION]... [FILE]...'),
1563 _('[OPTION]... [FILE]...'),
1563 inferrepo=True)
1564 inferrepo=True)
1564 def commit(ui, repo, *pats, **opts):
1565 def commit(ui, repo, *pats, **opts):
1565 """commit the specified files or all outstanding changes
1566 """commit the specified files or all outstanding changes
1566
1567
1567 Commit changes to the given files into the repository. Unlike a
1568 Commit changes to the given files into the repository. Unlike a
1568 centralized SCM, this operation is a local operation. See
1569 centralized SCM, this operation is a local operation. See
1569 :hg:`push` for a way to actively distribute your changes.
1570 :hg:`push` for a way to actively distribute your changes.
1570
1571
1571 If a list of files is omitted, all changes reported by :hg:`status`
1572 If a list of files is omitted, all changes reported by :hg:`status`
1572 will be committed.
1573 will be committed.
1573
1574
1574 If you are committing the result of a merge, do not provide any
1575 If you are committing the result of a merge, do not provide any
1575 filenames or -I/-X filters.
1576 filenames or -I/-X filters.
1576
1577
1577 If no commit message is specified, Mercurial starts your
1578 If no commit message is specified, Mercurial starts your
1578 configured editor where you can enter a message. In case your
1579 configured editor where you can enter a message. In case your
1579 commit fails, you will find a backup of your message in
1580 commit fails, you will find a backup of your message in
1580 ``.hg/last-message.txt``.
1581 ``.hg/last-message.txt``.
1581
1582
1582 The --close-branch flag can be used to mark the current branch
1583 The --close-branch flag can be used to mark the current branch
1583 head closed. When all heads of a branch are closed, the branch
1584 head closed. When all heads of a branch are closed, the branch
1584 will be considered closed and no longer listed.
1585 will be considered closed and no longer listed.
1585
1586
1586 The --amend flag can be used to amend the parent of the
1587 The --amend flag can be used to amend the parent of the
1587 working directory with a new commit that contains the changes
1588 working directory with a new commit that contains the changes
1588 in the parent in addition to those currently reported by :hg:`status`,
1589 in the parent in addition to those currently reported by :hg:`status`,
1589 if there are any. The old commit is stored in a backup bundle in
1590 if there are any. The old commit is stored in a backup bundle in
1590 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1591 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1591 on how to restore it).
1592 on how to restore it).
1592
1593
1593 Message, user and date are taken from the amended commit unless
1594 Message, user and date are taken from the amended commit unless
1594 specified. When a message isn't specified on the command line,
1595 specified. When a message isn't specified on the command line,
1595 the editor will open with the message of the amended commit.
1596 the editor will open with the message of the amended commit.
1596
1597
1597 It is not possible to amend public changesets (see :hg:`help phases`)
1598 It is not possible to amend public changesets (see :hg:`help phases`)
1598 or changesets that have children.
1599 or changesets that have children.
1599
1600
1600 See :hg:`help dates` for a list of formats valid for -d/--date.
1601 See :hg:`help dates` for a list of formats valid for -d/--date.
1601
1602
1602 Returns 0 on success, 1 if nothing changed.
1603 Returns 0 on success, 1 if nothing changed.
1603
1604
1604 .. container:: verbose
1605 .. container:: verbose
1605
1606
1606 Examples:
1607 Examples:
1607
1608
1608 - commit all files ending in .py::
1609 - commit all files ending in .py::
1609
1610
1610 hg commit --include "set:**.py"
1611 hg commit --include "set:**.py"
1611
1612
1612 - commit all non-binary files::
1613 - commit all non-binary files::
1613
1614
1614 hg commit --exclude "set:binary()"
1615 hg commit --exclude "set:binary()"
1615
1616
1616 - amend the current commit and set the date to now::
1617 - amend the current commit and set the date to now::
1617
1618
1618 hg commit --amend --date now
1619 hg commit --amend --date now
1619 """
1620 """
1620 wlock = lock = None
1621 wlock = lock = None
1621 try:
1622 try:
1622 wlock = repo.wlock()
1623 wlock = repo.wlock()
1623 lock = repo.lock()
1624 lock = repo.lock()
1624 return _docommit(ui, repo, *pats, **opts)
1625 return _docommit(ui, repo, *pats, **opts)
1625 finally:
1626 finally:
1626 release(lock, wlock)
1627 release(lock, wlock)
1627
1628
1628 def _docommit(ui, repo, *pats, **opts):
1629 def _docommit(ui, repo, *pats, **opts):
1629 if opts.get('interactive'):
1630 if opts.get('interactive'):
1630 opts.pop('interactive')
1631 opts.pop('interactive')
1631 ret = cmdutil.dorecord(ui, repo, commit, None, False,
1632 ret = cmdutil.dorecord(ui, repo, commit, None, False,
1632 cmdutil.recordfilter, *pats, **opts)
1633 cmdutil.recordfilter, *pats, **opts)
1633 # ret can be 0 (no changes to record) or the value returned by
1634 # ret can be 0 (no changes to record) or the value returned by
1634 # commit(), 1 if nothing changed or None on success.
1635 # commit(), 1 if nothing changed or None on success.
1635 return 1 if ret == 0 else ret
1636 return 1 if ret == 0 else ret
1636
1637
1637 if opts.get('subrepos'):
1638 if opts.get('subrepos'):
1638 if opts.get('amend'):
1639 if opts.get('amend'):
1639 raise error.Abort(_('cannot amend with --subrepos'))
1640 raise error.Abort(_('cannot amend with --subrepos'))
1640 # Let --subrepos on the command line override config setting.
1641 # Let --subrepos on the command line override config setting.
1641 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1642 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1642
1643
1643 cmdutil.checkunfinished(repo, commit=True)
1644 cmdutil.checkunfinished(repo, commit=True)
1644
1645
1645 branch = repo[None].branch()
1646 branch = repo[None].branch()
1646 bheads = repo.branchheads(branch)
1647 bheads = repo.branchheads(branch)
1647
1648
1648 extra = {}
1649 extra = {}
1649 if opts.get('close_branch'):
1650 if opts.get('close_branch'):
1650 extra['close'] = 1
1651 extra['close'] = 1
1651
1652
1652 if not bheads:
1653 if not bheads:
1653 raise error.Abort(_('can only close branch heads'))
1654 raise error.Abort(_('can only close branch heads'))
1654 elif opts.get('amend'):
1655 elif opts.get('amend'):
1655 if repo[None].parents()[0].p1().branch() != branch and \
1656 if repo[None].parents()[0].p1().branch() != branch and \
1656 repo[None].parents()[0].p2().branch() != branch:
1657 repo[None].parents()[0].p2().branch() != branch:
1657 raise error.Abort(_('can only close branch heads'))
1658 raise error.Abort(_('can only close branch heads'))
1658
1659
1659 if opts.get('amend'):
1660 if opts.get('amend'):
1660 if ui.configbool('ui', 'commitsubrepos'):
1661 if ui.configbool('ui', 'commitsubrepos'):
1661 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1662 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1662
1663
1663 old = repo['.']
1664 old = repo['.']
1664 if not old.mutable():
1665 if not old.mutable():
1665 raise error.Abort(_('cannot amend public changesets'))
1666 raise error.Abort(_('cannot amend public changesets'))
1666 if len(repo[None].parents()) > 1:
1667 if len(repo[None].parents()) > 1:
1667 raise error.Abort(_('cannot amend while merging'))
1668 raise error.Abort(_('cannot amend while merging'))
1668 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1669 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1669 if not allowunstable and old.children():
1670 if not allowunstable and old.children():
1670 raise error.Abort(_('cannot amend changeset with children'))
1671 raise error.Abort(_('cannot amend changeset with children'))
1671
1672
1672 # Currently histedit gets confused if an amend happens while histedit
1673 # Currently histedit gets confused if an amend happens while histedit
1673 # is in progress. Since we have a checkunfinished command, we are
1674 # is in progress. Since we have a checkunfinished command, we are
1674 # temporarily honoring it.
1675 # temporarily honoring it.
1675 #
1676 #
1676 # Note: eventually this guard will be removed. Please do not expect
1677 # Note: eventually this guard will be removed. Please do not expect
1677 # this behavior to remain.
1678 # this behavior to remain.
1678 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
1679 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
1679 cmdutil.checkunfinished(repo)
1680 cmdutil.checkunfinished(repo)
1680
1681
1681 # commitfunc is used only for temporary amend commit by cmdutil.amend
1682 # commitfunc is used only for temporary amend commit by cmdutil.amend
1682 def commitfunc(ui, repo, message, match, opts):
1683 def commitfunc(ui, repo, message, match, opts):
1683 return repo.commit(message,
1684 return repo.commit(message,
1684 opts.get('user') or old.user(),
1685 opts.get('user') or old.user(),
1685 opts.get('date') or old.date(),
1686 opts.get('date') or old.date(),
1686 match,
1687 match,
1687 extra=extra)
1688 extra=extra)
1688
1689
1689 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1690 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1690 if node == old.node():
1691 if node == old.node():
1691 ui.status(_("nothing changed\n"))
1692 ui.status(_("nothing changed\n"))
1692 return 1
1693 return 1
1693 else:
1694 else:
1694 def commitfunc(ui, repo, message, match, opts):
1695 def commitfunc(ui, repo, message, match, opts):
1695 backup = ui.backupconfig('phases', 'new-commit')
1696 backup = ui.backupconfig('phases', 'new-commit')
1696 baseui = repo.baseui
1697 baseui = repo.baseui
1697 basebackup = baseui.backupconfig('phases', 'new-commit')
1698 basebackup = baseui.backupconfig('phases', 'new-commit')
1698 try:
1699 try:
1699 if opts.get('secret'):
1700 if opts.get('secret'):
1700 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1701 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1701 # Propagate to subrepos
1702 # Propagate to subrepos
1702 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1703 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1703
1704
1704 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1705 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1705 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1706 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1706 return repo.commit(message, opts.get('user'), opts.get('date'),
1707 return repo.commit(message, opts.get('user'), opts.get('date'),
1707 match,
1708 match,
1708 editor=editor,
1709 editor=editor,
1709 extra=extra)
1710 extra=extra)
1710 finally:
1711 finally:
1711 ui.restoreconfig(backup)
1712 ui.restoreconfig(backup)
1712 repo.baseui.restoreconfig(basebackup)
1713 repo.baseui.restoreconfig(basebackup)
1713
1714
1714
1715
1715 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1716 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1716
1717
1717 if not node:
1718 if not node:
1718 stat = cmdutil.postcommitstatus(repo, pats, opts)
1719 stat = cmdutil.postcommitstatus(repo, pats, opts)
1719 if stat[3]:
1720 if stat[3]:
1720 ui.status(_("nothing changed (%d missing files, see "
1721 ui.status(_("nothing changed (%d missing files, see "
1721 "'hg status')\n") % len(stat[3]))
1722 "'hg status')\n") % len(stat[3]))
1722 else:
1723 else:
1723 ui.status(_("nothing changed\n"))
1724 ui.status(_("nothing changed\n"))
1724 return 1
1725 return 1
1725
1726
1726 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1727 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1727
1728
1728 @command('config|showconfig|debugconfig',
1729 @command('config|showconfig|debugconfig',
1729 [('u', 'untrusted', None, _('show untrusted configuration options')),
1730 [('u', 'untrusted', None, _('show untrusted configuration options')),
1730 ('e', 'edit', None, _('edit user config')),
1731 ('e', 'edit', None, _('edit user config')),
1731 ('l', 'local', None, _('edit repository config')),
1732 ('l', 'local', None, _('edit repository config')),
1732 ('g', 'global', None, _('edit global config'))] + formatteropts,
1733 ('g', 'global', None, _('edit global config'))] + formatteropts,
1733 _('[-u] [NAME]...'),
1734 _('[-u] [NAME]...'),
1734 optionalrepo=True)
1735 optionalrepo=True)
1735 def config(ui, repo, *values, **opts):
1736 def config(ui, repo, *values, **opts):
1736 """show combined config settings from all hgrc files
1737 """show combined config settings from all hgrc files
1737
1738
1738 With no arguments, print names and values of all config items.
1739 With no arguments, print names and values of all config items.
1739
1740
1740 With one argument of the form section.name, print just the value
1741 With one argument of the form section.name, print just the value
1741 of that config item.
1742 of that config item.
1742
1743
1743 With multiple arguments, print names and values of all config
1744 With multiple arguments, print names and values of all config
1744 items with matching section names.
1745 items with matching section names.
1745
1746
1746 With --edit, start an editor on the user-level config file. With
1747 With --edit, start an editor on the user-level config file. With
1747 --global, edit the system-wide config file. With --local, edit the
1748 --global, edit the system-wide config file. With --local, edit the
1748 repository-level config file.
1749 repository-level config file.
1749
1750
1750 With --debug, the source (filename and line number) is printed
1751 With --debug, the source (filename and line number) is printed
1751 for each config item.
1752 for each config item.
1752
1753
1753 See :hg:`help config` for more information about config files.
1754 See :hg:`help config` for more information about config files.
1754
1755
1755 Returns 0 on success, 1 if NAME does not exist.
1756 Returns 0 on success, 1 if NAME does not exist.
1756
1757
1757 """
1758 """
1758
1759
1759 if opts.get('edit') or opts.get('local') or opts.get('global'):
1760 if opts.get('edit') or opts.get('local') or opts.get('global'):
1760 if opts.get('local') and opts.get('global'):
1761 if opts.get('local') and opts.get('global'):
1761 raise error.Abort(_("can't use --local and --global together"))
1762 raise error.Abort(_("can't use --local and --global together"))
1762
1763
1763 if opts.get('local'):
1764 if opts.get('local'):
1764 if not repo:
1765 if not repo:
1765 raise error.Abort(_("can't use --local outside a repository"))
1766 raise error.Abort(_("can't use --local outside a repository"))
1766 paths = [repo.join('hgrc')]
1767 paths = [repo.join('hgrc')]
1767 elif opts.get('global'):
1768 elif opts.get('global'):
1768 paths = scmutil.systemrcpath()
1769 paths = scmutil.systemrcpath()
1769 else:
1770 else:
1770 paths = scmutil.userrcpath()
1771 paths = scmutil.userrcpath()
1771
1772
1772 for f in paths:
1773 for f in paths:
1773 if os.path.exists(f):
1774 if os.path.exists(f):
1774 break
1775 break
1775 else:
1776 else:
1776 if opts.get('global'):
1777 if opts.get('global'):
1777 samplehgrc = uimod.samplehgrcs['global']
1778 samplehgrc = uimod.samplehgrcs['global']
1778 elif opts.get('local'):
1779 elif opts.get('local'):
1779 samplehgrc = uimod.samplehgrcs['local']
1780 samplehgrc = uimod.samplehgrcs['local']
1780 else:
1781 else:
1781 samplehgrc = uimod.samplehgrcs['user']
1782 samplehgrc = uimod.samplehgrcs['user']
1782
1783
1783 f = paths[0]
1784 f = paths[0]
1784 fp = open(f, "w")
1785 fp = open(f, "w")
1785 fp.write(samplehgrc)
1786 fp.write(samplehgrc)
1786 fp.close()
1787 fp.close()
1787
1788
1788 editor = ui.geteditor()
1789 editor = ui.geteditor()
1789 ui.system("%s \"%s\"" % (editor, f),
1790 ui.system("%s \"%s\"" % (editor, f),
1790 onerr=error.Abort, errprefix=_("edit failed"))
1791 onerr=error.Abort, errprefix=_("edit failed"))
1791 return
1792 return
1792
1793
1793 fm = ui.formatter('config', opts)
1794 fm = ui.formatter('config', opts)
1794 for f in scmutil.rcpath():
1795 for f in scmutil.rcpath():
1795 ui.debug('read config from: %s\n' % f)
1796 ui.debug('read config from: %s\n' % f)
1796 untrusted = bool(opts.get('untrusted'))
1797 untrusted = bool(opts.get('untrusted'))
1797 if values:
1798 if values:
1798 sections = [v for v in values if '.' not in v]
1799 sections = [v for v in values if '.' not in v]
1799 items = [v for v in values if '.' in v]
1800 items = [v for v in values if '.' in v]
1800 if len(items) > 1 or items and sections:
1801 if len(items) > 1 or items and sections:
1801 raise error.Abort(_('only one config item permitted'))
1802 raise error.Abort(_('only one config item permitted'))
1802 matched = False
1803 matched = False
1803 for section, name, value in ui.walkconfig(untrusted=untrusted):
1804 for section, name, value in ui.walkconfig(untrusted=untrusted):
1804 source = ui.configsource(section, name, untrusted)
1805 source = ui.configsource(section, name, untrusted)
1805 value = str(value)
1806 value = str(value)
1806 if fm.isplain():
1807 if fm.isplain():
1807 source = source or 'none'
1808 source = source or 'none'
1808 value = value.replace('\n', '\\n')
1809 value = value.replace('\n', '\\n')
1809 entryname = section + '.' + name
1810 entryname = section + '.' + name
1810 if values:
1811 if values:
1811 for v in values:
1812 for v in values:
1812 if v == section:
1813 if v == section:
1813 fm.startitem()
1814 fm.startitem()
1814 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1815 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1815 fm.write('name value', '%s=%s\n', entryname, value)
1816 fm.write('name value', '%s=%s\n', entryname, value)
1816 matched = True
1817 matched = True
1817 elif v == entryname:
1818 elif v == entryname:
1818 fm.startitem()
1819 fm.startitem()
1819 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1820 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1820 fm.write('value', '%s\n', value)
1821 fm.write('value', '%s\n', value)
1821 fm.data(name=entryname)
1822 fm.data(name=entryname)
1822 matched = True
1823 matched = True
1823 else:
1824 else:
1824 fm.startitem()
1825 fm.startitem()
1825 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1826 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1826 fm.write('name value', '%s=%s\n', entryname, value)
1827 fm.write('name value', '%s=%s\n', entryname, value)
1827 matched = True
1828 matched = True
1828 fm.end()
1829 fm.end()
1829 if matched:
1830 if matched:
1830 return 0
1831 return 0
1831 return 1
1832 return 1
1832
1833
1833 @command('copy|cp',
1834 @command('copy|cp',
1834 [('A', 'after', None, _('record a copy that has already occurred')),
1835 [('A', 'after', None, _('record a copy that has already occurred')),
1835 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1836 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1836 ] + walkopts + dryrunopts,
1837 ] + walkopts + dryrunopts,
1837 _('[OPTION]... [SOURCE]... DEST'))
1838 _('[OPTION]... [SOURCE]... DEST'))
1838 def copy(ui, repo, *pats, **opts):
1839 def copy(ui, repo, *pats, **opts):
1839 """mark files as copied for the next commit
1840 """mark files as copied for the next commit
1840
1841
1841 Mark dest as having copies of source files. If dest is a
1842 Mark dest as having copies of source files. If dest is a
1842 directory, copies are put in that directory. If dest is a file,
1843 directory, copies are put in that directory. If dest is a file,
1843 the source must be a single file.
1844 the source must be a single file.
1844
1845
1845 By default, this command copies the contents of files as they
1846 By default, this command copies the contents of files as they
1846 exist in the working directory. If invoked with -A/--after, the
1847 exist in the working directory. If invoked with -A/--after, the
1847 operation is recorded, but no copying is performed.
1848 operation is recorded, but no copying is performed.
1848
1849
1849 This command takes effect with the next commit. To undo a copy
1850 This command takes effect with the next commit. To undo a copy
1850 before that, see :hg:`revert`.
1851 before that, see :hg:`revert`.
1851
1852
1852 Returns 0 on success, 1 if errors are encountered.
1853 Returns 0 on success, 1 if errors are encountered.
1853 """
1854 """
1854 with repo.wlock(False):
1855 with repo.wlock(False):
1855 return cmdutil.copy(ui, repo, pats, opts)
1856 return cmdutil.copy(ui, repo, pats, opts)
1856
1857
1857 @command('^diff',
1858 @command('^diff',
1858 [('r', 'rev', [], _('revision'), _('REV')),
1859 [('r', 'rev', [], _('revision'), _('REV')),
1859 ('c', 'change', '', _('change made by revision'), _('REV'))
1860 ('c', 'change', '', _('change made by revision'), _('REV'))
1860 ] + diffopts + diffopts2 + walkopts + subrepoopts,
1861 ] + diffopts + diffopts2 + walkopts + subrepoopts,
1861 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
1862 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
1862 inferrepo=True)
1863 inferrepo=True)
1863 def diff(ui, repo, *pats, **opts):
1864 def diff(ui, repo, *pats, **opts):
1864 """diff repository (or selected files)
1865 """diff repository (or selected files)
1865
1866
1866 Show differences between revisions for the specified files.
1867 Show differences between revisions for the specified files.
1867
1868
1868 Differences between files are shown using the unified diff format.
1869 Differences between files are shown using the unified diff format.
1869
1870
1870 .. note::
1871 .. note::
1871
1872
1872 :hg:`diff` may generate unexpected results for merges, as it will
1873 :hg:`diff` may generate unexpected results for merges, as it will
1873 default to comparing against the working directory's first
1874 default to comparing against the working directory's first
1874 parent changeset if no revisions are specified.
1875 parent changeset if no revisions are specified.
1875
1876
1876 When two revision arguments are given, then changes are shown
1877 When two revision arguments are given, then changes are shown
1877 between those revisions. If only one revision is specified then
1878 between those revisions. If only one revision is specified then
1878 that revision is compared to the working directory, and, when no
1879 that revision is compared to the working directory, and, when no
1879 revisions are specified, the working directory files are compared
1880 revisions are specified, the working directory files are compared
1880 to its first parent.
1881 to its first parent.
1881
1882
1882 Alternatively you can specify -c/--change with a revision to see
1883 Alternatively you can specify -c/--change with a revision to see
1883 the changes in that changeset relative to its first parent.
1884 the changes in that changeset relative to its first parent.
1884
1885
1885 Without the -a/--text option, diff will avoid generating diffs of
1886 Without the -a/--text option, diff will avoid generating diffs of
1886 files it detects as binary. With -a, diff will generate a diff
1887 files it detects as binary. With -a, diff will generate a diff
1887 anyway, probably with undesirable results.
1888 anyway, probably with undesirable results.
1888
1889
1889 Use the -g/--git option to generate diffs in the git extended diff
1890 Use the -g/--git option to generate diffs in the git extended diff
1890 format. For more information, read :hg:`help diffs`.
1891 format. For more information, read :hg:`help diffs`.
1891
1892
1892 .. container:: verbose
1893 .. container:: verbose
1893
1894
1894 Examples:
1895 Examples:
1895
1896
1896 - compare a file in the current working directory to its parent::
1897 - compare a file in the current working directory to its parent::
1897
1898
1898 hg diff foo.c
1899 hg diff foo.c
1899
1900
1900 - compare two historical versions of a directory, with rename info::
1901 - compare two historical versions of a directory, with rename info::
1901
1902
1902 hg diff --git -r 1.0:1.2 lib/
1903 hg diff --git -r 1.0:1.2 lib/
1903
1904
1904 - get change stats relative to the last change on some date::
1905 - get change stats relative to the last change on some date::
1905
1906
1906 hg diff --stat -r "date('may 2')"
1907 hg diff --stat -r "date('may 2')"
1907
1908
1908 - diff all newly-added files that contain a keyword::
1909 - diff all newly-added files that contain a keyword::
1909
1910
1910 hg diff "set:added() and grep(GNU)"
1911 hg diff "set:added() and grep(GNU)"
1911
1912
1912 - compare a revision and its parents::
1913 - compare a revision and its parents::
1913
1914
1914 hg diff -c 9353 # compare against first parent
1915 hg diff -c 9353 # compare against first parent
1915 hg diff -r 9353^:9353 # same using revset syntax
1916 hg diff -r 9353^:9353 # same using revset syntax
1916 hg diff -r 9353^2:9353 # compare against the second parent
1917 hg diff -r 9353^2:9353 # compare against the second parent
1917
1918
1918 Returns 0 on success.
1919 Returns 0 on success.
1919 """
1920 """
1920
1921
1921 revs = opts.get('rev')
1922 revs = opts.get('rev')
1922 change = opts.get('change')
1923 change = opts.get('change')
1923 stat = opts.get('stat')
1924 stat = opts.get('stat')
1924 reverse = opts.get('reverse')
1925 reverse = opts.get('reverse')
1925
1926
1926 if revs and change:
1927 if revs and change:
1927 msg = _('cannot specify --rev and --change at the same time')
1928 msg = _('cannot specify --rev and --change at the same time')
1928 raise error.Abort(msg)
1929 raise error.Abort(msg)
1929 elif change:
1930 elif change:
1930 node2 = scmutil.revsingle(repo, change, None).node()
1931 node2 = scmutil.revsingle(repo, change, None).node()
1931 node1 = repo[node2].p1().node()
1932 node1 = repo[node2].p1().node()
1932 else:
1933 else:
1933 node1, node2 = scmutil.revpair(repo, revs)
1934 node1, node2 = scmutil.revpair(repo, revs)
1934
1935
1935 if reverse:
1936 if reverse:
1936 node1, node2 = node2, node1
1937 node1, node2 = node2, node1
1937
1938
1938 diffopts = patch.diffallopts(ui, opts)
1939 diffopts = patch.diffallopts(ui, opts)
1939 m = scmutil.match(repo[node2], pats, opts)
1940 m = scmutil.match(repo[node2], pats, opts)
1940 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
1941 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
1941 listsubrepos=opts.get('subrepos'),
1942 listsubrepos=opts.get('subrepos'),
1942 root=opts.get('root'))
1943 root=opts.get('root'))
1943
1944
1944 @command('^export',
1945 @command('^export',
1945 [('o', 'output', '',
1946 [('o', 'output', '',
1946 _('print output to file with formatted name'), _('FORMAT')),
1947 _('print output to file with formatted name'), _('FORMAT')),
1947 ('', 'switch-parent', None, _('diff against the second parent')),
1948 ('', 'switch-parent', None, _('diff against the second parent')),
1948 ('r', 'rev', [], _('revisions to export'), _('REV')),
1949 ('r', 'rev', [], _('revisions to export'), _('REV')),
1949 ] + diffopts,
1950 ] + diffopts,
1950 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
1951 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
1951 def export(ui, repo, *changesets, **opts):
1952 def export(ui, repo, *changesets, **opts):
1952 """dump the header and diffs for one or more changesets
1953 """dump the header and diffs for one or more changesets
1953
1954
1954 Print the changeset header and diffs for one or more revisions.
1955 Print the changeset header and diffs for one or more revisions.
1955 If no revision is given, the parent of the working directory is used.
1956 If no revision is given, the parent of the working directory is used.
1956
1957
1957 The information shown in the changeset header is: author, date,
1958 The information shown in the changeset header is: author, date,
1958 branch name (if non-default), changeset hash, parent(s) and commit
1959 branch name (if non-default), changeset hash, parent(s) and commit
1959 comment.
1960 comment.
1960
1961
1961 .. note::
1962 .. note::
1962
1963
1963 :hg:`export` may generate unexpected diff output for merge
1964 :hg:`export` may generate unexpected diff output for merge
1964 changesets, as it will compare the merge changeset against its
1965 changesets, as it will compare the merge changeset against its
1965 first parent only.
1966 first parent only.
1966
1967
1967 Output may be to a file, in which case the name of the file is
1968 Output may be to a file, in which case the name of the file is
1968 given using a format string. The formatting rules are as follows:
1969 given using a format string. The formatting rules are as follows:
1969
1970
1970 :``%%``: literal "%" character
1971 :``%%``: literal "%" character
1971 :``%H``: changeset hash (40 hexadecimal digits)
1972 :``%H``: changeset hash (40 hexadecimal digits)
1972 :``%N``: number of patches being generated
1973 :``%N``: number of patches being generated
1973 :``%R``: changeset revision number
1974 :``%R``: changeset revision number
1974 :``%b``: basename of the exporting repository
1975 :``%b``: basename of the exporting repository
1975 :``%h``: short-form changeset hash (12 hexadecimal digits)
1976 :``%h``: short-form changeset hash (12 hexadecimal digits)
1976 :``%m``: first line of the commit message (only alphanumeric characters)
1977 :``%m``: first line of the commit message (only alphanumeric characters)
1977 :``%n``: zero-padded sequence number, starting at 1
1978 :``%n``: zero-padded sequence number, starting at 1
1978 :``%r``: zero-padded changeset revision number
1979 :``%r``: zero-padded changeset revision number
1979
1980
1980 Without the -a/--text option, export will avoid generating diffs
1981 Without the -a/--text option, export will avoid generating diffs
1981 of files it detects as binary. With -a, export will generate a
1982 of files it detects as binary. With -a, export will generate a
1982 diff anyway, probably with undesirable results.
1983 diff anyway, probably with undesirable results.
1983
1984
1984 Use the -g/--git option to generate diffs in the git extended diff
1985 Use the -g/--git option to generate diffs in the git extended diff
1985 format. See :hg:`help diffs` for more information.
1986 format. See :hg:`help diffs` for more information.
1986
1987
1987 With the --switch-parent option, the diff will be against the
1988 With the --switch-parent option, the diff will be against the
1988 second parent. It can be useful to review a merge.
1989 second parent. It can be useful to review a merge.
1989
1990
1990 .. container:: verbose
1991 .. container:: verbose
1991
1992
1992 Examples:
1993 Examples:
1993
1994
1994 - use export and import to transplant a bugfix to the current
1995 - use export and import to transplant a bugfix to the current
1995 branch::
1996 branch::
1996
1997
1997 hg export -r 9353 | hg import -
1998 hg export -r 9353 | hg import -
1998
1999
1999 - export all the changesets between two revisions to a file with
2000 - export all the changesets between two revisions to a file with
2000 rename information::
2001 rename information::
2001
2002
2002 hg export --git -r 123:150 > changes.txt
2003 hg export --git -r 123:150 > changes.txt
2003
2004
2004 - split outgoing changes into a series of patches with
2005 - split outgoing changes into a series of patches with
2005 descriptive names::
2006 descriptive names::
2006
2007
2007 hg export -r "outgoing()" -o "%n-%m.patch"
2008 hg export -r "outgoing()" -o "%n-%m.patch"
2008
2009
2009 Returns 0 on success.
2010 Returns 0 on success.
2010 """
2011 """
2011 changesets += tuple(opts.get('rev', []))
2012 changesets += tuple(opts.get('rev', []))
2012 if not changesets:
2013 if not changesets:
2013 changesets = ['.']
2014 changesets = ['.']
2014 revs = scmutil.revrange(repo, changesets)
2015 revs = scmutil.revrange(repo, changesets)
2015 if not revs:
2016 if not revs:
2016 raise error.Abort(_("export requires at least one changeset"))
2017 raise error.Abort(_("export requires at least one changeset"))
2017 if len(revs) > 1:
2018 if len(revs) > 1:
2018 ui.note(_('exporting patches:\n'))
2019 ui.note(_('exporting patches:\n'))
2019 else:
2020 else:
2020 ui.note(_('exporting patch:\n'))
2021 ui.note(_('exporting patch:\n'))
2021 cmdutil.export(repo, revs, template=opts.get('output'),
2022 cmdutil.export(repo, revs, template=opts.get('output'),
2022 switch_parent=opts.get('switch_parent'),
2023 switch_parent=opts.get('switch_parent'),
2023 opts=patch.diffallopts(ui, opts))
2024 opts=patch.diffallopts(ui, opts))
2024
2025
2025 @command('files',
2026 @command('files',
2026 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
2027 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
2027 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
2028 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
2028 ] + walkopts + formatteropts + subrepoopts,
2029 ] + walkopts + formatteropts + subrepoopts,
2029 _('[OPTION]... [FILE]...'))
2030 _('[OPTION]... [FILE]...'))
2030 def files(ui, repo, *pats, **opts):
2031 def files(ui, repo, *pats, **opts):
2031 """list tracked files
2032 """list tracked files
2032
2033
2033 Print files under Mercurial control in the working directory or
2034 Print files under Mercurial control in the working directory or
2034 specified revision for given files (excluding removed files).
2035 specified revision for given files (excluding removed files).
2035 Files can be specified as filenames or filesets.
2036 Files can be specified as filenames or filesets.
2036
2037
2037 If no files are given to match, this command prints the names
2038 If no files are given to match, this command prints the names
2038 of all files under Mercurial control.
2039 of all files under Mercurial control.
2039
2040
2040 .. container:: verbose
2041 .. container:: verbose
2041
2042
2042 Examples:
2043 Examples:
2043
2044
2044 - list all files under the current directory::
2045 - list all files under the current directory::
2045
2046
2046 hg files .
2047 hg files .
2047
2048
2048 - shows sizes and flags for current revision::
2049 - shows sizes and flags for current revision::
2049
2050
2050 hg files -vr .
2051 hg files -vr .
2051
2052
2052 - list all files named README::
2053 - list all files named README::
2053
2054
2054 hg files -I "**/README"
2055 hg files -I "**/README"
2055
2056
2056 - list all binary files::
2057 - list all binary files::
2057
2058
2058 hg files "set:binary()"
2059 hg files "set:binary()"
2059
2060
2060 - find files containing a regular expression::
2061 - find files containing a regular expression::
2061
2062
2062 hg files "set:grep('bob')"
2063 hg files "set:grep('bob')"
2063
2064
2064 - search tracked file contents with xargs and grep::
2065 - search tracked file contents with xargs and grep::
2065
2066
2066 hg files -0 | xargs -0 grep foo
2067 hg files -0 | xargs -0 grep foo
2067
2068
2068 See :hg:`help patterns` and :hg:`help filesets` for more information
2069 See :hg:`help patterns` and :hg:`help filesets` for more information
2069 on specifying file patterns.
2070 on specifying file patterns.
2070
2071
2071 Returns 0 if a match is found, 1 otherwise.
2072 Returns 0 if a match is found, 1 otherwise.
2072
2073
2073 """
2074 """
2074 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2075 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2075
2076
2076 end = '\n'
2077 end = '\n'
2077 if opts.get('print0'):
2078 if opts.get('print0'):
2078 end = '\0'
2079 end = '\0'
2079 fmt = '%s' + end
2080 fmt = '%s' + end
2080
2081
2081 m = scmutil.match(ctx, pats, opts)
2082 m = scmutil.match(ctx, pats, opts)
2082 with ui.formatter('files', opts) as fm:
2083 with ui.formatter('files', opts) as fm:
2083 return cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
2084 return cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
2084
2085
2085 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
2086 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
2086 def forget(ui, repo, *pats, **opts):
2087 def forget(ui, repo, *pats, **opts):
2087 """forget the specified files on the next commit
2088 """forget the specified files on the next commit
2088
2089
2089 Mark the specified files so they will no longer be tracked
2090 Mark the specified files so they will no longer be tracked
2090 after the next commit.
2091 after the next commit.
2091
2092
2092 This only removes files from the current branch, not from the
2093 This only removes files from the current branch, not from the
2093 entire project history, and it does not delete them from the
2094 entire project history, and it does not delete them from the
2094 working directory.
2095 working directory.
2095
2096
2096 To delete the file from the working directory, see :hg:`remove`.
2097 To delete the file from the working directory, see :hg:`remove`.
2097
2098
2098 To undo a forget before the next commit, see :hg:`add`.
2099 To undo a forget before the next commit, see :hg:`add`.
2099
2100
2100 .. container:: verbose
2101 .. container:: verbose
2101
2102
2102 Examples:
2103 Examples:
2103
2104
2104 - forget newly-added binary files::
2105 - forget newly-added binary files::
2105
2106
2106 hg forget "set:added() and binary()"
2107 hg forget "set:added() and binary()"
2107
2108
2108 - forget files that would be excluded by .hgignore::
2109 - forget files that would be excluded by .hgignore::
2109
2110
2110 hg forget "set:hgignore()"
2111 hg forget "set:hgignore()"
2111
2112
2112 Returns 0 on success.
2113 Returns 0 on success.
2113 """
2114 """
2114
2115
2115 if not pats:
2116 if not pats:
2116 raise error.Abort(_('no files specified'))
2117 raise error.Abort(_('no files specified'))
2117
2118
2118 m = scmutil.match(repo[None], pats, opts)
2119 m = scmutil.match(repo[None], pats, opts)
2119 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2120 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2120 return rejected and 1 or 0
2121 return rejected and 1 or 0
2121
2122
2122 @command(
2123 @command(
2123 'graft',
2124 'graft',
2124 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2125 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2125 ('c', 'continue', False, _('resume interrupted graft')),
2126 ('c', 'continue', False, _('resume interrupted graft')),
2126 ('e', 'edit', False, _('invoke editor on commit messages')),
2127 ('e', 'edit', False, _('invoke editor on commit messages')),
2127 ('', 'log', None, _('append graft info to log message')),
2128 ('', 'log', None, _('append graft info to log message')),
2128 ('f', 'force', False, _('force graft')),
2129 ('f', 'force', False, _('force graft')),
2129 ('D', 'currentdate', False,
2130 ('D', 'currentdate', False,
2130 _('record the current date as commit date')),
2131 _('record the current date as commit date')),
2131 ('U', 'currentuser', False,
2132 ('U', 'currentuser', False,
2132 _('record the current user as committer'), _('DATE'))]
2133 _('record the current user as committer'), _('DATE'))]
2133 + commitopts2 + mergetoolopts + dryrunopts,
2134 + commitopts2 + mergetoolopts + dryrunopts,
2134 _('[OPTION]... [-r REV]... REV...'))
2135 _('[OPTION]... [-r REV]... REV...'))
2135 def graft(ui, repo, *revs, **opts):
2136 def graft(ui, repo, *revs, **opts):
2136 '''copy changes from other branches onto the current branch
2137 '''copy changes from other branches onto the current branch
2137
2138
2138 This command uses Mercurial's merge logic to copy individual
2139 This command uses Mercurial's merge logic to copy individual
2139 changes from other branches without merging branches in the
2140 changes from other branches without merging branches in the
2140 history graph. This is sometimes known as 'backporting' or
2141 history graph. This is sometimes known as 'backporting' or
2141 'cherry-picking'. By default, graft will copy user, date, and
2142 'cherry-picking'. By default, graft will copy user, date, and
2142 description from the source changesets.
2143 description from the source changesets.
2143
2144
2144 Changesets that are ancestors of the current revision, that have
2145 Changesets that are ancestors of the current revision, that have
2145 already been grafted, or that are merges will be skipped.
2146 already been grafted, or that are merges will be skipped.
2146
2147
2147 If --log is specified, log messages will have a comment appended
2148 If --log is specified, log messages will have a comment appended
2148 of the form::
2149 of the form::
2149
2150
2150 (grafted from CHANGESETHASH)
2151 (grafted from CHANGESETHASH)
2151
2152
2152 If --force is specified, revisions will be grafted even if they
2153 If --force is specified, revisions will be grafted even if they
2153 are already ancestors of or have been grafted to the destination.
2154 are already ancestors of or have been grafted to the destination.
2154 This is useful when the revisions have since been backed out.
2155 This is useful when the revisions have since been backed out.
2155
2156
2156 If a graft merge results in conflicts, the graft process is
2157 If a graft merge results in conflicts, the graft process is
2157 interrupted so that the current merge can be manually resolved.
2158 interrupted so that the current merge can be manually resolved.
2158 Once all conflicts are addressed, the graft process can be
2159 Once all conflicts are addressed, the graft process can be
2159 continued with the -c/--continue option.
2160 continued with the -c/--continue option.
2160
2161
2161 .. note::
2162 .. note::
2162
2163
2163 The -c/--continue option does not reapply earlier options, except
2164 The -c/--continue option does not reapply earlier options, except
2164 for --force.
2165 for --force.
2165
2166
2166 .. container:: verbose
2167 .. container:: verbose
2167
2168
2168 Examples:
2169 Examples:
2169
2170
2170 - copy a single change to the stable branch and edit its description::
2171 - copy a single change to the stable branch and edit its description::
2171
2172
2172 hg update stable
2173 hg update stable
2173 hg graft --edit 9393
2174 hg graft --edit 9393
2174
2175
2175 - graft a range of changesets with one exception, updating dates::
2176 - graft a range of changesets with one exception, updating dates::
2176
2177
2177 hg graft -D "2085::2093 and not 2091"
2178 hg graft -D "2085::2093 and not 2091"
2178
2179
2179 - continue a graft after resolving conflicts::
2180 - continue a graft after resolving conflicts::
2180
2181
2181 hg graft -c
2182 hg graft -c
2182
2183
2183 - show the source of a grafted changeset::
2184 - show the source of a grafted changeset::
2184
2185
2185 hg log --debug -r .
2186 hg log --debug -r .
2186
2187
2187 - show revisions sorted by date::
2188 - show revisions sorted by date::
2188
2189
2189 hg log -r "sort(all(), date)"
2190 hg log -r "sort(all(), date)"
2190
2191
2191 See :hg:`help revisions` for more about specifying revisions.
2192 See :hg:`help revisions` for more about specifying revisions.
2192
2193
2193 Returns 0 on successful completion.
2194 Returns 0 on successful completion.
2194 '''
2195 '''
2195 with repo.wlock():
2196 with repo.wlock():
2196 return _dograft(ui, repo, *revs, **opts)
2197 return _dograft(ui, repo, *revs, **opts)
2197
2198
2198 def _dograft(ui, repo, *revs, **opts):
2199 def _dograft(ui, repo, *revs, **opts):
2199 if revs and opts.get('rev'):
2200 if revs and opts.get('rev'):
2200 ui.warn(_('warning: inconsistent use of --rev might give unexpected '
2201 ui.warn(_('warning: inconsistent use of --rev might give unexpected '
2201 'revision ordering!\n'))
2202 'revision ordering!\n'))
2202
2203
2203 revs = list(revs)
2204 revs = list(revs)
2204 revs.extend(opts.get('rev'))
2205 revs.extend(opts.get('rev'))
2205
2206
2206 if not opts.get('user') and opts.get('currentuser'):
2207 if not opts.get('user') and opts.get('currentuser'):
2207 opts['user'] = ui.username()
2208 opts['user'] = ui.username()
2208 if not opts.get('date') and opts.get('currentdate'):
2209 if not opts.get('date') and opts.get('currentdate'):
2209 opts['date'] = "%d %d" % util.makedate()
2210 opts['date'] = "%d %d" % util.makedate()
2210
2211
2211 editor = cmdutil.getcommiteditor(editform='graft', **opts)
2212 editor = cmdutil.getcommiteditor(editform='graft', **opts)
2212
2213
2213 cont = False
2214 cont = False
2214 if opts.get('continue'):
2215 if opts.get('continue'):
2215 cont = True
2216 cont = True
2216 if revs:
2217 if revs:
2217 raise error.Abort(_("can't specify --continue and revisions"))
2218 raise error.Abort(_("can't specify --continue and revisions"))
2218 # read in unfinished revisions
2219 # read in unfinished revisions
2219 try:
2220 try:
2220 nodes = repo.vfs.read('graftstate').splitlines()
2221 nodes = repo.vfs.read('graftstate').splitlines()
2221 revs = [repo[node].rev() for node in nodes]
2222 revs = [repo[node].rev() for node in nodes]
2222 except IOError as inst:
2223 except IOError as inst:
2223 if inst.errno != errno.ENOENT:
2224 if inst.errno != errno.ENOENT:
2224 raise
2225 raise
2225 cmdutil.wrongtooltocontinue(repo, _('graft'))
2226 cmdutil.wrongtooltocontinue(repo, _('graft'))
2226 else:
2227 else:
2227 cmdutil.checkunfinished(repo)
2228 cmdutil.checkunfinished(repo)
2228 cmdutil.bailifchanged(repo)
2229 cmdutil.bailifchanged(repo)
2229 if not revs:
2230 if not revs:
2230 raise error.Abort(_('no revisions specified'))
2231 raise error.Abort(_('no revisions specified'))
2231 revs = scmutil.revrange(repo, revs)
2232 revs = scmutil.revrange(repo, revs)
2232
2233
2233 skipped = set()
2234 skipped = set()
2234 # check for merges
2235 # check for merges
2235 for rev in repo.revs('%ld and merge()', revs):
2236 for rev in repo.revs('%ld and merge()', revs):
2236 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2237 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2237 skipped.add(rev)
2238 skipped.add(rev)
2238 revs = [r for r in revs if r not in skipped]
2239 revs = [r for r in revs if r not in skipped]
2239 if not revs:
2240 if not revs:
2240 return -1
2241 return -1
2241
2242
2242 # Don't check in the --continue case, in effect retaining --force across
2243 # Don't check in the --continue case, in effect retaining --force across
2243 # --continues. That's because without --force, any revisions we decided to
2244 # --continues. That's because without --force, any revisions we decided to
2244 # skip would have been filtered out here, so they wouldn't have made their
2245 # skip would have been filtered out here, so they wouldn't have made their
2245 # way to the graftstate. With --force, any revisions we would have otherwise
2246 # way to the graftstate. With --force, any revisions we would have otherwise
2246 # skipped would not have been filtered out, and if they hadn't been applied
2247 # skipped would not have been filtered out, and if they hadn't been applied
2247 # already, they'd have been in the graftstate.
2248 # already, they'd have been in the graftstate.
2248 if not (cont or opts.get('force')):
2249 if not (cont or opts.get('force')):
2249 # check for ancestors of dest branch
2250 # check for ancestors of dest branch
2250 crev = repo['.'].rev()
2251 crev = repo['.'].rev()
2251 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2252 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2252 # XXX make this lazy in the future
2253 # XXX make this lazy in the future
2253 # don't mutate while iterating, create a copy
2254 # don't mutate while iterating, create a copy
2254 for rev in list(revs):
2255 for rev in list(revs):
2255 if rev in ancestors:
2256 if rev in ancestors:
2256 ui.warn(_('skipping ancestor revision %d:%s\n') %
2257 ui.warn(_('skipping ancestor revision %d:%s\n') %
2257 (rev, repo[rev]))
2258 (rev, repo[rev]))
2258 # XXX remove on list is slow
2259 # XXX remove on list is slow
2259 revs.remove(rev)
2260 revs.remove(rev)
2260 if not revs:
2261 if not revs:
2261 return -1
2262 return -1
2262
2263
2263 # analyze revs for earlier grafts
2264 # analyze revs for earlier grafts
2264 ids = {}
2265 ids = {}
2265 for ctx in repo.set("%ld", revs):
2266 for ctx in repo.set("%ld", revs):
2266 ids[ctx.hex()] = ctx.rev()
2267 ids[ctx.hex()] = ctx.rev()
2267 n = ctx.extra().get('source')
2268 n = ctx.extra().get('source')
2268 if n:
2269 if n:
2269 ids[n] = ctx.rev()
2270 ids[n] = ctx.rev()
2270
2271
2271 # check ancestors for earlier grafts
2272 # check ancestors for earlier grafts
2272 ui.debug('scanning for duplicate grafts\n')
2273 ui.debug('scanning for duplicate grafts\n')
2273
2274
2274 for rev in repo.changelog.findmissingrevs(revs, [crev]):
2275 for rev in repo.changelog.findmissingrevs(revs, [crev]):
2275 ctx = repo[rev]
2276 ctx = repo[rev]
2276 n = ctx.extra().get('source')
2277 n = ctx.extra().get('source')
2277 if n in ids:
2278 if n in ids:
2278 try:
2279 try:
2279 r = repo[n].rev()
2280 r = repo[n].rev()
2280 except error.RepoLookupError:
2281 except error.RepoLookupError:
2281 r = None
2282 r = None
2282 if r in revs:
2283 if r in revs:
2283 ui.warn(_('skipping revision %d:%s '
2284 ui.warn(_('skipping revision %d:%s '
2284 '(already grafted to %d:%s)\n')
2285 '(already grafted to %d:%s)\n')
2285 % (r, repo[r], rev, ctx))
2286 % (r, repo[r], rev, ctx))
2286 revs.remove(r)
2287 revs.remove(r)
2287 elif ids[n] in revs:
2288 elif ids[n] in revs:
2288 if r is None:
2289 if r is None:
2289 ui.warn(_('skipping already grafted revision %d:%s '
2290 ui.warn(_('skipping already grafted revision %d:%s '
2290 '(%d:%s also has unknown origin %s)\n')
2291 '(%d:%s also has unknown origin %s)\n')
2291 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
2292 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
2292 else:
2293 else:
2293 ui.warn(_('skipping already grafted revision %d:%s '
2294 ui.warn(_('skipping already grafted revision %d:%s '
2294 '(%d:%s also has origin %d:%s)\n')
2295 '(%d:%s also has origin %d:%s)\n')
2295 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
2296 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
2296 revs.remove(ids[n])
2297 revs.remove(ids[n])
2297 elif ctx.hex() in ids:
2298 elif ctx.hex() in ids:
2298 r = ids[ctx.hex()]
2299 r = ids[ctx.hex()]
2299 ui.warn(_('skipping already grafted revision %d:%s '
2300 ui.warn(_('skipping already grafted revision %d:%s '
2300 '(was grafted from %d:%s)\n') %
2301 '(was grafted from %d:%s)\n') %
2301 (r, repo[r], rev, ctx))
2302 (r, repo[r], rev, ctx))
2302 revs.remove(r)
2303 revs.remove(r)
2303 if not revs:
2304 if not revs:
2304 return -1
2305 return -1
2305
2306
2306 for pos, ctx in enumerate(repo.set("%ld", revs)):
2307 for pos, ctx in enumerate(repo.set("%ld", revs)):
2307 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
2308 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
2308 ctx.description().split('\n', 1)[0])
2309 ctx.description().split('\n', 1)[0])
2309 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
2310 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
2310 if names:
2311 if names:
2311 desc += ' (%s)' % ' '.join(names)
2312 desc += ' (%s)' % ' '.join(names)
2312 ui.status(_('grafting %s\n') % desc)
2313 ui.status(_('grafting %s\n') % desc)
2313 if opts.get('dry_run'):
2314 if opts.get('dry_run'):
2314 continue
2315 continue
2315
2316
2316 source = ctx.extra().get('source')
2317 source = ctx.extra().get('source')
2317 extra = {}
2318 extra = {}
2318 if source:
2319 if source:
2319 extra['source'] = source
2320 extra['source'] = source
2320 extra['intermediate-source'] = ctx.hex()
2321 extra['intermediate-source'] = ctx.hex()
2321 else:
2322 else:
2322 extra['source'] = ctx.hex()
2323 extra['source'] = ctx.hex()
2323 user = ctx.user()
2324 user = ctx.user()
2324 if opts.get('user'):
2325 if opts.get('user'):
2325 user = opts['user']
2326 user = opts['user']
2326 date = ctx.date()
2327 date = ctx.date()
2327 if opts.get('date'):
2328 if opts.get('date'):
2328 date = opts['date']
2329 date = opts['date']
2329 message = ctx.description()
2330 message = ctx.description()
2330 if opts.get('log'):
2331 if opts.get('log'):
2331 message += '\n(grafted from %s)' % ctx.hex()
2332 message += '\n(grafted from %s)' % ctx.hex()
2332
2333
2333 # we don't merge the first commit when continuing
2334 # we don't merge the first commit when continuing
2334 if not cont:
2335 if not cont:
2335 # perform the graft merge with p1(rev) as 'ancestor'
2336 # perform the graft merge with p1(rev) as 'ancestor'
2336 try:
2337 try:
2337 # ui.forcemerge is an internal variable, do not document
2338 # ui.forcemerge is an internal variable, do not document
2338 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
2339 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
2339 'graft')
2340 'graft')
2340 stats = mergemod.graft(repo, ctx, ctx.p1(),
2341 stats = mergemod.graft(repo, ctx, ctx.p1(),
2341 ['local', 'graft'])
2342 ['local', 'graft'])
2342 finally:
2343 finally:
2343 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
2344 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
2344 # report any conflicts
2345 # report any conflicts
2345 if stats and stats[3] > 0:
2346 if stats and stats[3] > 0:
2346 # write out state for --continue
2347 # write out state for --continue
2347 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2348 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2348 repo.vfs.write('graftstate', ''.join(nodelines))
2349 repo.vfs.write('graftstate', ''.join(nodelines))
2349 extra = ''
2350 extra = ''
2350 if opts.get('user'):
2351 if opts.get('user'):
2351 extra += ' --user %s' % util.shellquote(opts['user'])
2352 extra += ' --user %s' % util.shellquote(opts['user'])
2352 if opts.get('date'):
2353 if opts.get('date'):
2353 extra += ' --date %s' % util.shellquote(opts['date'])
2354 extra += ' --date %s' % util.shellquote(opts['date'])
2354 if opts.get('log'):
2355 if opts.get('log'):
2355 extra += ' --log'
2356 extra += ' --log'
2356 hint=_("use 'hg resolve' and 'hg graft --continue%s'") % extra
2357 hint=_("use 'hg resolve' and 'hg graft --continue%s'") % extra
2357 raise error.Abort(
2358 raise error.Abort(
2358 _("unresolved conflicts, can't continue"),
2359 _("unresolved conflicts, can't continue"),
2359 hint=hint)
2360 hint=hint)
2360 else:
2361 else:
2361 cont = False
2362 cont = False
2362
2363
2363 # commit
2364 # commit
2364 node = repo.commit(text=message, user=user,
2365 node = repo.commit(text=message, user=user,
2365 date=date, extra=extra, editor=editor)
2366 date=date, extra=extra, editor=editor)
2366 if node is None:
2367 if node is None:
2367 ui.warn(
2368 ui.warn(
2368 _('note: graft of %d:%s created no changes to commit\n') %
2369 _('note: graft of %d:%s created no changes to commit\n') %
2369 (ctx.rev(), ctx))
2370 (ctx.rev(), ctx))
2370
2371
2371 # remove state when we complete successfully
2372 # remove state when we complete successfully
2372 if not opts.get('dry_run'):
2373 if not opts.get('dry_run'):
2373 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
2374 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
2374
2375
2375 return 0
2376 return 0
2376
2377
2377 @command('grep',
2378 @command('grep',
2378 [('0', 'print0', None, _('end fields with NUL')),
2379 [('0', 'print0', None, _('end fields with NUL')),
2379 ('', 'all', None, _('print all revisions that match')),
2380 ('', 'all', None, _('print all revisions that match')),
2380 ('a', 'text', None, _('treat all files as text')),
2381 ('a', 'text', None, _('treat all files as text')),
2381 ('f', 'follow', None,
2382 ('f', 'follow', None,
2382 _('follow changeset history,'
2383 _('follow changeset history,'
2383 ' or file history across copies and renames')),
2384 ' or file history across copies and renames')),
2384 ('i', 'ignore-case', None, _('ignore case when matching')),
2385 ('i', 'ignore-case', None, _('ignore case when matching')),
2385 ('l', 'files-with-matches', None,
2386 ('l', 'files-with-matches', None,
2386 _('print only filenames and revisions that match')),
2387 _('print only filenames and revisions that match')),
2387 ('n', 'line-number', None, _('print matching line numbers')),
2388 ('n', 'line-number', None, _('print matching line numbers')),
2388 ('r', 'rev', [],
2389 ('r', 'rev', [],
2389 _('only search files changed within revision range'), _('REV')),
2390 _('only search files changed within revision range'), _('REV')),
2390 ('u', 'user', None, _('list the author (long with -v)')),
2391 ('u', 'user', None, _('list the author (long with -v)')),
2391 ('d', 'date', None, _('list the date (short with -q)')),
2392 ('d', 'date', None, _('list the date (short with -q)')),
2392 ] + formatteropts + walkopts,
2393 ] + formatteropts + walkopts,
2393 _('[OPTION]... PATTERN [FILE]...'),
2394 _('[OPTION]... PATTERN [FILE]...'),
2394 inferrepo=True)
2395 inferrepo=True)
2395 def grep(ui, repo, pattern, *pats, **opts):
2396 def grep(ui, repo, pattern, *pats, **opts):
2396 """search revision history for a pattern in specified files
2397 """search revision history for a pattern in specified files
2397
2398
2398 Search revision history for a regular expression in the specified
2399 Search revision history for a regular expression in the specified
2399 files or the entire project.
2400 files or the entire project.
2400
2401
2401 By default, grep prints the most recent revision number for each
2402 By default, grep prints the most recent revision number for each
2402 file in which it finds a match. To get it to print every revision
2403 file in which it finds a match. To get it to print every revision
2403 that contains a change in match status ("-" for a match that becomes
2404 that contains a change in match status ("-" for a match that becomes
2404 a non-match, or "+" for a non-match that becomes a match), use the
2405 a non-match, or "+" for a non-match that becomes a match), use the
2405 --all flag.
2406 --all flag.
2406
2407
2407 PATTERN can be any Python (roughly Perl-compatible) regular
2408 PATTERN can be any Python (roughly Perl-compatible) regular
2408 expression.
2409 expression.
2409
2410
2410 If no FILEs are specified (and -f/--follow isn't set), all files in
2411 If no FILEs are specified (and -f/--follow isn't set), all files in
2411 the repository are searched, including those that don't exist in the
2412 the repository are searched, including those that don't exist in the
2412 current branch or have been deleted in a prior changeset.
2413 current branch or have been deleted in a prior changeset.
2413
2414
2414 Returns 0 if a match is found, 1 otherwise.
2415 Returns 0 if a match is found, 1 otherwise.
2415 """
2416 """
2416 reflags = re.M
2417 reflags = re.M
2417 if opts.get('ignore_case'):
2418 if opts.get('ignore_case'):
2418 reflags |= re.I
2419 reflags |= re.I
2419 try:
2420 try:
2420 regexp = util.re.compile(pattern, reflags)
2421 regexp = util.re.compile(pattern, reflags)
2421 except re.error as inst:
2422 except re.error as inst:
2422 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2423 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2423 return 1
2424 return 1
2424 sep, eol = ':', '\n'
2425 sep, eol = ':', '\n'
2425 if opts.get('print0'):
2426 if opts.get('print0'):
2426 sep = eol = '\0'
2427 sep = eol = '\0'
2427
2428
2428 getfile = util.lrucachefunc(repo.file)
2429 getfile = util.lrucachefunc(repo.file)
2429
2430
2430 def matchlines(body):
2431 def matchlines(body):
2431 begin = 0
2432 begin = 0
2432 linenum = 0
2433 linenum = 0
2433 while begin < len(body):
2434 while begin < len(body):
2434 match = regexp.search(body, begin)
2435 match = regexp.search(body, begin)
2435 if not match:
2436 if not match:
2436 break
2437 break
2437 mstart, mend = match.span()
2438 mstart, mend = match.span()
2438 linenum += body.count('\n', begin, mstart) + 1
2439 linenum += body.count('\n', begin, mstart) + 1
2439 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2440 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2440 begin = body.find('\n', mend) + 1 or len(body) + 1
2441 begin = body.find('\n', mend) + 1 or len(body) + 1
2441 lend = begin - 1
2442 lend = begin - 1
2442 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2443 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2443
2444
2444 class linestate(object):
2445 class linestate(object):
2445 def __init__(self, line, linenum, colstart, colend):
2446 def __init__(self, line, linenum, colstart, colend):
2446 self.line = line
2447 self.line = line
2447 self.linenum = linenum
2448 self.linenum = linenum
2448 self.colstart = colstart
2449 self.colstart = colstart
2449 self.colend = colend
2450 self.colend = colend
2450
2451
2451 def __hash__(self):
2452 def __hash__(self):
2452 return hash((self.linenum, self.line))
2453 return hash((self.linenum, self.line))
2453
2454
2454 def __eq__(self, other):
2455 def __eq__(self, other):
2455 return self.line == other.line
2456 return self.line == other.line
2456
2457
2457 def findpos(self):
2458 def findpos(self):
2458 """Iterate all (start, end) indices of matches"""
2459 """Iterate all (start, end) indices of matches"""
2459 yield self.colstart, self.colend
2460 yield self.colstart, self.colend
2460 p = self.colend
2461 p = self.colend
2461 while p < len(self.line):
2462 while p < len(self.line):
2462 m = regexp.search(self.line, p)
2463 m = regexp.search(self.line, p)
2463 if not m:
2464 if not m:
2464 break
2465 break
2465 yield m.span()
2466 yield m.span()
2466 p = m.end()
2467 p = m.end()
2467
2468
2468 matches = {}
2469 matches = {}
2469 copies = {}
2470 copies = {}
2470 def grepbody(fn, rev, body):
2471 def grepbody(fn, rev, body):
2471 matches[rev].setdefault(fn, [])
2472 matches[rev].setdefault(fn, [])
2472 m = matches[rev][fn]
2473 m = matches[rev][fn]
2473 for lnum, cstart, cend, line in matchlines(body):
2474 for lnum, cstart, cend, line in matchlines(body):
2474 s = linestate(line, lnum, cstart, cend)
2475 s = linestate(line, lnum, cstart, cend)
2475 m.append(s)
2476 m.append(s)
2476
2477
2477 def difflinestates(a, b):
2478 def difflinestates(a, b):
2478 sm = difflib.SequenceMatcher(None, a, b)
2479 sm = difflib.SequenceMatcher(None, a, b)
2479 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2480 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2480 if tag == 'insert':
2481 if tag == 'insert':
2481 for i in xrange(blo, bhi):
2482 for i in xrange(blo, bhi):
2482 yield ('+', b[i])
2483 yield ('+', b[i])
2483 elif tag == 'delete':
2484 elif tag == 'delete':
2484 for i in xrange(alo, ahi):
2485 for i in xrange(alo, ahi):
2485 yield ('-', a[i])
2486 yield ('-', a[i])
2486 elif tag == 'replace':
2487 elif tag == 'replace':
2487 for i in xrange(alo, ahi):
2488 for i in xrange(alo, ahi):
2488 yield ('-', a[i])
2489 yield ('-', a[i])
2489 for i in xrange(blo, bhi):
2490 for i in xrange(blo, bhi):
2490 yield ('+', b[i])
2491 yield ('+', b[i])
2491
2492
2492 def display(fm, fn, ctx, pstates, states):
2493 def display(fm, fn, ctx, pstates, states):
2493 rev = ctx.rev()
2494 rev = ctx.rev()
2494 if fm.isplain():
2495 if fm.isplain():
2495 formatuser = ui.shortuser
2496 formatuser = ui.shortuser
2496 else:
2497 else:
2497 formatuser = str
2498 formatuser = str
2498 if ui.quiet:
2499 if ui.quiet:
2499 datefmt = '%Y-%m-%d'
2500 datefmt = '%Y-%m-%d'
2500 else:
2501 else:
2501 datefmt = '%a %b %d %H:%M:%S %Y %1%2'
2502 datefmt = '%a %b %d %H:%M:%S %Y %1%2'
2502 found = False
2503 found = False
2503 @util.cachefunc
2504 @util.cachefunc
2504 def binary():
2505 def binary():
2505 flog = getfile(fn)
2506 flog = getfile(fn)
2506 return util.binary(flog.read(ctx.filenode(fn)))
2507 return util.binary(flog.read(ctx.filenode(fn)))
2507
2508
2508 fieldnamemap = {'filename': 'file', 'linenumber': 'line_number'}
2509 fieldnamemap = {'filename': 'file', 'linenumber': 'line_number'}
2509 if opts.get('all'):
2510 if opts.get('all'):
2510 iter = difflinestates(pstates, states)
2511 iter = difflinestates(pstates, states)
2511 else:
2512 else:
2512 iter = [('', l) for l in states]
2513 iter = [('', l) for l in states]
2513 for change, l in iter:
2514 for change, l in iter:
2514 fm.startitem()
2515 fm.startitem()
2515 fm.data(node=fm.hexfunc(ctx.node()))
2516 fm.data(node=fm.hexfunc(ctx.node()))
2516 cols = [
2517 cols = [
2517 ('filename', fn, True),
2518 ('filename', fn, True),
2518 ('rev', rev, True),
2519 ('rev', rev, True),
2519 ('linenumber', l.linenum, opts.get('line_number')),
2520 ('linenumber', l.linenum, opts.get('line_number')),
2520 ]
2521 ]
2521 if opts.get('all'):
2522 if opts.get('all'):
2522 cols.append(('change', change, True))
2523 cols.append(('change', change, True))
2523 cols.extend([
2524 cols.extend([
2524 ('user', formatuser(ctx.user()), opts.get('user')),
2525 ('user', formatuser(ctx.user()), opts.get('user')),
2525 ('date', fm.formatdate(ctx.date(), datefmt), opts.get('date')),
2526 ('date', fm.formatdate(ctx.date(), datefmt), opts.get('date')),
2526 ])
2527 ])
2527 lastcol = next(name for name, data, cond in reversed(cols) if cond)
2528 lastcol = next(name for name, data, cond in reversed(cols) if cond)
2528 for name, data, cond in cols:
2529 for name, data, cond in cols:
2529 field = fieldnamemap.get(name, name)
2530 field = fieldnamemap.get(name, name)
2530 fm.condwrite(cond, field, '%s', data, label='grep.%s' % name)
2531 fm.condwrite(cond, field, '%s', data, label='grep.%s' % name)
2531 if cond and name != lastcol:
2532 if cond and name != lastcol:
2532 fm.plain(sep, label='grep.sep')
2533 fm.plain(sep, label='grep.sep')
2533 if not opts.get('files_with_matches'):
2534 if not opts.get('files_with_matches'):
2534 fm.plain(sep, label='grep.sep')
2535 fm.plain(sep, label='grep.sep')
2535 if not opts.get('text') and binary():
2536 if not opts.get('text') and binary():
2536 fm.plain(_(" Binary file matches"))
2537 fm.plain(_(" Binary file matches"))
2537 else:
2538 else:
2538 displaymatches(fm.nested('texts'), l)
2539 displaymatches(fm.nested('texts'), l)
2539 fm.plain(eol)
2540 fm.plain(eol)
2540 found = True
2541 found = True
2541 if opts.get('files_with_matches'):
2542 if opts.get('files_with_matches'):
2542 break
2543 break
2543 return found
2544 return found
2544
2545
2545 def displaymatches(fm, l):
2546 def displaymatches(fm, l):
2546 p = 0
2547 p = 0
2547 for s, e in l.findpos():
2548 for s, e in l.findpos():
2548 if p < s:
2549 if p < s:
2549 fm.startitem()
2550 fm.startitem()
2550 fm.write('text', '%s', l.line[p:s])
2551 fm.write('text', '%s', l.line[p:s])
2551 fm.data(matched=False)
2552 fm.data(matched=False)
2552 fm.startitem()
2553 fm.startitem()
2553 fm.write('text', '%s', l.line[s:e], label='grep.match')
2554 fm.write('text', '%s', l.line[s:e], label='grep.match')
2554 fm.data(matched=True)
2555 fm.data(matched=True)
2555 p = e
2556 p = e
2556 if p < len(l.line):
2557 if p < len(l.line):
2557 fm.startitem()
2558 fm.startitem()
2558 fm.write('text', '%s', l.line[p:])
2559 fm.write('text', '%s', l.line[p:])
2559 fm.data(matched=False)
2560 fm.data(matched=False)
2560 fm.end()
2561 fm.end()
2561
2562
2562 skip = {}
2563 skip = {}
2563 revfiles = {}
2564 revfiles = {}
2564 matchfn = scmutil.match(repo[None], pats, opts)
2565 matchfn = scmutil.match(repo[None], pats, opts)
2565 found = False
2566 found = False
2566 follow = opts.get('follow')
2567 follow = opts.get('follow')
2567
2568
2568 def prep(ctx, fns):
2569 def prep(ctx, fns):
2569 rev = ctx.rev()
2570 rev = ctx.rev()
2570 pctx = ctx.p1()
2571 pctx = ctx.p1()
2571 parent = pctx.rev()
2572 parent = pctx.rev()
2572 matches.setdefault(rev, {})
2573 matches.setdefault(rev, {})
2573 matches.setdefault(parent, {})
2574 matches.setdefault(parent, {})
2574 files = revfiles.setdefault(rev, [])
2575 files = revfiles.setdefault(rev, [])
2575 for fn in fns:
2576 for fn in fns:
2576 flog = getfile(fn)
2577 flog = getfile(fn)
2577 try:
2578 try:
2578 fnode = ctx.filenode(fn)
2579 fnode = ctx.filenode(fn)
2579 except error.LookupError:
2580 except error.LookupError:
2580 continue
2581 continue
2581
2582
2582 copied = flog.renamed(fnode)
2583 copied = flog.renamed(fnode)
2583 copy = follow and copied and copied[0]
2584 copy = follow and copied and copied[0]
2584 if copy:
2585 if copy:
2585 copies.setdefault(rev, {})[fn] = copy
2586 copies.setdefault(rev, {})[fn] = copy
2586 if fn in skip:
2587 if fn in skip:
2587 if copy:
2588 if copy:
2588 skip[copy] = True
2589 skip[copy] = True
2589 continue
2590 continue
2590 files.append(fn)
2591 files.append(fn)
2591
2592
2592 if fn not in matches[rev]:
2593 if fn not in matches[rev]:
2593 grepbody(fn, rev, flog.read(fnode))
2594 grepbody(fn, rev, flog.read(fnode))
2594
2595
2595 pfn = copy or fn
2596 pfn = copy or fn
2596 if pfn not in matches[parent]:
2597 if pfn not in matches[parent]:
2597 try:
2598 try:
2598 fnode = pctx.filenode(pfn)
2599 fnode = pctx.filenode(pfn)
2599 grepbody(pfn, parent, flog.read(fnode))
2600 grepbody(pfn, parent, flog.read(fnode))
2600 except error.LookupError:
2601 except error.LookupError:
2601 pass
2602 pass
2602
2603
2603 fm = ui.formatter('grep', opts)
2604 fm = ui.formatter('grep', opts)
2604 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2605 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2605 rev = ctx.rev()
2606 rev = ctx.rev()
2606 parent = ctx.p1().rev()
2607 parent = ctx.p1().rev()
2607 for fn in sorted(revfiles.get(rev, [])):
2608 for fn in sorted(revfiles.get(rev, [])):
2608 states = matches[rev][fn]
2609 states = matches[rev][fn]
2609 copy = copies.get(rev, {}).get(fn)
2610 copy = copies.get(rev, {}).get(fn)
2610 if fn in skip:
2611 if fn in skip:
2611 if copy:
2612 if copy:
2612 skip[copy] = True
2613 skip[copy] = True
2613 continue
2614 continue
2614 pstates = matches.get(parent, {}).get(copy or fn, [])
2615 pstates = matches.get(parent, {}).get(copy or fn, [])
2615 if pstates or states:
2616 if pstates or states:
2616 r = display(fm, fn, ctx, pstates, states)
2617 r = display(fm, fn, ctx, pstates, states)
2617 found = found or r
2618 found = found or r
2618 if r and not opts.get('all'):
2619 if r and not opts.get('all'):
2619 skip[fn] = True
2620 skip[fn] = True
2620 if copy:
2621 if copy:
2621 skip[copy] = True
2622 skip[copy] = True
2622 del matches[rev]
2623 del matches[rev]
2623 del revfiles[rev]
2624 del revfiles[rev]
2624 fm.end()
2625 fm.end()
2625
2626
2626 return not found
2627 return not found
2627
2628
2628 @command('heads',
2629 @command('heads',
2629 [('r', 'rev', '',
2630 [('r', 'rev', '',
2630 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2631 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2631 ('t', 'topo', False, _('show topological heads only')),
2632 ('t', 'topo', False, _('show topological heads only')),
2632 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2633 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2633 ('c', 'closed', False, _('show normal and closed branch heads')),
2634 ('c', 'closed', False, _('show normal and closed branch heads')),
2634 ] + templateopts,
2635 ] + templateopts,
2635 _('[-ct] [-r STARTREV] [REV]...'))
2636 _('[-ct] [-r STARTREV] [REV]...'))
2636 def heads(ui, repo, *branchrevs, **opts):
2637 def heads(ui, repo, *branchrevs, **opts):
2637 """show branch heads
2638 """show branch heads
2638
2639
2639 With no arguments, show all open branch heads in the repository.
2640 With no arguments, show all open branch heads in the repository.
2640 Branch heads are changesets that have no descendants on the
2641 Branch heads are changesets that have no descendants on the
2641 same branch. They are where development generally takes place and
2642 same branch. They are where development generally takes place and
2642 are the usual targets for update and merge operations.
2643 are the usual targets for update and merge operations.
2643
2644
2644 If one or more REVs are given, only open branch heads on the
2645 If one or more REVs are given, only open branch heads on the
2645 branches associated with the specified changesets are shown. This
2646 branches associated with the specified changesets are shown. This
2646 means that you can use :hg:`heads .` to see the heads on the
2647 means that you can use :hg:`heads .` to see the heads on the
2647 currently checked-out branch.
2648 currently checked-out branch.
2648
2649
2649 If -c/--closed is specified, also show branch heads marked closed
2650 If -c/--closed is specified, also show branch heads marked closed
2650 (see :hg:`commit --close-branch`).
2651 (see :hg:`commit --close-branch`).
2651
2652
2652 If STARTREV is specified, only those heads that are descendants of
2653 If STARTREV is specified, only those heads that are descendants of
2653 STARTREV will be displayed.
2654 STARTREV will be displayed.
2654
2655
2655 If -t/--topo is specified, named branch mechanics will be ignored and only
2656 If -t/--topo is specified, named branch mechanics will be ignored and only
2656 topological heads (changesets with no children) will be shown.
2657 topological heads (changesets with no children) will be shown.
2657
2658
2658 Returns 0 if matching heads are found, 1 if not.
2659 Returns 0 if matching heads are found, 1 if not.
2659 """
2660 """
2660
2661
2661 start = None
2662 start = None
2662 if 'rev' in opts:
2663 if 'rev' in opts:
2663 start = scmutil.revsingle(repo, opts['rev'], None).node()
2664 start = scmutil.revsingle(repo, opts['rev'], None).node()
2664
2665
2665 if opts.get('topo'):
2666 if opts.get('topo'):
2666 heads = [repo[h] for h in repo.heads(start)]
2667 heads = [repo[h] for h in repo.heads(start)]
2667 else:
2668 else:
2668 heads = []
2669 heads = []
2669 for branch in repo.branchmap():
2670 for branch in repo.branchmap():
2670 heads += repo.branchheads(branch, start, opts.get('closed'))
2671 heads += repo.branchheads(branch, start, opts.get('closed'))
2671 heads = [repo[h] for h in heads]
2672 heads = [repo[h] for h in heads]
2672
2673
2673 if branchrevs:
2674 if branchrevs:
2674 branches = set(repo[br].branch() for br in branchrevs)
2675 branches = set(repo[br].branch() for br in branchrevs)
2675 heads = [h for h in heads if h.branch() in branches]
2676 heads = [h for h in heads if h.branch() in branches]
2676
2677
2677 if opts.get('active') and branchrevs:
2678 if opts.get('active') and branchrevs:
2678 dagheads = repo.heads(start)
2679 dagheads = repo.heads(start)
2679 heads = [h for h in heads if h.node() in dagheads]
2680 heads = [h for h in heads if h.node() in dagheads]
2680
2681
2681 if branchrevs:
2682 if branchrevs:
2682 haveheads = set(h.branch() for h in heads)
2683 haveheads = set(h.branch() for h in heads)
2683 if branches - haveheads:
2684 if branches - haveheads:
2684 headless = ', '.join(b for b in branches - haveheads)
2685 headless = ', '.join(b for b in branches - haveheads)
2685 msg = _('no open branch heads found on branches %s')
2686 msg = _('no open branch heads found on branches %s')
2686 if opts.get('rev'):
2687 if opts.get('rev'):
2687 msg += _(' (started at %s)') % opts['rev']
2688 msg += _(' (started at %s)') % opts['rev']
2688 ui.warn((msg + '\n') % headless)
2689 ui.warn((msg + '\n') % headless)
2689
2690
2690 if not heads:
2691 if not heads:
2691 return 1
2692 return 1
2692
2693
2693 heads = sorted(heads, key=lambda x: -x.rev())
2694 heads = sorted(heads, key=lambda x: -x.rev())
2694 displayer = cmdutil.show_changeset(ui, repo, opts)
2695 displayer = cmdutil.show_changeset(ui, repo, opts)
2695 for ctx in heads:
2696 for ctx in heads:
2696 displayer.show(ctx)
2697 displayer.show(ctx)
2697 displayer.close()
2698 displayer.close()
2698
2699
2699 @command('help',
2700 @command('help',
2700 [('e', 'extension', None, _('show only help for extensions')),
2701 [('e', 'extension', None, _('show only help for extensions')),
2701 ('c', 'command', None, _('show only help for commands')),
2702 ('c', 'command', None, _('show only help for commands')),
2702 ('k', 'keyword', None, _('show topics matching keyword')),
2703 ('k', 'keyword', None, _('show topics matching keyword')),
2703 ('s', 'system', [], _('show help for specific platform(s)')),
2704 ('s', 'system', [], _('show help for specific platform(s)')),
2704 ],
2705 ],
2705 _('[-ecks] [TOPIC]'),
2706 _('[-ecks] [TOPIC]'),
2706 norepo=True)
2707 norepo=True)
2707 def help_(ui, name=None, **opts):
2708 def help_(ui, name=None, **opts):
2708 """show help for a given topic or a help overview
2709 """show help for a given topic or a help overview
2709
2710
2710 With no arguments, print a list of commands with short help messages.
2711 With no arguments, print a list of commands with short help messages.
2711
2712
2712 Given a topic, extension, or command name, print help for that
2713 Given a topic, extension, or command name, print help for that
2713 topic.
2714 topic.
2714
2715
2715 Returns 0 if successful.
2716 Returns 0 if successful.
2716 """
2717 """
2717
2718
2718 textwidth = ui.configint('ui', 'textwidth', 78)
2719 textwidth = ui.configint('ui', 'textwidth', 78)
2719 termwidth = ui.termwidth() - 2
2720 termwidth = ui.termwidth() - 2
2720 if textwidth <= 0 or termwidth < textwidth:
2721 if textwidth <= 0 or termwidth < textwidth:
2721 textwidth = termwidth
2722 textwidth = termwidth
2722
2723
2723 keep = opts.get('system') or []
2724 keep = opts.get('system') or []
2724 if len(keep) == 0:
2725 if len(keep) == 0:
2725 if pycompat.sysplatform.startswith('win'):
2726 if pycompat.sysplatform.startswith('win'):
2726 keep.append('windows')
2727 keep.append('windows')
2727 elif pycompat.sysplatform == 'OpenVMS':
2728 elif pycompat.sysplatform == 'OpenVMS':
2728 keep.append('vms')
2729 keep.append('vms')
2729 elif pycompat.sysplatform == 'plan9':
2730 elif pycompat.sysplatform == 'plan9':
2730 keep.append('plan9')
2731 keep.append('plan9')
2731 else:
2732 else:
2732 keep.append('unix')
2733 keep.append('unix')
2733 keep.append(pycompat.sysplatform.lower())
2734 keep.append(pycompat.sysplatform.lower())
2734 if ui.verbose:
2735 if ui.verbose:
2735 keep.append('verbose')
2736 keep.append('verbose')
2736
2737
2737 fullname = name
2738 fullname = name
2738 section = None
2739 section = None
2739 subtopic = None
2740 subtopic = None
2740 if name and '.' in name:
2741 if name and '.' in name:
2741 name, remaining = name.split('.', 1)
2742 name, remaining = name.split('.', 1)
2742 remaining = encoding.lower(remaining)
2743 remaining = encoding.lower(remaining)
2743 if '.' in remaining:
2744 if '.' in remaining:
2744 subtopic, section = remaining.split('.', 1)
2745 subtopic, section = remaining.split('.', 1)
2745 else:
2746 else:
2746 if name in help.subtopics:
2747 if name in help.subtopics:
2747 subtopic = remaining
2748 subtopic = remaining
2748 else:
2749 else:
2749 section = remaining
2750 section = remaining
2750
2751
2751 text = help.help_(ui, name, subtopic=subtopic, **opts)
2752 text = help.help_(ui, name, subtopic=subtopic, **opts)
2752
2753
2753 formatted, pruned = minirst.format(text, textwidth, keep=keep,
2754 formatted, pruned = minirst.format(text, textwidth, keep=keep,
2754 section=section)
2755 section=section)
2755
2756
2756 # We could have been given a weird ".foo" section without a name
2757 # We could have been given a weird ".foo" section without a name
2757 # to look for, or we could have simply failed to found "foo.bar"
2758 # to look for, or we could have simply failed to found "foo.bar"
2758 # because bar isn't a section of foo
2759 # because bar isn't a section of foo
2759 if section and not (formatted and name):
2760 if section and not (formatted and name):
2760 raise error.Abort(_("help section not found: %s") % fullname)
2761 raise error.Abort(_("help section not found: %s") % fullname)
2761
2762
2762 if 'verbose' in pruned:
2763 if 'verbose' in pruned:
2763 keep.append('omitted')
2764 keep.append('omitted')
2764 else:
2765 else:
2765 keep.append('notomitted')
2766 keep.append('notomitted')
2766 formatted, pruned = minirst.format(text, textwidth, keep=keep,
2767 formatted, pruned = minirst.format(text, textwidth, keep=keep,
2767 section=section)
2768 section=section)
2768 ui.write(formatted)
2769 ui.write(formatted)
2769
2770
2770
2771
2771 @command('identify|id',
2772 @command('identify|id',
2772 [('r', 'rev', '',
2773 [('r', 'rev', '',
2773 _('identify the specified revision'), _('REV')),
2774 _('identify the specified revision'), _('REV')),
2774 ('n', 'num', None, _('show local revision number')),
2775 ('n', 'num', None, _('show local revision number')),
2775 ('i', 'id', None, _('show global revision id')),
2776 ('i', 'id', None, _('show global revision id')),
2776 ('b', 'branch', None, _('show branch')),
2777 ('b', 'branch', None, _('show branch')),
2777 ('t', 'tags', None, _('show tags')),
2778 ('t', 'tags', None, _('show tags')),
2778 ('B', 'bookmarks', None, _('show bookmarks')),
2779 ('B', 'bookmarks', None, _('show bookmarks')),
2779 ] + remoteopts,
2780 ] + remoteopts,
2780 _('[-nibtB] [-r REV] [SOURCE]'),
2781 _('[-nibtB] [-r REV] [SOURCE]'),
2781 optionalrepo=True)
2782 optionalrepo=True)
2782 def identify(ui, repo, source=None, rev=None,
2783 def identify(ui, repo, source=None, rev=None,
2783 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
2784 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
2784 """identify the working directory or specified revision
2785 """identify the working directory or specified revision
2785
2786
2786 Print a summary identifying the repository state at REV using one or
2787 Print a summary identifying the repository state at REV using one or
2787 two parent hash identifiers, followed by a "+" if the working
2788 two parent hash identifiers, followed by a "+" if the working
2788 directory has uncommitted changes, the branch name (if not default),
2789 directory has uncommitted changes, the branch name (if not default),
2789 a list of tags, and a list of bookmarks.
2790 a list of tags, and a list of bookmarks.
2790
2791
2791 When REV is not given, print a summary of the current state of the
2792 When REV is not given, print a summary of the current state of the
2792 repository.
2793 repository.
2793
2794
2794 Specifying a path to a repository root or Mercurial bundle will
2795 Specifying a path to a repository root or Mercurial bundle will
2795 cause lookup to operate on that repository/bundle.
2796 cause lookup to operate on that repository/bundle.
2796
2797
2797 .. container:: verbose
2798 .. container:: verbose
2798
2799
2799 Examples:
2800 Examples:
2800
2801
2801 - generate a build identifier for the working directory::
2802 - generate a build identifier for the working directory::
2802
2803
2803 hg id --id > build-id.dat
2804 hg id --id > build-id.dat
2804
2805
2805 - find the revision corresponding to a tag::
2806 - find the revision corresponding to a tag::
2806
2807
2807 hg id -n -r 1.3
2808 hg id -n -r 1.3
2808
2809
2809 - check the most recent revision of a remote repository::
2810 - check the most recent revision of a remote repository::
2810
2811
2811 hg id -r tip https://www.mercurial-scm.org/repo/hg/
2812 hg id -r tip https://www.mercurial-scm.org/repo/hg/
2812
2813
2813 See :hg:`log` for generating more information about specific revisions,
2814 See :hg:`log` for generating more information about specific revisions,
2814 including full hash identifiers.
2815 including full hash identifiers.
2815
2816
2816 Returns 0 if successful.
2817 Returns 0 if successful.
2817 """
2818 """
2818
2819
2819 if not repo and not source:
2820 if not repo and not source:
2820 raise error.Abort(_("there is no Mercurial repository here "
2821 raise error.Abort(_("there is no Mercurial repository here "
2821 "(.hg not found)"))
2822 "(.hg not found)"))
2822
2823
2823 if ui.debugflag:
2824 if ui.debugflag:
2824 hexfunc = hex
2825 hexfunc = hex
2825 else:
2826 else:
2826 hexfunc = short
2827 hexfunc = short
2827 default = not (num or id or branch or tags or bookmarks)
2828 default = not (num or id or branch or tags or bookmarks)
2828 output = []
2829 output = []
2829 revs = []
2830 revs = []
2830
2831
2831 if source:
2832 if source:
2832 source, branches = hg.parseurl(ui.expandpath(source))
2833 source, branches = hg.parseurl(ui.expandpath(source))
2833 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
2834 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
2834 repo = peer.local()
2835 repo = peer.local()
2835 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
2836 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
2836
2837
2837 if not repo:
2838 if not repo:
2838 if num or branch or tags:
2839 if num or branch or tags:
2839 raise error.Abort(
2840 raise error.Abort(
2840 _("can't query remote revision number, branch, or tags"))
2841 _("can't query remote revision number, branch, or tags"))
2841 if not rev and revs:
2842 if not rev and revs:
2842 rev = revs[0]
2843 rev = revs[0]
2843 if not rev:
2844 if not rev:
2844 rev = "tip"
2845 rev = "tip"
2845
2846
2846 remoterev = peer.lookup(rev)
2847 remoterev = peer.lookup(rev)
2847 if default or id:
2848 if default or id:
2848 output = [hexfunc(remoterev)]
2849 output = [hexfunc(remoterev)]
2849
2850
2850 def getbms():
2851 def getbms():
2851 bms = []
2852 bms = []
2852
2853
2853 if 'bookmarks' in peer.listkeys('namespaces'):
2854 if 'bookmarks' in peer.listkeys('namespaces'):
2854 hexremoterev = hex(remoterev)
2855 hexremoterev = hex(remoterev)
2855 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
2856 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
2856 if bmr == hexremoterev]
2857 if bmr == hexremoterev]
2857
2858
2858 return sorted(bms)
2859 return sorted(bms)
2859
2860
2860 if bookmarks:
2861 if bookmarks:
2861 output.extend(getbms())
2862 output.extend(getbms())
2862 elif default and not ui.quiet:
2863 elif default and not ui.quiet:
2863 # multiple bookmarks for a single parent separated by '/'
2864 # multiple bookmarks for a single parent separated by '/'
2864 bm = '/'.join(getbms())
2865 bm = '/'.join(getbms())
2865 if bm:
2866 if bm:
2866 output.append(bm)
2867 output.append(bm)
2867 else:
2868 else:
2868 ctx = scmutil.revsingle(repo, rev, None)
2869 ctx = scmutil.revsingle(repo, rev, None)
2869
2870
2870 if ctx.rev() is None:
2871 if ctx.rev() is None:
2871 ctx = repo[None]
2872 ctx = repo[None]
2872 parents = ctx.parents()
2873 parents = ctx.parents()
2873 taglist = []
2874 taglist = []
2874 for p in parents:
2875 for p in parents:
2875 taglist.extend(p.tags())
2876 taglist.extend(p.tags())
2876
2877
2877 changed = ""
2878 changed = ""
2878 if default or id or num:
2879 if default or id or num:
2879 if (any(repo.status())
2880 if (any(repo.status())
2880 or any(ctx.sub(s).dirty() for s in ctx.substate)):
2881 or any(ctx.sub(s).dirty() for s in ctx.substate)):
2881 changed = '+'
2882 changed = '+'
2882 if default or id:
2883 if default or id:
2883 output = ["%s%s" %
2884 output = ["%s%s" %
2884 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
2885 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
2885 if num:
2886 if num:
2886 output.append("%s%s" %
2887 output.append("%s%s" %
2887 ('+'.join([str(p.rev()) for p in parents]), changed))
2888 ('+'.join([str(p.rev()) for p in parents]), changed))
2888 else:
2889 else:
2889 if default or id:
2890 if default or id:
2890 output = [hexfunc(ctx.node())]
2891 output = [hexfunc(ctx.node())]
2891 if num:
2892 if num:
2892 output.append(str(ctx.rev()))
2893 output.append(str(ctx.rev()))
2893 taglist = ctx.tags()
2894 taglist = ctx.tags()
2894
2895
2895 if default and not ui.quiet:
2896 if default and not ui.quiet:
2896 b = ctx.branch()
2897 b = ctx.branch()
2897 if b != 'default':
2898 if b != 'default':
2898 output.append("(%s)" % b)
2899 output.append("(%s)" % b)
2899
2900
2900 # multiple tags for a single parent separated by '/'
2901 # multiple tags for a single parent separated by '/'
2901 t = '/'.join(taglist)
2902 t = '/'.join(taglist)
2902 if t:
2903 if t:
2903 output.append(t)
2904 output.append(t)
2904
2905
2905 # multiple bookmarks for a single parent separated by '/'
2906 # multiple bookmarks for a single parent separated by '/'
2906 bm = '/'.join(ctx.bookmarks())
2907 bm = '/'.join(ctx.bookmarks())
2907 if bm:
2908 if bm:
2908 output.append(bm)
2909 output.append(bm)
2909 else:
2910 else:
2910 if branch:
2911 if branch:
2911 output.append(ctx.branch())
2912 output.append(ctx.branch())
2912
2913
2913 if tags:
2914 if tags:
2914 output.extend(taglist)
2915 output.extend(taglist)
2915
2916
2916 if bookmarks:
2917 if bookmarks:
2917 output.extend(ctx.bookmarks())
2918 output.extend(ctx.bookmarks())
2918
2919
2919 ui.write("%s\n" % ' '.join(output))
2920 ui.write("%s\n" % ' '.join(output))
2920
2921
2921 @command('import|patch',
2922 @command('import|patch',
2922 [('p', 'strip', 1,
2923 [('p', 'strip', 1,
2923 _('directory strip option for patch. This has the same '
2924 _('directory strip option for patch. This has the same '
2924 'meaning as the corresponding patch option'), _('NUM')),
2925 'meaning as the corresponding patch option'), _('NUM')),
2925 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
2926 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
2926 ('e', 'edit', False, _('invoke editor on commit messages')),
2927 ('e', 'edit', False, _('invoke editor on commit messages')),
2927 ('f', 'force', None,
2928 ('f', 'force', None,
2928 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
2929 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
2929 ('', 'no-commit', None,
2930 ('', 'no-commit', None,
2930 _("don't commit, just update the working directory")),
2931 _("don't commit, just update the working directory")),
2931 ('', 'bypass', None,
2932 ('', 'bypass', None,
2932 _("apply patch without touching the working directory")),
2933 _("apply patch without touching the working directory")),
2933 ('', 'partial', None,
2934 ('', 'partial', None,
2934 _('commit even if some hunks fail')),
2935 _('commit even if some hunks fail')),
2935 ('', 'exact', None,
2936 ('', 'exact', None,
2936 _('abort if patch would apply lossily')),
2937 _('abort if patch would apply lossily')),
2937 ('', 'prefix', '',
2938 ('', 'prefix', '',
2938 _('apply patch to subdirectory'), _('DIR')),
2939 _('apply patch to subdirectory'), _('DIR')),
2939 ('', 'import-branch', None,
2940 ('', 'import-branch', None,
2940 _('use any branch information in patch (implied by --exact)'))] +
2941 _('use any branch information in patch (implied by --exact)'))] +
2941 commitopts + commitopts2 + similarityopts,
2942 commitopts + commitopts2 + similarityopts,
2942 _('[OPTION]... PATCH...'))
2943 _('[OPTION]... PATCH...'))
2943 def import_(ui, repo, patch1=None, *patches, **opts):
2944 def import_(ui, repo, patch1=None, *patches, **opts):
2944 """import an ordered set of patches
2945 """import an ordered set of patches
2945
2946
2946 Import a list of patches and commit them individually (unless
2947 Import a list of patches and commit them individually (unless
2947 --no-commit is specified).
2948 --no-commit is specified).
2948
2949
2949 To read a patch from standard input (stdin), use "-" as the patch
2950 To read a patch from standard input (stdin), use "-" as the patch
2950 name. If a URL is specified, the patch will be downloaded from
2951 name. If a URL is specified, the patch will be downloaded from
2951 there.
2952 there.
2952
2953
2953 Import first applies changes to the working directory (unless
2954 Import first applies changes to the working directory (unless
2954 --bypass is specified), import will abort if there are outstanding
2955 --bypass is specified), import will abort if there are outstanding
2955 changes.
2956 changes.
2956
2957
2957 Use --bypass to apply and commit patches directly to the
2958 Use --bypass to apply and commit patches directly to the
2958 repository, without affecting the working directory. Without
2959 repository, without affecting the working directory. Without
2959 --exact, patches will be applied on top of the working directory
2960 --exact, patches will be applied on top of the working directory
2960 parent revision.
2961 parent revision.
2961
2962
2962 You can import a patch straight from a mail message. Even patches
2963 You can import a patch straight from a mail message. Even patches
2963 as attachments work (to use the body part, it must have type
2964 as attachments work (to use the body part, it must have type
2964 text/plain or text/x-patch). From and Subject headers of email
2965 text/plain or text/x-patch). From and Subject headers of email
2965 message are used as default committer and commit message. All
2966 message are used as default committer and commit message. All
2966 text/plain body parts before first diff are added to the commit
2967 text/plain body parts before first diff are added to the commit
2967 message.
2968 message.
2968
2969
2969 If the imported patch was generated by :hg:`export`, user and
2970 If the imported patch was generated by :hg:`export`, user and
2970 description from patch override values from message headers and
2971 description from patch override values from message headers and
2971 body. Values given on command line with -m/--message and -u/--user
2972 body. Values given on command line with -m/--message and -u/--user
2972 override these.
2973 override these.
2973
2974
2974 If --exact is specified, import will set the working directory to
2975 If --exact is specified, import will set the working directory to
2975 the parent of each patch before applying it, and will abort if the
2976 the parent of each patch before applying it, and will abort if the
2976 resulting changeset has a different ID than the one recorded in
2977 resulting changeset has a different ID than the one recorded in
2977 the patch. This will guard against various ways that portable
2978 the patch. This will guard against various ways that portable
2978 patch formats and mail systems might fail to transfer Mercurial
2979 patch formats and mail systems might fail to transfer Mercurial
2979 data or metadata. See :hg:`bundle` for lossless transmission.
2980 data or metadata. See :hg:`bundle` for lossless transmission.
2980
2981
2981 Use --partial to ensure a changeset will be created from the patch
2982 Use --partial to ensure a changeset will be created from the patch
2982 even if some hunks fail to apply. Hunks that fail to apply will be
2983 even if some hunks fail to apply. Hunks that fail to apply will be
2983 written to a <target-file>.rej file. Conflicts can then be resolved
2984 written to a <target-file>.rej file. Conflicts can then be resolved
2984 by hand before :hg:`commit --amend` is run to update the created
2985 by hand before :hg:`commit --amend` is run to update the created
2985 changeset. This flag exists to let people import patches that
2986 changeset. This flag exists to let people import patches that
2986 partially apply without losing the associated metadata (author,
2987 partially apply without losing the associated metadata (author,
2987 date, description, ...).
2988 date, description, ...).
2988
2989
2989 .. note::
2990 .. note::
2990
2991
2991 When no hunks apply cleanly, :hg:`import --partial` will create
2992 When no hunks apply cleanly, :hg:`import --partial` will create
2992 an empty changeset, importing only the patch metadata.
2993 an empty changeset, importing only the patch metadata.
2993
2994
2994 With -s/--similarity, hg will attempt to discover renames and
2995 With -s/--similarity, hg will attempt to discover renames and
2995 copies in the patch in the same way as :hg:`addremove`.
2996 copies in the patch in the same way as :hg:`addremove`.
2996
2997
2997 It is possible to use external patch programs to perform the patch
2998 It is possible to use external patch programs to perform the patch
2998 by setting the ``ui.patch`` configuration option. For the default
2999 by setting the ``ui.patch`` configuration option. For the default
2999 internal tool, the fuzz can also be configured via ``patch.fuzz``.
3000 internal tool, the fuzz can also be configured via ``patch.fuzz``.
3000 See :hg:`help config` for more information about configuration
3001 See :hg:`help config` for more information about configuration
3001 files and how to use these options.
3002 files and how to use these options.
3002
3003
3003 See :hg:`help dates` for a list of formats valid for -d/--date.
3004 See :hg:`help dates` for a list of formats valid for -d/--date.
3004
3005
3005 .. container:: verbose
3006 .. container:: verbose
3006
3007
3007 Examples:
3008 Examples:
3008
3009
3009 - import a traditional patch from a website and detect renames::
3010 - import a traditional patch from a website and detect renames::
3010
3011
3011 hg import -s 80 http://example.com/bugfix.patch
3012 hg import -s 80 http://example.com/bugfix.patch
3012
3013
3013 - import a changeset from an hgweb server::
3014 - import a changeset from an hgweb server::
3014
3015
3015 hg import https://www.mercurial-scm.org/repo/hg/rev/5ca8c111e9aa
3016 hg import https://www.mercurial-scm.org/repo/hg/rev/5ca8c111e9aa
3016
3017
3017 - import all the patches in an Unix-style mbox::
3018 - import all the patches in an Unix-style mbox::
3018
3019
3019 hg import incoming-patches.mbox
3020 hg import incoming-patches.mbox
3020
3021
3021 - import patches from stdin::
3022 - import patches from stdin::
3022
3023
3023 hg import -
3024 hg import -
3024
3025
3025 - attempt to exactly restore an exported changeset (not always
3026 - attempt to exactly restore an exported changeset (not always
3026 possible)::
3027 possible)::
3027
3028
3028 hg import --exact proposed-fix.patch
3029 hg import --exact proposed-fix.patch
3029
3030
3030 - use an external tool to apply a patch which is too fuzzy for
3031 - use an external tool to apply a patch which is too fuzzy for
3031 the default internal tool.
3032 the default internal tool.
3032
3033
3033 hg import --config ui.patch="patch --merge" fuzzy.patch
3034 hg import --config ui.patch="patch --merge" fuzzy.patch
3034
3035
3035 - change the default fuzzing from 2 to a less strict 7
3036 - change the default fuzzing from 2 to a less strict 7
3036
3037
3037 hg import --config ui.fuzz=7 fuzz.patch
3038 hg import --config ui.fuzz=7 fuzz.patch
3038
3039
3039 Returns 0 on success, 1 on partial success (see --partial).
3040 Returns 0 on success, 1 on partial success (see --partial).
3040 """
3041 """
3041
3042
3042 if not patch1:
3043 if not patch1:
3043 raise error.Abort(_('need at least one patch to import'))
3044 raise error.Abort(_('need at least one patch to import'))
3044
3045
3045 patches = (patch1,) + patches
3046 patches = (patch1,) + patches
3046
3047
3047 date = opts.get('date')
3048 date = opts.get('date')
3048 if date:
3049 if date:
3049 opts['date'] = util.parsedate(date)
3050 opts['date'] = util.parsedate(date)
3050
3051
3051 exact = opts.get('exact')
3052 exact = opts.get('exact')
3052 update = not opts.get('bypass')
3053 update = not opts.get('bypass')
3053 if not update and opts.get('no_commit'):
3054 if not update and opts.get('no_commit'):
3054 raise error.Abort(_('cannot use --no-commit with --bypass'))
3055 raise error.Abort(_('cannot use --no-commit with --bypass'))
3055 try:
3056 try:
3056 sim = float(opts.get('similarity') or 0)
3057 sim = float(opts.get('similarity') or 0)
3057 except ValueError:
3058 except ValueError:
3058 raise error.Abort(_('similarity must be a number'))
3059 raise error.Abort(_('similarity must be a number'))
3059 if sim < 0 or sim > 100:
3060 if sim < 0 or sim > 100:
3060 raise error.Abort(_('similarity must be between 0 and 100'))
3061 raise error.Abort(_('similarity must be between 0 and 100'))
3061 if sim and not update:
3062 if sim and not update:
3062 raise error.Abort(_('cannot use --similarity with --bypass'))
3063 raise error.Abort(_('cannot use --similarity with --bypass'))
3063 if exact:
3064 if exact:
3064 if opts.get('edit'):
3065 if opts.get('edit'):
3065 raise error.Abort(_('cannot use --exact with --edit'))
3066 raise error.Abort(_('cannot use --exact with --edit'))
3066 if opts.get('prefix'):
3067 if opts.get('prefix'):
3067 raise error.Abort(_('cannot use --exact with --prefix'))
3068 raise error.Abort(_('cannot use --exact with --prefix'))
3068
3069
3069 base = opts["base"]
3070 base = opts["base"]
3070 wlock = dsguard = lock = tr = None
3071 wlock = dsguard = lock = tr = None
3071 msgs = []
3072 msgs = []
3072 ret = 0
3073 ret = 0
3073
3074
3074
3075
3075 try:
3076 try:
3076 wlock = repo.wlock()
3077 wlock = repo.wlock()
3077
3078
3078 if update:
3079 if update:
3079 cmdutil.checkunfinished(repo)
3080 cmdutil.checkunfinished(repo)
3080 if (exact or not opts.get('force')):
3081 if (exact or not opts.get('force')):
3081 cmdutil.bailifchanged(repo)
3082 cmdutil.bailifchanged(repo)
3082
3083
3083 if not opts.get('no_commit'):
3084 if not opts.get('no_commit'):
3084 lock = repo.lock()
3085 lock = repo.lock()
3085 tr = repo.transaction('import')
3086 tr = repo.transaction('import')
3086 else:
3087 else:
3087 dsguard = dirstateguard.dirstateguard(repo, 'import')
3088 dsguard = dirstateguard.dirstateguard(repo, 'import')
3088 parents = repo[None].parents()
3089 parents = repo[None].parents()
3089 for patchurl in patches:
3090 for patchurl in patches:
3090 if patchurl == '-':
3091 if patchurl == '-':
3091 ui.status(_('applying patch from stdin\n'))
3092 ui.status(_('applying patch from stdin\n'))
3092 patchfile = ui.fin
3093 patchfile = ui.fin
3093 patchurl = 'stdin' # for error message
3094 patchurl = 'stdin' # for error message
3094 else:
3095 else:
3095 patchurl = os.path.join(base, patchurl)
3096 patchurl = os.path.join(base, patchurl)
3096 ui.status(_('applying %s\n') % patchurl)
3097 ui.status(_('applying %s\n') % patchurl)
3097 patchfile = hg.openpath(ui, patchurl)
3098 patchfile = hg.openpath(ui, patchurl)
3098
3099
3099 haspatch = False
3100 haspatch = False
3100 for hunk in patch.split(patchfile):
3101 for hunk in patch.split(patchfile):
3101 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
3102 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
3102 parents, opts,
3103 parents, opts,
3103 msgs, hg.clean)
3104 msgs, hg.clean)
3104 if msg:
3105 if msg:
3105 haspatch = True
3106 haspatch = True
3106 ui.note(msg + '\n')
3107 ui.note(msg + '\n')
3107 if update or exact:
3108 if update or exact:
3108 parents = repo[None].parents()
3109 parents = repo[None].parents()
3109 else:
3110 else:
3110 parents = [repo[node]]
3111 parents = [repo[node]]
3111 if rej:
3112 if rej:
3112 ui.write_err(_("patch applied partially\n"))
3113 ui.write_err(_("patch applied partially\n"))
3113 ui.write_err(_("(fix the .rej files and run "
3114 ui.write_err(_("(fix the .rej files and run "
3114 "`hg commit --amend`)\n"))
3115 "`hg commit --amend`)\n"))
3115 ret = 1
3116 ret = 1
3116 break
3117 break
3117
3118
3118 if not haspatch:
3119 if not haspatch:
3119 raise error.Abort(_('%s: no diffs found') % patchurl)
3120 raise error.Abort(_('%s: no diffs found') % patchurl)
3120
3121
3121 if tr:
3122 if tr:
3122 tr.close()
3123 tr.close()
3123 if msgs:
3124 if msgs:
3124 repo.savecommitmessage('\n* * *\n'.join(msgs))
3125 repo.savecommitmessage('\n* * *\n'.join(msgs))
3125 if dsguard:
3126 if dsguard:
3126 dsguard.close()
3127 dsguard.close()
3127 return ret
3128 return ret
3128 finally:
3129 finally:
3129 if tr:
3130 if tr:
3130 tr.release()
3131 tr.release()
3131 release(lock, dsguard, wlock)
3132 release(lock, dsguard, wlock)
3132
3133
3133 @command('incoming|in',
3134 @command('incoming|in',
3134 [('f', 'force', None,
3135 [('f', 'force', None,
3135 _('run even if remote repository is unrelated')),
3136 _('run even if remote repository is unrelated')),
3136 ('n', 'newest-first', None, _('show newest record first')),
3137 ('n', 'newest-first', None, _('show newest record first')),
3137 ('', 'bundle', '',
3138 ('', 'bundle', '',
3138 _('file to store the bundles into'), _('FILE')),
3139 _('file to store the bundles into'), _('FILE')),
3139 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3140 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3140 ('B', 'bookmarks', False, _("compare bookmarks")),
3141 ('B', 'bookmarks', False, _("compare bookmarks")),
3141 ('b', 'branch', [],
3142 ('b', 'branch', [],
3142 _('a specific branch you would like to pull'), _('BRANCH')),
3143 _('a specific branch you would like to pull'), _('BRANCH')),
3143 ] + logopts + remoteopts + subrepoopts,
3144 ] + logopts + remoteopts + subrepoopts,
3144 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3145 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3145 def incoming(ui, repo, source="default", **opts):
3146 def incoming(ui, repo, source="default", **opts):
3146 """show new changesets found in source
3147 """show new changesets found in source
3147
3148
3148 Show new changesets found in the specified path/URL or the default
3149 Show new changesets found in the specified path/URL or the default
3149 pull location. These are the changesets that would have been pulled
3150 pull location. These are the changesets that would have been pulled
3150 if a pull at the time you issued this command.
3151 if a pull at the time you issued this command.
3151
3152
3152 See pull for valid source format details.
3153 See pull for valid source format details.
3153
3154
3154 .. container:: verbose
3155 .. container:: verbose
3155
3156
3156 With -B/--bookmarks, the result of bookmark comparison between
3157 With -B/--bookmarks, the result of bookmark comparison between
3157 local and remote repositories is displayed. With -v/--verbose,
3158 local and remote repositories is displayed. With -v/--verbose,
3158 status is also displayed for each bookmark like below::
3159 status is also displayed for each bookmark like below::
3159
3160
3160 BM1 01234567890a added
3161 BM1 01234567890a added
3161 BM2 1234567890ab advanced
3162 BM2 1234567890ab advanced
3162 BM3 234567890abc diverged
3163 BM3 234567890abc diverged
3163 BM4 34567890abcd changed
3164 BM4 34567890abcd changed
3164
3165
3165 The action taken locally when pulling depends on the
3166 The action taken locally when pulling depends on the
3166 status of each bookmark:
3167 status of each bookmark:
3167
3168
3168 :``added``: pull will create it
3169 :``added``: pull will create it
3169 :``advanced``: pull will update it
3170 :``advanced``: pull will update it
3170 :``diverged``: pull will create a divergent bookmark
3171 :``diverged``: pull will create a divergent bookmark
3171 :``changed``: result depends on remote changesets
3172 :``changed``: result depends on remote changesets
3172
3173
3173 From the point of view of pulling behavior, bookmark
3174 From the point of view of pulling behavior, bookmark
3174 existing only in the remote repository are treated as ``added``,
3175 existing only in the remote repository are treated as ``added``,
3175 even if it is in fact locally deleted.
3176 even if it is in fact locally deleted.
3176
3177
3177 .. container:: verbose
3178 .. container:: verbose
3178
3179
3179 For remote repository, using --bundle avoids downloading the
3180 For remote repository, using --bundle avoids downloading the
3180 changesets twice if the incoming is followed by a pull.
3181 changesets twice if the incoming is followed by a pull.
3181
3182
3182 Examples:
3183 Examples:
3183
3184
3184 - show incoming changes with patches and full description::
3185 - show incoming changes with patches and full description::
3185
3186
3186 hg incoming -vp
3187 hg incoming -vp
3187
3188
3188 - show incoming changes excluding merges, store a bundle::
3189 - show incoming changes excluding merges, store a bundle::
3189
3190
3190 hg in -vpM --bundle incoming.hg
3191 hg in -vpM --bundle incoming.hg
3191 hg pull incoming.hg
3192 hg pull incoming.hg
3192
3193
3193 - briefly list changes inside a bundle::
3194 - briefly list changes inside a bundle::
3194
3195
3195 hg in changes.hg -T "{desc|firstline}\\n"
3196 hg in changes.hg -T "{desc|firstline}\\n"
3196
3197
3197 Returns 0 if there are incoming changes, 1 otherwise.
3198 Returns 0 if there are incoming changes, 1 otherwise.
3198 """
3199 """
3199 if opts.get('graph'):
3200 if opts.get('graph'):
3200 cmdutil.checkunsupportedgraphflags([], opts)
3201 cmdutil.checkunsupportedgraphflags([], opts)
3201 def display(other, chlist, displayer):
3202 def display(other, chlist, displayer):
3202 revdag = cmdutil.graphrevs(other, chlist, opts)
3203 revdag = cmdutil.graphrevs(other, chlist, opts)
3203 cmdutil.displaygraph(ui, repo, revdag, displayer,
3204 cmdutil.displaygraph(ui, repo, revdag, displayer,
3204 graphmod.asciiedges)
3205 graphmod.asciiedges)
3205
3206
3206 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3207 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3207 return 0
3208 return 0
3208
3209
3209 if opts.get('bundle') and opts.get('subrepos'):
3210 if opts.get('bundle') and opts.get('subrepos'):
3210 raise error.Abort(_('cannot combine --bundle and --subrepos'))
3211 raise error.Abort(_('cannot combine --bundle and --subrepos'))
3211
3212
3212 if opts.get('bookmarks'):
3213 if opts.get('bookmarks'):
3213 source, branches = hg.parseurl(ui.expandpath(source),
3214 source, branches = hg.parseurl(ui.expandpath(source),
3214 opts.get('branch'))
3215 opts.get('branch'))
3215 other = hg.peer(repo, opts, source)
3216 other = hg.peer(repo, opts, source)
3216 if 'bookmarks' not in other.listkeys('namespaces'):
3217 if 'bookmarks' not in other.listkeys('namespaces'):
3217 ui.warn(_("remote doesn't support bookmarks\n"))
3218 ui.warn(_("remote doesn't support bookmarks\n"))
3218 return 0
3219 return 0
3219 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3220 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3220 return bookmarks.incoming(ui, repo, other)
3221 return bookmarks.incoming(ui, repo, other)
3221
3222
3222 repo._subtoppath = ui.expandpath(source)
3223 repo._subtoppath = ui.expandpath(source)
3223 try:
3224 try:
3224 return hg.incoming(ui, repo, source, opts)
3225 return hg.incoming(ui, repo, source, opts)
3225 finally:
3226 finally:
3226 del repo._subtoppath
3227 del repo._subtoppath
3227
3228
3228
3229
3229 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
3230 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
3230 norepo=True)
3231 norepo=True)
3231 def init(ui, dest=".", **opts):
3232 def init(ui, dest=".", **opts):
3232 """create a new repository in the given directory
3233 """create a new repository in the given directory
3233
3234
3234 Initialize a new repository in the given directory. If the given
3235 Initialize a new repository in the given directory. If the given
3235 directory does not exist, it will be created.
3236 directory does not exist, it will be created.
3236
3237
3237 If no directory is given, the current directory is used.
3238 If no directory is given, the current directory is used.
3238
3239
3239 It is possible to specify an ``ssh://`` URL as the destination.
3240 It is possible to specify an ``ssh://`` URL as the destination.
3240 See :hg:`help urls` for more information.
3241 See :hg:`help urls` for more information.
3241
3242
3242 Returns 0 on success.
3243 Returns 0 on success.
3243 """
3244 """
3244 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3245 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3245
3246
3246 @command('locate',
3247 @command('locate',
3247 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3248 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3248 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3249 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3249 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3250 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3250 ] + walkopts,
3251 ] + walkopts,
3251 _('[OPTION]... [PATTERN]...'))
3252 _('[OPTION]... [PATTERN]...'))
3252 def locate(ui, repo, *pats, **opts):
3253 def locate(ui, repo, *pats, **opts):
3253 """locate files matching specific patterns (DEPRECATED)
3254 """locate files matching specific patterns (DEPRECATED)
3254
3255
3255 Print files under Mercurial control in the working directory whose
3256 Print files under Mercurial control in the working directory whose
3256 names match the given patterns.
3257 names match the given patterns.
3257
3258
3258 By default, this command searches all directories in the working
3259 By default, this command searches all directories in the working
3259 directory. To search just the current directory and its
3260 directory. To search just the current directory and its
3260 subdirectories, use "--include .".
3261 subdirectories, use "--include .".
3261
3262
3262 If no patterns are given to match, this command prints the names
3263 If no patterns are given to match, this command prints the names
3263 of all files under Mercurial control in the working directory.
3264 of all files under Mercurial control in the working directory.
3264
3265
3265 If you want to feed the output of this command into the "xargs"
3266 If you want to feed the output of this command into the "xargs"
3266 command, use the -0 option to both this command and "xargs". This
3267 command, use the -0 option to both this command and "xargs". This
3267 will avoid the problem of "xargs" treating single filenames that
3268 will avoid the problem of "xargs" treating single filenames that
3268 contain whitespace as multiple filenames.
3269 contain whitespace as multiple filenames.
3269
3270
3270 See :hg:`help files` for a more versatile command.
3271 See :hg:`help files` for a more versatile command.
3271
3272
3272 Returns 0 if a match is found, 1 otherwise.
3273 Returns 0 if a match is found, 1 otherwise.
3273 """
3274 """
3274 if opts.get('print0'):
3275 if opts.get('print0'):
3275 end = '\0'
3276 end = '\0'
3276 else:
3277 else:
3277 end = '\n'
3278 end = '\n'
3278 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3279 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3279
3280
3280 ret = 1
3281 ret = 1
3281 ctx = repo[rev]
3282 ctx = repo[rev]
3282 m = scmutil.match(ctx, pats, opts, default='relglob',
3283 m = scmutil.match(ctx, pats, opts, default='relglob',
3283 badfn=lambda x, y: False)
3284 badfn=lambda x, y: False)
3284
3285
3285 for abs in ctx.matches(m):
3286 for abs in ctx.matches(m):
3286 if opts.get('fullpath'):
3287 if opts.get('fullpath'):
3287 ui.write(repo.wjoin(abs), end)
3288 ui.write(repo.wjoin(abs), end)
3288 else:
3289 else:
3289 ui.write(((pats and m.rel(abs)) or abs), end)
3290 ui.write(((pats and m.rel(abs)) or abs), end)
3290 ret = 0
3291 ret = 0
3291
3292
3292 return ret
3293 return ret
3293
3294
3294 @command('^log|history',
3295 @command('^log|history',
3295 [('f', 'follow', None,
3296 [('f', 'follow', None,
3296 _('follow changeset history, or file history across copies and renames')),
3297 _('follow changeset history, or file history across copies and renames')),
3297 ('', 'follow-first', None,
3298 ('', 'follow-first', None,
3298 _('only follow the first parent of merge changesets (DEPRECATED)')),
3299 _('only follow the first parent of merge changesets (DEPRECATED)')),
3299 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3300 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3300 ('C', 'copies', None, _('show copied files')),
3301 ('C', 'copies', None, _('show copied files')),
3301 ('k', 'keyword', [],
3302 ('k', 'keyword', [],
3302 _('do case-insensitive search for a given text'), _('TEXT')),
3303 _('do case-insensitive search for a given text'), _('TEXT')),
3303 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
3304 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
3304 ('', 'removed', None, _('include revisions where files were removed')),
3305 ('', 'removed', None, _('include revisions where files were removed')),
3305 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3306 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3306 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3307 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3307 ('', 'only-branch', [],
3308 ('', 'only-branch', [],
3308 _('show only changesets within the given named branch (DEPRECATED)'),
3309 _('show only changesets within the given named branch (DEPRECATED)'),
3309 _('BRANCH')),
3310 _('BRANCH')),
3310 ('b', 'branch', [],
3311 ('b', 'branch', [],
3311 _('show changesets within the given named branch'), _('BRANCH')),
3312 _('show changesets within the given named branch'), _('BRANCH')),
3312 ('P', 'prune', [],
3313 ('P', 'prune', [],
3313 _('do not display revision or any of its ancestors'), _('REV')),
3314 _('do not display revision or any of its ancestors'), _('REV')),
3314 ] + logopts + walkopts,
3315 ] + logopts + walkopts,
3315 _('[OPTION]... [FILE]'),
3316 _('[OPTION]... [FILE]'),
3316 inferrepo=True)
3317 inferrepo=True)
3317 def log(ui, repo, *pats, **opts):
3318 def log(ui, repo, *pats, **opts):
3318 """show revision history of entire repository or files
3319 """show revision history of entire repository or files
3319
3320
3320 Print the revision history of the specified files or the entire
3321 Print the revision history of the specified files or the entire
3321 project.
3322 project.
3322
3323
3323 If no revision range is specified, the default is ``tip:0`` unless
3324 If no revision range is specified, the default is ``tip:0`` unless
3324 --follow is set, in which case the working directory parent is
3325 --follow is set, in which case the working directory parent is
3325 used as the starting revision.
3326 used as the starting revision.
3326
3327
3327 File history is shown without following rename or copy history of
3328 File history is shown without following rename or copy history of
3328 files. Use -f/--follow with a filename to follow history across
3329 files. Use -f/--follow with a filename to follow history across
3329 renames and copies. --follow without a filename will only show
3330 renames and copies. --follow without a filename will only show
3330 ancestors or descendants of the starting revision.
3331 ancestors or descendants of the starting revision.
3331
3332
3332 By default this command prints revision number and changeset id,
3333 By default this command prints revision number and changeset id,
3333 tags, non-trivial parents, user, date and time, and a summary for
3334 tags, non-trivial parents, user, date and time, and a summary for
3334 each commit. When the -v/--verbose switch is used, the list of
3335 each commit. When the -v/--verbose switch is used, the list of
3335 changed files and full commit message are shown.
3336 changed files and full commit message are shown.
3336
3337
3337 With --graph the revisions are shown as an ASCII art DAG with the most
3338 With --graph the revisions are shown as an ASCII art DAG with the most
3338 recent changeset at the top.
3339 recent changeset at the top.
3339 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
3340 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
3340 and '+' represents a fork where the changeset from the lines below is a
3341 and '+' represents a fork where the changeset from the lines below is a
3341 parent of the 'o' merge on the same line.
3342 parent of the 'o' merge on the same line.
3342
3343
3343 .. note::
3344 .. note::
3344
3345
3345 :hg:`log --patch` may generate unexpected diff output for merge
3346 :hg:`log --patch` may generate unexpected diff output for merge
3346 changesets, as it will only compare the merge changeset against
3347 changesets, as it will only compare the merge changeset against
3347 its first parent. Also, only files different from BOTH parents
3348 its first parent. Also, only files different from BOTH parents
3348 will appear in files:.
3349 will appear in files:.
3349
3350
3350 .. note::
3351 .. note::
3351
3352
3352 For performance reasons, :hg:`log FILE` may omit duplicate changes
3353 For performance reasons, :hg:`log FILE` may omit duplicate changes
3353 made on branches and will not show removals or mode changes. To
3354 made on branches and will not show removals or mode changes. To
3354 see all such changes, use the --removed switch.
3355 see all such changes, use the --removed switch.
3355
3356
3356 .. container:: verbose
3357 .. container:: verbose
3357
3358
3358 Some examples:
3359 Some examples:
3359
3360
3360 - changesets with full descriptions and file lists::
3361 - changesets with full descriptions and file lists::
3361
3362
3362 hg log -v
3363 hg log -v
3363
3364
3364 - changesets ancestral to the working directory::
3365 - changesets ancestral to the working directory::
3365
3366
3366 hg log -f
3367 hg log -f
3367
3368
3368 - last 10 commits on the current branch::
3369 - last 10 commits on the current branch::
3369
3370
3370 hg log -l 10 -b .
3371 hg log -l 10 -b .
3371
3372
3372 - changesets showing all modifications of a file, including removals::
3373 - changesets showing all modifications of a file, including removals::
3373
3374
3374 hg log --removed file.c
3375 hg log --removed file.c
3375
3376
3376 - all changesets that touch a directory, with diffs, excluding merges::
3377 - all changesets that touch a directory, with diffs, excluding merges::
3377
3378
3378 hg log -Mp lib/
3379 hg log -Mp lib/
3379
3380
3380 - all revision numbers that match a keyword::
3381 - all revision numbers that match a keyword::
3381
3382
3382 hg log -k bug --template "{rev}\\n"
3383 hg log -k bug --template "{rev}\\n"
3383
3384
3384 - the full hash identifier of the working directory parent::
3385 - the full hash identifier of the working directory parent::
3385
3386
3386 hg log -r . --template "{node}\\n"
3387 hg log -r . --template "{node}\\n"
3387
3388
3388 - list available log templates::
3389 - list available log templates::
3389
3390
3390 hg log -T list
3391 hg log -T list
3391
3392
3392 - check if a given changeset is included in a tagged release::
3393 - check if a given changeset is included in a tagged release::
3393
3394
3394 hg log -r "a21ccf and ancestor(1.9)"
3395 hg log -r "a21ccf and ancestor(1.9)"
3395
3396
3396 - find all changesets by some user in a date range::
3397 - find all changesets by some user in a date range::
3397
3398
3398 hg log -k alice -d "may 2008 to jul 2008"
3399 hg log -k alice -d "may 2008 to jul 2008"
3399
3400
3400 - summary of all changesets after the last tag::
3401 - summary of all changesets after the last tag::
3401
3402
3402 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3403 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3403
3404
3404 See :hg:`help dates` for a list of formats valid for -d/--date.
3405 See :hg:`help dates` for a list of formats valid for -d/--date.
3405
3406
3406 See :hg:`help revisions` for more about specifying and ordering
3407 See :hg:`help revisions` for more about specifying and ordering
3407 revisions.
3408 revisions.
3408
3409
3409 See :hg:`help templates` for more about pre-packaged styles and
3410 See :hg:`help templates` for more about pre-packaged styles and
3410 specifying custom templates.
3411 specifying custom templates.
3411
3412
3412 Returns 0 on success.
3413 Returns 0 on success.
3413
3414
3414 """
3415 """
3415 if opts.get('follow') and opts.get('rev'):
3416 if opts.get('follow') and opts.get('rev'):
3416 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
3417 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
3417 del opts['follow']
3418 del opts['follow']
3418
3419
3419 if opts.get('graph'):
3420 if opts.get('graph'):
3420 return cmdutil.graphlog(ui, repo, *pats, **opts)
3421 return cmdutil.graphlog(ui, repo, *pats, **opts)
3421
3422
3422 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
3423 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
3423 limit = cmdutil.loglimit(opts)
3424 limit = cmdutil.loglimit(opts)
3424 count = 0
3425 count = 0
3425
3426
3426 getrenamed = None
3427 getrenamed = None
3427 if opts.get('copies'):
3428 if opts.get('copies'):
3428 endrev = None
3429 endrev = None
3429 if opts.get('rev'):
3430 if opts.get('rev'):
3430 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
3431 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
3431 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3432 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3432
3433
3433 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
3434 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
3434 for rev in revs:
3435 for rev in revs:
3435 if count == limit:
3436 if count == limit:
3436 break
3437 break
3437 ctx = repo[rev]
3438 ctx = repo[rev]
3438 copies = None
3439 copies = None
3439 if getrenamed is not None and rev:
3440 if getrenamed is not None and rev:
3440 copies = []
3441 copies = []
3441 for fn in ctx.files():
3442 for fn in ctx.files():
3442 rename = getrenamed(fn, rev)
3443 rename = getrenamed(fn, rev)
3443 if rename:
3444 if rename:
3444 copies.append((fn, rename[0]))
3445 copies.append((fn, rename[0]))
3445 if filematcher:
3446 if filematcher:
3446 revmatchfn = filematcher(ctx.rev())
3447 revmatchfn = filematcher(ctx.rev())
3447 else:
3448 else:
3448 revmatchfn = None
3449 revmatchfn = None
3449 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
3450 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
3450 if displayer.flush(ctx):
3451 if displayer.flush(ctx):
3451 count += 1
3452 count += 1
3452
3453
3453 displayer.close()
3454 displayer.close()
3454
3455
3455 @command('manifest',
3456 @command('manifest',
3456 [('r', 'rev', '', _('revision to display'), _('REV')),
3457 [('r', 'rev', '', _('revision to display'), _('REV')),
3457 ('', 'all', False, _("list files from all revisions"))]
3458 ('', 'all', False, _("list files from all revisions"))]
3458 + formatteropts,
3459 + formatteropts,
3459 _('[-r REV]'))
3460 _('[-r REV]'))
3460 def manifest(ui, repo, node=None, rev=None, **opts):
3461 def manifest(ui, repo, node=None, rev=None, **opts):
3461 """output the current or given revision of the project manifest
3462 """output the current or given revision of the project manifest
3462
3463
3463 Print a list of version controlled files for the given revision.
3464 Print a list of version controlled files for the given revision.
3464 If no revision is given, the first parent of the working directory
3465 If no revision is given, the first parent of the working directory
3465 is used, or the null revision if no revision is checked out.
3466 is used, or the null revision if no revision is checked out.
3466
3467
3467 With -v, print file permissions, symlink and executable bits.
3468 With -v, print file permissions, symlink and executable bits.
3468 With --debug, print file revision hashes.
3469 With --debug, print file revision hashes.
3469
3470
3470 If option --all is specified, the list of all files from all revisions
3471 If option --all is specified, the list of all files from all revisions
3471 is printed. This includes deleted and renamed files.
3472 is printed. This includes deleted and renamed files.
3472
3473
3473 Returns 0 on success.
3474 Returns 0 on success.
3474 """
3475 """
3475
3476
3476 fm = ui.formatter('manifest', opts)
3477 fm = ui.formatter('manifest', opts)
3477
3478
3478 if opts.get('all'):
3479 if opts.get('all'):
3479 if rev or node:
3480 if rev or node:
3480 raise error.Abort(_("can't specify a revision with --all"))
3481 raise error.Abort(_("can't specify a revision with --all"))
3481
3482
3482 res = []
3483 res = []
3483 prefix = "data/"
3484 prefix = "data/"
3484 suffix = ".i"
3485 suffix = ".i"
3485 plen = len(prefix)
3486 plen = len(prefix)
3486 slen = len(suffix)
3487 slen = len(suffix)
3487 with repo.lock():
3488 with repo.lock():
3488 for fn, b, size in repo.store.datafiles():
3489 for fn, b, size in repo.store.datafiles():
3489 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
3490 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
3490 res.append(fn[plen:-slen])
3491 res.append(fn[plen:-slen])
3491 for f in res:
3492 for f in res:
3492 fm.startitem()
3493 fm.startitem()
3493 fm.write("path", '%s\n', f)
3494 fm.write("path", '%s\n', f)
3494 fm.end()
3495 fm.end()
3495 return
3496 return
3496
3497
3497 if rev and node:
3498 if rev and node:
3498 raise error.Abort(_("please specify just one revision"))
3499 raise error.Abort(_("please specify just one revision"))
3499
3500
3500 if not node:
3501 if not node:
3501 node = rev
3502 node = rev
3502
3503
3503 char = {'l': '@', 'x': '*', '': ''}
3504 char = {'l': '@', 'x': '*', '': ''}
3504 mode = {'l': '644', 'x': '755', '': '644'}
3505 mode = {'l': '644', 'x': '755', '': '644'}
3505 ctx = scmutil.revsingle(repo, node)
3506 ctx = scmutil.revsingle(repo, node)
3506 mf = ctx.manifest()
3507 mf = ctx.manifest()
3507 for f in ctx:
3508 for f in ctx:
3508 fm.startitem()
3509 fm.startitem()
3509 fl = ctx[f].flags()
3510 fl = ctx[f].flags()
3510 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
3511 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
3511 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
3512 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
3512 fm.write('path', '%s\n', f)
3513 fm.write('path', '%s\n', f)
3513 fm.end()
3514 fm.end()
3514
3515
3515 @command('^merge',
3516 @command('^merge',
3516 [('f', 'force', None,
3517 [('f', 'force', None,
3517 _('force a merge including outstanding changes (DEPRECATED)')),
3518 _('force a merge including outstanding changes (DEPRECATED)')),
3518 ('r', 'rev', '', _('revision to merge'), _('REV')),
3519 ('r', 'rev', '', _('revision to merge'), _('REV')),
3519 ('P', 'preview', None,
3520 ('P', 'preview', None,
3520 _('review revisions to merge (no merge is performed)'))
3521 _('review revisions to merge (no merge is performed)'))
3521 ] + mergetoolopts,
3522 ] + mergetoolopts,
3522 _('[-P] [[-r] REV]'))
3523 _('[-P] [[-r] REV]'))
3523 def merge(ui, repo, node=None, **opts):
3524 def merge(ui, repo, node=None, **opts):
3524 """merge another revision into working directory
3525 """merge another revision into working directory
3525
3526
3526 The current working directory is updated with all changes made in
3527 The current working directory is updated with all changes made in
3527 the requested revision since the last common predecessor revision.
3528 the requested revision since the last common predecessor revision.
3528
3529
3529 Files that changed between either parent are marked as changed for
3530 Files that changed between either parent are marked as changed for
3530 the next commit and a commit must be performed before any further
3531 the next commit and a commit must be performed before any further
3531 updates to the repository are allowed. The next commit will have
3532 updates to the repository are allowed. The next commit will have
3532 two parents.
3533 two parents.
3533
3534
3534 ``--tool`` can be used to specify the merge tool used for file
3535 ``--tool`` can be used to specify the merge tool used for file
3535 merges. It overrides the HGMERGE environment variable and your
3536 merges. It overrides the HGMERGE environment variable and your
3536 configuration files. See :hg:`help merge-tools` for options.
3537 configuration files. See :hg:`help merge-tools` for options.
3537
3538
3538 If no revision is specified, the working directory's parent is a
3539 If no revision is specified, the working directory's parent is a
3539 head revision, and the current branch contains exactly one other
3540 head revision, and the current branch contains exactly one other
3540 head, the other head is merged with by default. Otherwise, an
3541 head, the other head is merged with by default. Otherwise, an
3541 explicit revision with which to merge with must be provided.
3542 explicit revision with which to merge with must be provided.
3542
3543
3543 See :hg:`help resolve` for information on handling file conflicts.
3544 See :hg:`help resolve` for information on handling file conflicts.
3544
3545
3545 To undo an uncommitted merge, use :hg:`update --clean .` which
3546 To undo an uncommitted merge, use :hg:`update --clean .` which
3546 will check out a clean copy of the original merge parent, losing
3547 will check out a clean copy of the original merge parent, losing
3547 all changes.
3548 all changes.
3548
3549
3549 Returns 0 on success, 1 if there are unresolved files.
3550 Returns 0 on success, 1 if there are unresolved files.
3550 """
3551 """
3551
3552
3552 if opts.get('rev') and node:
3553 if opts.get('rev') and node:
3553 raise error.Abort(_("please specify just one revision"))
3554 raise error.Abort(_("please specify just one revision"))
3554 if not node:
3555 if not node:
3555 node = opts.get('rev')
3556 node = opts.get('rev')
3556
3557
3557 if node:
3558 if node:
3558 node = scmutil.revsingle(repo, node).node()
3559 node = scmutil.revsingle(repo, node).node()
3559
3560
3560 if not node:
3561 if not node:
3561 node = repo[destutil.destmerge(repo)].node()
3562 node = repo[destutil.destmerge(repo)].node()
3562
3563
3563 if opts.get('preview'):
3564 if opts.get('preview'):
3564 # find nodes that are ancestors of p2 but not of p1
3565 # find nodes that are ancestors of p2 but not of p1
3565 p1 = repo.lookup('.')
3566 p1 = repo.lookup('.')
3566 p2 = repo.lookup(node)
3567 p2 = repo.lookup(node)
3567 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
3568 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
3568
3569
3569 displayer = cmdutil.show_changeset(ui, repo, opts)
3570 displayer = cmdutil.show_changeset(ui, repo, opts)
3570 for node in nodes:
3571 for node in nodes:
3571 displayer.show(repo[node])
3572 displayer.show(repo[node])
3572 displayer.close()
3573 displayer.close()
3573 return 0
3574 return 0
3574
3575
3575 try:
3576 try:
3576 # ui.forcemerge is an internal variable, do not document
3577 # ui.forcemerge is an internal variable, do not document
3577 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
3578 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
3578 force = opts.get('force')
3579 force = opts.get('force')
3579 labels = ['working copy', 'merge rev']
3580 labels = ['working copy', 'merge rev']
3580 return hg.merge(repo, node, force=force, mergeforce=force,
3581 return hg.merge(repo, node, force=force, mergeforce=force,
3581 labels=labels)
3582 labels=labels)
3582 finally:
3583 finally:
3583 ui.setconfig('ui', 'forcemerge', '', 'merge')
3584 ui.setconfig('ui', 'forcemerge', '', 'merge')
3584
3585
3585 @command('outgoing|out',
3586 @command('outgoing|out',
3586 [('f', 'force', None, _('run even when the destination is unrelated')),
3587 [('f', 'force', None, _('run even when the destination is unrelated')),
3587 ('r', 'rev', [],
3588 ('r', 'rev', [],
3588 _('a changeset intended to be included in the destination'), _('REV')),
3589 _('a changeset intended to be included in the destination'), _('REV')),
3589 ('n', 'newest-first', None, _('show newest record first')),
3590 ('n', 'newest-first', None, _('show newest record first')),
3590 ('B', 'bookmarks', False, _('compare bookmarks')),
3591 ('B', 'bookmarks', False, _('compare bookmarks')),
3591 ('b', 'branch', [], _('a specific branch you would like to push'),
3592 ('b', 'branch', [], _('a specific branch you would like to push'),
3592 _('BRANCH')),
3593 _('BRANCH')),
3593 ] + logopts + remoteopts + subrepoopts,
3594 ] + logopts + remoteopts + subrepoopts,
3594 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
3595 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
3595 def outgoing(ui, repo, dest=None, **opts):
3596 def outgoing(ui, repo, dest=None, **opts):
3596 """show changesets not found in the destination
3597 """show changesets not found in the destination
3597
3598
3598 Show changesets not found in the specified destination repository
3599 Show changesets not found in the specified destination repository
3599 or the default push location. These are the changesets that would
3600 or the default push location. These are the changesets that would
3600 be pushed if a push was requested.
3601 be pushed if a push was requested.
3601
3602
3602 See pull for details of valid destination formats.
3603 See pull for details of valid destination formats.
3603
3604
3604 .. container:: verbose
3605 .. container:: verbose
3605
3606
3606 With -B/--bookmarks, the result of bookmark comparison between
3607 With -B/--bookmarks, the result of bookmark comparison between
3607 local and remote repositories is displayed. With -v/--verbose,
3608 local and remote repositories is displayed. With -v/--verbose,
3608 status is also displayed for each bookmark like below::
3609 status is also displayed for each bookmark like below::
3609
3610
3610 BM1 01234567890a added
3611 BM1 01234567890a added
3611 BM2 deleted
3612 BM2 deleted
3612 BM3 234567890abc advanced
3613 BM3 234567890abc advanced
3613 BM4 34567890abcd diverged
3614 BM4 34567890abcd diverged
3614 BM5 4567890abcde changed
3615 BM5 4567890abcde changed
3615
3616
3616 The action taken when pushing depends on the
3617 The action taken when pushing depends on the
3617 status of each bookmark:
3618 status of each bookmark:
3618
3619
3619 :``added``: push with ``-B`` will create it
3620 :``added``: push with ``-B`` will create it
3620 :``deleted``: push with ``-B`` will delete it
3621 :``deleted``: push with ``-B`` will delete it
3621 :``advanced``: push will update it
3622 :``advanced``: push will update it
3622 :``diverged``: push with ``-B`` will update it
3623 :``diverged``: push with ``-B`` will update it
3623 :``changed``: push with ``-B`` will update it
3624 :``changed``: push with ``-B`` will update it
3624
3625
3625 From the point of view of pushing behavior, bookmarks
3626 From the point of view of pushing behavior, bookmarks
3626 existing only in the remote repository are treated as
3627 existing only in the remote repository are treated as
3627 ``deleted``, even if it is in fact added remotely.
3628 ``deleted``, even if it is in fact added remotely.
3628
3629
3629 Returns 0 if there are outgoing changes, 1 otherwise.
3630 Returns 0 if there are outgoing changes, 1 otherwise.
3630 """
3631 """
3631 if opts.get('graph'):
3632 if opts.get('graph'):
3632 cmdutil.checkunsupportedgraphflags([], opts)
3633 cmdutil.checkunsupportedgraphflags([], opts)
3633 o, other = hg._outgoing(ui, repo, dest, opts)
3634 o, other = hg._outgoing(ui, repo, dest, opts)
3634 if not o:
3635 if not o:
3635 cmdutil.outgoinghooks(ui, repo, other, opts, o)
3636 cmdutil.outgoinghooks(ui, repo, other, opts, o)
3636 return
3637 return
3637
3638
3638 revdag = cmdutil.graphrevs(repo, o, opts)
3639 revdag = cmdutil.graphrevs(repo, o, opts)
3639 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
3640 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
3640 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
3641 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
3641 cmdutil.outgoinghooks(ui, repo, other, opts, o)
3642 cmdutil.outgoinghooks(ui, repo, other, opts, o)
3642 return 0
3643 return 0
3643
3644
3644 if opts.get('bookmarks'):
3645 if opts.get('bookmarks'):
3645 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3646 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3646 dest, branches = hg.parseurl(dest, opts.get('branch'))
3647 dest, branches = hg.parseurl(dest, opts.get('branch'))
3647 other = hg.peer(repo, opts, dest)
3648 other = hg.peer(repo, opts, dest)
3648 if 'bookmarks' not in other.listkeys('namespaces'):
3649 if 'bookmarks' not in other.listkeys('namespaces'):
3649 ui.warn(_("remote doesn't support bookmarks\n"))
3650 ui.warn(_("remote doesn't support bookmarks\n"))
3650 return 0
3651 return 0
3651 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
3652 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
3652 return bookmarks.outgoing(ui, repo, other)
3653 return bookmarks.outgoing(ui, repo, other)
3653
3654
3654 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
3655 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
3655 try:
3656 try:
3656 return hg.outgoing(ui, repo, dest, opts)
3657 return hg.outgoing(ui, repo, dest, opts)
3657 finally:
3658 finally:
3658 del repo._subtoppath
3659 del repo._subtoppath
3659
3660
3660 @command('parents',
3661 @command('parents',
3661 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
3662 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
3662 ] + templateopts,
3663 ] + templateopts,
3663 _('[-r REV] [FILE]'),
3664 _('[-r REV] [FILE]'),
3664 inferrepo=True)
3665 inferrepo=True)
3665 def parents(ui, repo, file_=None, **opts):
3666 def parents(ui, repo, file_=None, **opts):
3666 """show the parents of the working directory or revision (DEPRECATED)
3667 """show the parents of the working directory or revision (DEPRECATED)
3667
3668
3668 Print the working directory's parent revisions. If a revision is
3669 Print the working directory's parent revisions. If a revision is
3669 given via -r/--rev, the parent of that revision will be printed.
3670 given via -r/--rev, the parent of that revision will be printed.
3670 If a file argument is given, the revision in which the file was
3671 If a file argument is given, the revision in which the file was
3671 last changed (before the working directory revision or the
3672 last changed (before the working directory revision or the
3672 argument to --rev if given) is printed.
3673 argument to --rev if given) is printed.
3673
3674
3674 This command is equivalent to::
3675 This command is equivalent to::
3675
3676
3676 hg log -r "p1()+p2()" or
3677 hg log -r "p1()+p2()" or
3677 hg log -r "p1(REV)+p2(REV)" or
3678 hg log -r "p1(REV)+p2(REV)" or
3678 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
3679 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
3679 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
3680 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
3680
3681
3681 See :hg:`summary` and :hg:`help revsets` for related information.
3682 See :hg:`summary` and :hg:`help revsets` for related information.
3682
3683
3683 Returns 0 on success.
3684 Returns 0 on success.
3684 """
3685 """
3685
3686
3686 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3687 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3687
3688
3688 if file_:
3689 if file_:
3689 m = scmutil.match(ctx, (file_,), opts)
3690 m = scmutil.match(ctx, (file_,), opts)
3690 if m.anypats() or len(m.files()) != 1:
3691 if m.anypats() or len(m.files()) != 1:
3691 raise error.Abort(_('can only specify an explicit filename'))
3692 raise error.Abort(_('can only specify an explicit filename'))
3692 file_ = m.files()[0]
3693 file_ = m.files()[0]
3693 filenodes = []
3694 filenodes = []
3694 for cp in ctx.parents():
3695 for cp in ctx.parents():
3695 if not cp:
3696 if not cp:
3696 continue
3697 continue
3697 try:
3698 try:
3698 filenodes.append(cp.filenode(file_))
3699 filenodes.append(cp.filenode(file_))
3699 except error.LookupError:
3700 except error.LookupError:
3700 pass
3701 pass
3701 if not filenodes:
3702 if not filenodes:
3702 raise error.Abort(_("'%s' not found in manifest!") % file_)
3703 raise error.Abort(_("'%s' not found in manifest!") % file_)
3703 p = []
3704 p = []
3704 for fn in filenodes:
3705 for fn in filenodes:
3705 fctx = repo.filectx(file_, fileid=fn)
3706 fctx = repo.filectx(file_, fileid=fn)
3706 p.append(fctx.node())
3707 p.append(fctx.node())
3707 else:
3708 else:
3708 p = [cp.node() for cp in ctx.parents()]
3709 p = [cp.node() for cp in ctx.parents()]
3709
3710
3710 displayer = cmdutil.show_changeset(ui, repo, opts)
3711 displayer = cmdutil.show_changeset(ui, repo, opts)
3711 for n in p:
3712 for n in p:
3712 if n != nullid:
3713 if n != nullid:
3713 displayer.show(repo[n])
3714 displayer.show(repo[n])
3714 displayer.close()
3715 displayer.close()
3715
3716
3716 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True)
3717 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True)
3717 def paths(ui, repo, search=None, **opts):
3718 def paths(ui, repo, search=None, **opts):
3718 """show aliases for remote repositories
3719 """show aliases for remote repositories
3719
3720
3720 Show definition of symbolic path name NAME. If no name is given,
3721 Show definition of symbolic path name NAME. If no name is given,
3721 show definition of all available names.
3722 show definition of all available names.
3722
3723
3723 Option -q/--quiet suppresses all output when searching for NAME
3724 Option -q/--quiet suppresses all output when searching for NAME
3724 and shows only the path names when listing all definitions.
3725 and shows only the path names when listing all definitions.
3725
3726
3726 Path names are defined in the [paths] section of your
3727 Path names are defined in the [paths] section of your
3727 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
3728 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
3728 repository, ``.hg/hgrc`` is used, too.
3729 repository, ``.hg/hgrc`` is used, too.
3729
3730
3730 The path names ``default`` and ``default-push`` have a special
3731 The path names ``default`` and ``default-push`` have a special
3731 meaning. When performing a push or pull operation, they are used
3732 meaning. When performing a push or pull operation, they are used
3732 as fallbacks if no location is specified on the command-line.
3733 as fallbacks if no location is specified on the command-line.
3733 When ``default-push`` is set, it will be used for push and
3734 When ``default-push`` is set, it will be used for push and
3734 ``default`` will be used for pull; otherwise ``default`` is used
3735 ``default`` will be used for pull; otherwise ``default`` is used
3735 as the fallback for both. When cloning a repository, the clone
3736 as the fallback for both. When cloning a repository, the clone
3736 source is written as ``default`` in ``.hg/hgrc``.
3737 source is written as ``default`` in ``.hg/hgrc``.
3737
3738
3738 .. note::
3739 .. note::
3739
3740
3740 ``default`` and ``default-push`` apply to all inbound (e.g.
3741 ``default`` and ``default-push`` apply to all inbound (e.g.
3741 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
3742 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
3742 and :hg:`bundle`) operations.
3743 and :hg:`bundle`) operations.
3743
3744
3744 See :hg:`help urls` for more information.
3745 See :hg:`help urls` for more information.
3745
3746
3746 Returns 0 on success.
3747 Returns 0 on success.
3747 """
3748 """
3748 if search:
3749 if search:
3749 pathitems = [(name, path) for name, path in ui.paths.iteritems()
3750 pathitems = [(name, path) for name, path in ui.paths.iteritems()
3750 if name == search]
3751 if name == search]
3751 else:
3752 else:
3752 pathitems = sorted(ui.paths.iteritems())
3753 pathitems = sorted(ui.paths.iteritems())
3753
3754
3754 fm = ui.formatter('paths', opts)
3755 fm = ui.formatter('paths', opts)
3755 if fm.isplain():
3756 if fm.isplain():
3756 hidepassword = util.hidepassword
3757 hidepassword = util.hidepassword
3757 else:
3758 else:
3758 hidepassword = str
3759 hidepassword = str
3759 if ui.quiet:
3760 if ui.quiet:
3760 namefmt = '%s\n'
3761 namefmt = '%s\n'
3761 else:
3762 else:
3762 namefmt = '%s = '
3763 namefmt = '%s = '
3763 showsubopts = not search and not ui.quiet
3764 showsubopts = not search and not ui.quiet
3764
3765
3765 for name, path in pathitems:
3766 for name, path in pathitems:
3766 fm.startitem()
3767 fm.startitem()
3767 fm.condwrite(not search, 'name', namefmt, name)
3768 fm.condwrite(not search, 'name', namefmt, name)
3768 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
3769 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
3769 for subopt, value in sorted(path.suboptions.items()):
3770 for subopt, value in sorted(path.suboptions.items()):
3770 assert subopt not in ('name', 'url')
3771 assert subopt not in ('name', 'url')
3771 if showsubopts:
3772 if showsubopts:
3772 fm.plain('%s:%s = ' % (name, subopt))
3773 fm.plain('%s:%s = ' % (name, subopt))
3773 fm.condwrite(showsubopts, subopt, '%s\n', value)
3774 fm.condwrite(showsubopts, subopt, '%s\n', value)
3774
3775
3775 fm.end()
3776 fm.end()
3776
3777
3777 if search and not pathitems:
3778 if search and not pathitems:
3778 if not ui.quiet:
3779 if not ui.quiet:
3779 ui.warn(_("not found!\n"))
3780 ui.warn(_("not found!\n"))
3780 return 1
3781 return 1
3781 else:
3782 else:
3782 return 0
3783 return 0
3783
3784
3784 @command('phase',
3785 @command('phase',
3785 [('p', 'public', False, _('set changeset phase to public')),
3786 [('p', 'public', False, _('set changeset phase to public')),
3786 ('d', 'draft', False, _('set changeset phase to draft')),
3787 ('d', 'draft', False, _('set changeset phase to draft')),
3787 ('s', 'secret', False, _('set changeset phase to secret')),
3788 ('s', 'secret', False, _('set changeset phase to secret')),
3788 ('f', 'force', False, _('allow to move boundary backward')),
3789 ('f', 'force', False, _('allow to move boundary backward')),
3789 ('r', 'rev', [], _('target revision'), _('REV')),
3790 ('r', 'rev', [], _('target revision'), _('REV')),
3790 ],
3791 ],
3791 _('[-p|-d|-s] [-f] [-r] [REV...]'))
3792 _('[-p|-d|-s] [-f] [-r] [REV...]'))
3792 def phase(ui, repo, *revs, **opts):
3793 def phase(ui, repo, *revs, **opts):
3793 """set or show the current phase name
3794 """set or show the current phase name
3794
3795
3795 With no argument, show the phase name of the current revision(s).
3796 With no argument, show the phase name of the current revision(s).
3796
3797
3797 With one of -p/--public, -d/--draft or -s/--secret, change the
3798 With one of -p/--public, -d/--draft or -s/--secret, change the
3798 phase value of the specified revisions.
3799 phase value of the specified revisions.
3799
3800
3800 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
3801 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
3801 lower phase to an higher phase. Phases are ordered as follows::
3802 lower phase to an higher phase. Phases are ordered as follows::
3802
3803
3803 public < draft < secret
3804 public < draft < secret
3804
3805
3805 Returns 0 on success, 1 if some phases could not be changed.
3806 Returns 0 on success, 1 if some phases could not be changed.
3806
3807
3807 (For more information about the phases concept, see :hg:`help phases`.)
3808 (For more information about the phases concept, see :hg:`help phases`.)
3808 """
3809 """
3809 # search for a unique phase argument
3810 # search for a unique phase argument
3810 targetphase = None
3811 targetphase = None
3811 for idx, name in enumerate(phases.phasenames):
3812 for idx, name in enumerate(phases.phasenames):
3812 if opts[name]:
3813 if opts[name]:
3813 if targetphase is not None:
3814 if targetphase is not None:
3814 raise error.Abort(_('only one phase can be specified'))
3815 raise error.Abort(_('only one phase can be specified'))
3815 targetphase = idx
3816 targetphase = idx
3816
3817
3817 # look for specified revision
3818 # look for specified revision
3818 revs = list(revs)
3819 revs = list(revs)
3819 revs.extend(opts['rev'])
3820 revs.extend(opts['rev'])
3820 if not revs:
3821 if not revs:
3821 # display both parents as the second parent phase can influence
3822 # display both parents as the second parent phase can influence
3822 # the phase of a merge commit
3823 # the phase of a merge commit
3823 revs = [c.rev() for c in repo[None].parents()]
3824 revs = [c.rev() for c in repo[None].parents()]
3824
3825
3825 revs = scmutil.revrange(repo, revs)
3826 revs = scmutil.revrange(repo, revs)
3826
3827
3827 lock = None
3828 lock = None
3828 ret = 0
3829 ret = 0
3829 if targetphase is None:
3830 if targetphase is None:
3830 # display
3831 # display
3831 for r in revs:
3832 for r in revs:
3832 ctx = repo[r]
3833 ctx = repo[r]
3833 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
3834 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
3834 else:
3835 else:
3835 tr = None
3836 tr = None
3836 lock = repo.lock()
3837 lock = repo.lock()
3837 try:
3838 try:
3838 tr = repo.transaction("phase")
3839 tr = repo.transaction("phase")
3839 # set phase
3840 # set phase
3840 if not revs:
3841 if not revs:
3841 raise error.Abort(_('empty revision set'))
3842 raise error.Abort(_('empty revision set'))
3842 nodes = [repo[r].node() for r in revs]
3843 nodes = [repo[r].node() for r in revs]
3843 # moving revision from public to draft may hide them
3844 # moving revision from public to draft may hide them
3844 # We have to check result on an unfiltered repository
3845 # We have to check result on an unfiltered repository
3845 unfi = repo.unfiltered()
3846 unfi = repo.unfiltered()
3846 getphase = unfi._phasecache.phase
3847 getphase = unfi._phasecache.phase
3847 olddata = [getphase(unfi, r) for r in unfi]
3848 olddata = [getphase(unfi, r) for r in unfi]
3848 phases.advanceboundary(repo, tr, targetphase, nodes)
3849 phases.advanceboundary(repo, tr, targetphase, nodes)
3849 if opts['force']:
3850 if opts['force']:
3850 phases.retractboundary(repo, tr, targetphase, nodes)
3851 phases.retractboundary(repo, tr, targetphase, nodes)
3851 tr.close()
3852 tr.close()
3852 finally:
3853 finally:
3853 if tr is not None:
3854 if tr is not None:
3854 tr.release()
3855 tr.release()
3855 lock.release()
3856 lock.release()
3856 getphase = unfi._phasecache.phase
3857 getphase = unfi._phasecache.phase
3857 newdata = [getphase(unfi, r) for r in unfi]
3858 newdata = [getphase(unfi, r) for r in unfi]
3858 changes = sum(newdata[r] != olddata[r] for r in unfi)
3859 changes = sum(newdata[r] != olddata[r] for r in unfi)
3859 cl = unfi.changelog
3860 cl = unfi.changelog
3860 rejected = [n for n in nodes
3861 rejected = [n for n in nodes
3861 if newdata[cl.rev(n)] < targetphase]
3862 if newdata[cl.rev(n)] < targetphase]
3862 if rejected:
3863 if rejected:
3863 ui.warn(_('cannot move %i changesets to a higher '
3864 ui.warn(_('cannot move %i changesets to a higher '
3864 'phase, use --force\n') % len(rejected))
3865 'phase, use --force\n') % len(rejected))
3865 ret = 1
3866 ret = 1
3866 if changes:
3867 if changes:
3867 msg = _('phase changed for %i changesets\n') % changes
3868 msg = _('phase changed for %i changesets\n') % changes
3868 if ret:
3869 if ret:
3869 ui.status(msg)
3870 ui.status(msg)
3870 else:
3871 else:
3871 ui.note(msg)
3872 ui.note(msg)
3872 else:
3873 else:
3873 ui.warn(_('no phases changed\n'))
3874 ui.warn(_('no phases changed\n'))
3874 return ret
3875 return ret
3875
3876
3876 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
3877 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
3877 """Run after a changegroup has been added via pull/unbundle
3878 """Run after a changegroup has been added via pull/unbundle
3878
3879
3879 This takes arguments below:
3880 This takes arguments below:
3880
3881
3881 :modheads: change of heads by pull/unbundle
3882 :modheads: change of heads by pull/unbundle
3882 :optupdate: updating working directory is needed or not
3883 :optupdate: updating working directory is needed or not
3883 :checkout: update destination revision (or None to default destination)
3884 :checkout: update destination revision (or None to default destination)
3884 :brev: a name, which might be a bookmark to be activated after updating
3885 :brev: a name, which might be a bookmark to be activated after updating
3885 """
3886 """
3886 if modheads == 0:
3887 if modheads == 0:
3887 return
3888 return
3888 if optupdate:
3889 if optupdate:
3889 try:
3890 try:
3890 return hg.updatetotally(ui, repo, checkout, brev)
3891 return hg.updatetotally(ui, repo, checkout, brev)
3891 except error.UpdateAbort as inst:
3892 except error.UpdateAbort as inst:
3892 msg = _("not updating: %s") % str(inst)
3893 msg = _("not updating: %s") % str(inst)
3893 hint = inst.hint
3894 hint = inst.hint
3894 raise error.UpdateAbort(msg, hint=hint)
3895 raise error.UpdateAbort(msg, hint=hint)
3895 if modheads > 1:
3896 if modheads > 1:
3896 currentbranchheads = len(repo.branchheads())
3897 currentbranchheads = len(repo.branchheads())
3897 if currentbranchheads == modheads:
3898 if currentbranchheads == modheads:
3898 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
3899 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
3899 elif currentbranchheads > 1:
3900 elif currentbranchheads > 1:
3900 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
3901 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
3901 "merge)\n"))
3902 "merge)\n"))
3902 else:
3903 else:
3903 ui.status(_("(run 'hg heads' to see heads)\n"))
3904 ui.status(_("(run 'hg heads' to see heads)\n"))
3904 else:
3905 else:
3905 ui.status(_("(run 'hg update' to get a working copy)\n"))
3906 ui.status(_("(run 'hg update' to get a working copy)\n"))
3906
3907
3907 @command('^pull',
3908 @command('^pull',
3908 [('u', 'update', None,
3909 [('u', 'update', None,
3909 _('update to new branch head if changesets were pulled')),
3910 _('update to new branch head if changesets were pulled')),
3910 ('f', 'force', None, _('run even when remote repository is unrelated')),
3911 ('f', 'force', None, _('run even when remote repository is unrelated')),
3911 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3912 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3912 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
3913 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
3913 ('b', 'branch', [], _('a specific branch you would like to pull'),
3914 ('b', 'branch', [], _('a specific branch you would like to pull'),
3914 _('BRANCH')),
3915 _('BRANCH')),
3915 ] + remoteopts,
3916 ] + remoteopts,
3916 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
3917 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
3917 def pull(ui, repo, source="default", **opts):
3918 def pull(ui, repo, source="default", **opts):
3918 """pull changes from the specified source
3919 """pull changes from the specified source
3919
3920
3920 Pull changes from a remote repository to a local one.
3921 Pull changes from a remote repository to a local one.
3921
3922
3922 This finds all changes from the repository at the specified path
3923 This finds all changes from the repository at the specified path
3923 or URL and adds them to a local repository (the current one unless
3924 or URL and adds them to a local repository (the current one unless
3924 -R is specified). By default, this does not update the copy of the
3925 -R is specified). By default, this does not update the copy of the
3925 project in the working directory.
3926 project in the working directory.
3926
3927
3927 Use :hg:`incoming` if you want to see what would have been added
3928 Use :hg:`incoming` if you want to see what would have been added
3928 by a pull at the time you issued this command. If you then decide
3929 by a pull at the time you issued this command. If you then decide
3929 to add those changes to the repository, you should use :hg:`pull
3930 to add those changes to the repository, you should use :hg:`pull
3930 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
3931 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
3931
3932
3932 If SOURCE is omitted, the 'default' path will be used.
3933 If SOURCE is omitted, the 'default' path will be used.
3933 See :hg:`help urls` for more information.
3934 See :hg:`help urls` for more information.
3934
3935
3935 Specifying bookmark as ``.`` is equivalent to specifying the active
3936 Specifying bookmark as ``.`` is equivalent to specifying the active
3936 bookmark's name.
3937 bookmark's name.
3937
3938
3938 Returns 0 on success, 1 if an update had unresolved files.
3939 Returns 0 on success, 1 if an update had unresolved files.
3939 """
3940 """
3940 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
3941 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
3941 ui.status(_('pulling from %s\n') % util.hidepassword(source))
3942 ui.status(_('pulling from %s\n') % util.hidepassword(source))
3942 other = hg.peer(repo, opts, source)
3943 other = hg.peer(repo, opts, source)
3943 try:
3944 try:
3944 revs, checkout = hg.addbranchrevs(repo, other, branches,
3945 revs, checkout = hg.addbranchrevs(repo, other, branches,
3945 opts.get('rev'))
3946 opts.get('rev'))
3946
3947
3947
3948
3948 pullopargs = {}
3949 pullopargs = {}
3949 if opts.get('bookmark'):
3950 if opts.get('bookmark'):
3950 if not revs:
3951 if not revs:
3951 revs = []
3952 revs = []
3952 # The list of bookmark used here is not the one used to actually
3953 # The list of bookmark used here is not the one used to actually
3953 # update the bookmark name. This can result in the revision pulled
3954 # update the bookmark name. This can result in the revision pulled
3954 # not ending up with the name of the bookmark because of a race
3955 # not ending up with the name of the bookmark because of a race
3955 # condition on the server. (See issue 4689 for details)
3956 # condition on the server. (See issue 4689 for details)
3956 remotebookmarks = other.listkeys('bookmarks')
3957 remotebookmarks = other.listkeys('bookmarks')
3957 pullopargs['remotebookmarks'] = remotebookmarks
3958 pullopargs['remotebookmarks'] = remotebookmarks
3958 for b in opts['bookmark']:
3959 for b in opts['bookmark']:
3959 b = repo._bookmarks.expandname(b)
3960 b = repo._bookmarks.expandname(b)
3960 if b not in remotebookmarks:
3961 if b not in remotebookmarks:
3961 raise error.Abort(_('remote bookmark %s not found!') % b)
3962 raise error.Abort(_('remote bookmark %s not found!') % b)
3962 revs.append(remotebookmarks[b])
3963 revs.append(remotebookmarks[b])
3963
3964
3964 if revs:
3965 if revs:
3965 try:
3966 try:
3966 # When 'rev' is a bookmark name, we cannot guarantee that it
3967 # When 'rev' is a bookmark name, we cannot guarantee that it
3967 # will be updated with that name because of a race condition
3968 # will be updated with that name because of a race condition
3968 # server side. (See issue 4689 for details)
3969 # server side. (See issue 4689 for details)
3969 oldrevs = revs
3970 oldrevs = revs
3970 revs = [] # actually, nodes
3971 revs = [] # actually, nodes
3971 for r in oldrevs:
3972 for r in oldrevs:
3972 node = other.lookup(r)
3973 node = other.lookup(r)
3973 revs.append(node)
3974 revs.append(node)
3974 if r == checkout:
3975 if r == checkout:
3975 checkout = node
3976 checkout = node
3976 except error.CapabilityError:
3977 except error.CapabilityError:
3977 err = _("other repository doesn't support revision lookup, "
3978 err = _("other repository doesn't support revision lookup, "
3978 "so a rev cannot be specified.")
3979 "so a rev cannot be specified.")
3979 raise error.Abort(err)
3980 raise error.Abort(err)
3980
3981
3981 pullopargs.update(opts.get('opargs', {}))
3982 pullopargs.update(opts.get('opargs', {}))
3982 modheads = exchange.pull(repo, other, heads=revs,
3983 modheads = exchange.pull(repo, other, heads=revs,
3983 force=opts.get('force'),
3984 force=opts.get('force'),
3984 bookmarks=opts.get('bookmark', ()),
3985 bookmarks=opts.get('bookmark', ()),
3985 opargs=pullopargs).cgresult
3986 opargs=pullopargs).cgresult
3986
3987
3987 # brev is a name, which might be a bookmark to be activated at
3988 # brev is a name, which might be a bookmark to be activated at
3988 # the end of the update. In other words, it is an explicit
3989 # the end of the update. In other words, it is an explicit
3989 # destination of the update
3990 # destination of the update
3990 brev = None
3991 brev = None
3991
3992
3992 if checkout:
3993 if checkout:
3993 checkout = str(repo.changelog.rev(checkout))
3994 checkout = str(repo.changelog.rev(checkout))
3994
3995
3995 # order below depends on implementation of
3996 # order below depends on implementation of
3996 # hg.addbranchrevs(). opts['bookmark'] is ignored,
3997 # hg.addbranchrevs(). opts['bookmark'] is ignored,
3997 # because 'checkout' is determined without it.
3998 # because 'checkout' is determined without it.
3998 if opts.get('rev'):
3999 if opts.get('rev'):
3999 brev = opts['rev'][0]
4000 brev = opts['rev'][0]
4000 elif opts.get('branch'):
4001 elif opts.get('branch'):
4001 brev = opts['branch'][0]
4002 brev = opts['branch'][0]
4002 else:
4003 else:
4003 brev = branches[0]
4004 brev = branches[0]
4004 repo._subtoppath = source
4005 repo._subtoppath = source
4005 try:
4006 try:
4006 ret = postincoming(ui, repo, modheads, opts.get('update'),
4007 ret = postincoming(ui, repo, modheads, opts.get('update'),
4007 checkout, brev)
4008 checkout, brev)
4008
4009
4009 finally:
4010 finally:
4010 del repo._subtoppath
4011 del repo._subtoppath
4011
4012
4012 finally:
4013 finally:
4013 other.close()
4014 other.close()
4014 return ret
4015 return ret
4015
4016
4016 @command('^push',
4017 @command('^push',
4017 [('f', 'force', None, _('force push')),
4018 [('f', 'force', None, _('force push')),
4018 ('r', 'rev', [],
4019 ('r', 'rev', [],
4019 _('a changeset intended to be included in the destination'),
4020 _('a changeset intended to be included in the destination'),
4020 _('REV')),
4021 _('REV')),
4021 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4022 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4022 ('b', 'branch', [],
4023 ('b', 'branch', [],
4023 _('a specific branch you would like to push'), _('BRANCH')),
4024 _('a specific branch you would like to push'), _('BRANCH')),
4024 ('', 'new-branch', False, _('allow pushing a new branch')),
4025 ('', 'new-branch', False, _('allow pushing a new branch')),
4025 ] + remoteopts,
4026 ] + remoteopts,
4026 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4027 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4027 def push(ui, repo, dest=None, **opts):
4028 def push(ui, repo, dest=None, **opts):
4028 """push changes to the specified destination
4029 """push changes to the specified destination
4029
4030
4030 Push changesets from the local repository to the specified
4031 Push changesets from the local repository to the specified
4031 destination.
4032 destination.
4032
4033
4033 This operation is symmetrical to pull: it is identical to a pull
4034 This operation is symmetrical to pull: it is identical to a pull
4034 in the destination repository from the current one.
4035 in the destination repository from the current one.
4035
4036
4036 By default, push will not allow creation of new heads at the
4037 By default, push will not allow creation of new heads at the
4037 destination, since multiple heads would make it unclear which head
4038 destination, since multiple heads would make it unclear which head
4038 to use. In this situation, it is recommended to pull and merge
4039 to use. In this situation, it is recommended to pull and merge
4039 before pushing.
4040 before pushing.
4040
4041
4041 Use --new-branch if you want to allow push to create a new named
4042 Use --new-branch if you want to allow push to create a new named
4042 branch that is not present at the destination. This allows you to
4043 branch that is not present at the destination. This allows you to
4043 only create a new branch without forcing other changes.
4044 only create a new branch without forcing other changes.
4044
4045
4045 .. note::
4046 .. note::
4046
4047
4047 Extra care should be taken with the -f/--force option,
4048 Extra care should be taken with the -f/--force option,
4048 which will push all new heads on all branches, an action which will
4049 which will push all new heads on all branches, an action which will
4049 almost always cause confusion for collaborators.
4050 almost always cause confusion for collaborators.
4050
4051
4051 If -r/--rev is used, the specified revision and all its ancestors
4052 If -r/--rev is used, the specified revision and all its ancestors
4052 will be pushed to the remote repository.
4053 will be pushed to the remote repository.
4053
4054
4054 If -B/--bookmark is used, the specified bookmarked revision, its
4055 If -B/--bookmark is used, the specified bookmarked revision, its
4055 ancestors, and the bookmark will be pushed to the remote
4056 ancestors, and the bookmark will be pushed to the remote
4056 repository. Specifying ``.`` is equivalent to specifying the active
4057 repository. Specifying ``.`` is equivalent to specifying the active
4057 bookmark's name.
4058 bookmark's name.
4058
4059
4059 Please see :hg:`help urls` for important details about ``ssh://``
4060 Please see :hg:`help urls` for important details about ``ssh://``
4060 URLs. If DESTINATION is omitted, a default path will be used.
4061 URLs. If DESTINATION is omitted, a default path will be used.
4061
4062
4062 Returns 0 if push was successful, 1 if nothing to push.
4063 Returns 0 if push was successful, 1 if nothing to push.
4063 """
4064 """
4064
4065
4065 if opts.get('bookmark'):
4066 if opts.get('bookmark'):
4066 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
4067 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
4067 for b in opts['bookmark']:
4068 for b in opts['bookmark']:
4068 # translate -B options to -r so changesets get pushed
4069 # translate -B options to -r so changesets get pushed
4069 b = repo._bookmarks.expandname(b)
4070 b = repo._bookmarks.expandname(b)
4070 if b in repo._bookmarks:
4071 if b in repo._bookmarks:
4071 opts.setdefault('rev', []).append(b)
4072 opts.setdefault('rev', []).append(b)
4072 else:
4073 else:
4073 # if we try to push a deleted bookmark, translate it to null
4074 # if we try to push a deleted bookmark, translate it to null
4074 # this lets simultaneous -r, -b options continue working
4075 # this lets simultaneous -r, -b options continue working
4075 opts.setdefault('rev', []).append("null")
4076 opts.setdefault('rev', []).append("null")
4076
4077
4077 path = ui.paths.getpath(dest, default=('default-push', 'default'))
4078 path = ui.paths.getpath(dest, default=('default-push', 'default'))
4078 if not path:
4079 if not path:
4079 raise error.Abort(_('default repository not configured!'),
4080 raise error.Abort(_('default repository not configured!'),
4080 hint=_("see 'hg help config.paths'"))
4081 hint=_("see 'hg help config.paths'"))
4081 dest = path.pushloc or path.loc
4082 dest = path.pushloc or path.loc
4082 branches = (path.branch, opts.get('branch') or [])
4083 branches = (path.branch, opts.get('branch') or [])
4083 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4084 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4084 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4085 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4085 other = hg.peer(repo, opts, dest)
4086 other = hg.peer(repo, opts, dest)
4086
4087
4087 if revs:
4088 if revs:
4088 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4089 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4089 if not revs:
4090 if not revs:
4090 raise error.Abort(_("specified revisions evaluate to an empty set"),
4091 raise error.Abort(_("specified revisions evaluate to an empty set"),
4091 hint=_("use different revision arguments"))
4092 hint=_("use different revision arguments"))
4092 elif path.pushrev:
4093 elif path.pushrev:
4093 # It doesn't make any sense to specify ancestor revisions. So limit
4094 # It doesn't make any sense to specify ancestor revisions. So limit
4094 # to DAG heads to make discovery simpler.
4095 # to DAG heads to make discovery simpler.
4095 expr = revset.formatspec('heads(%r)', path.pushrev)
4096 expr = revset.formatspec('heads(%r)', path.pushrev)
4096 revs = scmutil.revrange(repo, [expr])
4097 revs = scmutil.revrange(repo, [expr])
4097 revs = [repo[rev].node() for rev in revs]
4098 revs = [repo[rev].node() for rev in revs]
4098 if not revs:
4099 if not revs:
4099 raise error.Abort(_('default push revset for path evaluates to an '
4100 raise error.Abort(_('default push revset for path evaluates to an '
4100 'empty set'))
4101 'empty set'))
4101
4102
4102 repo._subtoppath = dest
4103 repo._subtoppath = dest
4103 try:
4104 try:
4104 # push subrepos depth-first for coherent ordering
4105 # push subrepos depth-first for coherent ordering
4105 c = repo['']
4106 c = repo['']
4106 subs = c.substate # only repos that are committed
4107 subs = c.substate # only repos that are committed
4107 for s in sorted(subs):
4108 for s in sorted(subs):
4108 result = c.sub(s).push(opts)
4109 result = c.sub(s).push(opts)
4109 if result == 0:
4110 if result == 0:
4110 return not result
4111 return not result
4111 finally:
4112 finally:
4112 del repo._subtoppath
4113 del repo._subtoppath
4113 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
4114 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
4114 newbranch=opts.get('new_branch'),
4115 newbranch=opts.get('new_branch'),
4115 bookmarks=opts.get('bookmark', ()),
4116 bookmarks=opts.get('bookmark', ()),
4116 opargs=opts.get('opargs'))
4117 opargs=opts.get('opargs'))
4117
4118
4118 result = not pushop.cgresult
4119 result = not pushop.cgresult
4119
4120
4120 if pushop.bkresult is not None:
4121 if pushop.bkresult is not None:
4121 if pushop.bkresult == 2:
4122 if pushop.bkresult == 2:
4122 result = 2
4123 result = 2
4123 elif not result and pushop.bkresult:
4124 elif not result and pushop.bkresult:
4124 result = 2
4125 result = 2
4125
4126
4126 return result
4127 return result
4127
4128
4128 @command('recover', [])
4129 @command('recover', [])
4129 def recover(ui, repo):
4130 def recover(ui, repo):
4130 """roll back an interrupted transaction
4131 """roll back an interrupted transaction
4131
4132
4132 Recover from an interrupted commit or pull.
4133 Recover from an interrupted commit or pull.
4133
4134
4134 This command tries to fix the repository status after an
4135 This command tries to fix the repository status after an
4135 interrupted operation. It should only be necessary when Mercurial
4136 interrupted operation. It should only be necessary when Mercurial
4136 suggests it.
4137 suggests it.
4137
4138
4138 Returns 0 if successful, 1 if nothing to recover or verify fails.
4139 Returns 0 if successful, 1 if nothing to recover or verify fails.
4139 """
4140 """
4140 if repo.recover():
4141 if repo.recover():
4141 return hg.verify(repo)
4142 return hg.verify(repo)
4142 return 1
4143 return 1
4143
4144
4144 @command('^remove|rm',
4145 @command('^remove|rm',
4145 [('A', 'after', None, _('record delete for missing files')),
4146 [('A', 'after', None, _('record delete for missing files')),
4146 ('f', 'force', None,
4147 ('f', 'force', None,
4147 _('forget added files, delete modified files')),
4148 _('forget added files, delete modified files')),
4148 ] + subrepoopts + walkopts,
4149 ] + subrepoopts + walkopts,
4149 _('[OPTION]... FILE...'),
4150 _('[OPTION]... FILE...'),
4150 inferrepo=True)
4151 inferrepo=True)
4151 def remove(ui, repo, *pats, **opts):
4152 def remove(ui, repo, *pats, **opts):
4152 """remove the specified files on the next commit
4153 """remove the specified files on the next commit
4153
4154
4154 Schedule the indicated files for removal from the current branch.
4155 Schedule the indicated files for removal from the current branch.
4155
4156
4156 This command schedules the files to be removed at the next commit.
4157 This command schedules the files to be removed at the next commit.
4157 To undo a remove before that, see :hg:`revert`. To undo added
4158 To undo a remove before that, see :hg:`revert`. To undo added
4158 files, see :hg:`forget`.
4159 files, see :hg:`forget`.
4159
4160
4160 .. container:: verbose
4161 .. container:: verbose
4161
4162
4162 -A/--after can be used to remove only files that have already
4163 -A/--after can be used to remove only files that have already
4163 been deleted, -f/--force can be used to force deletion, and -Af
4164 been deleted, -f/--force can be used to force deletion, and -Af
4164 can be used to remove files from the next revision without
4165 can be used to remove files from the next revision without
4165 deleting them from the working directory.
4166 deleting them from the working directory.
4166
4167
4167 The following table details the behavior of remove for different
4168 The following table details the behavior of remove for different
4168 file states (columns) and option combinations (rows). The file
4169 file states (columns) and option combinations (rows). The file
4169 states are Added [A], Clean [C], Modified [M] and Missing [!]
4170 states are Added [A], Clean [C], Modified [M] and Missing [!]
4170 (as reported by :hg:`status`). The actions are Warn, Remove
4171 (as reported by :hg:`status`). The actions are Warn, Remove
4171 (from branch) and Delete (from disk):
4172 (from branch) and Delete (from disk):
4172
4173
4173 ========= == == == ==
4174 ========= == == == ==
4174 opt/state A C M !
4175 opt/state A C M !
4175 ========= == == == ==
4176 ========= == == == ==
4176 none W RD W R
4177 none W RD W R
4177 -f R RD RD R
4178 -f R RD RD R
4178 -A W W W R
4179 -A W W W R
4179 -Af R R R R
4180 -Af R R R R
4180 ========= == == == ==
4181 ========= == == == ==
4181
4182
4182 .. note::
4183 .. note::
4183
4184
4184 :hg:`remove` never deletes files in Added [A] state from the
4185 :hg:`remove` never deletes files in Added [A] state from the
4185 working directory, not even if ``--force`` is specified.
4186 working directory, not even if ``--force`` is specified.
4186
4187
4187 Returns 0 on success, 1 if any warnings encountered.
4188 Returns 0 on success, 1 if any warnings encountered.
4188 """
4189 """
4189
4190
4190 after, force = opts.get('after'), opts.get('force')
4191 after, force = opts.get('after'), opts.get('force')
4191 if not pats and not after:
4192 if not pats and not after:
4192 raise error.Abort(_('no files specified'))
4193 raise error.Abort(_('no files specified'))
4193
4194
4194 m = scmutil.match(repo[None], pats, opts)
4195 m = scmutil.match(repo[None], pats, opts)
4195 subrepos = opts.get('subrepos')
4196 subrepos = opts.get('subrepos')
4196 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
4197 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
4197
4198
4198 @command('rename|move|mv',
4199 @command('rename|move|mv',
4199 [('A', 'after', None, _('record a rename that has already occurred')),
4200 [('A', 'after', None, _('record a rename that has already occurred')),
4200 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4201 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4201 ] + walkopts + dryrunopts,
4202 ] + walkopts + dryrunopts,
4202 _('[OPTION]... SOURCE... DEST'))
4203 _('[OPTION]... SOURCE... DEST'))
4203 def rename(ui, repo, *pats, **opts):
4204 def rename(ui, repo, *pats, **opts):
4204 """rename files; equivalent of copy + remove
4205 """rename files; equivalent of copy + remove
4205
4206
4206 Mark dest as copies of sources; mark sources for deletion. If dest
4207 Mark dest as copies of sources; mark sources for deletion. If dest
4207 is a directory, copies are put in that directory. If dest is a
4208 is a directory, copies are put in that directory. If dest is a
4208 file, there can only be one source.
4209 file, there can only be one source.
4209
4210
4210 By default, this command copies the contents of files as they
4211 By default, this command copies the contents of files as they
4211 exist in the working directory. If invoked with -A/--after, the
4212 exist in the working directory. If invoked with -A/--after, the
4212 operation is recorded, but no copying is performed.
4213 operation is recorded, but no copying is performed.
4213
4214
4214 This command takes effect at the next commit. To undo a rename
4215 This command takes effect at the next commit. To undo a rename
4215 before that, see :hg:`revert`.
4216 before that, see :hg:`revert`.
4216
4217
4217 Returns 0 on success, 1 if errors are encountered.
4218 Returns 0 on success, 1 if errors are encountered.
4218 """
4219 """
4219 with repo.wlock(False):
4220 with repo.wlock(False):
4220 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4221 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4221
4222
4222 @command('resolve',
4223 @command('resolve',
4223 [('a', 'all', None, _('select all unresolved files')),
4224 [('a', 'all', None, _('select all unresolved files')),
4224 ('l', 'list', None, _('list state of files needing merge')),
4225 ('l', 'list', None, _('list state of files needing merge')),
4225 ('m', 'mark', None, _('mark files as resolved')),
4226 ('m', 'mark', None, _('mark files as resolved')),
4226 ('u', 'unmark', None, _('mark files as unresolved')),
4227 ('u', 'unmark', None, _('mark files as unresolved')),
4227 ('n', 'no-status', None, _('hide status prefix'))]
4228 ('n', 'no-status', None, _('hide status prefix'))]
4228 + mergetoolopts + walkopts + formatteropts,
4229 + mergetoolopts + walkopts + formatteropts,
4229 _('[OPTION]... [FILE]...'),
4230 _('[OPTION]... [FILE]...'),
4230 inferrepo=True)
4231 inferrepo=True)
4231 def resolve(ui, repo, *pats, **opts):
4232 def resolve(ui, repo, *pats, **opts):
4232 """redo merges or set/view the merge status of files
4233 """redo merges or set/view the merge status of files
4233
4234
4234 Merges with unresolved conflicts are often the result of
4235 Merges with unresolved conflicts are often the result of
4235 non-interactive merging using the ``internal:merge`` configuration
4236 non-interactive merging using the ``internal:merge`` configuration
4236 setting, or a command-line merge tool like ``diff3``. The resolve
4237 setting, or a command-line merge tool like ``diff3``. The resolve
4237 command is used to manage the files involved in a merge, after
4238 command is used to manage the files involved in a merge, after
4238 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4239 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4239 working directory must have two parents). See :hg:`help
4240 working directory must have two parents). See :hg:`help
4240 merge-tools` for information on configuring merge tools.
4241 merge-tools` for information on configuring merge tools.
4241
4242
4242 The resolve command can be used in the following ways:
4243 The resolve command can be used in the following ways:
4243
4244
4244 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4245 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4245 files, discarding any previous merge attempts. Re-merging is not
4246 files, discarding any previous merge attempts. Re-merging is not
4246 performed for files already marked as resolved. Use ``--all/-a``
4247 performed for files already marked as resolved. Use ``--all/-a``
4247 to select all unresolved files. ``--tool`` can be used to specify
4248 to select all unresolved files. ``--tool`` can be used to specify
4248 the merge tool used for the given files. It overrides the HGMERGE
4249 the merge tool used for the given files. It overrides the HGMERGE
4249 environment variable and your configuration files. Previous file
4250 environment variable and your configuration files. Previous file
4250 contents are saved with a ``.orig`` suffix.
4251 contents are saved with a ``.orig`` suffix.
4251
4252
4252 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4253 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4253 (e.g. after having manually fixed-up the files). The default is
4254 (e.g. after having manually fixed-up the files). The default is
4254 to mark all unresolved files.
4255 to mark all unresolved files.
4255
4256
4256 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4257 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4257 default is to mark all resolved files.
4258 default is to mark all resolved files.
4258
4259
4259 - :hg:`resolve -l`: list files which had or still have conflicts.
4260 - :hg:`resolve -l`: list files which had or still have conflicts.
4260 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4261 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4261
4262
4262 .. note::
4263 .. note::
4263
4264
4264 Mercurial will not let you commit files with unresolved merge
4265 Mercurial will not let you commit files with unresolved merge
4265 conflicts. You must use :hg:`resolve -m ...` before you can
4266 conflicts. You must use :hg:`resolve -m ...` before you can
4266 commit after a conflicting merge.
4267 commit after a conflicting merge.
4267
4268
4268 Returns 0 on success, 1 if any files fail a resolve attempt.
4269 Returns 0 on success, 1 if any files fail a resolve attempt.
4269 """
4270 """
4270
4271
4271 flaglist = 'all mark unmark list no_status'.split()
4272 flaglist = 'all mark unmark list no_status'.split()
4272 all, mark, unmark, show, nostatus = \
4273 all, mark, unmark, show, nostatus = \
4273 [opts.get(o) for o in flaglist]
4274 [opts.get(o) for o in flaglist]
4274
4275
4275 if (show and (mark or unmark)) or (mark and unmark):
4276 if (show and (mark or unmark)) or (mark and unmark):
4276 raise error.Abort(_("too many options specified"))
4277 raise error.Abort(_("too many options specified"))
4277 if pats and all:
4278 if pats and all:
4278 raise error.Abort(_("can't specify --all and patterns"))
4279 raise error.Abort(_("can't specify --all and patterns"))
4279 if not (all or pats or show or mark or unmark):
4280 if not (all or pats or show or mark or unmark):
4280 raise error.Abort(_('no files or directories specified'),
4281 raise error.Abort(_('no files or directories specified'),
4281 hint=('use --all to re-merge all unresolved files'))
4282 hint=('use --all to re-merge all unresolved files'))
4282
4283
4283 if show:
4284 if show:
4284 fm = ui.formatter('resolve', opts)
4285 fm = ui.formatter('resolve', opts)
4285 ms = mergemod.mergestate.read(repo)
4286 ms = mergemod.mergestate.read(repo)
4286 m = scmutil.match(repo[None], pats, opts)
4287 m = scmutil.match(repo[None], pats, opts)
4287 for f in ms:
4288 for f in ms:
4288 if not m(f):
4289 if not m(f):
4289 continue
4290 continue
4290 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
4291 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
4291 'd': 'driverresolved'}[ms[f]]
4292 'd': 'driverresolved'}[ms[f]]
4292 fm.startitem()
4293 fm.startitem()
4293 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
4294 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
4294 fm.write('path', '%s\n', f, label=l)
4295 fm.write('path', '%s\n', f, label=l)
4295 fm.end()
4296 fm.end()
4296 return 0
4297 return 0
4297
4298
4298 with repo.wlock():
4299 with repo.wlock():
4299 ms = mergemod.mergestate.read(repo)
4300 ms = mergemod.mergestate.read(repo)
4300
4301
4301 if not (ms.active() or repo.dirstate.p2() != nullid):
4302 if not (ms.active() or repo.dirstate.p2() != nullid):
4302 raise error.Abort(
4303 raise error.Abort(
4303 _('resolve command not applicable when not merging'))
4304 _('resolve command not applicable when not merging'))
4304
4305
4305 wctx = repo[None]
4306 wctx = repo[None]
4306
4307
4307 if ms.mergedriver and ms.mdstate() == 'u':
4308 if ms.mergedriver and ms.mdstate() == 'u':
4308 proceed = mergemod.driverpreprocess(repo, ms, wctx)
4309 proceed = mergemod.driverpreprocess(repo, ms, wctx)
4309 ms.commit()
4310 ms.commit()
4310 # allow mark and unmark to go through
4311 # allow mark and unmark to go through
4311 if not mark and not unmark and not proceed:
4312 if not mark and not unmark and not proceed:
4312 return 1
4313 return 1
4313
4314
4314 m = scmutil.match(wctx, pats, opts)
4315 m = scmutil.match(wctx, pats, opts)
4315 ret = 0
4316 ret = 0
4316 didwork = False
4317 didwork = False
4317 runconclude = False
4318 runconclude = False
4318
4319
4319 tocomplete = []
4320 tocomplete = []
4320 for f in ms:
4321 for f in ms:
4321 if not m(f):
4322 if not m(f):
4322 continue
4323 continue
4323
4324
4324 didwork = True
4325 didwork = True
4325
4326
4326 # don't let driver-resolved files be marked, and run the conclude
4327 # don't let driver-resolved files be marked, and run the conclude
4327 # step if asked to resolve
4328 # step if asked to resolve
4328 if ms[f] == "d":
4329 if ms[f] == "d":
4329 exact = m.exact(f)
4330 exact = m.exact(f)
4330 if mark:
4331 if mark:
4331 if exact:
4332 if exact:
4332 ui.warn(_('not marking %s as it is driver-resolved\n')
4333 ui.warn(_('not marking %s as it is driver-resolved\n')
4333 % f)
4334 % f)
4334 elif unmark:
4335 elif unmark:
4335 if exact:
4336 if exact:
4336 ui.warn(_('not unmarking %s as it is driver-resolved\n')
4337 ui.warn(_('not unmarking %s as it is driver-resolved\n')
4337 % f)
4338 % f)
4338 else:
4339 else:
4339 runconclude = True
4340 runconclude = True
4340 continue
4341 continue
4341
4342
4342 if mark:
4343 if mark:
4343 ms.mark(f, "r")
4344 ms.mark(f, "r")
4344 elif unmark:
4345 elif unmark:
4345 ms.mark(f, "u")
4346 ms.mark(f, "u")
4346 else:
4347 else:
4347 # backup pre-resolve (merge uses .orig for its own purposes)
4348 # backup pre-resolve (merge uses .orig for its own purposes)
4348 a = repo.wjoin(f)
4349 a = repo.wjoin(f)
4349 try:
4350 try:
4350 util.copyfile(a, a + ".resolve")
4351 util.copyfile(a, a + ".resolve")
4351 except (IOError, OSError) as inst:
4352 except (IOError, OSError) as inst:
4352 if inst.errno != errno.ENOENT:
4353 if inst.errno != errno.ENOENT:
4353 raise
4354 raise
4354
4355
4355 try:
4356 try:
4356 # preresolve file
4357 # preresolve file
4357 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4358 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4358 'resolve')
4359 'resolve')
4359 complete, r = ms.preresolve(f, wctx)
4360 complete, r = ms.preresolve(f, wctx)
4360 if not complete:
4361 if not complete:
4361 tocomplete.append(f)
4362 tocomplete.append(f)
4362 elif r:
4363 elif r:
4363 ret = 1
4364 ret = 1
4364 finally:
4365 finally:
4365 ui.setconfig('ui', 'forcemerge', '', 'resolve')
4366 ui.setconfig('ui', 'forcemerge', '', 'resolve')
4366 ms.commit()
4367 ms.commit()
4367
4368
4368 # replace filemerge's .orig file with our resolve file, but only
4369 # replace filemerge's .orig file with our resolve file, but only
4369 # for merges that are complete
4370 # for merges that are complete
4370 if complete:
4371 if complete:
4371 try:
4372 try:
4372 util.rename(a + ".resolve",
4373 util.rename(a + ".resolve",
4373 scmutil.origpath(ui, repo, a))
4374 scmutil.origpath(ui, repo, a))
4374 except OSError as inst:
4375 except OSError as inst:
4375 if inst.errno != errno.ENOENT:
4376 if inst.errno != errno.ENOENT:
4376 raise
4377 raise
4377
4378
4378 for f in tocomplete:
4379 for f in tocomplete:
4379 try:
4380 try:
4380 # resolve file
4381 # resolve file
4381 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4382 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4382 'resolve')
4383 'resolve')
4383 r = ms.resolve(f, wctx)
4384 r = ms.resolve(f, wctx)
4384 if r:
4385 if r:
4385 ret = 1
4386 ret = 1
4386 finally:
4387 finally:
4387 ui.setconfig('ui', 'forcemerge', '', 'resolve')
4388 ui.setconfig('ui', 'forcemerge', '', 'resolve')
4388 ms.commit()
4389 ms.commit()
4389
4390
4390 # replace filemerge's .orig file with our resolve file
4391 # replace filemerge's .orig file with our resolve file
4391 a = repo.wjoin(f)
4392 a = repo.wjoin(f)
4392 try:
4393 try:
4393 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
4394 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
4394 except OSError as inst:
4395 except OSError as inst:
4395 if inst.errno != errno.ENOENT:
4396 if inst.errno != errno.ENOENT:
4396 raise
4397 raise
4397
4398
4398 ms.commit()
4399 ms.commit()
4399 ms.recordactions()
4400 ms.recordactions()
4400
4401
4401 if not didwork and pats:
4402 if not didwork and pats:
4402 hint = None
4403 hint = None
4403 if not any([p for p in pats if p.find(':') >= 0]):
4404 if not any([p for p in pats if p.find(':') >= 0]):
4404 pats = ['path:%s' % p for p in pats]
4405 pats = ['path:%s' % p for p in pats]
4405 m = scmutil.match(wctx, pats, opts)
4406 m = scmutil.match(wctx, pats, opts)
4406 for f in ms:
4407 for f in ms:
4407 if not m(f):
4408 if not m(f):
4408 continue
4409 continue
4409 flags = ''.join(['-%s ' % o[0] for o in flaglist
4410 flags = ''.join(['-%s ' % o[0] for o in flaglist
4410 if opts.get(o)])
4411 if opts.get(o)])
4411 hint = _("(try: hg resolve %s%s)\n") % (
4412 hint = _("(try: hg resolve %s%s)\n") % (
4412 flags,
4413 flags,
4413 ' '.join(pats))
4414 ' '.join(pats))
4414 break
4415 break
4415 ui.warn(_("arguments do not match paths that need resolving\n"))
4416 ui.warn(_("arguments do not match paths that need resolving\n"))
4416 if hint:
4417 if hint:
4417 ui.warn(hint)
4418 ui.warn(hint)
4418 elif ms.mergedriver and ms.mdstate() != 's':
4419 elif ms.mergedriver and ms.mdstate() != 's':
4419 # run conclude step when either a driver-resolved file is requested
4420 # run conclude step when either a driver-resolved file is requested
4420 # or there are no driver-resolved files
4421 # or there are no driver-resolved files
4421 # we can't use 'ret' to determine whether any files are unresolved
4422 # we can't use 'ret' to determine whether any files are unresolved
4422 # because we might not have tried to resolve some
4423 # because we might not have tried to resolve some
4423 if ((runconclude or not list(ms.driverresolved()))
4424 if ((runconclude or not list(ms.driverresolved()))
4424 and not list(ms.unresolved())):
4425 and not list(ms.unresolved())):
4425 proceed = mergemod.driverconclude(repo, ms, wctx)
4426 proceed = mergemod.driverconclude(repo, ms, wctx)
4426 ms.commit()
4427 ms.commit()
4427 if not proceed:
4428 if not proceed:
4428 return 1
4429 return 1
4429
4430
4430 # Nudge users into finishing an unfinished operation
4431 # Nudge users into finishing an unfinished operation
4431 unresolvedf = list(ms.unresolved())
4432 unresolvedf = list(ms.unresolved())
4432 driverresolvedf = list(ms.driverresolved())
4433 driverresolvedf = list(ms.driverresolved())
4433 if not unresolvedf and not driverresolvedf:
4434 if not unresolvedf and not driverresolvedf:
4434 ui.status(_('(no more unresolved files)\n'))
4435 ui.status(_('(no more unresolved files)\n'))
4435 cmdutil.checkafterresolved(repo)
4436 cmdutil.checkafterresolved(repo)
4436 elif not unresolvedf:
4437 elif not unresolvedf:
4437 ui.status(_('(no more unresolved files -- '
4438 ui.status(_('(no more unresolved files -- '
4438 'run "hg resolve --all" to conclude)\n'))
4439 'run "hg resolve --all" to conclude)\n'))
4439
4440
4440 return ret
4441 return ret
4441
4442
4442 @command('revert',
4443 @command('revert',
4443 [('a', 'all', None, _('revert all changes when no arguments given')),
4444 [('a', 'all', None, _('revert all changes when no arguments given')),
4444 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4445 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4445 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4446 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4446 ('C', 'no-backup', None, _('do not save backup copies of files')),
4447 ('C', 'no-backup', None, _('do not save backup copies of files')),
4447 ('i', 'interactive', None,
4448 ('i', 'interactive', None,
4448 _('interactively select the changes (EXPERIMENTAL)')),
4449 _('interactively select the changes (EXPERIMENTAL)')),
4449 ] + walkopts + dryrunopts,
4450 ] + walkopts + dryrunopts,
4450 _('[OPTION]... [-r REV] [NAME]...'))
4451 _('[OPTION]... [-r REV] [NAME]...'))
4451 def revert(ui, repo, *pats, **opts):
4452 def revert(ui, repo, *pats, **opts):
4452 """restore files to their checkout state
4453 """restore files to their checkout state
4453
4454
4454 .. note::
4455 .. note::
4455
4456
4456 To check out earlier revisions, you should use :hg:`update REV`.
4457 To check out earlier revisions, you should use :hg:`update REV`.
4457 To cancel an uncommitted merge (and lose your changes),
4458 To cancel an uncommitted merge (and lose your changes),
4458 use :hg:`update --clean .`.
4459 use :hg:`update --clean .`.
4459
4460
4460 With no revision specified, revert the specified files or directories
4461 With no revision specified, revert the specified files or directories
4461 to the contents they had in the parent of the working directory.
4462 to the contents they had in the parent of the working directory.
4462 This restores the contents of files to an unmodified
4463 This restores the contents of files to an unmodified
4463 state and unschedules adds, removes, copies, and renames. If the
4464 state and unschedules adds, removes, copies, and renames. If the
4464 working directory has two parents, you must explicitly specify a
4465 working directory has two parents, you must explicitly specify a
4465 revision.
4466 revision.
4466
4467
4467 Using the -r/--rev or -d/--date options, revert the given files or
4468 Using the -r/--rev or -d/--date options, revert the given files or
4468 directories to their states as of a specific revision. Because
4469 directories to their states as of a specific revision. Because
4469 revert does not change the working directory parents, this will
4470 revert does not change the working directory parents, this will
4470 cause these files to appear modified. This can be helpful to "back
4471 cause these files to appear modified. This can be helpful to "back
4471 out" some or all of an earlier change. See :hg:`backout` for a
4472 out" some or all of an earlier change. See :hg:`backout` for a
4472 related method.
4473 related method.
4473
4474
4474 Modified files are saved with a .orig suffix before reverting.
4475 Modified files are saved with a .orig suffix before reverting.
4475 To disable these backups, use --no-backup. It is possible to store
4476 To disable these backups, use --no-backup. It is possible to store
4476 the backup files in a custom directory relative to the root of the
4477 the backup files in a custom directory relative to the root of the
4477 repository by setting the ``ui.origbackuppath`` configuration
4478 repository by setting the ``ui.origbackuppath`` configuration
4478 option.
4479 option.
4479
4480
4480 See :hg:`help dates` for a list of formats valid for -d/--date.
4481 See :hg:`help dates` for a list of formats valid for -d/--date.
4481
4482
4482 See :hg:`help backout` for a way to reverse the effect of an
4483 See :hg:`help backout` for a way to reverse the effect of an
4483 earlier changeset.
4484 earlier changeset.
4484
4485
4485 Returns 0 on success.
4486 Returns 0 on success.
4486 """
4487 """
4487
4488
4488 if opts.get("date"):
4489 if opts.get("date"):
4489 if opts.get("rev"):
4490 if opts.get("rev"):
4490 raise error.Abort(_("you can't specify a revision and a date"))
4491 raise error.Abort(_("you can't specify a revision and a date"))
4491 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4492 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4492
4493
4493 parent, p2 = repo.dirstate.parents()
4494 parent, p2 = repo.dirstate.parents()
4494 if not opts.get('rev') and p2 != nullid:
4495 if not opts.get('rev') and p2 != nullid:
4495 # revert after merge is a trap for new users (issue2915)
4496 # revert after merge is a trap for new users (issue2915)
4496 raise error.Abort(_('uncommitted merge with no revision specified'),
4497 raise error.Abort(_('uncommitted merge with no revision specified'),
4497 hint=_("use 'hg update' or see 'hg help revert'"))
4498 hint=_("use 'hg update' or see 'hg help revert'"))
4498
4499
4499 ctx = scmutil.revsingle(repo, opts.get('rev'))
4500 ctx = scmutil.revsingle(repo, opts.get('rev'))
4500
4501
4501 if (not (pats or opts.get('include') or opts.get('exclude') or
4502 if (not (pats or opts.get('include') or opts.get('exclude') or
4502 opts.get('all') or opts.get('interactive'))):
4503 opts.get('all') or opts.get('interactive'))):
4503 msg = _("no files or directories specified")
4504 msg = _("no files or directories specified")
4504 if p2 != nullid:
4505 if p2 != nullid:
4505 hint = _("uncommitted merge, use --all to discard all changes,"
4506 hint = _("uncommitted merge, use --all to discard all changes,"
4506 " or 'hg update -C .' to abort the merge")
4507 " or 'hg update -C .' to abort the merge")
4507 raise error.Abort(msg, hint=hint)
4508 raise error.Abort(msg, hint=hint)
4508 dirty = any(repo.status())
4509 dirty = any(repo.status())
4509 node = ctx.node()
4510 node = ctx.node()
4510 if node != parent:
4511 if node != parent:
4511 if dirty:
4512 if dirty:
4512 hint = _("uncommitted changes, use --all to discard all"
4513 hint = _("uncommitted changes, use --all to discard all"
4513 " changes, or 'hg update %s' to update") % ctx.rev()
4514 " changes, or 'hg update %s' to update") % ctx.rev()
4514 else:
4515 else:
4515 hint = _("use --all to revert all files,"
4516 hint = _("use --all to revert all files,"
4516 " or 'hg update %s' to update") % ctx.rev()
4517 " or 'hg update %s' to update") % ctx.rev()
4517 elif dirty:
4518 elif dirty:
4518 hint = _("uncommitted changes, use --all to discard all changes")
4519 hint = _("uncommitted changes, use --all to discard all changes")
4519 else:
4520 else:
4520 hint = _("use --all to revert all files")
4521 hint = _("use --all to revert all files")
4521 raise error.Abort(msg, hint=hint)
4522 raise error.Abort(msg, hint=hint)
4522
4523
4523 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
4524 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
4524
4525
4525 @command('rollback', dryrunopts +
4526 @command('rollback', dryrunopts +
4526 [('f', 'force', False, _('ignore safety measures'))])
4527 [('f', 'force', False, _('ignore safety measures'))])
4527 def rollback(ui, repo, **opts):
4528 def rollback(ui, repo, **opts):
4528 """roll back the last transaction (DANGEROUS) (DEPRECATED)
4529 """roll back the last transaction (DANGEROUS) (DEPRECATED)
4529
4530
4530 Please use :hg:`commit --amend` instead of rollback to correct
4531 Please use :hg:`commit --amend` instead of rollback to correct
4531 mistakes in the last commit.
4532 mistakes in the last commit.
4532
4533
4533 This command should be used with care. There is only one level of
4534 This command should be used with care. There is only one level of
4534 rollback, and there is no way to undo a rollback. It will also
4535 rollback, and there is no way to undo a rollback. It will also
4535 restore the dirstate at the time of the last transaction, losing
4536 restore the dirstate at the time of the last transaction, losing
4536 any dirstate changes since that time. This command does not alter
4537 any dirstate changes since that time. This command does not alter
4537 the working directory.
4538 the working directory.
4538
4539
4539 Transactions are used to encapsulate the effects of all commands
4540 Transactions are used to encapsulate the effects of all commands
4540 that create new changesets or propagate existing changesets into a
4541 that create new changesets or propagate existing changesets into a
4541 repository.
4542 repository.
4542
4543
4543 .. container:: verbose
4544 .. container:: verbose
4544
4545
4545 For example, the following commands are transactional, and their
4546 For example, the following commands are transactional, and their
4546 effects can be rolled back:
4547 effects can be rolled back:
4547
4548
4548 - commit
4549 - commit
4549 - import
4550 - import
4550 - pull
4551 - pull
4551 - push (with this repository as the destination)
4552 - push (with this repository as the destination)
4552 - unbundle
4553 - unbundle
4553
4554
4554 To avoid permanent data loss, rollback will refuse to rollback a
4555 To avoid permanent data loss, rollback will refuse to rollback a
4555 commit transaction if it isn't checked out. Use --force to
4556 commit transaction if it isn't checked out. Use --force to
4556 override this protection.
4557 override this protection.
4557
4558
4558 The rollback command can be entirely disabled by setting the
4559 The rollback command can be entirely disabled by setting the
4559 ``ui.rollback`` configuration setting to false. If you're here
4560 ``ui.rollback`` configuration setting to false. If you're here
4560 because you want to use rollback and it's disabled, you can
4561 because you want to use rollback and it's disabled, you can
4561 re-enable the command by setting ``ui.rollback`` to true.
4562 re-enable the command by setting ``ui.rollback`` to true.
4562
4563
4563 This command is not intended for use on public repositories. Once
4564 This command is not intended for use on public repositories. Once
4564 changes are visible for pull by other users, rolling a transaction
4565 changes are visible for pull by other users, rolling a transaction
4565 back locally is ineffective (someone else may already have pulled
4566 back locally is ineffective (someone else may already have pulled
4566 the changes). Furthermore, a race is possible with readers of the
4567 the changes). Furthermore, a race is possible with readers of the
4567 repository; for example an in-progress pull from the repository
4568 repository; for example an in-progress pull from the repository
4568 may fail if a rollback is performed.
4569 may fail if a rollback is performed.
4569
4570
4570 Returns 0 on success, 1 if no rollback data is available.
4571 Returns 0 on success, 1 if no rollback data is available.
4571 """
4572 """
4572 if not ui.configbool('ui', 'rollback', True):
4573 if not ui.configbool('ui', 'rollback', True):
4573 raise error.Abort(_('rollback is disabled because it is unsafe'),
4574 raise error.Abort(_('rollback is disabled because it is unsafe'),
4574 hint=('see `hg help -v rollback` for information'))
4575 hint=('see `hg help -v rollback` for information'))
4575 return repo.rollback(dryrun=opts.get('dry_run'),
4576 return repo.rollback(dryrun=opts.get('dry_run'),
4576 force=opts.get('force'))
4577 force=opts.get('force'))
4577
4578
4578 @command('root', [])
4579 @command('root', [])
4579 def root(ui, repo):
4580 def root(ui, repo):
4580 """print the root (top) of the current working directory
4581 """print the root (top) of the current working directory
4581
4582
4582 Print the root directory of the current repository.
4583 Print the root directory of the current repository.
4583
4584
4584 Returns 0 on success.
4585 Returns 0 on success.
4585 """
4586 """
4586 ui.write(repo.root + "\n")
4587 ui.write(repo.root + "\n")
4587
4588
4588 @command('^serve',
4589 @command('^serve',
4589 [('A', 'accesslog', '', _('name of access log file to write to'),
4590 [('A', 'accesslog', '', _('name of access log file to write to'),
4590 _('FILE')),
4591 _('FILE')),
4591 ('d', 'daemon', None, _('run server in background')),
4592 ('d', 'daemon', None, _('run server in background')),
4592 ('', 'daemon-postexec', [], _('used internally by daemon mode')),
4593 ('', 'daemon-postexec', [], _('used internally by daemon mode')),
4593 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4594 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4594 # use string type, then we can check if something was passed
4595 # use string type, then we can check if something was passed
4595 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4596 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4596 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4597 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4597 _('ADDR')),
4598 _('ADDR')),
4598 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4599 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4599 _('PREFIX')),
4600 _('PREFIX')),
4600 ('n', 'name', '',
4601 ('n', 'name', '',
4601 _('name to show in web pages (default: working directory)'), _('NAME')),
4602 _('name to show in web pages (default: working directory)'), _('NAME')),
4602 ('', 'web-conf', '',
4603 ('', 'web-conf', '',
4603 _("name of the hgweb config file (see 'hg help hgweb')"), _('FILE')),
4604 _("name of the hgweb config file (see 'hg help hgweb')"), _('FILE')),
4604 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4605 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4605 _('FILE')),
4606 _('FILE')),
4606 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4607 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4607 ('', 'stdio', None, _('for remote clients')),
4608 ('', 'stdio', None, _('for remote clients')),
4608 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
4609 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
4609 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4610 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4610 ('', 'style', '', _('template style to use'), _('STYLE')),
4611 ('', 'style', '', _('template style to use'), _('STYLE')),
4611 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4612 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4612 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
4613 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
4613 _('[OPTION]...'),
4614 _('[OPTION]...'),
4614 optionalrepo=True)
4615 optionalrepo=True)
4615 def serve(ui, repo, **opts):
4616 def serve(ui, repo, **opts):
4616 """start stand-alone webserver
4617 """start stand-alone webserver
4617
4618
4618 Start a local HTTP repository browser and pull server. You can use
4619 Start a local HTTP repository browser and pull server. You can use
4619 this for ad-hoc sharing and browsing of repositories. It is
4620 this for ad-hoc sharing and browsing of repositories. It is
4620 recommended to use a real web server to serve a repository for
4621 recommended to use a real web server to serve a repository for
4621 longer periods of time.
4622 longer periods of time.
4622
4623
4623 Please note that the server does not implement access control.
4624 Please note that the server does not implement access control.
4624 This means that, by default, anybody can read from the server and
4625 This means that, by default, anybody can read from the server and
4625 nobody can write to it by default. Set the ``web.allow_push``
4626 nobody can write to it by default. Set the ``web.allow_push``
4626 option to ``*`` to allow everybody to push to the server. You
4627 option to ``*`` to allow everybody to push to the server. You
4627 should use a real web server if you need to authenticate users.
4628 should use a real web server if you need to authenticate users.
4628
4629
4629 By default, the server logs accesses to stdout and errors to
4630 By default, the server logs accesses to stdout and errors to
4630 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
4631 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
4631 files.
4632 files.
4632
4633
4633 To have the server choose a free port number to listen on, specify
4634 To have the server choose a free port number to listen on, specify
4634 a port number of 0; in this case, the server will print the port
4635 a port number of 0; in this case, the server will print the port
4635 number it uses.
4636 number it uses.
4636
4637
4637 Returns 0 on success.
4638 Returns 0 on success.
4638 """
4639 """
4639
4640
4640 if opts["stdio"] and opts["cmdserver"]:
4641 if opts["stdio"] and opts["cmdserver"]:
4641 raise error.Abort(_("cannot use --stdio with --cmdserver"))
4642 raise error.Abort(_("cannot use --stdio with --cmdserver"))
4642
4643
4643 if opts["stdio"]:
4644 if opts["stdio"]:
4644 if repo is None:
4645 if repo is None:
4645 raise error.RepoError(_("there is no Mercurial repository here"
4646 raise error.RepoError(_("there is no Mercurial repository here"
4646 " (.hg not found)"))
4647 " (.hg not found)"))
4647 s = sshserver.sshserver(ui, repo)
4648 s = sshserver.sshserver(ui, repo)
4648 s.serve_forever()
4649 s.serve_forever()
4649
4650
4650 service = server.createservice(ui, repo, opts)
4651 service = server.createservice(ui, repo, opts)
4651 return server.runservice(opts, initfn=service.init, runfn=service.run)
4652 return server.runservice(opts, initfn=service.init, runfn=service.run)
4652
4653
4653 @command('^status|st',
4654 @command('^status|st',
4654 [('A', 'all', None, _('show status of all files')),
4655 [('A', 'all', None, _('show status of all files')),
4655 ('m', 'modified', None, _('show only modified files')),
4656 ('m', 'modified', None, _('show only modified files')),
4656 ('a', 'added', None, _('show only added files')),
4657 ('a', 'added', None, _('show only added files')),
4657 ('r', 'removed', None, _('show only removed files')),
4658 ('r', 'removed', None, _('show only removed files')),
4658 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4659 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4659 ('c', 'clean', None, _('show only files without changes')),
4660 ('c', 'clean', None, _('show only files without changes')),
4660 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4661 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4661 ('i', 'ignored', None, _('show only ignored files')),
4662 ('i', 'ignored', None, _('show only ignored files')),
4662 ('n', 'no-status', None, _('hide status prefix')),
4663 ('n', 'no-status', None, _('hide status prefix')),
4663 ('C', 'copies', None, _('show source of copied files')),
4664 ('C', 'copies', None, _('show source of copied files')),
4664 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4665 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4665 ('', 'rev', [], _('show difference from revision'), _('REV')),
4666 ('', 'rev', [], _('show difference from revision'), _('REV')),
4666 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
4667 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
4667 ] + walkopts + subrepoopts + formatteropts,
4668 ] + walkopts + subrepoopts + formatteropts,
4668 _('[OPTION]... [FILE]...'),
4669 _('[OPTION]... [FILE]...'),
4669 inferrepo=True)
4670 inferrepo=True)
4670 def status(ui, repo, *pats, **opts):
4671 def status(ui, repo, *pats, **opts):
4671 """show changed files in the working directory
4672 """show changed files in the working directory
4672
4673
4673 Show status of files in the repository. If names are given, only
4674 Show status of files in the repository. If names are given, only
4674 files that match are shown. Files that are clean or ignored or
4675 files that match are shown. Files that are clean or ignored or
4675 the source of a copy/move operation, are not listed unless
4676 the source of a copy/move operation, are not listed unless
4676 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
4677 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
4677 Unless options described with "show only ..." are given, the
4678 Unless options described with "show only ..." are given, the
4678 options -mardu are used.
4679 options -mardu are used.
4679
4680
4680 Option -q/--quiet hides untracked (unknown and ignored) files
4681 Option -q/--quiet hides untracked (unknown and ignored) files
4681 unless explicitly requested with -u/--unknown or -i/--ignored.
4682 unless explicitly requested with -u/--unknown or -i/--ignored.
4682
4683
4683 .. note::
4684 .. note::
4684
4685
4685 :hg:`status` may appear to disagree with diff if permissions have
4686 :hg:`status` may appear to disagree with diff if permissions have
4686 changed or a merge has occurred. The standard diff format does
4687 changed or a merge has occurred. The standard diff format does
4687 not report permission changes and diff only reports changes
4688 not report permission changes and diff only reports changes
4688 relative to one merge parent.
4689 relative to one merge parent.
4689
4690
4690 If one revision is given, it is used as the base revision.
4691 If one revision is given, it is used as the base revision.
4691 If two revisions are given, the differences between them are
4692 If two revisions are given, the differences between them are
4692 shown. The --change option can also be used as a shortcut to list
4693 shown. The --change option can also be used as a shortcut to list
4693 the changed files of a revision from its first parent.
4694 the changed files of a revision from its first parent.
4694
4695
4695 The codes used to show the status of files are::
4696 The codes used to show the status of files are::
4696
4697
4697 M = modified
4698 M = modified
4698 A = added
4699 A = added
4699 R = removed
4700 R = removed
4700 C = clean
4701 C = clean
4701 ! = missing (deleted by non-hg command, but still tracked)
4702 ! = missing (deleted by non-hg command, but still tracked)
4702 ? = not tracked
4703 ? = not tracked
4703 I = ignored
4704 I = ignored
4704 = origin of the previous file (with --copies)
4705 = origin of the previous file (with --copies)
4705
4706
4706 .. container:: verbose
4707 .. container:: verbose
4707
4708
4708 Examples:
4709 Examples:
4709
4710
4710 - show changes in the working directory relative to a
4711 - show changes in the working directory relative to a
4711 changeset::
4712 changeset::
4712
4713
4713 hg status --rev 9353
4714 hg status --rev 9353
4714
4715
4715 - show changes in the working directory relative to the
4716 - show changes in the working directory relative to the
4716 current directory (see :hg:`help patterns` for more information)::
4717 current directory (see :hg:`help patterns` for more information)::
4717
4718
4718 hg status re:
4719 hg status re:
4719
4720
4720 - show all changes including copies in an existing changeset::
4721 - show all changes including copies in an existing changeset::
4721
4722
4722 hg status --copies --change 9353
4723 hg status --copies --change 9353
4723
4724
4724 - get a NUL separated list of added files, suitable for xargs::
4725 - get a NUL separated list of added files, suitable for xargs::
4725
4726
4726 hg status -an0
4727 hg status -an0
4727
4728
4728 Returns 0 on success.
4729 Returns 0 on success.
4729 """
4730 """
4730
4731
4731 revs = opts.get('rev')
4732 revs = opts.get('rev')
4732 change = opts.get('change')
4733 change = opts.get('change')
4733
4734
4734 if revs and change:
4735 if revs and change:
4735 msg = _('cannot specify --rev and --change at the same time')
4736 msg = _('cannot specify --rev and --change at the same time')
4736 raise error.Abort(msg)
4737 raise error.Abort(msg)
4737 elif change:
4738 elif change:
4738 node2 = scmutil.revsingle(repo, change, None).node()
4739 node2 = scmutil.revsingle(repo, change, None).node()
4739 node1 = repo[node2].p1().node()
4740 node1 = repo[node2].p1().node()
4740 else:
4741 else:
4741 node1, node2 = scmutil.revpair(repo, revs)
4742 node1, node2 = scmutil.revpair(repo, revs)
4742
4743
4743 if pats:
4744 if pats:
4744 cwd = repo.getcwd()
4745 cwd = repo.getcwd()
4745 else:
4746 else:
4746 cwd = ''
4747 cwd = ''
4747
4748
4748 if opts.get('print0'):
4749 if opts.get('print0'):
4749 end = '\0'
4750 end = '\0'
4750 else:
4751 else:
4751 end = '\n'
4752 end = '\n'
4752 copy = {}
4753 copy = {}
4753 states = 'modified added removed deleted unknown ignored clean'.split()
4754 states = 'modified added removed deleted unknown ignored clean'.split()
4754 show = [k for k in states if opts.get(k)]
4755 show = [k for k in states if opts.get(k)]
4755 if opts.get('all'):
4756 if opts.get('all'):
4756 show += ui.quiet and (states[:4] + ['clean']) or states
4757 show += ui.quiet and (states[:4] + ['clean']) or states
4757 if not show:
4758 if not show:
4758 if ui.quiet:
4759 if ui.quiet:
4759 show = states[:4]
4760 show = states[:4]
4760 else:
4761 else:
4761 show = states[:5]
4762 show = states[:5]
4762
4763
4763 m = scmutil.match(repo[node2], pats, opts)
4764 m = scmutil.match(repo[node2], pats, opts)
4764 stat = repo.status(node1, node2, m,
4765 stat = repo.status(node1, node2, m,
4765 'ignored' in show, 'clean' in show, 'unknown' in show,
4766 'ignored' in show, 'clean' in show, 'unknown' in show,
4766 opts.get('subrepos'))
4767 opts.get('subrepos'))
4767 changestates = zip(states, 'MAR!?IC', stat)
4768 changestates = zip(states, 'MAR!?IC', stat)
4768
4769
4769 if (opts.get('all') or opts.get('copies')
4770 if (opts.get('all') or opts.get('copies')
4770 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
4771 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
4771 copy = copies.pathcopies(repo[node1], repo[node2], m)
4772 copy = copies.pathcopies(repo[node1], repo[node2], m)
4772
4773
4773 fm = ui.formatter('status', opts)
4774 fm = ui.formatter('status', opts)
4774 fmt = '%s' + end
4775 fmt = '%s' + end
4775 showchar = not opts.get('no_status')
4776 showchar = not opts.get('no_status')
4776
4777
4777 for state, char, files in changestates:
4778 for state, char, files in changestates:
4778 if state in show:
4779 if state in show:
4779 label = 'status.' + state
4780 label = 'status.' + state
4780 for f in files:
4781 for f in files:
4781 fm.startitem()
4782 fm.startitem()
4782 fm.condwrite(showchar, 'status', '%s ', char, label=label)
4783 fm.condwrite(showchar, 'status', '%s ', char, label=label)
4783 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
4784 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
4784 if f in copy:
4785 if f in copy:
4785 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
4786 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
4786 label='status.copied')
4787 label='status.copied')
4787 fm.end()
4788 fm.end()
4788
4789
4789 @command('^summary|sum',
4790 @command('^summary|sum',
4790 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
4791 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
4791 def summary(ui, repo, **opts):
4792 def summary(ui, repo, **opts):
4792 """summarize working directory state
4793 """summarize working directory state
4793
4794
4794 This generates a brief summary of the working directory state,
4795 This generates a brief summary of the working directory state,
4795 including parents, branch, commit status, phase and available updates.
4796 including parents, branch, commit status, phase and available updates.
4796
4797
4797 With the --remote option, this will check the default paths for
4798 With the --remote option, this will check the default paths for
4798 incoming and outgoing changes. This can be time-consuming.
4799 incoming and outgoing changes. This can be time-consuming.
4799
4800
4800 Returns 0 on success.
4801 Returns 0 on success.
4801 """
4802 """
4802
4803
4803 ctx = repo[None]
4804 ctx = repo[None]
4804 parents = ctx.parents()
4805 parents = ctx.parents()
4805 pnode = parents[0].node()
4806 pnode = parents[0].node()
4806 marks = []
4807 marks = []
4807
4808
4808 ms = None
4809 ms = None
4809 try:
4810 try:
4810 ms = mergemod.mergestate.read(repo)
4811 ms = mergemod.mergestate.read(repo)
4811 except error.UnsupportedMergeRecords as e:
4812 except error.UnsupportedMergeRecords as e:
4812 s = ' '.join(e.recordtypes)
4813 s = ' '.join(e.recordtypes)
4813 ui.warn(
4814 ui.warn(
4814 _('warning: merge state has unsupported record types: %s\n') % s)
4815 _('warning: merge state has unsupported record types: %s\n') % s)
4815 unresolved = 0
4816 unresolved = 0
4816 else:
4817 else:
4817 unresolved = [f for f in ms if ms[f] == 'u']
4818 unresolved = [f for f in ms if ms[f] == 'u']
4818
4819
4819 for p in parents:
4820 for p in parents:
4820 # label with log.changeset (instead of log.parent) since this
4821 # label with log.changeset (instead of log.parent) since this
4821 # shows a working directory parent *changeset*:
4822 # shows a working directory parent *changeset*:
4822 # i18n: column positioning for "hg summary"
4823 # i18n: column positioning for "hg summary"
4823 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
4824 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
4824 label=cmdutil._changesetlabels(p))
4825 label=cmdutil._changesetlabels(p))
4825 ui.write(' '.join(p.tags()), label='log.tag')
4826 ui.write(' '.join(p.tags()), label='log.tag')
4826 if p.bookmarks():
4827 if p.bookmarks():
4827 marks.extend(p.bookmarks())
4828 marks.extend(p.bookmarks())
4828 if p.rev() == -1:
4829 if p.rev() == -1:
4829 if not len(repo):
4830 if not len(repo):
4830 ui.write(_(' (empty repository)'))
4831 ui.write(_(' (empty repository)'))
4831 else:
4832 else:
4832 ui.write(_(' (no revision checked out)'))
4833 ui.write(_(' (no revision checked out)'))
4833 if p.troubled():
4834 if p.troubled():
4834 ui.write(' ('
4835 ui.write(' ('
4835 + ', '.join(ui.label(trouble, 'trouble.%s' % trouble)
4836 + ', '.join(ui.label(trouble, 'trouble.%s' % trouble)
4836 for trouble in p.troubles())
4837 for trouble in p.troubles())
4837 + ')')
4838 + ')')
4838 ui.write('\n')
4839 ui.write('\n')
4839 if p.description():
4840 if p.description():
4840 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
4841 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
4841 label='log.summary')
4842 label='log.summary')
4842
4843
4843 branch = ctx.branch()
4844 branch = ctx.branch()
4844 bheads = repo.branchheads(branch)
4845 bheads = repo.branchheads(branch)
4845 # i18n: column positioning for "hg summary"
4846 # i18n: column positioning for "hg summary"
4846 m = _('branch: %s\n') % branch
4847 m = _('branch: %s\n') % branch
4847 if branch != 'default':
4848 if branch != 'default':
4848 ui.write(m, label='log.branch')
4849 ui.write(m, label='log.branch')
4849 else:
4850 else:
4850 ui.status(m, label='log.branch')
4851 ui.status(m, label='log.branch')
4851
4852
4852 if marks:
4853 if marks:
4853 active = repo._activebookmark
4854 active = repo._activebookmark
4854 # i18n: column positioning for "hg summary"
4855 # i18n: column positioning for "hg summary"
4855 ui.write(_('bookmarks:'), label='log.bookmark')
4856 ui.write(_('bookmarks:'), label='log.bookmark')
4856 if active is not None:
4857 if active is not None:
4857 if active in marks:
4858 if active in marks:
4858 ui.write(' *' + active, label=activebookmarklabel)
4859 ui.write(' *' + active, label=activebookmarklabel)
4859 marks.remove(active)
4860 marks.remove(active)
4860 else:
4861 else:
4861 ui.write(' [%s]' % active, label=activebookmarklabel)
4862 ui.write(' [%s]' % active, label=activebookmarklabel)
4862 for m in marks:
4863 for m in marks:
4863 ui.write(' ' + m, label='log.bookmark')
4864 ui.write(' ' + m, label='log.bookmark')
4864 ui.write('\n', label='log.bookmark')
4865 ui.write('\n', label='log.bookmark')
4865
4866
4866 status = repo.status(unknown=True)
4867 status = repo.status(unknown=True)
4867
4868
4868 c = repo.dirstate.copies()
4869 c = repo.dirstate.copies()
4869 copied, renamed = [], []
4870 copied, renamed = [], []
4870 for d, s in c.iteritems():
4871 for d, s in c.iteritems():
4871 if s in status.removed:
4872 if s in status.removed:
4872 status.removed.remove(s)
4873 status.removed.remove(s)
4873 renamed.append(d)
4874 renamed.append(d)
4874 else:
4875 else:
4875 copied.append(d)
4876 copied.append(d)
4876 if d in status.added:
4877 if d in status.added:
4877 status.added.remove(d)
4878 status.added.remove(d)
4878
4879
4879 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
4880 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
4880
4881
4881 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
4882 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
4882 (ui.label(_('%d added'), 'status.added'), status.added),
4883 (ui.label(_('%d added'), 'status.added'), status.added),
4883 (ui.label(_('%d removed'), 'status.removed'), status.removed),
4884 (ui.label(_('%d removed'), 'status.removed'), status.removed),
4884 (ui.label(_('%d renamed'), 'status.copied'), renamed),
4885 (ui.label(_('%d renamed'), 'status.copied'), renamed),
4885 (ui.label(_('%d copied'), 'status.copied'), copied),
4886 (ui.label(_('%d copied'), 'status.copied'), copied),
4886 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
4887 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
4887 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
4888 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
4888 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
4889 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
4889 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
4890 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
4890 t = []
4891 t = []
4891 for l, s in labels:
4892 for l, s in labels:
4892 if s:
4893 if s:
4893 t.append(l % len(s))
4894 t.append(l % len(s))
4894
4895
4895 t = ', '.join(t)
4896 t = ', '.join(t)
4896 cleanworkdir = False
4897 cleanworkdir = False
4897
4898
4898 if repo.vfs.exists('graftstate'):
4899 if repo.vfs.exists('graftstate'):
4899 t += _(' (graft in progress)')
4900 t += _(' (graft in progress)')
4900 if repo.vfs.exists('updatestate'):
4901 if repo.vfs.exists('updatestate'):
4901 t += _(' (interrupted update)')
4902 t += _(' (interrupted update)')
4902 elif len(parents) > 1:
4903 elif len(parents) > 1:
4903 t += _(' (merge)')
4904 t += _(' (merge)')
4904 elif branch != parents[0].branch():
4905 elif branch != parents[0].branch():
4905 t += _(' (new branch)')
4906 t += _(' (new branch)')
4906 elif (parents[0].closesbranch() and
4907 elif (parents[0].closesbranch() and
4907 pnode in repo.branchheads(branch, closed=True)):
4908 pnode in repo.branchheads(branch, closed=True)):
4908 t += _(' (head closed)')
4909 t += _(' (head closed)')
4909 elif not (status.modified or status.added or status.removed or renamed or
4910 elif not (status.modified or status.added or status.removed or renamed or
4910 copied or subs):
4911 copied or subs):
4911 t += _(' (clean)')
4912 t += _(' (clean)')
4912 cleanworkdir = True
4913 cleanworkdir = True
4913 elif pnode not in bheads:
4914 elif pnode not in bheads:
4914 t += _(' (new branch head)')
4915 t += _(' (new branch head)')
4915
4916
4916 if parents:
4917 if parents:
4917 pendingphase = max(p.phase() for p in parents)
4918 pendingphase = max(p.phase() for p in parents)
4918 else:
4919 else:
4919 pendingphase = phases.public
4920 pendingphase = phases.public
4920
4921
4921 if pendingphase > phases.newcommitphase(ui):
4922 if pendingphase > phases.newcommitphase(ui):
4922 t += ' (%s)' % phases.phasenames[pendingphase]
4923 t += ' (%s)' % phases.phasenames[pendingphase]
4923
4924
4924 if cleanworkdir:
4925 if cleanworkdir:
4925 # i18n: column positioning for "hg summary"
4926 # i18n: column positioning for "hg summary"
4926 ui.status(_('commit: %s\n') % t.strip())
4927 ui.status(_('commit: %s\n') % t.strip())
4927 else:
4928 else:
4928 # i18n: column positioning for "hg summary"
4929 # i18n: column positioning for "hg summary"
4929 ui.write(_('commit: %s\n') % t.strip())
4930 ui.write(_('commit: %s\n') % t.strip())
4930
4931
4931 # all ancestors of branch heads - all ancestors of parent = new csets
4932 # all ancestors of branch heads - all ancestors of parent = new csets
4932 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
4933 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
4933 bheads))
4934 bheads))
4934
4935
4935 if new == 0:
4936 if new == 0:
4936 # i18n: column positioning for "hg summary"
4937 # i18n: column positioning for "hg summary"
4937 ui.status(_('update: (current)\n'))
4938 ui.status(_('update: (current)\n'))
4938 elif pnode not in bheads:
4939 elif pnode not in bheads:
4939 # i18n: column positioning for "hg summary"
4940 # i18n: column positioning for "hg summary"
4940 ui.write(_('update: %d new changesets (update)\n') % new)
4941 ui.write(_('update: %d new changesets (update)\n') % new)
4941 else:
4942 else:
4942 # i18n: column positioning for "hg summary"
4943 # i18n: column positioning for "hg summary"
4943 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
4944 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
4944 (new, len(bheads)))
4945 (new, len(bheads)))
4945
4946
4946 t = []
4947 t = []
4947 draft = len(repo.revs('draft()'))
4948 draft = len(repo.revs('draft()'))
4948 if draft:
4949 if draft:
4949 t.append(_('%d draft') % draft)
4950 t.append(_('%d draft') % draft)
4950 secret = len(repo.revs('secret()'))
4951 secret = len(repo.revs('secret()'))
4951 if secret:
4952 if secret:
4952 t.append(_('%d secret') % secret)
4953 t.append(_('%d secret') % secret)
4953
4954
4954 if draft or secret:
4955 if draft or secret:
4955 ui.status(_('phases: %s\n') % ', '.join(t))
4956 ui.status(_('phases: %s\n') % ', '.join(t))
4956
4957
4957 if obsolete.isenabled(repo, obsolete.createmarkersopt):
4958 if obsolete.isenabled(repo, obsolete.createmarkersopt):
4958 for trouble in ("unstable", "divergent", "bumped"):
4959 for trouble in ("unstable", "divergent", "bumped"):
4959 numtrouble = len(repo.revs(trouble + "()"))
4960 numtrouble = len(repo.revs(trouble + "()"))
4960 # We write all the possibilities to ease translation
4961 # We write all the possibilities to ease translation
4961 troublemsg = {
4962 troublemsg = {
4962 "unstable": _("unstable: %d changesets"),
4963 "unstable": _("unstable: %d changesets"),
4963 "divergent": _("divergent: %d changesets"),
4964 "divergent": _("divergent: %d changesets"),
4964 "bumped": _("bumped: %d changesets"),
4965 "bumped": _("bumped: %d changesets"),
4965 }
4966 }
4966 if numtrouble > 0:
4967 if numtrouble > 0:
4967 ui.status(troublemsg[trouble] % numtrouble + "\n")
4968 ui.status(troublemsg[trouble] % numtrouble + "\n")
4968
4969
4969 cmdutil.summaryhooks(ui, repo)
4970 cmdutil.summaryhooks(ui, repo)
4970
4971
4971 if opts.get('remote'):
4972 if opts.get('remote'):
4972 needsincoming, needsoutgoing = True, True
4973 needsincoming, needsoutgoing = True, True
4973 else:
4974 else:
4974 needsincoming, needsoutgoing = False, False
4975 needsincoming, needsoutgoing = False, False
4975 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
4976 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
4976 if i:
4977 if i:
4977 needsincoming = True
4978 needsincoming = True
4978 if o:
4979 if o:
4979 needsoutgoing = True
4980 needsoutgoing = True
4980 if not needsincoming and not needsoutgoing:
4981 if not needsincoming and not needsoutgoing:
4981 return
4982 return
4982
4983
4983 def getincoming():
4984 def getincoming():
4984 source, branches = hg.parseurl(ui.expandpath('default'))
4985 source, branches = hg.parseurl(ui.expandpath('default'))
4985 sbranch = branches[0]
4986 sbranch = branches[0]
4986 try:
4987 try:
4987 other = hg.peer(repo, {}, source)
4988 other = hg.peer(repo, {}, source)
4988 except error.RepoError:
4989 except error.RepoError:
4989 if opts.get('remote'):
4990 if opts.get('remote'):
4990 raise
4991 raise
4991 return source, sbranch, None, None, None
4992 return source, sbranch, None, None, None
4992 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
4993 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
4993 if revs:
4994 if revs:
4994 revs = [other.lookup(rev) for rev in revs]
4995 revs = [other.lookup(rev) for rev in revs]
4995 ui.debug('comparing with %s\n' % util.hidepassword(source))
4996 ui.debug('comparing with %s\n' % util.hidepassword(source))
4996 repo.ui.pushbuffer()
4997 repo.ui.pushbuffer()
4997 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
4998 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
4998 repo.ui.popbuffer()
4999 repo.ui.popbuffer()
4999 return source, sbranch, other, commoninc, commoninc[1]
5000 return source, sbranch, other, commoninc, commoninc[1]
5000
5001
5001 if needsincoming:
5002 if needsincoming:
5002 source, sbranch, sother, commoninc, incoming = getincoming()
5003 source, sbranch, sother, commoninc, incoming = getincoming()
5003 else:
5004 else:
5004 source = sbranch = sother = commoninc = incoming = None
5005 source = sbranch = sother = commoninc = incoming = None
5005
5006
5006 def getoutgoing():
5007 def getoutgoing():
5007 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5008 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5008 dbranch = branches[0]
5009 dbranch = branches[0]
5009 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5010 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5010 if source != dest:
5011 if source != dest:
5011 try:
5012 try:
5012 dother = hg.peer(repo, {}, dest)
5013 dother = hg.peer(repo, {}, dest)
5013 except error.RepoError:
5014 except error.RepoError:
5014 if opts.get('remote'):
5015 if opts.get('remote'):
5015 raise
5016 raise
5016 return dest, dbranch, None, None
5017 return dest, dbranch, None, None
5017 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5018 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5018 elif sother is None:
5019 elif sother is None:
5019 # there is no explicit destination peer, but source one is invalid
5020 # there is no explicit destination peer, but source one is invalid
5020 return dest, dbranch, None, None
5021 return dest, dbranch, None, None
5021 else:
5022 else:
5022 dother = sother
5023 dother = sother
5023 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5024 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5024 common = None
5025 common = None
5025 else:
5026 else:
5026 common = commoninc
5027 common = commoninc
5027 if revs:
5028 if revs:
5028 revs = [repo.lookup(rev) for rev in revs]
5029 revs = [repo.lookup(rev) for rev in revs]
5029 repo.ui.pushbuffer()
5030 repo.ui.pushbuffer()
5030 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5031 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5031 commoninc=common)
5032 commoninc=common)
5032 repo.ui.popbuffer()
5033 repo.ui.popbuffer()
5033 return dest, dbranch, dother, outgoing
5034 return dest, dbranch, dother, outgoing
5034
5035
5035 if needsoutgoing:
5036 if needsoutgoing:
5036 dest, dbranch, dother, outgoing = getoutgoing()
5037 dest, dbranch, dother, outgoing = getoutgoing()
5037 else:
5038 else:
5038 dest = dbranch = dother = outgoing = None
5039 dest = dbranch = dother = outgoing = None
5039
5040
5040 if opts.get('remote'):
5041 if opts.get('remote'):
5041 t = []
5042 t = []
5042 if incoming:
5043 if incoming:
5043 t.append(_('1 or more incoming'))
5044 t.append(_('1 or more incoming'))
5044 o = outgoing.missing
5045 o = outgoing.missing
5045 if o:
5046 if o:
5046 t.append(_('%d outgoing') % len(o))
5047 t.append(_('%d outgoing') % len(o))
5047 other = dother or sother
5048 other = dother or sother
5048 if 'bookmarks' in other.listkeys('namespaces'):
5049 if 'bookmarks' in other.listkeys('namespaces'):
5049 counts = bookmarks.summary(repo, other)
5050 counts = bookmarks.summary(repo, other)
5050 if counts[0] > 0:
5051 if counts[0] > 0:
5051 t.append(_('%d incoming bookmarks') % counts[0])
5052 t.append(_('%d incoming bookmarks') % counts[0])
5052 if counts[1] > 0:
5053 if counts[1] > 0:
5053 t.append(_('%d outgoing bookmarks') % counts[1])
5054 t.append(_('%d outgoing bookmarks') % counts[1])
5054
5055
5055 if t:
5056 if t:
5056 # i18n: column positioning for "hg summary"
5057 # i18n: column positioning for "hg summary"
5057 ui.write(_('remote: %s\n') % (', '.join(t)))
5058 ui.write(_('remote: %s\n') % (', '.join(t)))
5058 else:
5059 else:
5059 # i18n: column positioning for "hg summary"
5060 # i18n: column positioning for "hg summary"
5060 ui.status(_('remote: (synced)\n'))
5061 ui.status(_('remote: (synced)\n'))
5061
5062
5062 cmdutil.summaryremotehooks(ui, repo, opts,
5063 cmdutil.summaryremotehooks(ui, repo, opts,
5063 ((source, sbranch, sother, commoninc),
5064 ((source, sbranch, sother, commoninc),
5064 (dest, dbranch, dother, outgoing)))
5065 (dest, dbranch, dother, outgoing)))
5065
5066
5066 @command('tag',
5067 @command('tag',
5067 [('f', 'force', None, _('force tag')),
5068 [('f', 'force', None, _('force tag')),
5068 ('l', 'local', None, _('make the tag local')),
5069 ('l', 'local', None, _('make the tag local')),
5069 ('r', 'rev', '', _('revision to tag'), _('REV')),
5070 ('r', 'rev', '', _('revision to tag'), _('REV')),
5070 ('', 'remove', None, _('remove a tag')),
5071 ('', 'remove', None, _('remove a tag')),
5071 # -l/--local is already there, commitopts cannot be used
5072 # -l/--local is already there, commitopts cannot be used
5072 ('e', 'edit', None, _('invoke editor on commit messages')),
5073 ('e', 'edit', None, _('invoke editor on commit messages')),
5073 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5074 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5074 ] + commitopts2,
5075 ] + commitopts2,
5075 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5076 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5076 def tag(ui, repo, name1, *names, **opts):
5077 def tag(ui, repo, name1, *names, **opts):
5077 """add one or more tags for the current or given revision
5078 """add one or more tags for the current or given revision
5078
5079
5079 Name a particular revision using <name>.
5080 Name a particular revision using <name>.
5080
5081
5081 Tags are used to name particular revisions of the repository and are
5082 Tags are used to name particular revisions of the repository and are
5082 very useful to compare different revisions, to go back to significant
5083 very useful to compare different revisions, to go back to significant
5083 earlier versions or to mark branch points as releases, etc. Changing
5084 earlier versions or to mark branch points as releases, etc. Changing
5084 an existing tag is normally disallowed; use -f/--force to override.
5085 an existing tag is normally disallowed; use -f/--force to override.
5085
5086
5086 If no revision is given, the parent of the working directory is
5087 If no revision is given, the parent of the working directory is
5087 used.
5088 used.
5088
5089
5089 To facilitate version control, distribution, and merging of tags,
5090 To facilitate version control, distribution, and merging of tags,
5090 they are stored as a file named ".hgtags" which is managed similarly
5091 they are stored as a file named ".hgtags" which is managed similarly
5091 to other project files and can be hand-edited if necessary. This
5092 to other project files and can be hand-edited if necessary. This
5092 also means that tagging creates a new commit. The file
5093 also means that tagging creates a new commit. The file
5093 ".hg/localtags" is used for local tags (not shared among
5094 ".hg/localtags" is used for local tags (not shared among
5094 repositories).
5095 repositories).
5095
5096
5096 Tag commits are usually made at the head of a branch. If the parent
5097 Tag commits are usually made at the head of a branch. If the parent
5097 of the working directory is not a branch head, :hg:`tag` aborts; use
5098 of the working directory is not a branch head, :hg:`tag` aborts; use
5098 -f/--force to force the tag commit to be based on a non-head
5099 -f/--force to force the tag commit to be based on a non-head
5099 changeset.
5100 changeset.
5100
5101
5101 See :hg:`help dates` for a list of formats valid for -d/--date.
5102 See :hg:`help dates` for a list of formats valid for -d/--date.
5102
5103
5103 Since tag names have priority over branch names during revision
5104 Since tag names have priority over branch names during revision
5104 lookup, using an existing branch name as a tag name is discouraged.
5105 lookup, using an existing branch name as a tag name is discouraged.
5105
5106
5106 Returns 0 on success.
5107 Returns 0 on success.
5107 """
5108 """
5108 wlock = lock = None
5109 wlock = lock = None
5109 try:
5110 try:
5110 wlock = repo.wlock()
5111 wlock = repo.wlock()
5111 lock = repo.lock()
5112 lock = repo.lock()
5112 rev_ = "."
5113 rev_ = "."
5113 names = [t.strip() for t in (name1,) + names]
5114 names = [t.strip() for t in (name1,) + names]
5114 if len(names) != len(set(names)):
5115 if len(names) != len(set(names)):
5115 raise error.Abort(_('tag names must be unique'))
5116 raise error.Abort(_('tag names must be unique'))
5116 for n in names:
5117 for n in names:
5117 scmutil.checknewlabel(repo, n, 'tag')
5118 scmutil.checknewlabel(repo, n, 'tag')
5118 if not n:
5119 if not n:
5119 raise error.Abort(_('tag names cannot consist entirely of '
5120 raise error.Abort(_('tag names cannot consist entirely of '
5120 'whitespace'))
5121 'whitespace'))
5121 if opts.get('rev') and opts.get('remove'):
5122 if opts.get('rev') and opts.get('remove'):
5122 raise error.Abort(_("--rev and --remove are incompatible"))
5123 raise error.Abort(_("--rev and --remove are incompatible"))
5123 if opts.get('rev'):
5124 if opts.get('rev'):
5124 rev_ = opts['rev']
5125 rev_ = opts['rev']
5125 message = opts.get('message')
5126 message = opts.get('message')
5126 if opts.get('remove'):
5127 if opts.get('remove'):
5127 if opts.get('local'):
5128 if opts.get('local'):
5128 expectedtype = 'local'
5129 expectedtype = 'local'
5129 else:
5130 else:
5130 expectedtype = 'global'
5131 expectedtype = 'global'
5131
5132
5132 for n in names:
5133 for n in names:
5133 if not repo.tagtype(n):
5134 if not repo.tagtype(n):
5134 raise error.Abort(_("tag '%s' does not exist") % n)
5135 raise error.Abort(_("tag '%s' does not exist") % n)
5135 if repo.tagtype(n) != expectedtype:
5136 if repo.tagtype(n) != expectedtype:
5136 if expectedtype == 'global':
5137 if expectedtype == 'global':
5137 raise error.Abort(_("tag '%s' is not a global tag") % n)
5138 raise error.Abort(_("tag '%s' is not a global tag") % n)
5138 else:
5139 else:
5139 raise error.Abort(_("tag '%s' is not a local tag") % n)
5140 raise error.Abort(_("tag '%s' is not a local tag") % n)
5140 rev_ = 'null'
5141 rev_ = 'null'
5141 if not message:
5142 if not message:
5142 # we don't translate commit messages
5143 # we don't translate commit messages
5143 message = 'Removed tag %s' % ', '.join(names)
5144 message = 'Removed tag %s' % ', '.join(names)
5144 elif not opts.get('force'):
5145 elif not opts.get('force'):
5145 for n in names:
5146 for n in names:
5146 if n in repo.tags():
5147 if n in repo.tags():
5147 raise error.Abort(_("tag '%s' already exists "
5148 raise error.Abort(_("tag '%s' already exists "
5148 "(use -f to force)") % n)
5149 "(use -f to force)") % n)
5149 if not opts.get('local'):
5150 if not opts.get('local'):
5150 p1, p2 = repo.dirstate.parents()
5151 p1, p2 = repo.dirstate.parents()
5151 if p2 != nullid:
5152 if p2 != nullid:
5152 raise error.Abort(_('uncommitted merge'))
5153 raise error.Abort(_('uncommitted merge'))
5153 bheads = repo.branchheads()
5154 bheads = repo.branchheads()
5154 if not opts.get('force') and bheads and p1 not in bheads:
5155 if not opts.get('force') and bheads and p1 not in bheads:
5155 raise error.Abort(_('working directory is not at a branch head '
5156 raise error.Abort(_('working directory is not at a branch head '
5156 '(use -f to force)'))
5157 '(use -f to force)'))
5157 r = scmutil.revsingle(repo, rev_).node()
5158 r = scmutil.revsingle(repo, rev_).node()
5158
5159
5159 if not message:
5160 if not message:
5160 # we don't translate commit messages
5161 # we don't translate commit messages
5161 message = ('Added tag %s for changeset %s' %
5162 message = ('Added tag %s for changeset %s' %
5162 (', '.join(names), short(r)))
5163 (', '.join(names), short(r)))
5163
5164
5164 date = opts.get('date')
5165 date = opts.get('date')
5165 if date:
5166 if date:
5166 date = util.parsedate(date)
5167 date = util.parsedate(date)
5167
5168
5168 if opts.get('remove'):
5169 if opts.get('remove'):
5169 editform = 'tag.remove'
5170 editform = 'tag.remove'
5170 else:
5171 else:
5171 editform = 'tag.add'
5172 editform = 'tag.add'
5172 editor = cmdutil.getcommiteditor(editform=editform, **opts)
5173 editor = cmdutil.getcommiteditor(editform=editform, **opts)
5173
5174
5174 # don't allow tagging the null rev
5175 # don't allow tagging the null rev
5175 if (not opts.get('remove') and
5176 if (not opts.get('remove') and
5176 scmutil.revsingle(repo, rev_).rev() == nullrev):
5177 scmutil.revsingle(repo, rev_).rev() == nullrev):
5177 raise error.Abort(_("cannot tag null revision"))
5178 raise error.Abort(_("cannot tag null revision"))
5178
5179
5179 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
5180 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
5180 editor=editor)
5181 editor=editor)
5181 finally:
5182 finally:
5182 release(lock, wlock)
5183 release(lock, wlock)
5183
5184
5184 @command('tags', formatteropts, '')
5185 @command('tags', formatteropts, '')
5185 def tags(ui, repo, **opts):
5186 def tags(ui, repo, **opts):
5186 """list repository tags
5187 """list repository tags
5187
5188
5188 This lists both regular and local tags. When the -v/--verbose
5189 This lists both regular and local tags. When the -v/--verbose
5189 switch is used, a third column "local" is printed for local tags.
5190 switch is used, a third column "local" is printed for local tags.
5190 When the -q/--quiet switch is used, only the tag name is printed.
5191 When the -q/--quiet switch is used, only the tag name is printed.
5191
5192
5192 Returns 0 on success.
5193 Returns 0 on success.
5193 """
5194 """
5194
5195
5195 fm = ui.formatter('tags', opts)
5196 fm = ui.formatter('tags', opts)
5196 hexfunc = fm.hexfunc
5197 hexfunc = fm.hexfunc
5197 tagtype = ""
5198 tagtype = ""
5198
5199
5199 for t, n in reversed(repo.tagslist()):
5200 for t, n in reversed(repo.tagslist()):
5200 hn = hexfunc(n)
5201 hn = hexfunc(n)
5201 label = 'tags.normal'
5202 label = 'tags.normal'
5202 tagtype = ''
5203 tagtype = ''
5203 if repo.tagtype(t) == 'local':
5204 if repo.tagtype(t) == 'local':
5204 label = 'tags.local'
5205 label = 'tags.local'
5205 tagtype = 'local'
5206 tagtype = 'local'
5206
5207
5207 fm.startitem()
5208 fm.startitem()
5208 fm.write('tag', '%s', t, label=label)
5209 fm.write('tag', '%s', t, label=label)
5209 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5210 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5210 fm.condwrite(not ui.quiet, 'rev node', fmt,
5211 fm.condwrite(not ui.quiet, 'rev node', fmt,
5211 repo.changelog.rev(n), hn, label=label)
5212 repo.changelog.rev(n), hn, label=label)
5212 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5213 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5213 tagtype, label=label)
5214 tagtype, label=label)
5214 fm.plain('\n')
5215 fm.plain('\n')
5215 fm.end()
5216 fm.end()
5216
5217
5217 @command('tip',
5218 @command('tip',
5218 [('p', 'patch', None, _('show patch')),
5219 [('p', 'patch', None, _('show patch')),
5219 ('g', 'git', None, _('use git extended diff format')),
5220 ('g', 'git', None, _('use git extended diff format')),
5220 ] + templateopts,
5221 ] + templateopts,
5221 _('[-p] [-g]'))
5222 _('[-p] [-g]'))
5222 def tip(ui, repo, **opts):
5223 def tip(ui, repo, **opts):
5223 """show the tip revision (DEPRECATED)
5224 """show the tip revision (DEPRECATED)
5224
5225
5225 The tip revision (usually just called the tip) is the changeset
5226 The tip revision (usually just called the tip) is the changeset
5226 most recently added to the repository (and therefore the most
5227 most recently added to the repository (and therefore the most
5227 recently changed head).
5228 recently changed head).
5228
5229
5229 If you have just made a commit, that commit will be the tip. If
5230 If you have just made a commit, that commit will be the tip. If
5230 you have just pulled changes from another repository, the tip of
5231 you have just pulled changes from another repository, the tip of
5231 that repository becomes the current tip. The "tip" tag is special
5232 that repository becomes the current tip. The "tip" tag is special
5232 and cannot be renamed or assigned to a different changeset.
5233 and cannot be renamed or assigned to a different changeset.
5233
5234
5234 This command is deprecated, please use :hg:`heads` instead.
5235 This command is deprecated, please use :hg:`heads` instead.
5235
5236
5236 Returns 0 on success.
5237 Returns 0 on success.
5237 """
5238 """
5238 displayer = cmdutil.show_changeset(ui, repo, opts)
5239 displayer = cmdutil.show_changeset(ui, repo, opts)
5239 displayer.show(repo['tip'])
5240 displayer.show(repo['tip'])
5240 displayer.close()
5241 displayer.close()
5241
5242
5242 @command('unbundle',
5243 @command('unbundle',
5243 [('u', 'update', None,
5244 [('u', 'update', None,
5244 _('update to new branch head if changesets were unbundled'))],
5245 _('update to new branch head if changesets were unbundled'))],
5245 _('[-u] FILE...'))
5246 _('[-u] FILE...'))
5246 def unbundle(ui, repo, fname1, *fnames, **opts):
5247 def unbundle(ui, repo, fname1, *fnames, **opts):
5247 """apply one or more changegroup files
5248 """apply one or more changegroup files
5248
5249
5249 Apply one or more compressed changegroup files generated by the
5250 Apply one or more compressed changegroup files generated by the
5250 bundle command.
5251 bundle command.
5251
5252
5252 Returns 0 on success, 1 if an update has unresolved files.
5253 Returns 0 on success, 1 if an update has unresolved files.
5253 """
5254 """
5254 fnames = (fname1,) + fnames
5255 fnames = (fname1,) + fnames
5255
5256
5256 with repo.lock():
5257 with repo.lock():
5257 for fname in fnames:
5258 for fname in fnames:
5258 f = hg.openpath(ui, fname)
5259 f = hg.openpath(ui, fname)
5259 gen = exchange.readbundle(ui, f, fname)
5260 gen = exchange.readbundle(ui, f, fname)
5260 if isinstance(gen, bundle2.unbundle20):
5261 if isinstance(gen, bundle2.unbundle20):
5261 tr = repo.transaction('unbundle')
5262 tr = repo.transaction('unbundle')
5262 try:
5263 try:
5263 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
5264 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
5264 url='bundle:' + fname)
5265 url='bundle:' + fname)
5265 tr.close()
5266 tr.close()
5266 except error.BundleUnknownFeatureError as exc:
5267 except error.BundleUnknownFeatureError as exc:
5267 raise error.Abort(_('%s: unknown bundle feature, %s')
5268 raise error.Abort(_('%s: unknown bundle feature, %s')
5268 % (fname, exc),
5269 % (fname, exc),
5269 hint=_("see https://mercurial-scm.org/"
5270 hint=_("see https://mercurial-scm.org/"
5270 "wiki/BundleFeature for more "
5271 "wiki/BundleFeature for more "
5271 "information"))
5272 "information"))
5272 finally:
5273 finally:
5273 if tr:
5274 if tr:
5274 tr.release()
5275 tr.release()
5275 changes = [r.get('return', 0)
5276 changes = [r.get('return', 0)
5276 for r in op.records['changegroup']]
5277 for r in op.records['changegroup']]
5277 modheads = changegroup.combineresults(changes)
5278 modheads = changegroup.combineresults(changes)
5278 elif isinstance(gen, streamclone.streamcloneapplier):
5279 elif isinstance(gen, streamclone.streamcloneapplier):
5279 raise error.Abort(
5280 raise error.Abort(
5280 _('packed bundles cannot be applied with '
5281 _('packed bundles cannot be applied with '
5281 '"hg unbundle"'),
5282 '"hg unbundle"'),
5282 hint=_('use "hg debugapplystreamclonebundle"'))
5283 hint=_('use "hg debugapplystreamclonebundle"'))
5283 else:
5284 else:
5284 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
5285 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
5285
5286
5286 return postincoming(ui, repo, modheads, opts.get('update'), None, None)
5287 return postincoming(ui, repo, modheads, opts.get('update'), None, None)
5287
5288
5288 @command('^update|up|checkout|co',
5289 @command('^update|up|checkout|co',
5289 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5290 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5290 ('c', 'check', None, _('require clean working directory')),
5291 ('c', 'check', None, _('require clean working directory')),
5291 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5292 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5292 ('r', 'rev', '', _('revision'), _('REV'))
5293 ('r', 'rev', '', _('revision'), _('REV'))
5293 ] + mergetoolopts,
5294 ] + mergetoolopts,
5294 _('[-C|-c] [-d DATE] [[-r] REV]'))
5295 _('[-C|-c] [-d DATE] [[-r] REV]'))
5295 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
5296 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
5296 tool=None):
5297 tool=None):
5297 """update working directory (or switch revisions)
5298 """update working directory (or switch revisions)
5298
5299
5299 Update the repository's working directory to the specified
5300 Update the repository's working directory to the specified
5300 changeset. If no changeset is specified, update to the tip of the
5301 changeset. If no changeset is specified, update to the tip of the
5301 current named branch and move the active bookmark (see :hg:`help
5302 current named branch and move the active bookmark (see :hg:`help
5302 bookmarks`).
5303 bookmarks`).
5303
5304
5304 Update sets the working directory's parent revision to the specified
5305 Update sets the working directory's parent revision to the specified
5305 changeset (see :hg:`help parents`).
5306 changeset (see :hg:`help parents`).
5306
5307
5307 If the changeset is not a descendant or ancestor of the working
5308 If the changeset is not a descendant or ancestor of the working
5308 directory's parent and there are uncommitted changes, the update is
5309 directory's parent and there are uncommitted changes, the update is
5309 aborted. With the -c/--check option, the working directory is checked
5310 aborted. With the -c/--check option, the working directory is checked
5310 for uncommitted changes; if none are found, the working directory is
5311 for uncommitted changes; if none are found, the working directory is
5311 updated to the specified changeset.
5312 updated to the specified changeset.
5312
5313
5313 .. container:: verbose
5314 .. container:: verbose
5314
5315
5315 The -C/--clean and -c/--check options control what happens if the
5316 The -C/--clean and -c/--check options control what happens if the
5316 working directory contains uncommitted changes.
5317 working directory contains uncommitted changes.
5317 At most of one of them can be specified.
5318 At most of one of them can be specified.
5318
5319
5319 1. If no option is specified, and if
5320 1. If no option is specified, and if
5320 the requested changeset is an ancestor or descendant of
5321 the requested changeset is an ancestor or descendant of
5321 the working directory's parent, the uncommitted changes
5322 the working directory's parent, the uncommitted changes
5322 are merged into the requested changeset and the merged
5323 are merged into the requested changeset and the merged
5323 result is left uncommitted. If the requested changeset is
5324 result is left uncommitted. If the requested changeset is
5324 not an ancestor or descendant (that is, it is on another
5325 not an ancestor or descendant (that is, it is on another
5325 branch), the update is aborted and the uncommitted changes
5326 branch), the update is aborted and the uncommitted changes
5326 are preserved.
5327 are preserved.
5327
5328
5328 2. With the -c/--check option, the update is aborted and the
5329 2. With the -c/--check option, the update is aborted and the
5329 uncommitted changes are preserved.
5330 uncommitted changes are preserved.
5330
5331
5331 3. With the -C/--clean option, uncommitted changes are discarded and
5332 3. With the -C/--clean option, uncommitted changes are discarded and
5332 the working directory is updated to the requested changeset.
5333 the working directory is updated to the requested changeset.
5333
5334
5334 To cancel an uncommitted merge (and lose your changes), use
5335 To cancel an uncommitted merge (and lose your changes), use
5335 :hg:`update --clean .`.
5336 :hg:`update --clean .`.
5336
5337
5337 Use null as the changeset to remove the working directory (like
5338 Use null as the changeset to remove the working directory (like
5338 :hg:`clone -U`).
5339 :hg:`clone -U`).
5339
5340
5340 If you want to revert just one file to an older revision, use
5341 If you want to revert just one file to an older revision, use
5341 :hg:`revert [-r REV] NAME`.
5342 :hg:`revert [-r REV] NAME`.
5342
5343
5343 See :hg:`help dates` for a list of formats valid for -d/--date.
5344 See :hg:`help dates` for a list of formats valid for -d/--date.
5344
5345
5345 Returns 0 on success, 1 if there are unresolved files.
5346 Returns 0 on success, 1 if there are unresolved files.
5346 """
5347 """
5347 if rev and node:
5348 if rev and node:
5348 raise error.Abort(_("please specify just one revision"))
5349 raise error.Abort(_("please specify just one revision"))
5349
5350
5350 if rev is None or rev == '':
5351 if rev is None or rev == '':
5351 rev = node
5352 rev = node
5352
5353
5353 if date and rev is not None:
5354 if date and rev is not None:
5354 raise error.Abort(_("you can't specify a revision and a date"))
5355 raise error.Abort(_("you can't specify a revision and a date"))
5355
5356
5356 if check and clean:
5357 if check and clean:
5357 raise error.Abort(_("cannot specify both -c/--check and -C/--clean"))
5358 raise error.Abort(_("cannot specify both -c/--check and -C/--clean"))
5358
5359
5359 with repo.wlock():
5360 with repo.wlock():
5360 cmdutil.clearunfinished(repo)
5361 cmdutil.clearunfinished(repo)
5361
5362
5362 if date:
5363 if date:
5363 rev = cmdutil.finddate(ui, repo, date)
5364 rev = cmdutil.finddate(ui, repo, date)
5364
5365
5365 # if we defined a bookmark, we have to remember the original name
5366 # if we defined a bookmark, we have to remember the original name
5366 brev = rev
5367 brev = rev
5367 rev = scmutil.revsingle(repo, rev, rev).rev()
5368 rev = scmutil.revsingle(repo, rev, rev).rev()
5368
5369
5369 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
5370 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
5370
5371
5371 return hg.updatetotally(ui, repo, rev, brev, clean=clean, check=check)
5372 return hg.updatetotally(ui, repo, rev, brev, clean=clean, check=check)
5372
5373
5373 @command('verify', [])
5374 @command('verify', [])
5374 def verify(ui, repo):
5375 def verify(ui, repo):
5375 """verify the integrity of the repository
5376 """verify the integrity of the repository
5376
5377
5377 Verify the integrity of the current repository.
5378 Verify the integrity of the current repository.
5378
5379
5379 This will perform an extensive check of the repository's
5380 This will perform an extensive check of the repository's
5380 integrity, validating the hashes and checksums of each entry in
5381 integrity, validating the hashes and checksums of each entry in
5381 the changelog, manifest, and tracked files, as well as the
5382 the changelog, manifest, and tracked files, as well as the
5382 integrity of their crosslinks and indices.
5383 integrity of their crosslinks and indices.
5383
5384
5384 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
5385 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
5385 for more information about recovery from corruption of the
5386 for more information about recovery from corruption of the
5386 repository.
5387 repository.
5387
5388
5388 Returns 0 on success, 1 if errors are encountered.
5389 Returns 0 on success, 1 if errors are encountered.
5389 """
5390 """
5390 return hg.verify(repo)
5391 return hg.verify(repo)
5391
5392
5392 @command('version', [] + formatteropts, norepo=True)
5393 @command('version', [] + formatteropts, norepo=True)
5393 def version_(ui, **opts):
5394 def version_(ui, **opts):
5394 """output version and copyright information"""
5395 """output version and copyright information"""
5395 fm = ui.formatter("version", opts)
5396 fm = ui.formatter("version", opts)
5396 fm.startitem()
5397 fm.startitem()
5397 fm.write("ver", _("Mercurial Distributed SCM (version %s)\n"),
5398 fm.write("ver", _("Mercurial Distributed SCM (version %s)\n"),
5398 util.version())
5399 util.version())
5399 license = _(
5400 license = _(
5400 "(see https://mercurial-scm.org for more information)\n"
5401 "(see https://mercurial-scm.org for more information)\n"
5401 "\nCopyright (C) 2005-2017 Matt Mackall and others\n"
5402 "\nCopyright (C) 2005-2017 Matt Mackall and others\n"
5402 "This is free software; see the source for copying conditions. "
5403 "This is free software; see the source for copying conditions. "
5403 "There is NO\nwarranty; "
5404 "There is NO\nwarranty; "
5404 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5405 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5405 )
5406 )
5406 if not ui.quiet:
5407 if not ui.quiet:
5407 fm.plain(license)
5408 fm.plain(license)
5408
5409
5409 if ui.verbose:
5410 if ui.verbose:
5410 fm.plain(_("\nEnabled extensions:\n\n"))
5411 fm.plain(_("\nEnabled extensions:\n\n"))
5411 # format names and versions into columns
5412 # format names and versions into columns
5412 names = []
5413 names = []
5413 vers = []
5414 vers = []
5414 isinternals = []
5415 isinternals = []
5415 for name, module in extensions.extensions():
5416 for name, module in extensions.extensions():
5416 names.append(name)
5417 names.append(name)
5417 vers.append(extensions.moduleversion(module) or None)
5418 vers.append(extensions.moduleversion(module) or None)
5418 isinternals.append(extensions.ismoduleinternal(module))
5419 isinternals.append(extensions.ismoduleinternal(module))
5419 fn = fm.nested("extensions")
5420 fn = fm.nested("extensions")
5420 if names:
5421 if names:
5421 namefmt = " %%-%ds " % max(len(n) for n in names)
5422 namefmt = " %%-%ds " % max(len(n) for n in names)
5422 places = [_("external"), _("internal")]
5423 places = [_("external"), _("internal")]
5423 for n, v, p in zip(names, vers, isinternals):
5424 for n, v, p in zip(names, vers, isinternals):
5424 fn.startitem()
5425 fn.startitem()
5425 fn.condwrite(ui.verbose, "name", namefmt, n)
5426 fn.condwrite(ui.verbose, "name", namefmt, n)
5426 if ui.verbose:
5427 if ui.verbose:
5427 fn.plain("%s " % places[p])
5428 fn.plain("%s " % places[p])
5428 fn.data(bundled=p)
5429 fn.data(bundled=p)
5429 fn.condwrite(ui.verbose and v, "ver", "%s", v)
5430 fn.condwrite(ui.verbose and v, "ver", "%s", v)
5430 if ui.verbose:
5431 if ui.verbose:
5431 fn.plain("\n")
5432 fn.plain("\n")
5432 fn.end()
5433 fn.end()
5433 fm.end()
5434 fm.end()
5434
5435
5435 def loadcmdtable(ui, name, cmdtable):
5436 def loadcmdtable(ui, name, cmdtable):
5436 """Load command functions from specified cmdtable
5437 """Load command functions from specified cmdtable
5437 """
5438 """
5438 overrides = [cmd for cmd in cmdtable if cmd in table]
5439 overrides = [cmd for cmd in cmdtable if cmd in table]
5439 if overrides:
5440 if overrides:
5440 ui.warn(_("extension '%s' overrides commands: %s\n")
5441 ui.warn(_("extension '%s' overrides commands: %s\n")
5441 % (name, " ".join(overrides)))
5442 % (name, " ".join(overrides)))
5442 table.update(cmdtable)
5443 table.update(cmdtable)
@@ -1,166 +1,206 b''
1 $ cat >> fakepager.py <<EOF
1 $ cat >> fakepager.py <<EOF
2 > import sys
2 > import sys
3 > for line in sys.stdin:
3 > for line in sys.stdin:
4 > sys.stdout.write('paged! %r\n' % line)
4 > sys.stdout.write('paged! %r\n' % line)
5 > EOF
5 > EOF
6
6
7 Enable ui.formatted because pager won't fire without it, and set up
7 Enable ui.formatted because pager won't fire without it, and set up
8 pager and tell it to use our fake pager that lets us see when the
8 pager and tell it to use our fake pager that lets us see when the
9 pager was running.
9 pager was running.
10 $ cat >> $HGRCPATH <<EOF
10 $ cat >> $HGRCPATH <<EOF
11 > [ui]
11 > [ui]
12 > formatted = yes
12 > formatted = yes
13 > [extensions]
13 > [extensions]
14 > pager=
14 > pager=
15 > [pager]
15 > [pager]
16 > pager = python $TESTTMP/fakepager.py
16 > pager = python $TESTTMP/fakepager.py
17 > EOF
17 > EOF
18
18
19 $ hg init repo
19 $ hg init repo
20 $ cd repo
20 $ cd repo
21 $ echo a >> a
21 $ echo a >> a
22 $ hg add a
22 $ hg add a
23 $ hg ci -m 'add a'
23 $ hg ci -m 'add a'
24 $ for x in `python $TESTDIR/seq.py 1 10`; do
24 $ for x in `python $TESTDIR/seq.py 1 10`; do
25 > echo a $x >> a
25 > echo a $x >> a
26 > hg ci -m "modify a $x"
26 > hg ci -m "modify a $x"
27 > done
27 > done
28
28
29 By default diff and log are paged, but id is not:
29 By default diff and log are paged, but id is not:
30
30
31 $ hg diff -c 2 --pager=yes
31 $ hg diff -c 2 --pager=yes
32 paged! 'diff -r f4be7687d414 -r bce265549556 a\n'
32 paged! 'diff -r f4be7687d414 -r bce265549556 a\n'
33 paged! '--- a/a\tThu Jan 01 00:00:00 1970 +0000\n'
33 paged! '--- a/a\tThu Jan 01 00:00:00 1970 +0000\n'
34 paged! '+++ b/a\tThu Jan 01 00:00:00 1970 +0000\n'
34 paged! '+++ b/a\tThu Jan 01 00:00:00 1970 +0000\n'
35 paged! '@@ -1,2 +1,3 @@\n'
35 paged! '@@ -1,2 +1,3 @@\n'
36 paged! ' a\n'
36 paged! ' a\n'
37 paged! ' a 1\n'
37 paged! ' a 1\n'
38 paged! '+a 2\n'
38 paged! '+a 2\n'
39
39
40 $ hg log --limit 2
40 $ hg log --limit 2
41 paged! 'changeset: 10:46106edeeb38\n'
41 paged! 'changeset: 10:46106edeeb38\n'
42 paged! 'tag: tip\n'
42 paged! 'tag: tip\n'
43 paged! 'user: test\n'
43 paged! 'user: test\n'
44 paged! 'date: Thu Jan 01 00:00:00 1970 +0000\n'
44 paged! 'date: Thu Jan 01 00:00:00 1970 +0000\n'
45 paged! 'summary: modify a 10\n'
45 paged! 'summary: modify a 10\n'
46 paged! '\n'
46 paged! '\n'
47 paged! 'changeset: 9:6dd8ea7dd621\n'
47 paged! 'changeset: 9:6dd8ea7dd621\n'
48 paged! 'user: test\n'
48 paged! 'user: test\n'
49 paged! 'date: Thu Jan 01 00:00:00 1970 +0000\n'
49 paged! 'date: Thu Jan 01 00:00:00 1970 +0000\n'
50 paged! 'summary: modify a 9\n'
50 paged! 'summary: modify a 9\n'
51 paged! '\n'
51 paged! '\n'
52
52
53 $ hg id
53 $ hg id
54 46106edeeb38 tip
54 46106edeeb38 tip
55
55
56 We can enable the pager on id:
56 We can enable the pager on id:
57
57
58 $ hg --config pager.attend-id=yes id
58 $ hg --config pager.attend-id=yes id
59 paged! '46106edeeb38 tip\n'
59 paged! '46106edeeb38 tip\n'
60
60
61 Setting attend-$COMMAND to a false value works, even with pager in
61 Setting attend-$COMMAND to a false value works, even with pager in
62 core:
62 core:
63
63
64 $ hg --config pager.attend-diff=no diff -c 2
64 $ hg --config pager.attend-diff=no diff -c 2
65 diff -r f4be7687d414 -r bce265549556 a
65 diff -r f4be7687d414 -r bce265549556 a
66 --- a/a Thu Jan 01 00:00:00 1970 +0000
66 --- a/a Thu Jan 01 00:00:00 1970 +0000
67 +++ b/a Thu Jan 01 00:00:00 1970 +0000
67 +++ b/a Thu Jan 01 00:00:00 1970 +0000
68 @@ -1,2 +1,3 @@
68 @@ -1,2 +1,3 @@
69 a
69 a
70 a 1
70 a 1
71 +a 2
71 +a 2
72
72
73 If 'log' is in attend, then 'history' should also be paged:
73 If 'log' is in attend, then 'history' should also be paged:
74 $ hg history --limit 2 --config pager.attend=log
74 $ hg history --limit 2 --config pager.attend=log
75 paged! 'changeset: 10:46106edeeb38\n'
75 paged! 'changeset: 10:46106edeeb38\n'
76 paged! 'tag: tip\n'
76 paged! 'tag: tip\n'
77 paged! 'user: test\n'
77 paged! 'user: test\n'
78 paged! 'date: Thu Jan 01 00:00:00 1970 +0000\n'
78 paged! 'date: Thu Jan 01 00:00:00 1970 +0000\n'
79 paged! 'summary: modify a 10\n'
79 paged! 'summary: modify a 10\n'
80 paged! '\n'
80 paged! '\n'
81 paged! 'changeset: 9:6dd8ea7dd621\n'
81 paged! 'changeset: 9:6dd8ea7dd621\n'
82 paged! 'user: test\n'
82 paged! 'user: test\n'
83 paged! 'date: Thu Jan 01 00:00:00 1970 +0000\n'
83 paged! 'date: Thu Jan 01 00:00:00 1970 +0000\n'
84 paged! 'summary: modify a 9\n'
84 paged! 'summary: modify a 9\n'
85 paged! '\n'
85 paged! '\n'
86
86
87 Pager should not start if stdout is not a tty.
87 Pager should not start if stdout is not a tty.
88
88
89 $ hg log -l1 -q --config ui.formatted=False
89 $ hg log -l1 -q --config ui.formatted=False
90 10:46106edeeb38
90 10:46106edeeb38
91
91
92 Pager with color enabled allows colors to come through by default,
92 Pager with color enabled allows colors to come through by default,
93 even though stdout is no longer a tty.
93 even though stdout is no longer a tty.
94 $ cat >> $HGRCPATH <<EOF
94 $ cat >> $HGRCPATH <<EOF
95 > [extensions]
95 > [extensions]
96 > color=
96 > color=
97 > [color]
97 > [color]
98 > mode = ansi
98 > mode = ansi
99 > EOF
99 > EOF
100 $ hg log --limit 3
100 $ hg log --limit 3
101 paged! '\x1b[0;33mchangeset: 10:46106edeeb38\x1b[0m\n'
101 paged! '\x1b[0;33mchangeset: 10:46106edeeb38\x1b[0m\n'
102 paged! 'tag: tip\n'
102 paged! 'tag: tip\n'
103 paged! 'user: test\n'
103 paged! 'user: test\n'
104 paged! 'date: Thu Jan 01 00:00:00 1970 +0000\n'
104 paged! 'date: Thu Jan 01 00:00:00 1970 +0000\n'
105 paged! 'summary: modify a 10\n'
105 paged! 'summary: modify a 10\n'
106 paged! '\n'
106 paged! '\n'
107 paged! '\x1b[0;33mchangeset: 9:6dd8ea7dd621\x1b[0m\n'
107 paged! '\x1b[0;33mchangeset: 9:6dd8ea7dd621\x1b[0m\n'
108 paged! 'user: test\n'
108 paged! 'user: test\n'
109 paged! 'date: Thu Jan 01 00:00:00 1970 +0000\n'
109 paged! 'date: Thu Jan 01 00:00:00 1970 +0000\n'
110 paged! 'summary: modify a 9\n'
110 paged! 'summary: modify a 9\n'
111 paged! '\n'
111 paged! '\n'
112 paged! '\x1b[0;33mchangeset: 8:cff05a6312fe\x1b[0m\n'
112 paged! '\x1b[0;33mchangeset: 8:cff05a6312fe\x1b[0m\n'
113 paged! 'user: test\n'
113 paged! 'user: test\n'
114 paged! 'date: Thu Jan 01 00:00:00 1970 +0000\n'
114 paged! 'date: Thu Jan 01 00:00:00 1970 +0000\n'
115 paged! 'summary: modify a 8\n'
115 paged! 'summary: modify a 8\n'
116 paged! '\n'
116 paged! '\n'
117
117
118 Pager works with shell aliases.
118 Pager works with shell aliases.
119
119
120 $ cat >> $HGRCPATH <<EOF
120 $ cat >> $HGRCPATH <<EOF
121 > [alias]
121 > [alias]
122 > echoa = !echo a
122 > echoa = !echo a
123 > EOF
123 > EOF
124
124
125 $ hg echoa
125 $ hg echoa
126 a
126 a
127 $ hg --config pager.attend-echoa=yes echoa
127 $ hg --config pager.attend-echoa=yes echoa
128 paged! 'a\n'
128 paged! 'a\n'
129
129
130 Pager works with hg aliases including environment variables.
130 Pager works with hg aliases including environment variables.
131
131
132 $ cat >> $HGRCPATH <<'EOF'
132 $ cat >> $HGRCPATH <<'EOF'
133 > [alias]
133 > [alias]
134 > printa = log -T "$A\n" -r 0
134 > printa = log -T "$A\n" -r 0
135 > EOF
135 > EOF
136
136
137 $ A=1 hg --config pager.attend-printa=yes printa
137 $ A=1 hg --config pager.attend-printa=yes printa
138 paged! '1\n'
138 paged! '1\n'
139 $ A=2 hg --config pager.attend-printa=yes printa
139 $ A=2 hg --config pager.attend-printa=yes printa
140 paged! '2\n'
140 paged! '2\n'
141
141
142 Something that's explicitly attended is still not paginated if the
142 Something that's explicitly attended is still not paginated if the
143 pager is globally set to off using a flag:
143 pager is globally set to off using a flag:
144 $ A=2 hg --config pager.attend-printa=yes printa --pager=no
144 $ A=2 hg --config pager.attend-printa=yes printa --pager=no
145 2
145 2
146
146
147 Pager should not override the exit code of other commands
147 Pager should not override the exit code of other commands
148
148
149 $ cat >> $TESTTMP/fortytwo.py <<'EOF'
149 $ cat >> $TESTTMP/fortytwo.py <<'EOF'
150 > from mercurial import cmdutil, commands
150 > from mercurial import cmdutil, commands
151 > cmdtable = {}
151 > cmdtable = {}
152 > command = cmdutil.command(cmdtable)
152 > command = cmdutil.command(cmdtable)
153 > @command('fortytwo', [], 'fortytwo', norepo=True)
153 > @command('fortytwo', [], 'fortytwo', norepo=True)
154 > def fortytwo(ui, *opts):
154 > def fortytwo(ui, *opts):
155 > ui.write('42\n')
155 > ui.write('42\n')
156 > return 42
156 > return 42
157 > EOF
157 > EOF
158
158
159 $ cat >> $HGRCPATH <<'EOF'
159 $ cat >> $HGRCPATH <<'EOF'
160 > [extensions]
160 > [extensions]
161 > fortytwo = $TESTTMP/fortytwo.py
161 > fortytwo = $TESTTMP/fortytwo.py
162 > EOF
162 > EOF
163
163
164 $ hg fortytwo --pager=on
164 $ hg fortytwo --pager=on
165 paged! '42\n'
165 paged! '42\n'
166 [42]
166 [42]
167
168 A command that asks for paging using ui.pager() directly works:
169 $ hg blame a
170 paged! ' 0: a\n'
171 paged! ' 1: a 1\n'
172 paged! ' 2: a 2\n'
173 paged! ' 3: a 3\n'
174 paged! ' 4: a 4\n'
175 paged! ' 5: a 5\n'
176 paged! ' 6: a 6\n'
177 paged! ' 7: a 7\n'
178 paged! ' 8: a 8\n'
179 paged! ' 9: a 9\n'
180 paged! '10: a 10\n'
181 but not with HGPLAIN
182 $ HGPLAIN=1 hg blame a
183 0: a
184 1: a 1
185 2: a 2
186 3: a 3
187 4: a 4
188 5: a 5
189 6: a 6
190 7: a 7
191 8: a 8
192 9: a 9
193 10: a 10
194 explicit flags work too:
195 $ hg blame --pager=no a
196 0: a
197 1: a 1
198 2: a 2
199 3: a 3
200 4: a 4
201 5: a 5
202 6: a 6
203 7: a 7
204 8: a 8
205 9: a 9
206 10: a 10
General Comments 0
You need to be logged in to leave comments. Login now