##// END OF EJS Templates
log: migrate to modern pager API
Augie Fackler -
r31032:1cec1d86 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 = ['glog', 'log', 'qdiff']
113 attended = ['qdiff']
@@ -1,5449 +1,5450 b''
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9
9
10 import difflib
10 import difflib
11 import errno
11 import errno
12 import os
12 import os
13 import re
13 import re
14
14
15 from .i18n import _
15 from .i18n import _
16 from .node import (
16 from .node import (
17 hex,
17 hex,
18 nullid,
18 nullid,
19 nullrev,
19 nullrev,
20 short,
20 short,
21 )
21 )
22 from . import (
22 from . import (
23 archival,
23 archival,
24 bookmarks,
24 bookmarks,
25 bundle2,
25 bundle2,
26 changegroup,
26 changegroup,
27 cmdutil,
27 cmdutil,
28 copies,
28 copies,
29 destutil,
29 destutil,
30 dirstateguard,
30 dirstateguard,
31 discovery,
31 discovery,
32 encoding,
32 encoding,
33 error,
33 error,
34 exchange,
34 exchange,
35 extensions,
35 extensions,
36 graphmod,
36 graphmod,
37 hbisect,
37 hbisect,
38 help,
38 help,
39 hg,
39 hg,
40 lock as lockmod,
40 lock as lockmod,
41 merge as mergemod,
41 merge as mergemod,
42 minirst,
42 minirst,
43 obsolete,
43 obsolete,
44 patch,
44 patch,
45 phases,
45 phases,
46 pycompat,
46 pycompat,
47 revsetlang,
47 revsetlang,
48 scmutil,
48 scmutil,
49 server,
49 server,
50 sshserver,
50 sshserver,
51 streamclone,
51 streamclone,
52 templatekw,
52 templatekw,
53 ui as uimod,
53 ui as uimod,
54 util,
54 util,
55 )
55 )
56
56
57 release = lockmod.release
57 release = lockmod.release
58
58
59 table = {}
59 table = {}
60
60
61 command = cmdutil.command(table)
61 command = cmdutil.command(table)
62
62
63 # label constants
63 # label constants
64 # until 3.5, bookmarks.current was the advertised name, not
64 # until 3.5, bookmarks.current was the advertised name, not
65 # bookmarks.active, so we must use both to avoid breaking old
65 # bookmarks.active, so we must use both to avoid breaking old
66 # custom styles
66 # custom styles
67 activebookmarklabel = 'bookmarks.active bookmarks.current'
67 activebookmarklabel = 'bookmarks.active bookmarks.current'
68
68
69 # common command options
69 # common command options
70
70
71 globalopts = [
71 globalopts = [
72 ('R', 'repository', '',
72 ('R', 'repository', '',
73 _('repository root directory or name of overlay bundle file'),
73 _('repository root directory or name of overlay bundle file'),
74 _('REPO')),
74 _('REPO')),
75 ('', 'cwd', '',
75 ('', 'cwd', '',
76 _('change working directory'), _('DIR')),
76 _('change working directory'), _('DIR')),
77 ('y', 'noninteractive', None,
77 ('y', 'noninteractive', None,
78 _('do not prompt, automatically pick the first choice for all prompts')),
78 _('do not prompt, automatically pick the first choice for all prompts')),
79 ('q', 'quiet', None, _('suppress output')),
79 ('q', 'quiet', None, _('suppress output')),
80 ('v', 'verbose', None, _('enable additional output')),
80 ('v', 'verbose', None, _('enable additional output')),
81 ('', 'config', [],
81 ('', 'config', [],
82 _('set/override config option (use \'section.name=value\')'),
82 _('set/override config option (use \'section.name=value\')'),
83 _('CONFIG')),
83 _('CONFIG')),
84 ('', 'debug', None, _('enable debugging output')),
84 ('', 'debug', None, _('enable debugging output')),
85 ('', 'debugger', None, _('start debugger')),
85 ('', 'debugger', None, _('start debugger')),
86 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
86 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
87 _('ENCODE')),
87 _('ENCODE')),
88 ('', 'encodingmode', encoding.encodingmode,
88 ('', 'encodingmode', encoding.encodingmode,
89 _('set the charset encoding mode'), _('MODE')),
89 _('set the charset encoding mode'), _('MODE')),
90 ('', 'traceback', None, _('always print a traceback on exception')),
90 ('', 'traceback', None, _('always print a traceback on exception')),
91 ('', 'time', None, _('time how long the command takes')),
91 ('', 'time', None, _('time how long the command takes')),
92 ('', 'profile', None, _('print command execution profile')),
92 ('', 'profile', None, _('print command execution profile')),
93 ('', 'version', None, _('output version information and exit')),
93 ('', 'version', None, _('output version information and exit')),
94 ('h', 'help', None, _('display help and exit')),
94 ('h', 'help', None, _('display help and exit')),
95 ('', 'hidden', False, _('consider hidden changesets')),
95 ('', 'hidden', False, _('consider hidden changesets')),
96 ('', 'pager', 'auto',
96 ('', 'pager', 'auto',
97 _("when to paginate (boolean, always, auto, or never)"), _('TYPE')),
97 _("when to paginate (boolean, always, auto, or never)"), _('TYPE')),
98 ]
98 ]
99
99
100 dryrunopts = [('n', 'dry-run', None,
100 dryrunopts = [('n', 'dry-run', None,
101 _('do not perform actions, just print output'))]
101 _('do not perform actions, just print output'))]
102
102
103 remoteopts = [
103 remoteopts = [
104 ('e', 'ssh', '',
104 ('e', 'ssh', '',
105 _('specify ssh command to use'), _('CMD')),
105 _('specify ssh command to use'), _('CMD')),
106 ('', 'remotecmd', '',
106 ('', 'remotecmd', '',
107 _('specify hg command to run on the remote side'), _('CMD')),
107 _('specify hg command to run on the remote side'), _('CMD')),
108 ('', 'insecure', None,
108 ('', 'insecure', None,
109 _('do not verify server certificate (ignoring web.cacerts config)')),
109 _('do not verify server certificate (ignoring web.cacerts config)')),
110 ]
110 ]
111
111
112 walkopts = [
112 walkopts = [
113 ('I', 'include', [],
113 ('I', 'include', [],
114 _('include names matching the given patterns'), _('PATTERN')),
114 _('include names matching the given patterns'), _('PATTERN')),
115 ('X', 'exclude', [],
115 ('X', 'exclude', [],
116 _('exclude names matching the given patterns'), _('PATTERN')),
116 _('exclude names matching the given patterns'), _('PATTERN')),
117 ]
117 ]
118
118
119 commitopts = [
119 commitopts = [
120 ('m', 'message', '',
120 ('m', 'message', '',
121 _('use text as commit message'), _('TEXT')),
121 _('use text as commit message'), _('TEXT')),
122 ('l', 'logfile', '',
122 ('l', 'logfile', '',
123 _('read commit message from file'), _('FILE')),
123 _('read commit message from file'), _('FILE')),
124 ]
124 ]
125
125
126 commitopts2 = [
126 commitopts2 = [
127 ('d', 'date', '',
127 ('d', 'date', '',
128 _('record the specified date as commit date'), _('DATE')),
128 _('record the specified date as commit date'), _('DATE')),
129 ('u', 'user', '',
129 ('u', 'user', '',
130 _('record the specified user as committer'), _('USER')),
130 _('record the specified user as committer'), _('USER')),
131 ]
131 ]
132
132
133 # hidden for now
133 # hidden for now
134 formatteropts = [
134 formatteropts = [
135 ('T', 'template', '',
135 ('T', 'template', '',
136 _('display with template (EXPERIMENTAL)'), _('TEMPLATE')),
136 _('display with template (EXPERIMENTAL)'), _('TEMPLATE')),
137 ]
137 ]
138
138
139 templateopts = [
139 templateopts = [
140 ('', 'style', '',
140 ('', 'style', '',
141 _('display using template map file (DEPRECATED)'), _('STYLE')),
141 _('display using template map file (DEPRECATED)'), _('STYLE')),
142 ('T', 'template', '',
142 ('T', 'template', '',
143 _('display with template'), _('TEMPLATE')),
143 _('display with template'), _('TEMPLATE')),
144 ]
144 ]
145
145
146 logopts = [
146 logopts = [
147 ('p', 'patch', None, _('show patch')),
147 ('p', 'patch', None, _('show patch')),
148 ('g', 'git', None, _('use git extended diff format')),
148 ('g', 'git', None, _('use git extended diff format')),
149 ('l', 'limit', '',
149 ('l', 'limit', '',
150 _('limit number of changes displayed'), _('NUM')),
150 _('limit number of changes displayed'), _('NUM')),
151 ('M', 'no-merges', None, _('do not show merges')),
151 ('M', 'no-merges', None, _('do not show merges')),
152 ('', 'stat', None, _('output diffstat-style summary of changes')),
152 ('', 'stat', None, _('output diffstat-style summary of changes')),
153 ('G', 'graph', None, _("show the revision DAG")),
153 ('G', 'graph', None, _("show the revision DAG")),
154 ] + templateopts
154 ] + templateopts
155
155
156 diffopts = [
156 diffopts = [
157 ('a', 'text', None, _('treat all files as text')),
157 ('a', 'text', None, _('treat all files as text')),
158 ('g', 'git', None, _('use git extended diff format')),
158 ('g', 'git', None, _('use git extended diff format')),
159 ('', 'nodates', None, _('omit dates from diff headers'))
159 ('', 'nodates', None, _('omit dates from diff headers'))
160 ]
160 ]
161
161
162 diffwsopts = [
162 diffwsopts = [
163 ('w', 'ignore-all-space', None,
163 ('w', 'ignore-all-space', None,
164 _('ignore white space when comparing lines')),
164 _('ignore white space when comparing lines')),
165 ('b', 'ignore-space-change', None,
165 ('b', 'ignore-space-change', None,
166 _('ignore changes in the amount of white space')),
166 _('ignore changes in the amount of white space')),
167 ('B', 'ignore-blank-lines', None,
167 ('B', 'ignore-blank-lines', None,
168 _('ignore changes whose lines are all blank')),
168 _('ignore changes whose lines are all blank')),
169 ]
169 ]
170
170
171 diffopts2 = [
171 diffopts2 = [
172 ('', 'noprefix', None, _('omit a/ and b/ prefixes from filenames')),
172 ('', 'noprefix', None, _('omit a/ and b/ prefixes from filenames')),
173 ('p', 'show-function', None, _('show which function each change is in')),
173 ('p', 'show-function', None, _('show which function each change is in')),
174 ('', 'reverse', None, _('produce a diff that undoes the changes')),
174 ('', 'reverse', None, _('produce a diff that undoes the changes')),
175 ] + diffwsopts + [
175 ] + diffwsopts + [
176 ('U', 'unified', '',
176 ('U', 'unified', '',
177 _('number of lines of context to show'), _('NUM')),
177 _('number of lines of context to show'), _('NUM')),
178 ('', 'stat', None, _('output diffstat-style summary of changes')),
178 ('', 'stat', None, _('output diffstat-style summary of changes')),
179 ('', 'root', '', _('produce diffs relative to subdirectory'), _('DIR')),
179 ('', 'root', '', _('produce diffs relative to subdirectory'), _('DIR')),
180 ]
180 ]
181
181
182 mergetoolopts = [
182 mergetoolopts = [
183 ('t', 'tool', '', _('specify merge tool')),
183 ('t', 'tool', '', _('specify merge tool')),
184 ]
184 ]
185
185
186 similarityopts = [
186 similarityopts = [
187 ('s', 'similarity', '',
187 ('s', 'similarity', '',
188 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
188 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
189 ]
189 ]
190
190
191 subrepoopts = [
191 subrepoopts = [
192 ('S', 'subrepos', None,
192 ('S', 'subrepos', None,
193 _('recurse into subrepositories'))
193 _('recurse into subrepositories'))
194 ]
194 ]
195
195
196 debugrevlogopts = [
196 debugrevlogopts = [
197 ('c', 'changelog', False, _('open changelog')),
197 ('c', 'changelog', False, _('open changelog')),
198 ('m', 'manifest', False, _('open manifest')),
198 ('m', 'manifest', False, _('open manifest')),
199 ('', 'dir', '', _('open directory manifest')),
199 ('', 'dir', '', _('open directory manifest')),
200 ]
200 ]
201
201
202 # Commands start here, listed alphabetically
202 # Commands start here, listed alphabetically
203
203
204 @command('^add',
204 @command('^add',
205 walkopts + subrepoopts + dryrunopts,
205 walkopts + subrepoopts + dryrunopts,
206 _('[OPTION]... [FILE]...'),
206 _('[OPTION]... [FILE]...'),
207 inferrepo=True)
207 inferrepo=True)
208 def add(ui, repo, *pats, **opts):
208 def add(ui, repo, *pats, **opts):
209 """add the specified files on the next commit
209 """add the specified files on the next commit
210
210
211 Schedule files to be version controlled and added to the
211 Schedule files to be version controlled and added to the
212 repository.
212 repository.
213
213
214 The files will be added to the repository at the next commit. To
214 The files will be added to the repository at the next commit. To
215 undo an add before that, see :hg:`forget`.
215 undo an add before that, see :hg:`forget`.
216
216
217 If no names are given, add all files to the repository (except
217 If no names are given, add all files to the repository (except
218 files matching ``.hgignore``).
218 files matching ``.hgignore``).
219
219
220 .. container:: verbose
220 .. container:: verbose
221
221
222 Examples:
222 Examples:
223
223
224 - New (unknown) files are added
224 - New (unknown) files are added
225 automatically by :hg:`add`::
225 automatically by :hg:`add`::
226
226
227 $ ls
227 $ ls
228 foo.c
228 foo.c
229 $ hg status
229 $ hg status
230 ? foo.c
230 ? foo.c
231 $ hg add
231 $ hg add
232 adding foo.c
232 adding foo.c
233 $ hg status
233 $ hg status
234 A foo.c
234 A foo.c
235
235
236 - Specific files to be added can be specified::
236 - Specific files to be added can be specified::
237
237
238 $ ls
238 $ ls
239 bar.c foo.c
239 bar.c foo.c
240 $ hg status
240 $ hg status
241 ? bar.c
241 ? bar.c
242 ? foo.c
242 ? foo.c
243 $ hg add bar.c
243 $ hg add bar.c
244 $ hg status
244 $ hg status
245 A bar.c
245 A bar.c
246 ? foo.c
246 ? foo.c
247
247
248 Returns 0 if all files are successfully added.
248 Returns 0 if all files are successfully added.
249 """
249 """
250
250
251 m = scmutil.match(repo[None], pats, opts)
251 m = scmutil.match(repo[None], pats, opts)
252 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
252 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
253 return rejected and 1 or 0
253 return rejected and 1 or 0
254
254
255 @command('addremove',
255 @command('addremove',
256 similarityopts + subrepoopts + walkopts + dryrunopts,
256 similarityopts + subrepoopts + walkopts + dryrunopts,
257 _('[OPTION]... [FILE]...'),
257 _('[OPTION]... [FILE]...'),
258 inferrepo=True)
258 inferrepo=True)
259 def addremove(ui, repo, *pats, **opts):
259 def addremove(ui, repo, *pats, **opts):
260 """add all new files, delete all missing files
260 """add all new files, delete all missing files
261
261
262 Add all new files and remove all missing files from the
262 Add all new files and remove all missing files from the
263 repository.
263 repository.
264
264
265 Unless names are given, new files are ignored if they match any of
265 Unless names are given, new files are ignored if they match any of
266 the patterns in ``.hgignore``. As with add, these changes take
266 the patterns in ``.hgignore``. As with add, these changes take
267 effect at the next commit.
267 effect at the next commit.
268
268
269 Use the -s/--similarity option to detect renamed files. This
269 Use the -s/--similarity option to detect renamed files. This
270 option takes a percentage between 0 (disabled) and 100 (files must
270 option takes a percentage between 0 (disabled) and 100 (files must
271 be identical) as its parameter. With a parameter greater than 0,
271 be identical) as its parameter. With a parameter greater than 0,
272 this compares every removed file with every added file and records
272 this compares every removed file with every added file and records
273 those similar enough as renames. Detecting renamed files this way
273 those similar enough as renames. Detecting renamed files this way
274 can be expensive. After using this option, :hg:`status -C` can be
274 can be expensive. After using this option, :hg:`status -C` can be
275 used to check which files were identified as moved or renamed. If
275 used to check which files were identified as moved or renamed. If
276 not specified, -s/--similarity defaults to 100 and only renames of
276 not specified, -s/--similarity defaults to 100 and only renames of
277 identical files are detected.
277 identical files are detected.
278
278
279 .. container:: verbose
279 .. container:: verbose
280
280
281 Examples:
281 Examples:
282
282
283 - A number of files (bar.c and foo.c) are new,
283 - A number of files (bar.c and foo.c) are new,
284 while foobar.c has been removed (without using :hg:`remove`)
284 while foobar.c has been removed (without using :hg:`remove`)
285 from the repository::
285 from the repository::
286
286
287 $ ls
287 $ ls
288 bar.c foo.c
288 bar.c foo.c
289 $ hg status
289 $ hg status
290 ! foobar.c
290 ! foobar.c
291 ? bar.c
291 ? bar.c
292 ? foo.c
292 ? foo.c
293 $ hg addremove
293 $ hg addremove
294 adding bar.c
294 adding bar.c
295 adding foo.c
295 adding foo.c
296 removing foobar.c
296 removing foobar.c
297 $ hg status
297 $ hg status
298 A bar.c
298 A bar.c
299 A foo.c
299 A foo.c
300 R foobar.c
300 R foobar.c
301
301
302 - A file foobar.c was moved to foo.c without using :hg:`rename`.
302 - A file foobar.c was moved to foo.c without using :hg:`rename`.
303 Afterwards, it was edited slightly::
303 Afterwards, it was edited slightly::
304
304
305 $ ls
305 $ ls
306 foo.c
306 foo.c
307 $ hg status
307 $ hg status
308 ! foobar.c
308 ! foobar.c
309 ? foo.c
309 ? foo.c
310 $ hg addremove --similarity 90
310 $ hg addremove --similarity 90
311 removing foobar.c
311 removing foobar.c
312 adding foo.c
312 adding foo.c
313 recording removal of foobar.c as rename to foo.c (94% similar)
313 recording removal of foobar.c as rename to foo.c (94% similar)
314 $ hg status -C
314 $ hg status -C
315 A foo.c
315 A foo.c
316 foobar.c
316 foobar.c
317 R foobar.c
317 R foobar.c
318
318
319 Returns 0 if all files are successfully added.
319 Returns 0 if all files are successfully added.
320 """
320 """
321 try:
321 try:
322 sim = float(opts.get('similarity') or 100)
322 sim = float(opts.get('similarity') or 100)
323 except ValueError:
323 except ValueError:
324 raise error.Abort(_('similarity must be a number'))
324 raise error.Abort(_('similarity must be a number'))
325 if sim < 0 or sim > 100:
325 if sim < 0 or sim > 100:
326 raise error.Abort(_('similarity must be between 0 and 100'))
326 raise error.Abort(_('similarity must be between 0 and 100'))
327 matcher = scmutil.match(repo[None], pats, opts)
327 matcher = scmutil.match(repo[None], pats, opts)
328 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
328 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
329
329
330 @command('^annotate|blame',
330 @command('^annotate|blame',
331 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
331 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
332 ('', 'follow', None,
332 ('', 'follow', None,
333 _('follow copies/renames and list the filename (DEPRECATED)')),
333 _('follow copies/renames and list the filename (DEPRECATED)')),
334 ('', 'no-follow', None, _("don't follow copies and renames")),
334 ('', 'no-follow', None, _("don't follow copies and renames")),
335 ('a', 'text', None, _('treat all files as text')),
335 ('a', 'text', None, _('treat all files as text')),
336 ('u', 'user', None, _('list the author (long with -v)')),
336 ('u', 'user', None, _('list the author (long with -v)')),
337 ('f', 'file', None, _('list the filename')),
337 ('f', 'file', None, _('list the filename')),
338 ('d', 'date', None, _('list the date (short with -q)')),
338 ('d', 'date', None, _('list the date (short with -q)')),
339 ('n', 'number', None, _('list the revision number (default)')),
339 ('n', 'number', None, _('list the revision number (default)')),
340 ('c', 'changeset', None, _('list the changeset')),
340 ('c', 'changeset', None, _('list the changeset')),
341 ('l', 'line-number', None, _('show line number at the first appearance'))
341 ('l', 'line-number', None, _('show line number at the first appearance'))
342 ] + diffwsopts + walkopts + formatteropts,
342 ] + diffwsopts + walkopts + formatteropts,
343 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
343 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
344 inferrepo=True)
344 inferrepo=True)
345 def annotate(ui, repo, *pats, **opts):
345 def annotate(ui, repo, *pats, **opts):
346 """show changeset information by line for each file
346 """show changeset information by line for each file
347
347
348 List changes in files, showing the revision id responsible for
348 List changes in files, showing the revision id responsible for
349 each line.
349 each line.
350
350
351 This command is useful for discovering when a change was made and
351 This command is useful for discovering when a change was made and
352 by whom.
352 by whom.
353
353
354 If you include --file, --user, or --date, the revision number is
354 If you include --file, --user, or --date, the revision number is
355 suppressed unless you also include --number.
355 suppressed unless you also include --number.
356
356
357 Without the -a/--text option, annotate will avoid processing files
357 Without the -a/--text option, annotate will avoid processing files
358 it detects as binary. With -a, annotate will annotate the file
358 it detects as binary. With -a, annotate will annotate the file
359 anyway, although the results will probably be neither useful
359 anyway, although the results will probably be neither useful
360 nor desirable.
360 nor desirable.
361
361
362 Returns 0 on success.
362 Returns 0 on success.
363 """
363 """
364 if not pats:
364 if not pats:
365 raise error.Abort(_('at least one filename or pattern is required'))
365 raise error.Abort(_('at least one filename or pattern is required'))
366
366
367 if opts.get('follow'):
367 if opts.get('follow'):
368 # --follow is deprecated and now just an alias for -f/--file
368 # --follow is deprecated and now just an alias for -f/--file
369 # to mimic the behavior of Mercurial before version 1.5
369 # to mimic the behavior of Mercurial before version 1.5
370 opts['file'] = True
370 opts['file'] = True
371
371
372 ctx = scmutil.revsingle(repo, opts.get('rev'))
372 ctx = scmutil.revsingle(repo, opts.get('rev'))
373
373
374 fm = ui.formatter('annotate', opts)
374 fm = ui.formatter('annotate', opts)
375 if ui.quiet:
375 if ui.quiet:
376 datefunc = util.shortdate
376 datefunc = util.shortdate
377 else:
377 else:
378 datefunc = util.datestr
378 datefunc = util.datestr
379 if ctx.rev() is None:
379 if ctx.rev() is None:
380 def hexfn(node):
380 def hexfn(node):
381 if node is None:
381 if node is None:
382 return None
382 return None
383 else:
383 else:
384 return fm.hexfunc(node)
384 return fm.hexfunc(node)
385 if opts.get('changeset'):
385 if opts.get('changeset'):
386 # omit "+" suffix which is appended to node hex
386 # omit "+" suffix which is appended to node hex
387 def formatrev(rev):
387 def formatrev(rev):
388 if rev is None:
388 if rev is None:
389 return '%d' % ctx.p1().rev()
389 return '%d' % ctx.p1().rev()
390 else:
390 else:
391 return '%d' % rev
391 return '%d' % rev
392 else:
392 else:
393 def formatrev(rev):
393 def formatrev(rev):
394 if rev is None:
394 if rev is None:
395 return '%d+' % ctx.p1().rev()
395 return '%d+' % ctx.p1().rev()
396 else:
396 else:
397 return '%d ' % rev
397 return '%d ' % rev
398 def formathex(hex):
398 def formathex(hex):
399 if hex is None:
399 if hex is None:
400 return '%s+' % fm.hexfunc(ctx.p1().node())
400 return '%s+' % fm.hexfunc(ctx.p1().node())
401 else:
401 else:
402 return '%s ' % hex
402 return '%s ' % hex
403 else:
403 else:
404 hexfn = fm.hexfunc
404 hexfn = fm.hexfunc
405 formatrev = formathex = str
405 formatrev = formathex = str
406
406
407 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
407 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
408 ('number', ' ', lambda x: x[0].rev(), formatrev),
408 ('number', ' ', lambda x: x[0].rev(), formatrev),
409 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
409 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
410 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
410 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
411 ('file', ' ', lambda x: x[0].path(), str),
411 ('file', ' ', lambda x: x[0].path(), str),
412 ('line_number', ':', lambda x: x[1], str),
412 ('line_number', ':', lambda x: x[1], str),
413 ]
413 ]
414 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
414 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
415
415
416 if (not opts.get('user') and not opts.get('changeset')
416 if (not opts.get('user') and not opts.get('changeset')
417 and not opts.get('date') and not opts.get('file')):
417 and not opts.get('date') and not opts.get('file')):
418 opts['number'] = True
418 opts['number'] = True
419
419
420 linenumber = opts.get('line_number') is not None
420 linenumber = opts.get('line_number') is not None
421 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
421 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
422 raise error.Abort(_('at least one of -n/-c is required for -l'))
422 raise error.Abort(_('at least one of -n/-c is required for -l'))
423
423
424 ui.pager('annotate')
424 ui.pager('annotate')
425
425
426 if fm.isplain():
426 if fm.isplain():
427 def makefunc(get, fmt):
427 def makefunc(get, fmt):
428 return lambda x: fmt(get(x))
428 return lambda x: fmt(get(x))
429 else:
429 else:
430 def makefunc(get, fmt):
430 def makefunc(get, fmt):
431 return get
431 return get
432 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
432 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
433 if opts.get(op)]
433 if opts.get(op)]
434 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
434 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
435 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
435 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
436 if opts.get(op))
436 if opts.get(op))
437
437
438 def bad(x, y):
438 def bad(x, y):
439 raise error.Abort("%s: %s" % (x, y))
439 raise error.Abort("%s: %s" % (x, y))
440
440
441 m = scmutil.match(ctx, pats, opts, badfn=bad)
441 m = scmutil.match(ctx, pats, opts, badfn=bad)
442
442
443 follow = not opts.get('no_follow')
443 follow = not opts.get('no_follow')
444 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
444 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
445 whitespace=True)
445 whitespace=True)
446 for abs in ctx.walk(m):
446 for abs in ctx.walk(m):
447 fctx = ctx[abs]
447 fctx = ctx[abs]
448 if not opts.get('text') and util.binary(fctx.data()):
448 if not opts.get('text') and util.binary(fctx.data()):
449 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
449 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
450 continue
450 continue
451
451
452 lines = fctx.annotate(follow=follow, linenumber=linenumber,
452 lines = fctx.annotate(follow=follow, linenumber=linenumber,
453 diffopts=diffopts)
453 diffopts=diffopts)
454 if not lines:
454 if not lines:
455 continue
455 continue
456 formats = []
456 formats = []
457 pieces = []
457 pieces = []
458
458
459 for f, sep in funcmap:
459 for f, sep in funcmap:
460 l = [f(n) for n, dummy in lines]
460 l = [f(n) for n, dummy in lines]
461 if fm.isplain():
461 if fm.isplain():
462 sizes = [encoding.colwidth(x) for x in l]
462 sizes = [encoding.colwidth(x) for x in l]
463 ml = max(sizes)
463 ml = max(sizes)
464 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
464 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
465 else:
465 else:
466 formats.append(['%s' for x in l])
466 formats.append(['%s' for x in l])
467 pieces.append(l)
467 pieces.append(l)
468
468
469 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
469 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
470 fm.startitem()
470 fm.startitem()
471 fm.write(fields, "".join(f), *p)
471 fm.write(fields, "".join(f), *p)
472 fm.write('line', ": %s", l[1])
472 fm.write('line', ": %s", l[1])
473
473
474 if not lines[-1][1].endswith('\n'):
474 if not lines[-1][1].endswith('\n'):
475 fm.plain('\n')
475 fm.plain('\n')
476
476
477 fm.end()
477 fm.end()
478
478
479 @command('archive',
479 @command('archive',
480 [('', 'no-decode', None, _('do not pass files through decoders')),
480 [('', 'no-decode', None, _('do not pass files through decoders')),
481 ('p', 'prefix', '', _('directory prefix for files in archive'),
481 ('p', 'prefix', '', _('directory prefix for files in archive'),
482 _('PREFIX')),
482 _('PREFIX')),
483 ('r', 'rev', '', _('revision to distribute'), _('REV')),
483 ('r', 'rev', '', _('revision to distribute'), _('REV')),
484 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
484 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
485 ] + subrepoopts + walkopts,
485 ] + subrepoopts + walkopts,
486 _('[OPTION]... DEST'))
486 _('[OPTION]... DEST'))
487 def archive(ui, repo, dest, **opts):
487 def archive(ui, repo, dest, **opts):
488 '''create an unversioned archive of a repository revision
488 '''create an unversioned archive of a repository revision
489
489
490 By default, the revision used is the parent of the working
490 By default, the revision used is the parent of the working
491 directory; use -r/--rev to specify a different revision.
491 directory; use -r/--rev to specify a different revision.
492
492
493 The archive type is automatically detected based on file
493 The archive type is automatically detected based on file
494 extension (to override, use -t/--type).
494 extension (to override, use -t/--type).
495
495
496 .. container:: verbose
496 .. container:: verbose
497
497
498 Examples:
498 Examples:
499
499
500 - create a zip file containing the 1.0 release::
500 - create a zip file containing the 1.0 release::
501
501
502 hg archive -r 1.0 project-1.0.zip
502 hg archive -r 1.0 project-1.0.zip
503
503
504 - create a tarball excluding .hg files::
504 - create a tarball excluding .hg files::
505
505
506 hg archive project.tar.gz -X ".hg*"
506 hg archive project.tar.gz -X ".hg*"
507
507
508 Valid types are:
508 Valid types are:
509
509
510 :``files``: a directory full of files (default)
510 :``files``: a directory full of files (default)
511 :``tar``: tar archive, uncompressed
511 :``tar``: tar archive, uncompressed
512 :``tbz2``: tar archive, compressed using bzip2
512 :``tbz2``: tar archive, compressed using bzip2
513 :``tgz``: tar archive, compressed using gzip
513 :``tgz``: tar archive, compressed using gzip
514 :``uzip``: zip archive, uncompressed
514 :``uzip``: zip archive, uncompressed
515 :``zip``: zip archive, compressed using deflate
515 :``zip``: zip archive, compressed using deflate
516
516
517 The exact name of the destination archive or directory is given
517 The exact name of the destination archive or directory is given
518 using a format string; see :hg:`help export` for details.
518 using a format string; see :hg:`help export` for details.
519
519
520 Each member added to an archive file has a directory prefix
520 Each member added to an archive file has a directory prefix
521 prepended. Use -p/--prefix to specify a format string for the
521 prepended. Use -p/--prefix to specify a format string for the
522 prefix. The default is the basename of the archive, with suffixes
522 prefix. The default is the basename of the archive, with suffixes
523 removed.
523 removed.
524
524
525 Returns 0 on success.
525 Returns 0 on success.
526 '''
526 '''
527
527
528 ctx = scmutil.revsingle(repo, opts.get('rev'))
528 ctx = scmutil.revsingle(repo, opts.get('rev'))
529 if not ctx:
529 if not ctx:
530 raise error.Abort(_('no working directory: please specify a revision'))
530 raise error.Abort(_('no working directory: please specify a revision'))
531 node = ctx.node()
531 node = ctx.node()
532 dest = cmdutil.makefilename(repo, dest, node)
532 dest = cmdutil.makefilename(repo, dest, node)
533 if os.path.realpath(dest) == repo.root:
533 if os.path.realpath(dest) == repo.root:
534 raise error.Abort(_('repository root cannot be destination'))
534 raise error.Abort(_('repository root cannot be destination'))
535
535
536 kind = opts.get('type') or archival.guesskind(dest) or 'files'
536 kind = opts.get('type') or archival.guesskind(dest) or 'files'
537 prefix = opts.get('prefix')
537 prefix = opts.get('prefix')
538
538
539 if dest == '-':
539 if dest == '-':
540 if kind == 'files':
540 if kind == 'files':
541 raise error.Abort(_('cannot archive plain files to stdout'))
541 raise error.Abort(_('cannot archive plain files to stdout'))
542 dest = cmdutil.makefileobj(repo, dest)
542 dest = cmdutil.makefileobj(repo, dest)
543 if not prefix:
543 if not prefix:
544 prefix = os.path.basename(repo.root) + '-%h'
544 prefix = os.path.basename(repo.root) + '-%h'
545
545
546 prefix = cmdutil.makefilename(repo, prefix, node)
546 prefix = cmdutil.makefilename(repo, prefix, node)
547 matchfn = scmutil.match(ctx, [], opts)
547 matchfn = scmutil.match(ctx, [], opts)
548 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
548 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
549 matchfn, prefix, subrepos=opts.get('subrepos'))
549 matchfn, prefix, subrepos=opts.get('subrepos'))
550
550
551 @command('backout',
551 @command('backout',
552 [('', 'merge', None, _('merge with old dirstate parent after backout')),
552 [('', 'merge', None, _('merge with old dirstate parent after backout')),
553 ('', 'commit', None,
553 ('', 'commit', None,
554 _('commit if no conflicts were encountered (DEPRECATED)')),
554 _('commit if no conflicts were encountered (DEPRECATED)')),
555 ('', 'no-commit', None, _('do not commit')),
555 ('', 'no-commit', None, _('do not commit')),
556 ('', 'parent', '',
556 ('', 'parent', '',
557 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
557 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
558 ('r', 'rev', '', _('revision to backout'), _('REV')),
558 ('r', 'rev', '', _('revision to backout'), _('REV')),
559 ('e', 'edit', False, _('invoke editor on commit messages')),
559 ('e', 'edit', False, _('invoke editor on commit messages')),
560 ] + mergetoolopts + walkopts + commitopts + commitopts2,
560 ] + mergetoolopts + walkopts + commitopts + commitopts2,
561 _('[OPTION]... [-r] REV'))
561 _('[OPTION]... [-r] REV'))
562 def backout(ui, repo, node=None, rev=None, **opts):
562 def backout(ui, repo, node=None, rev=None, **opts):
563 '''reverse effect of earlier changeset
563 '''reverse effect of earlier changeset
564
564
565 Prepare a new changeset with the effect of REV undone in the
565 Prepare a new changeset with the effect of REV undone in the
566 current working directory. If no conflicts were encountered,
566 current working directory. If no conflicts were encountered,
567 it will be committed immediately.
567 it will be committed immediately.
568
568
569 If REV is the parent of the working directory, then this new changeset
569 If REV is the parent of the working directory, then this new changeset
570 is committed automatically (unless --no-commit is specified).
570 is committed automatically (unless --no-commit is specified).
571
571
572 .. note::
572 .. note::
573
573
574 :hg:`backout` cannot be used to fix either an unwanted or
574 :hg:`backout` cannot be used to fix either an unwanted or
575 incorrect merge.
575 incorrect merge.
576
576
577 .. container:: verbose
577 .. container:: verbose
578
578
579 Examples:
579 Examples:
580
580
581 - Reverse the effect of the parent of the working directory.
581 - Reverse the effect of the parent of the working directory.
582 This backout will be committed immediately::
582 This backout will be committed immediately::
583
583
584 hg backout -r .
584 hg backout -r .
585
585
586 - Reverse the effect of previous bad revision 23::
586 - Reverse the effect of previous bad revision 23::
587
587
588 hg backout -r 23
588 hg backout -r 23
589
589
590 - Reverse the effect of previous bad revision 23 and
590 - Reverse the effect of previous bad revision 23 and
591 leave changes uncommitted::
591 leave changes uncommitted::
592
592
593 hg backout -r 23 --no-commit
593 hg backout -r 23 --no-commit
594 hg commit -m "Backout revision 23"
594 hg commit -m "Backout revision 23"
595
595
596 By default, the pending changeset will have one parent,
596 By default, the pending changeset will have one parent,
597 maintaining a linear history. With --merge, the pending
597 maintaining a linear history. With --merge, the pending
598 changeset will instead have two parents: the old parent of the
598 changeset will instead have two parents: the old parent of the
599 working directory and a new child of REV that simply undoes REV.
599 working directory and a new child of REV that simply undoes REV.
600
600
601 Before version 1.7, the behavior without --merge was equivalent
601 Before version 1.7, the behavior without --merge was equivalent
602 to specifying --merge followed by :hg:`update --clean .` to
602 to specifying --merge followed by :hg:`update --clean .` to
603 cancel the merge and leave the child of REV as a head to be
603 cancel the merge and leave the child of REV as a head to be
604 merged separately.
604 merged separately.
605
605
606 See :hg:`help dates` for a list of formats valid for -d/--date.
606 See :hg:`help dates` for a list of formats valid for -d/--date.
607
607
608 See :hg:`help revert` for a way to restore files to the state
608 See :hg:`help revert` for a way to restore files to the state
609 of another revision.
609 of another revision.
610
610
611 Returns 0 on success, 1 if nothing to backout or there are unresolved
611 Returns 0 on success, 1 if nothing to backout or there are unresolved
612 files.
612 files.
613 '''
613 '''
614 wlock = lock = None
614 wlock = lock = None
615 try:
615 try:
616 wlock = repo.wlock()
616 wlock = repo.wlock()
617 lock = repo.lock()
617 lock = repo.lock()
618 return _dobackout(ui, repo, node, rev, **opts)
618 return _dobackout(ui, repo, node, rev, **opts)
619 finally:
619 finally:
620 release(lock, wlock)
620 release(lock, wlock)
621
621
622 def _dobackout(ui, repo, node=None, rev=None, **opts):
622 def _dobackout(ui, repo, node=None, rev=None, **opts):
623 if opts.get('commit') and opts.get('no_commit'):
623 if opts.get('commit') and opts.get('no_commit'):
624 raise error.Abort(_("cannot use --commit with --no-commit"))
624 raise error.Abort(_("cannot use --commit with --no-commit"))
625 if opts.get('merge') and opts.get('no_commit'):
625 if opts.get('merge') and opts.get('no_commit'):
626 raise error.Abort(_("cannot use --merge with --no-commit"))
626 raise error.Abort(_("cannot use --merge with --no-commit"))
627
627
628 if rev and node:
628 if rev and node:
629 raise error.Abort(_("please specify just one revision"))
629 raise error.Abort(_("please specify just one revision"))
630
630
631 if not rev:
631 if not rev:
632 rev = node
632 rev = node
633
633
634 if not rev:
634 if not rev:
635 raise error.Abort(_("please specify a revision to backout"))
635 raise error.Abort(_("please specify a revision to backout"))
636
636
637 date = opts.get('date')
637 date = opts.get('date')
638 if date:
638 if date:
639 opts['date'] = util.parsedate(date)
639 opts['date'] = util.parsedate(date)
640
640
641 cmdutil.checkunfinished(repo)
641 cmdutil.checkunfinished(repo)
642 cmdutil.bailifchanged(repo)
642 cmdutil.bailifchanged(repo)
643 node = scmutil.revsingle(repo, rev).node()
643 node = scmutil.revsingle(repo, rev).node()
644
644
645 op1, op2 = repo.dirstate.parents()
645 op1, op2 = repo.dirstate.parents()
646 if not repo.changelog.isancestor(node, op1):
646 if not repo.changelog.isancestor(node, op1):
647 raise error.Abort(_('cannot backout change that is not an ancestor'))
647 raise error.Abort(_('cannot backout change that is not an ancestor'))
648
648
649 p1, p2 = repo.changelog.parents(node)
649 p1, p2 = repo.changelog.parents(node)
650 if p1 == nullid:
650 if p1 == nullid:
651 raise error.Abort(_('cannot backout a change with no parents'))
651 raise error.Abort(_('cannot backout a change with no parents'))
652 if p2 != nullid:
652 if p2 != nullid:
653 if not opts.get('parent'):
653 if not opts.get('parent'):
654 raise error.Abort(_('cannot backout a merge changeset'))
654 raise error.Abort(_('cannot backout a merge changeset'))
655 p = repo.lookup(opts['parent'])
655 p = repo.lookup(opts['parent'])
656 if p not in (p1, p2):
656 if p not in (p1, p2):
657 raise error.Abort(_('%s is not a parent of %s') %
657 raise error.Abort(_('%s is not a parent of %s') %
658 (short(p), short(node)))
658 (short(p), short(node)))
659 parent = p
659 parent = p
660 else:
660 else:
661 if opts.get('parent'):
661 if opts.get('parent'):
662 raise error.Abort(_('cannot use --parent on non-merge changeset'))
662 raise error.Abort(_('cannot use --parent on non-merge changeset'))
663 parent = p1
663 parent = p1
664
664
665 # the backout should appear on the same branch
665 # the backout should appear on the same branch
666 branch = repo.dirstate.branch()
666 branch = repo.dirstate.branch()
667 bheads = repo.branchheads(branch)
667 bheads = repo.branchheads(branch)
668 rctx = scmutil.revsingle(repo, hex(parent))
668 rctx = scmutil.revsingle(repo, hex(parent))
669 if not opts.get('merge') and op1 != node:
669 if not opts.get('merge') and op1 != node:
670 dsguard = dirstateguard.dirstateguard(repo, 'backout')
670 dsguard = dirstateguard.dirstateguard(repo, 'backout')
671 try:
671 try:
672 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
672 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
673 'backout')
673 'backout')
674 stats = mergemod.update(repo, parent, True, True, node, False)
674 stats = mergemod.update(repo, parent, True, True, node, False)
675 repo.setparents(op1, op2)
675 repo.setparents(op1, op2)
676 dsguard.close()
676 dsguard.close()
677 hg._showstats(repo, stats)
677 hg._showstats(repo, stats)
678 if stats[3]:
678 if stats[3]:
679 repo.ui.status(_("use 'hg resolve' to retry unresolved "
679 repo.ui.status(_("use 'hg resolve' to retry unresolved "
680 "file merges\n"))
680 "file merges\n"))
681 return 1
681 return 1
682 finally:
682 finally:
683 ui.setconfig('ui', 'forcemerge', '', '')
683 ui.setconfig('ui', 'forcemerge', '', '')
684 lockmod.release(dsguard)
684 lockmod.release(dsguard)
685 else:
685 else:
686 hg.clean(repo, node, show_stats=False)
686 hg.clean(repo, node, show_stats=False)
687 repo.dirstate.setbranch(branch)
687 repo.dirstate.setbranch(branch)
688 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
688 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
689
689
690 if opts.get('no_commit'):
690 if opts.get('no_commit'):
691 msg = _("changeset %s backed out, "
691 msg = _("changeset %s backed out, "
692 "don't forget to commit.\n")
692 "don't forget to commit.\n")
693 ui.status(msg % short(node))
693 ui.status(msg % short(node))
694 return 0
694 return 0
695
695
696 def commitfunc(ui, repo, message, match, opts):
696 def commitfunc(ui, repo, message, match, opts):
697 editform = 'backout'
697 editform = 'backout'
698 e = cmdutil.getcommiteditor(editform=editform, **opts)
698 e = cmdutil.getcommiteditor(editform=editform, **opts)
699 if not message:
699 if not message:
700 # we don't translate commit messages
700 # we don't translate commit messages
701 message = "Backed out changeset %s" % short(node)
701 message = "Backed out changeset %s" % short(node)
702 e = cmdutil.getcommiteditor(edit=True, editform=editform)
702 e = cmdutil.getcommiteditor(edit=True, editform=editform)
703 return repo.commit(message, opts.get('user'), opts.get('date'),
703 return repo.commit(message, opts.get('user'), opts.get('date'),
704 match, editor=e)
704 match, editor=e)
705 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
705 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
706 if not newnode:
706 if not newnode:
707 ui.status(_("nothing changed\n"))
707 ui.status(_("nothing changed\n"))
708 return 1
708 return 1
709 cmdutil.commitstatus(repo, newnode, branch, bheads)
709 cmdutil.commitstatus(repo, newnode, branch, bheads)
710
710
711 def nice(node):
711 def nice(node):
712 return '%d:%s' % (repo.changelog.rev(node), short(node))
712 return '%d:%s' % (repo.changelog.rev(node), short(node))
713 ui.status(_('changeset %s backs out changeset %s\n') %
713 ui.status(_('changeset %s backs out changeset %s\n') %
714 (nice(repo.changelog.tip()), nice(node)))
714 (nice(repo.changelog.tip()), nice(node)))
715 if opts.get('merge') and op1 != node:
715 if opts.get('merge') and op1 != node:
716 hg.clean(repo, op1, show_stats=False)
716 hg.clean(repo, op1, show_stats=False)
717 ui.status(_('merging with changeset %s\n')
717 ui.status(_('merging with changeset %s\n')
718 % nice(repo.changelog.tip()))
718 % nice(repo.changelog.tip()))
719 try:
719 try:
720 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
720 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
721 'backout')
721 'backout')
722 return hg.merge(repo, hex(repo.changelog.tip()))
722 return hg.merge(repo, hex(repo.changelog.tip()))
723 finally:
723 finally:
724 ui.setconfig('ui', 'forcemerge', '', '')
724 ui.setconfig('ui', 'forcemerge', '', '')
725 return 0
725 return 0
726
726
727 @command('bisect',
727 @command('bisect',
728 [('r', 'reset', False, _('reset bisect state')),
728 [('r', 'reset', False, _('reset bisect state')),
729 ('g', 'good', False, _('mark changeset good')),
729 ('g', 'good', False, _('mark changeset good')),
730 ('b', 'bad', False, _('mark changeset bad')),
730 ('b', 'bad', False, _('mark changeset bad')),
731 ('s', 'skip', False, _('skip testing changeset')),
731 ('s', 'skip', False, _('skip testing changeset')),
732 ('e', 'extend', False, _('extend the bisect range')),
732 ('e', 'extend', False, _('extend the bisect range')),
733 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
733 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
734 ('U', 'noupdate', False, _('do not update to target'))],
734 ('U', 'noupdate', False, _('do not update to target'))],
735 _("[-gbsr] [-U] [-c CMD] [REV]"))
735 _("[-gbsr] [-U] [-c CMD] [REV]"))
736 def bisect(ui, repo, rev=None, extra=None, command=None,
736 def bisect(ui, repo, rev=None, extra=None, command=None,
737 reset=None, good=None, bad=None, skip=None, extend=None,
737 reset=None, good=None, bad=None, skip=None, extend=None,
738 noupdate=None):
738 noupdate=None):
739 """subdivision search of changesets
739 """subdivision search of changesets
740
740
741 This command helps to find changesets which introduce problems. To
741 This command helps to find changesets which introduce problems. To
742 use, mark the earliest changeset you know exhibits the problem as
742 use, mark the earliest changeset you know exhibits the problem as
743 bad, then mark the latest changeset which is free from the problem
743 bad, then mark the latest changeset which is free from the problem
744 as good. Bisect will update your working directory to a revision
744 as good. Bisect will update your working directory to a revision
745 for testing (unless the -U/--noupdate option is specified). Once
745 for testing (unless the -U/--noupdate option is specified). Once
746 you have performed tests, mark the working directory as good or
746 you have performed tests, mark the working directory as good or
747 bad, and bisect will either update to another candidate changeset
747 bad, and bisect will either update to another candidate changeset
748 or announce that it has found the bad revision.
748 or announce that it has found the bad revision.
749
749
750 As a shortcut, you can also use the revision argument to mark a
750 As a shortcut, you can also use the revision argument to mark a
751 revision as good or bad without checking it out first.
751 revision as good or bad without checking it out first.
752
752
753 If you supply a command, it will be used for automatic bisection.
753 If you supply a command, it will be used for automatic bisection.
754 The environment variable HG_NODE will contain the ID of the
754 The environment variable HG_NODE will contain the ID of the
755 changeset being tested. The exit status of the command will be
755 changeset being tested. The exit status of the command will be
756 used to mark revisions as good or bad: status 0 means good, 125
756 used to mark revisions as good or bad: status 0 means good, 125
757 means to skip the revision, 127 (command not found) will abort the
757 means to skip the revision, 127 (command not found) will abort the
758 bisection, and any other non-zero exit status means the revision
758 bisection, and any other non-zero exit status means the revision
759 is bad.
759 is bad.
760
760
761 .. container:: verbose
761 .. container:: verbose
762
762
763 Some examples:
763 Some examples:
764
764
765 - start a bisection with known bad revision 34, and good revision 12::
765 - start a bisection with known bad revision 34, and good revision 12::
766
766
767 hg bisect --bad 34
767 hg bisect --bad 34
768 hg bisect --good 12
768 hg bisect --good 12
769
769
770 - advance the current bisection by marking current revision as good or
770 - advance the current bisection by marking current revision as good or
771 bad::
771 bad::
772
772
773 hg bisect --good
773 hg bisect --good
774 hg bisect --bad
774 hg bisect --bad
775
775
776 - mark the current revision, or a known revision, to be skipped (e.g. if
776 - mark the current revision, or a known revision, to be skipped (e.g. if
777 that revision is not usable because of another issue)::
777 that revision is not usable because of another issue)::
778
778
779 hg bisect --skip
779 hg bisect --skip
780 hg bisect --skip 23
780 hg bisect --skip 23
781
781
782 - skip all revisions that do not touch directories ``foo`` or ``bar``::
782 - skip all revisions that do not touch directories ``foo`` or ``bar``::
783
783
784 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
784 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
785
785
786 - forget the current bisection::
786 - forget the current bisection::
787
787
788 hg bisect --reset
788 hg bisect --reset
789
789
790 - use 'make && make tests' to automatically find the first broken
790 - use 'make && make tests' to automatically find the first broken
791 revision::
791 revision::
792
792
793 hg bisect --reset
793 hg bisect --reset
794 hg bisect --bad 34
794 hg bisect --bad 34
795 hg bisect --good 12
795 hg bisect --good 12
796 hg bisect --command "make && make tests"
796 hg bisect --command "make && make tests"
797
797
798 - see all changesets whose states are already known in the current
798 - see all changesets whose states are already known in the current
799 bisection::
799 bisection::
800
800
801 hg log -r "bisect(pruned)"
801 hg log -r "bisect(pruned)"
802
802
803 - see the changeset currently being bisected (especially useful
803 - see the changeset currently being bisected (especially useful
804 if running with -U/--noupdate)::
804 if running with -U/--noupdate)::
805
805
806 hg log -r "bisect(current)"
806 hg log -r "bisect(current)"
807
807
808 - see all changesets that took part in the current bisection::
808 - see all changesets that took part in the current bisection::
809
809
810 hg log -r "bisect(range)"
810 hg log -r "bisect(range)"
811
811
812 - you can even get a nice graph::
812 - you can even get a nice graph::
813
813
814 hg log --graph -r "bisect(range)"
814 hg log --graph -r "bisect(range)"
815
815
816 See :hg:`help revisions.bisect` for more about the `bisect()` predicate.
816 See :hg:`help revisions.bisect` for more about the `bisect()` predicate.
817
817
818 Returns 0 on success.
818 Returns 0 on success.
819 """
819 """
820 # backward compatibility
820 # backward compatibility
821 if rev in "good bad reset init".split():
821 if rev in "good bad reset init".split():
822 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
822 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
823 cmd, rev, extra = rev, extra, None
823 cmd, rev, extra = rev, extra, None
824 if cmd == "good":
824 if cmd == "good":
825 good = True
825 good = True
826 elif cmd == "bad":
826 elif cmd == "bad":
827 bad = True
827 bad = True
828 else:
828 else:
829 reset = True
829 reset = True
830 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
830 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
831 raise error.Abort(_('incompatible arguments'))
831 raise error.Abort(_('incompatible arguments'))
832
832
833 cmdutil.checkunfinished(repo)
833 cmdutil.checkunfinished(repo)
834
834
835 if reset:
835 if reset:
836 hbisect.resetstate(repo)
836 hbisect.resetstate(repo)
837 return
837 return
838
838
839 state = hbisect.load_state(repo)
839 state = hbisect.load_state(repo)
840
840
841 # update state
841 # update state
842 if good or bad or skip:
842 if good or bad or skip:
843 if rev:
843 if rev:
844 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
844 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
845 else:
845 else:
846 nodes = [repo.lookup('.')]
846 nodes = [repo.lookup('.')]
847 if good:
847 if good:
848 state['good'] += nodes
848 state['good'] += nodes
849 elif bad:
849 elif bad:
850 state['bad'] += nodes
850 state['bad'] += nodes
851 elif skip:
851 elif skip:
852 state['skip'] += nodes
852 state['skip'] += nodes
853 hbisect.save_state(repo, state)
853 hbisect.save_state(repo, state)
854 if not (state['good'] and state['bad']):
854 if not (state['good'] and state['bad']):
855 return
855 return
856
856
857 def mayupdate(repo, node, show_stats=True):
857 def mayupdate(repo, node, show_stats=True):
858 """common used update sequence"""
858 """common used update sequence"""
859 if noupdate:
859 if noupdate:
860 return
860 return
861 cmdutil.bailifchanged(repo)
861 cmdutil.bailifchanged(repo)
862 return hg.clean(repo, node, show_stats=show_stats)
862 return hg.clean(repo, node, show_stats=show_stats)
863
863
864 displayer = cmdutil.show_changeset(ui, repo, {})
864 displayer = cmdutil.show_changeset(ui, repo, {})
865
865
866 if command:
866 if command:
867 changesets = 1
867 changesets = 1
868 if noupdate:
868 if noupdate:
869 try:
869 try:
870 node = state['current'][0]
870 node = state['current'][0]
871 except LookupError:
871 except LookupError:
872 raise error.Abort(_('current bisect revision is unknown - '
872 raise error.Abort(_('current bisect revision is unknown - '
873 'start a new bisect to fix'))
873 'start a new bisect to fix'))
874 else:
874 else:
875 node, p2 = repo.dirstate.parents()
875 node, p2 = repo.dirstate.parents()
876 if p2 != nullid:
876 if p2 != nullid:
877 raise error.Abort(_('current bisect revision is a merge'))
877 raise error.Abort(_('current bisect revision is a merge'))
878 if rev:
878 if rev:
879 node = repo[scmutil.revsingle(repo, rev, node)].node()
879 node = repo[scmutil.revsingle(repo, rev, node)].node()
880 try:
880 try:
881 while changesets:
881 while changesets:
882 # update state
882 # update state
883 state['current'] = [node]
883 state['current'] = [node]
884 hbisect.save_state(repo, state)
884 hbisect.save_state(repo, state)
885 status = ui.system(command, environ={'HG_NODE': hex(node)})
885 status = ui.system(command, environ={'HG_NODE': hex(node)})
886 if status == 125:
886 if status == 125:
887 transition = "skip"
887 transition = "skip"
888 elif status == 0:
888 elif status == 0:
889 transition = "good"
889 transition = "good"
890 # status < 0 means process was killed
890 # status < 0 means process was killed
891 elif status == 127:
891 elif status == 127:
892 raise error.Abort(_("failed to execute %s") % command)
892 raise error.Abort(_("failed to execute %s") % command)
893 elif status < 0:
893 elif status < 0:
894 raise error.Abort(_("%s killed") % command)
894 raise error.Abort(_("%s killed") % command)
895 else:
895 else:
896 transition = "bad"
896 transition = "bad"
897 state[transition].append(node)
897 state[transition].append(node)
898 ctx = repo[node]
898 ctx = repo[node]
899 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
899 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
900 hbisect.checkstate(state)
900 hbisect.checkstate(state)
901 # bisect
901 # bisect
902 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
902 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
903 # update to next check
903 # update to next check
904 node = nodes[0]
904 node = nodes[0]
905 mayupdate(repo, node, show_stats=False)
905 mayupdate(repo, node, show_stats=False)
906 finally:
906 finally:
907 state['current'] = [node]
907 state['current'] = [node]
908 hbisect.save_state(repo, state)
908 hbisect.save_state(repo, state)
909 hbisect.printresult(ui, repo, state, displayer, nodes, bgood)
909 hbisect.printresult(ui, repo, state, displayer, nodes, bgood)
910 return
910 return
911
911
912 hbisect.checkstate(state)
912 hbisect.checkstate(state)
913
913
914 # actually bisect
914 # actually bisect
915 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
915 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
916 if extend:
916 if extend:
917 if not changesets:
917 if not changesets:
918 extendnode = hbisect.extendrange(repo, state, nodes, good)
918 extendnode = hbisect.extendrange(repo, state, nodes, good)
919 if extendnode is not None:
919 if extendnode is not None:
920 ui.write(_("Extending search to changeset %d:%s\n")
920 ui.write(_("Extending search to changeset %d:%s\n")
921 % (extendnode.rev(), extendnode))
921 % (extendnode.rev(), extendnode))
922 state['current'] = [extendnode.node()]
922 state['current'] = [extendnode.node()]
923 hbisect.save_state(repo, state)
923 hbisect.save_state(repo, state)
924 return mayupdate(repo, extendnode.node())
924 return mayupdate(repo, extendnode.node())
925 raise error.Abort(_("nothing to extend"))
925 raise error.Abort(_("nothing to extend"))
926
926
927 if changesets == 0:
927 if changesets == 0:
928 hbisect.printresult(ui, repo, state, displayer, nodes, good)
928 hbisect.printresult(ui, repo, state, displayer, nodes, good)
929 else:
929 else:
930 assert len(nodes) == 1 # only a single node can be tested next
930 assert len(nodes) == 1 # only a single node can be tested next
931 node = nodes[0]
931 node = nodes[0]
932 # compute the approximate number of remaining tests
932 # compute the approximate number of remaining tests
933 tests, size = 0, 2
933 tests, size = 0, 2
934 while size <= changesets:
934 while size <= changesets:
935 tests, size = tests + 1, size * 2
935 tests, size = tests + 1, size * 2
936 rev = repo.changelog.rev(node)
936 rev = repo.changelog.rev(node)
937 ui.write(_("Testing changeset %d:%s "
937 ui.write(_("Testing changeset %d:%s "
938 "(%d changesets remaining, ~%d tests)\n")
938 "(%d changesets remaining, ~%d tests)\n")
939 % (rev, short(node), changesets, tests))
939 % (rev, short(node), changesets, tests))
940 state['current'] = [node]
940 state['current'] = [node]
941 hbisect.save_state(repo, state)
941 hbisect.save_state(repo, state)
942 return mayupdate(repo, node)
942 return mayupdate(repo, node)
943
943
944 @command('bookmarks|bookmark',
944 @command('bookmarks|bookmark',
945 [('f', 'force', False, _('force')),
945 [('f', 'force', False, _('force')),
946 ('r', 'rev', '', _('revision for bookmark action'), _('REV')),
946 ('r', 'rev', '', _('revision for bookmark action'), _('REV')),
947 ('d', 'delete', False, _('delete a given bookmark')),
947 ('d', 'delete', False, _('delete a given bookmark')),
948 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
948 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
949 ('i', 'inactive', False, _('mark a bookmark inactive')),
949 ('i', 'inactive', False, _('mark a bookmark inactive')),
950 ] + formatteropts,
950 ] + formatteropts,
951 _('hg bookmarks [OPTIONS]... [NAME]...'))
951 _('hg bookmarks [OPTIONS]... [NAME]...'))
952 def bookmark(ui, repo, *names, **opts):
952 def bookmark(ui, repo, *names, **opts):
953 '''create a new bookmark or list existing bookmarks
953 '''create a new bookmark or list existing bookmarks
954
954
955 Bookmarks are labels on changesets to help track lines of development.
955 Bookmarks are labels on changesets to help track lines of development.
956 Bookmarks are unversioned and can be moved, renamed and deleted.
956 Bookmarks are unversioned and can be moved, renamed and deleted.
957 Deleting or moving a bookmark has no effect on the associated changesets.
957 Deleting or moving a bookmark has no effect on the associated changesets.
958
958
959 Creating or updating to a bookmark causes it to be marked as 'active'.
959 Creating or updating to a bookmark causes it to be marked as 'active'.
960 The active bookmark is indicated with a '*'.
960 The active bookmark is indicated with a '*'.
961 When a commit is made, the active bookmark will advance to the new commit.
961 When a commit is made, the active bookmark will advance to the new commit.
962 A plain :hg:`update` will also advance an active bookmark, if possible.
962 A plain :hg:`update` will also advance an active bookmark, if possible.
963 Updating away from a bookmark will cause it to be deactivated.
963 Updating away from a bookmark will cause it to be deactivated.
964
964
965 Bookmarks can be pushed and pulled between repositories (see
965 Bookmarks can be pushed and pulled between repositories (see
966 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
966 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
967 diverged, a new 'divergent bookmark' of the form 'name@path' will
967 diverged, a new 'divergent bookmark' of the form 'name@path' will
968 be created. Using :hg:`merge` will resolve the divergence.
968 be created. Using :hg:`merge` will resolve the divergence.
969
969
970 A bookmark named '@' has the special property that :hg:`clone` will
970 A bookmark named '@' has the special property that :hg:`clone` will
971 check it out by default if it exists.
971 check it out by default if it exists.
972
972
973 .. container:: verbose
973 .. container:: verbose
974
974
975 Examples:
975 Examples:
976
976
977 - create an active bookmark for a new line of development::
977 - create an active bookmark for a new line of development::
978
978
979 hg book new-feature
979 hg book new-feature
980
980
981 - create an inactive bookmark as a place marker::
981 - create an inactive bookmark as a place marker::
982
982
983 hg book -i reviewed
983 hg book -i reviewed
984
984
985 - create an inactive bookmark on another changeset::
985 - create an inactive bookmark on another changeset::
986
986
987 hg book -r .^ tested
987 hg book -r .^ tested
988
988
989 - rename bookmark turkey to dinner::
989 - rename bookmark turkey to dinner::
990
990
991 hg book -m turkey dinner
991 hg book -m turkey dinner
992
992
993 - move the '@' bookmark from another branch::
993 - move the '@' bookmark from another branch::
994
994
995 hg book -f @
995 hg book -f @
996 '''
996 '''
997 force = opts.get('force')
997 force = opts.get('force')
998 rev = opts.get('rev')
998 rev = opts.get('rev')
999 delete = opts.get('delete')
999 delete = opts.get('delete')
1000 rename = opts.get('rename')
1000 rename = opts.get('rename')
1001 inactive = opts.get('inactive')
1001 inactive = opts.get('inactive')
1002
1002
1003 def checkformat(mark):
1003 def checkformat(mark):
1004 mark = mark.strip()
1004 mark = mark.strip()
1005 if not mark:
1005 if not mark:
1006 raise error.Abort(_("bookmark names cannot consist entirely of "
1006 raise error.Abort(_("bookmark names cannot consist entirely of "
1007 "whitespace"))
1007 "whitespace"))
1008 scmutil.checknewlabel(repo, mark, 'bookmark')
1008 scmutil.checknewlabel(repo, mark, 'bookmark')
1009 return mark
1009 return mark
1010
1010
1011 def checkconflict(repo, mark, cur, force=False, target=None):
1011 def checkconflict(repo, mark, cur, force=False, target=None):
1012 if mark in marks and not force:
1012 if mark in marks and not force:
1013 if target:
1013 if target:
1014 if marks[mark] == target and target == cur:
1014 if marks[mark] == target and target == cur:
1015 # re-activating a bookmark
1015 # re-activating a bookmark
1016 return
1016 return
1017 anc = repo.changelog.ancestors([repo[target].rev()])
1017 anc = repo.changelog.ancestors([repo[target].rev()])
1018 bmctx = repo[marks[mark]]
1018 bmctx = repo[marks[mark]]
1019 divs = [repo[b].node() for b in marks
1019 divs = [repo[b].node() for b in marks
1020 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
1020 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
1021
1021
1022 # allow resolving a single divergent bookmark even if moving
1022 # allow resolving a single divergent bookmark even if moving
1023 # the bookmark across branches when a revision is specified
1023 # the bookmark across branches when a revision is specified
1024 # that contains a divergent bookmark
1024 # that contains a divergent bookmark
1025 if bmctx.rev() not in anc and target in divs:
1025 if bmctx.rev() not in anc and target in divs:
1026 bookmarks.deletedivergent(repo, [target], mark)
1026 bookmarks.deletedivergent(repo, [target], mark)
1027 return
1027 return
1028
1028
1029 deletefrom = [b for b in divs
1029 deletefrom = [b for b in divs
1030 if repo[b].rev() in anc or b == target]
1030 if repo[b].rev() in anc or b == target]
1031 bookmarks.deletedivergent(repo, deletefrom, mark)
1031 bookmarks.deletedivergent(repo, deletefrom, mark)
1032 if bookmarks.validdest(repo, bmctx, repo[target]):
1032 if bookmarks.validdest(repo, bmctx, repo[target]):
1033 ui.status(_("moving bookmark '%s' forward from %s\n") %
1033 ui.status(_("moving bookmark '%s' forward from %s\n") %
1034 (mark, short(bmctx.node())))
1034 (mark, short(bmctx.node())))
1035 return
1035 return
1036 raise error.Abort(_("bookmark '%s' already exists "
1036 raise error.Abort(_("bookmark '%s' already exists "
1037 "(use -f to force)") % mark)
1037 "(use -f to force)") % mark)
1038 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
1038 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
1039 and not force):
1039 and not force):
1040 raise error.Abort(
1040 raise error.Abort(
1041 _("a bookmark cannot have the name of an existing branch"))
1041 _("a bookmark cannot have the name of an existing branch"))
1042
1042
1043 if delete and rename:
1043 if delete and rename:
1044 raise error.Abort(_("--delete and --rename are incompatible"))
1044 raise error.Abort(_("--delete and --rename are incompatible"))
1045 if delete and rev:
1045 if delete and rev:
1046 raise error.Abort(_("--rev is incompatible with --delete"))
1046 raise error.Abort(_("--rev is incompatible with --delete"))
1047 if rename and rev:
1047 if rename and rev:
1048 raise error.Abort(_("--rev is incompatible with --rename"))
1048 raise error.Abort(_("--rev is incompatible with --rename"))
1049 if not names and (delete or rev):
1049 if not names and (delete or rev):
1050 raise error.Abort(_("bookmark name required"))
1050 raise error.Abort(_("bookmark name required"))
1051
1051
1052 if delete or rename or names or inactive:
1052 if delete or rename or names or inactive:
1053 wlock = lock = tr = None
1053 wlock = lock = tr = None
1054 try:
1054 try:
1055 wlock = repo.wlock()
1055 wlock = repo.wlock()
1056 lock = repo.lock()
1056 lock = repo.lock()
1057 cur = repo.changectx('.').node()
1057 cur = repo.changectx('.').node()
1058 marks = repo._bookmarks
1058 marks = repo._bookmarks
1059 if delete:
1059 if delete:
1060 tr = repo.transaction('bookmark')
1060 tr = repo.transaction('bookmark')
1061 for mark in names:
1061 for mark in names:
1062 if mark not in marks:
1062 if mark not in marks:
1063 raise error.Abort(_("bookmark '%s' does not exist") %
1063 raise error.Abort(_("bookmark '%s' does not exist") %
1064 mark)
1064 mark)
1065 if mark == repo._activebookmark:
1065 if mark == repo._activebookmark:
1066 bookmarks.deactivate(repo)
1066 bookmarks.deactivate(repo)
1067 del marks[mark]
1067 del marks[mark]
1068
1068
1069 elif rename:
1069 elif rename:
1070 tr = repo.transaction('bookmark')
1070 tr = repo.transaction('bookmark')
1071 if not names:
1071 if not names:
1072 raise error.Abort(_("new bookmark name required"))
1072 raise error.Abort(_("new bookmark name required"))
1073 elif len(names) > 1:
1073 elif len(names) > 1:
1074 raise error.Abort(_("only one new bookmark name allowed"))
1074 raise error.Abort(_("only one new bookmark name allowed"))
1075 mark = checkformat(names[0])
1075 mark = checkformat(names[0])
1076 if rename not in marks:
1076 if rename not in marks:
1077 raise error.Abort(_("bookmark '%s' does not exist")
1077 raise error.Abort(_("bookmark '%s' does not exist")
1078 % rename)
1078 % rename)
1079 checkconflict(repo, mark, cur, force)
1079 checkconflict(repo, mark, cur, force)
1080 marks[mark] = marks[rename]
1080 marks[mark] = marks[rename]
1081 if repo._activebookmark == rename and not inactive:
1081 if repo._activebookmark == rename and not inactive:
1082 bookmarks.activate(repo, mark)
1082 bookmarks.activate(repo, mark)
1083 del marks[rename]
1083 del marks[rename]
1084 elif names:
1084 elif names:
1085 tr = repo.transaction('bookmark')
1085 tr = repo.transaction('bookmark')
1086 newact = None
1086 newact = None
1087 for mark in names:
1087 for mark in names:
1088 mark = checkformat(mark)
1088 mark = checkformat(mark)
1089 if newact is None:
1089 if newact is None:
1090 newact = mark
1090 newact = mark
1091 if inactive and mark == repo._activebookmark:
1091 if inactive and mark == repo._activebookmark:
1092 bookmarks.deactivate(repo)
1092 bookmarks.deactivate(repo)
1093 return
1093 return
1094 tgt = cur
1094 tgt = cur
1095 if rev:
1095 if rev:
1096 tgt = scmutil.revsingle(repo, rev).node()
1096 tgt = scmutil.revsingle(repo, rev).node()
1097 checkconflict(repo, mark, cur, force, tgt)
1097 checkconflict(repo, mark, cur, force, tgt)
1098 marks[mark] = tgt
1098 marks[mark] = tgt
1099 if not inactive and cur == marks[newact] and not rev:
1099 if not inactive and cur == marks[newact] and not rev:
1100 bookmarks.activate(repo, newact)
1100 bookmarks.activate(repo, newact)
1101 elif cur != tgt and newact == repo._activebookmark:
1101 elif cur != tgt and newact == repo._activebookmark:
1102 bookmarks.deactivate(repo)
1102 bookmarks.deactivate(repo)
1103 elif inactive:
1103 elif inactive:
1104 if len(marks) == 0:
1104 if len(marks) == 0:
1105 ui.status(_("no bookmarks set\n"))
1105 ui.status(_("no bookmarks set\n"))
1106 elif not repo._activebookmark:
1106 elif not repo._activebookmark:
1107 ui.status(_("no active bookmark\n"))
1107 ui.status(_("no active bookmark\n"))
1108 else:
1108 else:
1109 bookmarks.deactivate(repo)
1109 bookmarks.deactivate(repo)
1110 if tr is not None:
1110 if tr is not None:
1111 marks.recordchange(tr)
1111 marks.recordchange(tr)
1112 tr.close()
1112 tr.close()
1113 finally:
1113 finally:
1114 lockmod.release(tr, lock, wlock)
1114 lockmod.release(tr, lock, wlock)
1115 else: # show bookmarks
1115 else: # show bookmarks
1116 fm = ui.formatter('bookmarks', opts)
1116 fm = ui.formatter('bookmarks', opts)
1117 hexfn = fm.hexfunc
1117 hexfn = fm.hexfunc
1118 marks = repo._bookmarks
1118 marks = repo._bookmarks
1119 if len(marks) == 0 and fm.isplain():
1119 if len(marks) == 0 and fm.isplain():
1120 ui.status(_("no bookmarks set\n"))
1120 ui.status(_("no bookmarks set\n"))
1121 for bmark, n in sorted(marks.iteritems()):
1121 for bmark, n in sorted(marks.iteritems()):
1122 active = repo._activebookmark
1122 active = repo._activebookmark
1123 if bmark == active:
1123 if bmark == active:
1124 prefix, label = '*', activebookmarklabel
1124 prefix, label = '*', activebookmarklabel
1125 else:
1125 else:
1126 prefix, label = ' ', ''
1126 prefix, label = ' ', ''
1127
1127
1128 fm.startitem()
1128 fm.startitem()
1129 if not ui.quiet:
1129 if not ui.quiet:
1130 fm.plain(' %s ' % prefix, label=label)
1130 fm.plain(' %s ' % prefix, label=label)
1131 fm.write('bookmark', '%s', bmark, label=label)
1131 fm.write('bookmark', '%s', bmark, label=label)
1132 pad = " " * (25 - encoding.colwidth(bmark))
1132 pad = " " * (25 - encoding.colwidth(bmark))
1133 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1133 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1134 repo.changelog.rev(n), hexfn(n), label=label)
1134 repo.changelog.rev(n), hexfn(n), label=label)
1135 fm.data(active=(bmark == active))
1135 fm.data(active=(bmark == active))
1136 fm.plain('\n')
1136 fm.plain('\n')
1137 fm.end()
1137 fm.end()
1138
1138
1139 @command('branch',
1139 @command('branch',
1140 [('f', 'force', None,
1140 [('f', 'force', None,
1141 _('set branch name even if it shadows an existing branch')),
1141 _('set branch name even if it shadows an existing branch')),
1142 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1142 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1143 _('[-fC] [NAME]'))
1143 _('[-fC] [NAME]'))
1144 def branch(ui, repo, label=None, **opts):
1144 def branch(ui, repo, label=None, **opts):
1145 """set or show the current branch name
1145 """set or show the current branch name
1146
1146
1147 .. note::
1147 .. note::
1148
1148
1149 Branch names are permanent and global. Use :hg:`bookmark` to create a
1149 Branch names are permanent and global. Use :hg:`bookmark` to create a
1150 light-weight bookmark instead. See :hg:`help glossary` for more
1150 light-weight bookmark instead. See :hg:`help glossary` for more
1151 information about named branches and bookmarks.
1151 information about named branches and bookmarks.
1152
1152
1153 With no argument, show the current branch name. With one argument,
1153 With no argument, show the current branch name. With one argument,
1154 set the working directory branch name (the branch will not exist
1154 set the working directory branch name (the branch will not exist
1155 in the repository until the next commit). Standard practice
1155 in the repository until the next commit). Standard practice
1156 recommends that primary development take place on the 'default'
1156 recommends that primary development take place on the 'default'
1157 branch.
1157 branch.
1158
1158
1159 Unless -f/--force is specified, branch will not let you set a
1159 Unless -f/--force is specified, branch will not let you set a
1160 branch name that already exists.
1160 branch name that already exists.
1161
1161
1162 Use -C/--clean to reset the working directory branch to that of
1162 Use -C/--clean to reset the working directory branch to that of
1163 the parent of the working directory, negating a previous branch
1163 the parent of the working directory, negating a previous branch
1164 change.
1164 change.
1165
1165
1166 Use the command :hg:`update` to switch to an existing branch. Use
1166 Use the command :hg:`update` to switch to an existing branch. Use
1167 :hg:`commit --close-branch` to mark this branch head as closed.
1167 :hg:`commit --close-branch` to mark this branch head as closed.
1168 When all heads of a branch are closed, the branch will be
1168 When all heads of a branch are closed, the branch will be
1169 considered closed.
1169 considered closed.
1170
1170
1171 Returns 0 on success.
1171 Returns 0 on success.
1172 """
1172 """
1173 if label:
1173 if label:
1174 label = label.strip()
1174 label = label.strip()
1175
1175
1176 if not opts.get('clean') and not label:
1176 if not opts.get('clean') and not label:
1177 ui.write("%s\n" % repo.dirstate.branch())
1177 ui.write("%s\n" % repo.dirstate.branch())
1178 return
1178 return
1179
1179
1180 with repo.wlock():
1180 with repo.wlock():
1181 if opts.get('clean'):
1181 if opts.get('clean'):
1182 label = repo[None].p1().branch()
1182 label = repo[None].p1().branch()
1183 repo.dirstate.setbranch(label)
1183 repo.dirstate.setbranch(label)
1184 ui.status(_('reset working directory to branch %s\n') % label)
1184 ui.status(_('reset working directory to branch %s\n') % label)
1185 elif label:
1185 elif label:
1186 if not opts.get('force') and label in repo.branchmap():
1186 if not opts.get('force') and label in repo.branchmap():
1187 if label not in [p.branch() for p in repo[None].parents()]:
1187 if label not in [p.branch() for p in repo[None].parents()]:
1188 raise error.Abort(_('a branch of the same name already'
1188 raise error.Abort(_('a branch of the same name already'
1189 ' exists'),
1189 ' exists'),
1190 # i18n: "it" refers to an existing branch
1190 # i18n: "it" refers to an existing branch
1191 hint=_("use 'hg update' to switch to it"))
1191 hint=_("use 'hg update' to switch to it"))
1192 scmutil.checknewlabel(repo, label, 'branch')
1192 scmutil.checknewlabel(repo, label, 'branch')
1193 repo.dirstate.setbranch(label)
1193 repo.dirstate.setbranch(label)
1194 ui.status(_('marked working directory as branch %s\n') % label)
1194 ui.status(_('marked working directory as branch %s\n') % label)
1195
1195
1196 # find any open named branches aside from default
1196 # find any open named branches aside from default
1197 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1197 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1198 if n != "default" and not c]
1198 if n != "default" and not c]
1199 if not others:
1199 if not others:
1200 ui.status(_('(branches are permanent and global, '
1200 ui.status(_('(branches are permanent and global, '
1201 'did you want a bookmark?)\n'))
1201 'did you want a bookmark?)\n'))
1202
1202
1203 @command('branches',
1203 @command('branches',
1204 [('a', 'active', False,
1204 [('a', 'active', False,
1205 _('show only branches that have unmerged heads (DEPRECATED)')),
1205 _('show only branches that have unmerged heads (DEPRECATED)')),
1206 ('c', 'closed', False, _('show normal and closed branches')),
1206 ('c', 'closed', False, _('show normal and closed branches')),
1207 ] + formatteropts,
1207 ] + formatteropts,
1208 _('[-c]'))
1208 _('[-c]'))
1209 def branches(ui, repo, active=False, closed=False, **opts):
1209 def branches(ui, repo, active=False, closed=False, **opts):
1210 """list repository named branches
1210 """list repository named branches
1211
1211
1212 List the repository's named branches, indicating which ones are
1212 List the repository's named branches, indicating which ones are
1213 inactive. If -c/--closed is specified, also list branches which have
1213 inactive. If -c/--closed is specified, also list branches which have
1214 been marked closed (see :hg:`commit --close-branch`).
1214 been marked closed (see :hg:`commit --close-branch`).
1215
1215
1216 Use the command :hg:`update` to switch to an existing branch.
1216 Use the command :hg:`update` to switch to an existing branch.
1217
1217
1218 Returns 0.
1218 Returns 0.
1219 """
1219 """
1220
1220
1221 fm = ui.formatter('branches', opts)
1221 fm = ui.formatter('branches', opts)
1222 hexfunc = fm.hexfunc
1222 hexfunc = fm.hexfunc
1223
1223
1224 allheads = set(repo.heads())
1224 allheads = set(repo.heads())
1225 branches = []
1225 branches = []
1226 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1226 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1227 isactive = not isclosed and bool(set(heads) & allheads)
1227 isactive = not isclosed and bool(set(heads) & allheads)
1228 branches.append((tag, repo[tip], isactive, not isclosed))
1228 branches.append((tag, repo[tip], isactive, not isclosed))
1229 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1229 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1230 reverse=True)
1230 reverse=True)
1231
1231
1232 for tag, ctx, isactive, isopen in branches:
1232 for tag, ctx, isactive, isopen in branches:
1233 if active and not isactive:
1233 if active and not isactive:
1234 continue
1234 continue
1235 if isactive:
1235 if isactive:
1236 label = 'branches.active'
1236 label = 'branches.active'
1237 notice = ''
1237 notice = ''
1238 elif not isopen:
1238 elif not isopen:
1239 if not closed:
1239 if not closed:
1240 continue
1240 continue
1241 label = 'branches.closed'
1241 label = 'branches.closed'
1242 notice = _(' (closed)')
1242 notice = _(' (closed)')
1243 else:
1243 else:
1244 label = 'branches.inactive'
1244 label = 'branches.inactive'
1245 notice = _(' (inactive)')
1245 notice = _(' (inactive)')
1246 current = (tag == repo.dirstate.branch())
1246 current = (tag == repo.dirstate.branch())
1247 if current:
1247 if current:
1248 label = 'branches.current'
1248 label = 'branches.current'
1249
1249
1250 fm.startitem()
1250 fm.startitem()
1251 fm.write('branch', '%s', tag, label=label)
1251 fm.write('branch', '%s', tag, label=label)
1252 rev = ctx.rev()
1252 rev = ctx.rev()
1253 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1253 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1254 fmt = ' ' * padsize + ' %d:%s'
1254 fmt = ' ' * padsize + ' %d:%s'
1255 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1255 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1256 label='log.changeset changeset.%s' % ctx.phasestr())
1256 label='log.changeset changeset.%s' % ctx.phasestr())
1257 fm.data(active=isactive, closed=not isopen, current=current)
1257 fm.data(active=isactive, closed=not isopen, current=current)
1258 if not ui.quiet:
1258 if not ui.quiet:
1259 fm.plain(notice)
1259 fm.plain(notice)
1260 fm.plain('\n')
1260 fm.plain('\n')
1261 fm.end()
1261 fm.end()
1262
1262
1263 @command('bundle',
1263 @command('bundle',
1264 [('f', 'force', None, _('run even when the destination is unrelated')),
1264 [('f', 'force', None, _('run even when the destination is unrelated')),
1265 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1265 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1266 _('REV')),
1266 _('REV')),
1267 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1267 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1268 _('BRANCH')),
1268 _('BRANCH')),
1269 ('', 'base', [],
1269 ('', 'base', [],
1270 _('a base changeset assumed to be available at the destination'),
1270 _('a base changeset assumed to be available at the destination'),
1271 _('REV')),
1271 _('REV')),
1272 ('a', 'all', None, _('bundle all changesets in the repository')),
1272 ('a', 'all', None, _('bundle all changesets in the repository')),
1273 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1273 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1274 ] + remoteopts,
1274 ] + remoteopts,
1275 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1275 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1276 def bundle(ui, repo, fname, dest=None, **opts):
1276 def bundle(ui, repo, fname, dest=None, **opts):
1277 """create a changegroup file
1277 """create a changegroup file
1278
1278
1279 Generate a changegroup file collecting changesets to be added
1279 Generate a changegroup file collecting changesets to be added
1280 to a repository.
1280 to a repository.
1281
1281
1282 To create a bundle containing all changesets, use -a/--all
1282 To create a bundle containing all changesets, use -a/--all
1283 (or --base null). Otherwise, hg assumes the destination will have
1283 (or --base null). Otherwise, hg assumes the destination will have
1284 all the nodes you specify with --base parameters. Otherwise, hg
1284 all the nodes you specify with --base parameters. Otherwise, hg
1285 will assume the repository has all the nodes in destination, or
1285 will assume the repository has all the nodes in destination, or
1286 default-push/default if no destination is specified.
1286 default-push/default if no destination is specified.
1287
1287
1288 You can change bundle format with the -t/--type option. You can
1288 You can change bundle format with the -t/--type option. You can
1289 specify a compression, a bundle version or both using a dash
1289 specify a compression, a bundle version or both using a dash
1290 (comp-version). The available compression methods are: none, bzip2,
1290 (comp-version). The available compression methods are: none, bzip2,
1291 and gzip (by default, bundles are compressed using bzip2). The
1291 and gzip (by default, bundles are compressed using bzip2). The
1292 available formats are: v1, v2 (default to most suitable).
1292 available formats are: v1, v2 (default to most suitable).
1293
1293
1294 The bundle file can then be transferred using conventional means
1294 The bundle file can then be transferred using conventional means
1295 and applied to another repository with the unbundle or pull
1295 and applied to another repository with the unbundle or pull
1296 command. This is useful when direct push and pull are not
1296 command. This is useful when direct push and pull are not
1297 available or when exporting an entire repository is undesirable.
1297 available or when exporting an entire repository is undesirable.
1298
1298
1299 Applying bundles preserves all changeset contents including
1299 Applying bundles preserves all changeset contents including
1300 permissions, copy/rename information, and revision history.
1300 permissions, copy/rename information, and revision history.
1301
1301
1302 Returns 0 on success, 1 if no changes found.
1302 Returns 0 on success, 1 if no changes found.
1303 """
1303 """
1304 revs = None
1304 revs = None
1305 if 'rev' in opts:
1305 if 'rev' in opts:
1306 revstrings = opts['rev']
1306 revstrings = opts['rev']
1307 revs = scmutil.revrange(repo, revstrings)
1307 revs = scmutil.revrange(repo, revstrings)
1308 if revstrings and not revs:
1308 if revstrings and not revs:
1309 raise error.Abort(_('no commits to bundle'))
1309 raise error.Abort(_('no commits to bundle'))
1310
1310
1311 bundletype = opts.get('type', 'bzip2').lower()
1311 bundletype = opts.get('type', 'bzip2').lower()
1312 try:
1312 try:
1313 bcompression, cgversion, params = exchange.parsebundlespec(
1313 bcompression, cgversion, params = exchange.parsebundlespec(
1314 repo, bundletype, strict=False)
1314 repo, bundletype, strict=False)
1315 except error.UnsupportedBundleSpecification as e:
1315 except error.UnsupportedBundleSpecification as e:
1316 raise error.Abort(str(e),
1316 raise error.Abort(str(e),
1317 hint=_("see 'hg help bundle' for supported "
1317 hint=_("see 'hg help bundle' for supported "
1318 "values for --type"))
1318 "values for --type"))
1319
1319
1320 # Packed bundles are a pseudo bundle format for now.
1320 # Packed bundles are a pseudo bundle format for now.
1321 if cgversion == 's1':
1321 if cgversion == 's1':
1322 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1322 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1323 hint=_("use 'hg debugcreatestreamclonebundle'"))
1323 hint=_("use 'hg debugcreatestreamclonebundle'"))
1324
1324
1325 if opts.get('all'):
1325 if opts.get('all'):
1326 if dest:
1326 if dest:
1327 raise error.Abort(_("--all is incompatible with specifying "
1327 raise error.Abort(_("--all is incompatible with specifying "
1328 "a destination"))
1328 "a destination"))
1329 if opts.get('base'):
1329 if opts.get('base'):
1330 ui.warn(_("ignoring --base because --all was specified\n"))
1330 ui.warn(_("ignoring --base because --all was specified\n"))
1331 base = ['null']
1331 base = ['null']
1332 else:
1332 else:
1333 base = scmutil.revrange(repo, opts.get('base'))
1333 base = scmutil.revrange(repo, opts.get('base'))
1334 # TODO: get desired bundlecaps from command line.
1334 # TODO: get desired bundlecaps from command line.
1335 bundlecaps = None
1335 bundlecaps = None
1336 if cgversion not in changegroup.supportedoutgoingversions(repo):
1336 if cgversion not in changegroup.supportedoutgoingversions(repo):
1337 raise error.Abort(_("repository does not support bundle version %s") %
1337 raise error.Abort(_("repository does not support bundle version %s") %
1338 cgversion)
1338 cgversion)
1339
1339
1340 if base:
1340 if base:
1341 if dest:
1341 if dest:
1342 raise error.Abort(_("--base is incompatible with specifying "
1342 raise error.Abort(_("--base is incompatible with specifying "
1343 "a destination"))
1343 "a destination"))
1344 common = [repo.lookup(rev) for rev in base]
1344 common = [repo.lookup(rev) for rev in base]
1345 heads = revs and map(repo.lookup, revs) or None
1345 heads = revs and map(repo.lookup, revs) or None
1346 outgoing = discovery.outgoing(repo, common, heads)
1346 outgoing = discovery.outgoing(repo, common, heads)
1347 cg = changegroup.getchangegroup(repo, 'bundle', outgoing,
1347 cg = changegroup.getchangegroup(repo, 'bundle', outgoing,
1348 bundlecaps=bundlecaps,
1348 bundlecaps=bundlecaps,
1349 version=cgversion)
1349 version=cgversion)
1350 outgoing = None
1350 outgoing = None
1351 else:
1351 else:
1352 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1352 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1353 dest, branches = hg.parseurl(dest, opts.get('branch'))
1353 dest, branches = hg.parseurl(dest, opts.get('branch'))
1354 other = hg.peer(repo, opts, dest)
1354 other = hg.peer(repo, opts, dest)
1355 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1355 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1356 heads = revs and map(repo.lookup, revs) or revs
1356 heads = revs and map(repo.lookup, revs) or revs
1357 outgoing = discovery.findcommonoutgoing(repo, other,
1357 outgoing = discovery.findcommonoutgoing(repo, other,
1358 onlyheads=heads,
1358 onlyheads=heads,
1359 force=opts.get('force'),
1359 force=opts.get('force'),
1360 portable=True)
1360 portable=True)
1361 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1361 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1362 bundlecaps, version=cgversion)
1362 bundlecaps, version=cgversion)
1363 if not cg:
1363 if not cg:
1364 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1364 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1365 return 1
1365 return 1
1366
1366
1367 if cgversion == '01': #bundle1
1367 if cgversion == '01': #bundle1
1368 if bcompression is None:
1368 if bcompression is None:
1369 bcompression = 'UN'
1369 bcompression = 'UN'
1370 bversion = 'HG10' + bcompression
1370 bversion = 'HG10' + bcompression
1371 bcompression = None
1371 bcompression = None
1372 else:
1372 else:
1373 assert cgversion == '02'
1373 assert cgversion == '02'
1374 bversion = 'HG20'
1374 bversion = 'HG20'
1375
1375
1376 # TODO compression options should be derived from bundlespec parsing.
1376 # TODO compression options should be derived from bundlespec parsing.
1377 # This is a temporary hack to allow adjusting bundle compression
1377 # This is a temporary hack to allow adjusting bundle compression
1378 # level without a) formalizing the bundlespec changes to declare it
1378 # level without a) formalizing the bundlespec changes to declare it
1379 # b) introducing a command flag.
1379 # b) introducing a command flag.
1380 compopts = {}
1380 compopts = {}
1381 complevel = ui.configint('experimental', 'bundlecomplevel')
1381 complevel = ui.configint('experimental', 'bundlecomplevel')
1382 if complevel is not None:
1382 if complevel is not None:
1383 compopts['level'] = complevel
1383 compopts['level'] = complevel
1384
1384
1385 bundle2.writebundle(ui, cg, fname, bversion, compression=bcompression,
1385 bundle2.writebundle(ui, cg, fname, bversion, compression=bcompression,
1386 compopts=compopts)
1386 compopts=compopts)
1387
1387
1388 @command('cat',
1388 @command('cat',
1389 [('o', 'output', '',
1389 [('o', 'output', '',
1390 _('print output to file with formatted name'), _('FORMAT')),
1390 _('print output to file with formatted name'), _('FORMAT')),
1391 ('r', 'rev', '', _('print the given revision'), _('REV')),
1391 ('r', 'rev', '', _('print the given revision'), _('REV')),
1392 ('', 'decode', None, _('apply any matching decode filter')),
1392 ('', 'decode', None, _('apply any matching decode filter')),
1393 ] + walkopts,
1393 ] + walkopts,
1394 _('[OPTION]... FILE...'),
1394 _('[OPTION]... FILE...'),
1395 inferrepo=True)
1395 inferrepo=True)
1396 def cat(ui, repo, file1, *pats, **opts):
1396 def cat(ui, repo, file1, *pats, **opts):
1397 """output the current or given revision of files
1397 """output the current or given revision of files
1398
1398
1399 Print the specified files as they were at the given revision. If
1399 Print the specified files as they were at the given revision. If
1400 no revision is given, the parent of the working directory is used.
1400 no revision is given, the parent of the working directory is used.
1401
1401
1402 Output may be to a file, in which case the name of the file is
1402 Output may be to a file, in which case the name of the file is
1403 given using a format string. The formatting rules as follows:
1403 given using a format string. The formatting rules as follows:
1404
1404
1405 :``%%``: literal "%" character
1405 :``%%``: literal "%" character
1406 :``%s``: basename of file being printed
1406 :``%s``: basename of file being printed
1407 :``%d``: dirname of file being printed, or '.' if in repository root
1407 :``%d``: dirname of file being printed, or '.' if in repository root
1408 :``%p``: root-relative path name of file being printed
1408 :``%p``: root-relative path name of file being printed
1409 :``%H``: changeset hash (40 hexadecimal digits)
1409 :``%H``: changeset hash (40 hexadecimal digits)
1410 :``%R``: changeset revision number
1410 :``%R``: changeset revision number
1411 :``%h``: short-form changeset hash (12 hexadecimal digits)
1411 :``%h``: short-form changeset hash (12 hexadecimal digits)
1412 :``%r``: zero-padded changeset revision number
1412 :``%r``: zero-padded changeset revision number
1413 :``%b``: basename of the exporting repository
1413 :``%b``: basename of the exporting repository
1414
1414
1415 Returns 0 on success.
1415 Returns 0 on success.
1416 """
1416 """
1417 ctx = scmutil.revsingle(repo, opts.get('rev'))
1417 ctx = scmutil.revsingle(repo, opts.get('rev'))
1418 m = scmutil.match(ctx, (file1,) + pats, opts)
1418 m = scmutil.match(ctx, (file1,) + pats, opts)
1419
1419
1420 ui.pager('cat')
1420 ui.pager('cat')
1421 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1421 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1422
1422
1423 @command('^clone',
1423 @command('^clone',
1424 [('U', 'noupdate', None, _('the clone will include an empty working '
1424 [('U', 'noupdate', None, _('the clone will include an empty working '
1425 'directory (only a repository)')),
1425 'directory (only a repository)')),
1426 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1426 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1427 _('REV')),
1427 _('REV')),
1428 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1428 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1429 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1429 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1430 ('', 'pull', None, _('use pull protocol to copy metadata')),
1430 ('', 'pull', None, _('use pull protocol to copy metadata')),
1431 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1431 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1432 ] + remoteopts,
1432 ] + remoteopts,
1433 _('[OPTION]... SOURCE [DEST]'),
1433 _('[OPTION]... SOURCE [DEST]'),
1434 norepo=True)
1434 norepo=True)
1435 def clone(ui, source, dest=None, **opts):
1435 def clone(ui, source, dest=None, **opts):
1436 """make a copy of an existing repository
1436 """make a copy of an existing repository
1437
1437
1438 Create a copy of an existing repository in a new directory.
1438 Create a copy of an existing repository in a new directory.
1439
1439
1440 If no destination directory name is specified, it defaults to the
1440 If no destination directory name is specified, it defaults to the
1441 basename of the source.
1441 basename of the source.
1442
1442
1443 The location of the source is added to the new repository's
1443 The location of the source is added to the new repository's
1444 ``.hg/hgrc`` file, as the default to be used for future pulls.
1444 ``.hg/hgrc`` file, as the default to be used for future pulls.
1445
1445
1446 Only local paths and ``ssh://`` URLs are supported as
1446 Only local paths and ``ssh://`` URLs are supported as
1447 destinations. For ``ssh://`` destinations, no working directory or
1447 destinations. For ``ssh://`` destinations, no working directory or
1448 ``.hg/hgrc`` will be created on the remote side.
1448 ``.hg/hgrc`` will be created on the remote side.
1449
1449
1450 If the source repository has a bookmark called '@' set, that
1450 If the source repository has a bookmark called '@' set, that
1451 revision will be checked out in the new repository by default.
1451 revision will be checked out in the new repository by default.
1452
1452
1453 To check out a particular version, use -u/--update, or
1453 To check out a particular version, use -u/--update, or
1454 -U/--noupdate to create a clone with no working directory.
1454 -U/--noupdate to create a clone with no working directory.
1455
1455
1456 To pull only a subset of changesets, specify one or more revisions
1456 To pull only a subset of changesets, specify one or more revisions
1457 identifiers with -r/--rev or branches with -b/--branch. The
1457 identifiers with -r/--rev or branches with -b/--branch. The
1458 resulting clone will contain only the specified changesets and
1458 resulting clone will contain only the specified changesets and
1459 their ancestors. These options (or 'clone src#rev dest') imply
1459 their ancestors. These options (or 'clone src#rev dest') imply
1460 --pull, even for local source repositories.
1460 --pull, even for local source repositories.
1461
1461
1462 .. note::
1462 .. note::
1463
1463
1464 Specifying a tag will include the tagged changeset but not the
1464 Specifying a tag will include the tagged changeset but not the
1465 changeset containing the tag.
1465 changeset containing the tag.
1466
1466
1467 .. container:: verbose
1467 .. container:: verbose
1468
1468
1469 For efficiency, hardlinks are used for cloning whenever the
1469 For efficiency, hardlinks are used for cloning whenever the
1470 source and destination are on the same filesystem (note this
1470 source and destination are on the same filesystem (note this
1471 applies only to the repository data, not to the working
1471 applies only to the repository data, not to the working
1472 directory). Some filesystems, such as AFS, implement hardlinking
1472 directory). Some filesystems, such as AFS, implement hardlinking
1473 incorrectly, but do not report errors. In these cases, use the
1473 incorrectly, but do not report errors. In these cases, use the
1474 --pull option to avoid hardlinking.
1474 --pull option to avoid hardlinking.
1475
1475
1476 In some cases, you can clone repositories and the working
1476 In some cases, you can clone repositories and the working
1477 directory using full hardlinks with ::
1477 directory using full hardlinks with ::
1478
1478
1479 $ cp -al REPO REPOCLONE
1479 $ cp -al REPO REPOCLONE
1480
1480
1481 This is the fastest way to clone, but it is not always safe. The
1481 This is the fastest way to clone, but it is not always safe. The
1482 operation is not atomic (making sure REPO is not modified during
1482 operation is not atomic (making sure REPO is not modified during
1483 the operation is up to you) and you have to make sure your
1483 the operation is up to you) and you have to make sure your
1484 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1484 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1485 so). Also, this is not compatible with certain extensions that
1485 so). Also, this is not compatible with certain extensions that
1486 place their metadata under the .hg directory, such as mq.
1486 place their metadata under the .hg directory, such as mq.
1487
1487
1488 Mercurial will update the working directory to the first applicable
1488 Mercurial will update the working directory to the first applicable
1489 revision from this list:
1489 revision from this list:
1490
1490
1491 a) null if -U or the source repository has no changesets
1491 a) null if -U or the source repository has no changesets
1492 b) if -u . and the source repository is local, the first parent of
1492 b) if -u . and the source repository is local, the first parent of
1493 the source repository's working directory
1493 the source repository's working directory
1494 c) the changeset specified with -u (if a branch name, this means the
1494 c) the changeset specified with -u (if a branch name, this means the
1495 latest head of that branch)
1495 latest head of that branch)
1496 d) the changeset specified with -r
1496 d) the changeset specified with -r
1497 e) the tipmost head specified with -b
1497 e) the tipmost head specified with -b
1498 f) the tipmost head specified with the url#branch source syntax
1498 f) the tipmost head specified with the url#branch source syntax
1499 g) the revision marked with the '@' bookmark, if present
1499 g) the revision marked with the '@' bookmark, if present
1500 h) the tipmost head of the default branch
1500 h) the tipmost head of the default branch
1501 i) tip
1501 i) tip
1502
1502
1503 When cloning from servers that support it, Mercurial may fetch
1503 When cloning from servers that support it, Mercurial may fetch
1504 pre-generated data from a server-advertised URL. When this is done,
1504 pre-generated data from a server-advertised URL. When this is done,
1505 hooks operating on incoming changesets and changegroups may fire twice,
1505 hooks operating on incoming changesets and changegroups may fire twice,
1506 once for the bundle fetched from the URL and another for any additional
1506 once for the bundle fetched from the URL and another for any additional
1507 data not fetched from this URL. In addition, if an error occurs, the
1507 data not fetched from this URL. In addition, if an error occurs, the
1508 repository may be rolled back to a partial clone. This behavior may
1508 repository may be rolled back to a partial clone. This behavior may
1509 change in future releases. See :hg:`help -e clonebundles` for more.
1509 change in future releases. See :hg:`help -e clonebundles` for more.
1510
1510
1511 Examples:
1511 Examples:
1512
1512
1513 - clone a remote repository to a new directory named hg/::
1513 - clone a remote repository to a new directory named hg/::
1514
1514
1515 hg clone https://www.mercurial-scm.org/repo/hg/
1515 hg clone https://www.mercurial-scm.org/repo/hg/
1516
1516
1517 - create a lightweight local clone::
1517 - create a lightweight local clone::
1518
1518
1519 hg clone project/ project-feature/
1519 hg clone project/ project-feature/
1520
1520
1521 - clone from an absolute path on an ssh server (note double-slash)::
1521 - clone from an absolute path on an ssh server (note double-slash)::
1522
1522
1523 hg clone ssh://user@server//home/projects/alpha/
1523 hg clone ssh://user@server//home/projects/alpha/
1524
1524
1525 - do a high-speed clone over a LAN while checking out a
1525 - do a high-speed clone over a LAN while checking out a
1526 specified version::
1526 specified version::
1527
1527
1528 hg clone --uncompressed http://server/repo -u 1.5
1528 hg clone --uncompressed http://server/repo -u 1.5
1529
1529
1530 - create a repository without changesets after a particular revision::
1530 - create a repository without changesets after a particular revision::
1531
1531
1532 hg clone -r 04e544 experimental/ good/
1532 hg clone -r 04e544 experimental/ good/
1533
1533
1534 - clone (and track) a particular named branch::
1534 - clone (and track) a particular named branch::
1535
1535
1536 hg clone https://www.mercurial-scm.org/repo/hg/#stable
1536 hg clone https://www.mercurial-scm.org/repo/hg/#stable
1537
1537
1538 See :hg:`help urls` for details on specifying URLs.
1538 See :hg:`help urls` for details on specifying URLs.
1539
1539
1540 Returns 0 on success.
1540 Returns 0 on success.
1541 """
1541 """
1542 if opts.get('noupdate') and opts.get('updaterev'):
1542 if opts.get('noupdate') and opts.get('updaterev'):
1543 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1543 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1544
1544
1545 r = hg.clone(ui, opts, source, dest,
1545 r = hg.clone(ui, opts, source, dest,
1546 pull=opts.get('pull'),
1546 pull=opts.get('pull'),
1547 stream=opts.get('uncompressed'),
1547 stream=opts.get('uncompressed'),
1548 rev=opts.get('rev'),
1548 rev=opts.get('rev'),
1549 update=opts.get('updaterev') or not opts.get('noupdate'),
1549 update=opts.get('updaterev') or not opts.get('noupdate'),
1550 branch=opts.get('branch'),
1550 branch=opts.get('branch'),
1551 shareopts=opts.get('shareopts'))
1551 shareopts=opts.get('shareopts'))
1552
1552
1553 return r is None
1553 return r is None
1554
1554
1555 @command('^commit|ci',
1555 @command('^commit|ci',
1556 [('A', 'addremove', None,
1556 [('A', 'addremove', None,
1557 _('mark new/missing files as added/removed before committing')),
1557 _('mark new/missing files as added/removed before committing')),
1558 ('', 'close-branch', None,
1558 ('', 'close-branch', None,
1559 _('mark a branch head as closed')),
1559 _('mark a branch head as closed')),
1560 ('', 'amend', None, _('amend the parent of the working directory')),
1560 ('', 'amend', None, _('amend the parent of the working directory')),
1561 ('s', 'secret', None, _('use the secret phase for committing')),
1561 ('s', 'secret', None, _('use the secret phase for committing')),
1562 ('e', 'edit', None, _('invoke editor on commit messages')),
1562 ('e', 'edit', None, _('invoke editor on commit messages')),
1563 ('i', 'interactive', None, _('use interactive mode')),
1563 ('i', 'interactive', None, _('use interactive mode')),
1564 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1564 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1565 _('[OPTION]... [FILE]...'),
1565 _('[OPTION]... [FILE]...'),
1566 inferrepo=True)
1566 inferrepo=True)
1567 def commit(ui, repo, *pats, **opts):
1567 def commit(ui, repo, *pats, **opts):
1568 """commit the specified files or all outstanding changes
1568 """commit the specified files or all outstanding changes
1569
1569
1570 Commit changes to the given files into the repository. Unlike a
1570 Commit changes to the given files into the repository. Unlike a
1571 centralized SCM, this operation is a local operation. See
1571 centralized SCM, this operation is a local operation. See
1572 :hg:`push` for a way to actively distribute your changes.
1572 :hg:`push` for a way to actively distribute your changes.
1573
1573
1574 If a list of files is omitted, all changes reported by :hg:`status`
1574 If a list of files is omitted, all changes reported by :hg:`status`
1575 will be committed.
1575 will be committed.
1576
1576
1577 If you are committing the result of a merge, do not provide any
1577 If you are committing the result of a merge, do not provide any
1578 filenames or -I/-X filters.
1578 filenames or -I/-X filters.
1579
1579
1580 If no commit message is specified, Mercurial starts your
1580 If no commit message is specified, Mercurial starts your
1581 configured editor where you can enter a message. In case your
1581 configured editor where you can enter a message. In case your
1582 commit fails, you will find a backup of your message in
1582 commit fails, you will find a backup of your message in
1583 ``.hg/last-message.txt``.
1583 ``.hg/last-message.txt``.
1584
1584
1585 The --close-branch flag can be used to mark the current branch
1585 The --close-branch flag can be used to mark the current branch
1586 head closed. When all heads of a branch are closed, the branch
1586 head closed. When all heads of a branch are closed, the branch
1587 will be considered closed and no longer listed.
1587 will be considered closed and no longer listed.
1588
1588
1589 The --amend flag can be used to amend the parent of the
1589 The --amend flag can be used to amend the parent of the
1590 working directory with a new commit that contains the changes
1590 working directory with a new commit that contains the changes
1591 in the parent in addition to those currently reported by :hg:`status`,
1591 in the parent in addition to those currently reported by :hg:`status`,
1592 if there are any. The old commit is stored in a backup bundle in
1592 if there are any. The old commit is stored in a backup bundle in
1593 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1593 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1594 on how to restore it).
1594 on how to restore it).
1595
1595
1596 Message, user and date are taken from the amended commit unless
1596 Message, user and date are taken from the amended commit unless
1597 specified. When a message isn't specified on the command line,
1597 specified. When a message isn't specified on the command line,
1598 the editor will open with the message of the amended commit.
1598 the editor will open with the message of the amended commit.
1599
1599
1600 It is not possible to amend public changesets (see :hg:`help phases`)
1600 It is not possible to amend public changesets (see :hg:`help phases`)
1601 or changesets that have children.
1601 or changesets that have children.
1602
1602
1603 See :hg:`help dates` for a list of formats valid for -d/--date.
1603 See :hg:`help dates` for a list of formats valid for -d/--date.
1604
1604
1605 Returns 0 on success, 1 if nothing changed.
1605 Returns 0 on success, 1 if nothing changed.
1606
1606
1607 .. container:: verbose
1607 .. container:: verbose
1608
1608
1609 Examples:
1609 Examples:
1610
1610
1611 - commit all files ending in .py::
1611 - commit all files ending in .py::
1612
1612
1613 hg commit --include "set:**.py"
1613 hg commit --include "set:**.py"
1614
1614
1615 - commit all non-binary files::
1615 - commit all non-binary files::
1616
1616
1617 hg commit --exclude "set:binary()"
1617 hg commit --exclude "set:binary()"
1618
1618
1619 - amend the current commit and set the date to now::
1619 - amend the current commit and set the date to now::
1620
1620
1621 hg commit --amend --date now
1621 hg commit --amend --date now
1622 """
1622 """
1623 wlock = lock = None
1623 wlock = lock = None
1624 try:
1624 try:
1625 wlock = repo.wlock()
1625 wlock = repo.wlock()
1626 lock = repo.lock()
1626 lock = repo.lock()
1627 return _docommit(ui, repo, *pats, **opts)
1627 return _docommit(ui, repo, *pats, **opts)
1628 finally:
1628 finally:
1629 release(lock, wlock)
1629 release(lock, wlock)
1630
1630
1631 def _docommit(ui, repo, *pats, **opts):
1631 def _docommit(ui, repo, *pats, **opts):
1632 if opts.get('interactive'):
1632 if opts.get('interactive'):
1633 opts.pop('interactive')
1633 opts.pop('interactive')
1634 ret = cmdutil.dorecord(ui, repo, commit, None, False,
1634 ret = cmdutil.dorecord(ui, repo, commit, None, False,
1635 cmdutil.recordfilter, *pats, **opts)
1635 cmdutil.recordfilter, *pats, **opts)
1636 # ret can be 0 (no changes to record) or the value returned by
1636 # ret can be 0 (no changes to record) or the value returned by
1637 # commit(), 1 if nothing changed or None on success.
1637 # commit(), 1 if nothing changed or None on success.
1638 return 1 if ret == 0 else ret
1638 return 1 if ret == 0 else ret
1639
1639
1640 if opts.get('subrepos'):
1640 if opts.get('subrepos'):
1641 if opts.get('amend'):
1641 if opts.get('amend'):
1642 raise error.Abort(_('cannot amend with --subrepos'))
1642 raise error.Abort(_('cannot amend with --subrepos'))
1643 # Let --subrepos on the command line override config setting.
1643 # Let --subrepos on the command line override config setting.
1644 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1644 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1645
1645
1646 cmdutil.checkunfinished(repo, commit=True)
1646 cmdutil.checkunfinished(repo, commit=True)
1647
1647
1648 branch = repo[None].branch()
1648 branch = repo[None].branch()
1649 bheads = repo.branchheads(branch)
1649 bheads = repo.branchheads(branch)
1650
1650
1651 extra = {}
1651 extra = {}
1652 if opts.get('close_branch'):
1652 if opts.get('close_branch'):
1653 extra['close'] = 1
1653 extra['close'] = 1
1654
1654
1655 if not bheads:
1655 if not bheads:
1656 raise error.Abort(_('can only close branch heads'))
1656 raise error.Abort(_('can only close branch heads'))
1657 elif opts.get('amend'):
1657 elif opts.get('amend'):
1658 if repo[None].parents()[0].p1().branch() != branch and \
1658 if repo[None].parents()[0].p1().branch() != branch and \
1659 repo[None].parents()[0].p2().branch() != branch:
1659 repo[None].parents()[0].p2().branch() != branch:
1660 raise error.Abort(_('can only close branch heads'))
1660 raise error.Abort(_('can only close branch heads'))
1661
1661
1662 if opts.get('amend'):
1662 if opts.get('amend'):
1663 if ui.configbool('ui', 'commitsubrepos'):
1663 if ui.configbool('ui', 'commitsubrepos'):
1664 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1664 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1665
1665
1666 old = repo['.']
1666 old = repo['.']
1667 if not old.mutable():
1667 if not old.mutable():
1668 raise error.Abort(_('cannot amend public changesets'))
1668 raise error.Abort(_('cannot amend public changesets'))
1669 if len(repo[None].parents()) > 1:
1669 if len(repo[None].parents()) > 1:
1670 raise error.Abort(_('cannot amend while merging'))
1670 raise error.Abort(_('cannot amend while merging'))
1671 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1671 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1672 if not allowunstable and old.children():
1672 if not allowunstable and old.children():
1673 raise error.Abort(_('cannot amend changeset with children'))
1673 raise error.Abort(_('cannot amend changeset with children'))
1674
1674
1675 # Currently histedit gets confused if an amend happens while histedit
1675 # Currently histedit gets confused if an amend happens while histedit
1676 # is in progress. Since we have a checkunfinished command, we are
1676 # is in progress. Since we have a checkunfinished command, we are
1677 # temporarily honoring it.
1677 # temporarily honoring it.
1678 #
1678 #
1679 # Note: eventually this guard will be removed. Please do not expect
1679 # Note: eventually this guard will be removed. Please do not expect
1680 # this behavior to remain.
1680 # this behavior to remain.
1681 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
1681 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
1682 cmdutil.checkunfinished(repo)
1682 cmdutil.checkunfinished(repo)
1683
1683
1684 # commitfunc is used only for temporary amend commit by cmdutil.amend
1684 # commitfunc is used only for temporary amend commit by cmdutil.amend
1685 def commitfunc(ui, repo, message, match, opts):
1685 def commitfunc(ui, repo, message, match, opts):
1686 return repo.commit(message,
1686 return repo.commit(message,
1687 opts.get('user') or old.user(),
1687 opts.get('user') or old.user(),
1688 opts.get('date') or old.date(),
1688 opts.get('date') or old.date(),
1689 match,
1689 match,
1690 extra=extra)
1690 extra=extra)
1691
1691
1692 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1692 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1693 if node == old.node():
1693 if node == old.node():
1694 ui.status(_("nothing changed\n"))
1694 ui.status(_("nothing changed\n"))
1695 return 1
1695 return 1
1696 else:
1696 else:
1697 def commitfunc(ui, repo, message, match, opts):
1697 def commitfunc(ui, repo, message, match, opts):
1698 backup = ui.backupconfig('phases', 'new-commit')
1698 backup = ui.backupconfig('phases', 'new-commit')
1699 baseui = repo.baseui
1699 baseui = repo.baseui
1700 basebackup = baseui.backupconfig('phases', 'new-commit')
1700 basebackup = baseui.backupconfig('phases', 'new-commit')
1701 try:
1701 try:
1702 if opts.get('secret'):
1702 if opts.get('secret'):
1703 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1703 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1704 # Propagate to subrepos
1704 # Propagate to subrepos
1705 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1705 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1706
1706
1707 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1707 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1708 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1708 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1709 return repo.commit(message, opts.get('user'), opts.get('date'),
1709 return repo.commit(message, opts.get('user'), opts.get('date'),
1710 match,
1710 match,
1711 editor=editor,
1711 editor=editor,
1712 extra=extra)
1712 extra=extra)
1713 finally:
1713 finally:
1714 ui.restoreconfig(backup)
1714 ui.restoreconfig(backup)
1715 repo.baseui.restoreconfig(basebackup)
1715 repo.baseui.restoreconfig(basebackup)
1716
1716
1717
1717
1718 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1718 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1719
1719
1720 if not node:
1720 if not node:
1721 stat = cmdutil.postcommitstatus(repo, pats, opts)
1721 stat = cmdutil.postcommitstatus(repo, pats, opts)
1722 if stat[3]:
1722 if stat[3]:
1723 ui.status(_("nothing changed (%d missing files, see "
1723 ui.status(_("nothing changed (%d missing files, see "
1724 "'hg status')\n") % len(stat[3]))
1724 "'hg status')\n") % len(stat[3]))
1725 else:
1725 else:
1726 ui.status(_("nothing changed\n"))
1726 ui.status(_("nothing changed\n"))
1727 return 1
1727 return 1
1728
1728
1729 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1729 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1730
1730
1731 @command('config|showconfig|debugconfig',
1731 @command('config|showconfig|debugconfig',
1732 [('u', 'untrusted', None, _('show untrusted configuration options')),
1732 [('u', 'untrusted', None, _('show untrusted configuration options')),
1733 ('e', 'edit', None, _('edit user config')),
1733 ('e', 'edit', None, _('edit user config')),
1734 ('l', 'local', None, _('edit repository config')),
1734 ('l', 'local', None, _('edit repository config')),
1735 ('g', 'global', None, _('edit global config'))] + formatteropts,
1735 ('g', 'global', None, _('edit global config'))] + formatteropts,
1736 _('[-u] [NAME]...'),
1736 _('[-u] [NAME]...'),
1737 optionalrepo=True)
1737 optionalrepo=True)
1738 def config(ui, repo, *values, **opts):
1738 def config(ui, repo, *values, **opts):
1739 """show combined config settings from all hgrc files
1739 """show combined config settings from all hgrc files
1740
1740
1741 With no arguments, print names and values of all config items.
1741 With no arguments, print names and values of all config items.
1742
1742
1743 With one argument of the form section.name, print just the value
1743 With one argument of the form section.name, print just the value
1744 of that config item.
1744 of that config item.
1745
1745
1746 With multiple arguments, print names and values of all config
1746 With multiple arguments, print names and values of all config
1747 items with matching section names.
1747 items with matching section names.
1748
1748
1749 With --edit, start an editor on the user-level config file. With
1749 With --edit, start an editor on the user-level config file. With
1750 --global, edit the system-wide config file. With --local, edit the
1750 --global, edit the system-wide config file. With --local, edit the
1751 repository-level config file.
1751 repository-level config file.
1752
1752
1753 With --debug, the source (filename and line number) is printed
1753 With --debug, the source (filename and line number) is printed
1754 for each config item.
1754 for each config item.
1755
1755
1756 See :hg:`help config` for more information about config files.
1756 See :hg:`help config` for more information about config files.
1757
1757
1758 Returns 0 on success, 1 if NAME does not exist.
1758 Returns 0 on success, 1 if NAME does not exist.
1759
1759
1760 """
1760 """
1761
1761
1762 if opts.get('edit') or opts.get('local') or opts.get('global'):
1762 if opts.get('edit') or opts.get('local') or opts.get('global'):
1763 if opts.get('local') and opts.get('global'):
1763 if opts.get('local') and opts.get('global'):
1764 raise error.Abort(_("can't use --local and --global together"))
1764 raise error.Abort(_("can't use --local and --global together"))
1765
1765
1766 if opts.get('local'):
1766 if opts.get('local'):
1767 if not repo:
1767 if not repo:
1768 raise error.Abort(_("can't use --local outside a repository"))
1768 raise error.Abort(_("can't use --local outside a repository"))
1769 paths = [repo.join('hgrc')]
1769 paths = [repo.join('hgrc')]
1770 elif opts.get('global'):
1770 elif opts.get('global'):
1771 paths = scmutil.systemrcpath()
1771 paths = scmutil.systemrcpath()
1772 else:
1772 else:
1773 paths = scmutil.userrcpath()
1773 paths = scmutil.userrcpath()
1774
1774
1775 for f in paths:
1775 for f in paths:
1776 if os.path.exists(f):
1776 if os.path.exists(f):
1777 break
1777 break
1778 else:
1778 else:
1779 if opts.get('global'):
1779 if opts.get('global'):
1780 samplehgrc = uimod.samplehgrcs['global']
1780 samplehgrc = uimod.samplehgrcs['global']
1781 elif opts.get('local'):
1781 elif opts.get('local'):
1782 samplehgrc = uimod.samplehgrcs['local']
1782 samplehgrc = uimod.samplehgrcs['local']
1783 else:
1783 else:
1784 samplehgrc = uimod.samplehgrcs['user']
1784 samplehgrc = uimod.samplehgrcs['user']
1785
1785
1786 f = paths[0]
1786 f = paths[0]
1787 fp = open(f, "w")
1787 fp = open(f, "w")
1788 fp.write(samplehgrc)
1788 fp.write(samplehgrc)
1789 fp.close()
1789 fp.close()
1790
1790
1791 editor = ui.geteditor()
1791 editor = ui.geteditor()
1792 ui.system("%s \"%s\"" % (editor, f),
1792 ui.system("%s \"%s\"" % (editor, f),
1793 onerr=error.Abort, errprefix=_("edit failed"))
1793 onerr=error.Abort, errprefix=_("edit failed"))
1794 return
1794 return
1795
1795
1796 fm = ui.formatter('config', opts)
1796 fm = ui.formatter('config', opts)
1797 for f in scmutil.rcpath():
1797 for f in scmutil.rcpath():
1798 ui.debug('read config from: %s\n' % f)
1798 ui.debug('read config from: %s\n' % f)
1799 untrusted = bool(opts.get('untrusted'))
1799 untrusted = bool(opts.get('untrusted'))
1800 if values:
1800 if values:
1801 sections = [v for v in values if '.' not in v]
1801 sections = [v for v in values if '.' not in v]
1802 items = [v for v in values if '.' in v]
1802 items = [v for v in values if '.' in v]
1803 if len(items) > 1 or items and sections:
1803 if len(items) > 1 or items and sections:
1804 raise error.Abort(_('only one config item permitted'))
1804 raise error.Abort(_('only one config item permitted'))
1805 matched = False
1805 matched = False
1806 for section, name, value in ui.walkconfig(untrusted=untrusted):
1806 for section, name, value in ui.walkconfig(untrusted=untrusted):
1807 source = ui.configsource(section, name, untrusted)
1807 source = ui.configsource(section, name, untrusted)
1808 value = str(value)
1808 value = str(value)
1809 if fm.isplain():
1809 if fm.isplain():
1810 source = source or 'none'
1810 source = source or 'none'
1811 value = value.replace('\n', '\\n')
1811 value = value.replace('\n', '\\n')
1812 entryname = section + '.' + name
1812 entryname = section + '.' + name
1813 if values:
1813 if values:
1814 for v in values:
1814 for v in values:
1815 if v == section:
1815 if v == section:
1816 fm.startitem()
1816 fm.startitem()
1817 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1817 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1818 fm.write('name value', '%s=%s\n', entryname, value)
1818 fm.write('name value', '%s=%s\n', entryname, value)
1819 matched = True
1819 matched = True
1820 elif v == entryname:
1820 elif v == entryname:
1821 fm.startitem()
1821 fm.startitem()
1822 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1822 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1823 fm.write('value', '%s\n', value)
1823 fm.write('value', '%s\n', value)
1824 fm.data(name=entryname)
1824 fm.data(name=entryname)
1825 matched = True
1825 matched = True
1826 else:
1826 else:
1827 fm.startitem()
1827 fm.startitem()
1828 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1828 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1829 fm.write('name value', '%s=%s\n', entryname, value)
1829 fm.write('name value', '%s=%s\n', entryname, value)
1830 matched = True
1830 matched = True
1831 fm.end()
1831 fm.end()
1832 if matched:
1832 if matched:
1833 return 0
1833 return 0
1834 return 1
1834 return 1
1835
1835
1836 @command('copy|cp',
1836 @command('copy|cp',
1837 [('A', 'after', None, _('record a copy that has already occurred')),
1837 [('A', 'after', None, _('record a copy that has already occurred')),
1838 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1838 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1839 ] + walkopts + dryrunopts,
1839 ] + walkopts + dryrunopts,
1840 _('[OPTION]... [SOURCE]... DEST'))
1840 _('[OPTION]... [SOURCE]... DEST'))
1841 def copy(ui, repo, *pats, **opts):
1841 def copy(ui, repo, *pats, **opts):
1842 """mark files as copied for the next commit
1842 """mark files as copied for the next commit
1843
1843
1844 Mark dest as having copies of source files. If dest is a
1844 Mark dest as having copies of source files. If dest is a
1845 directory, copies are put in that directory. If dest is a file,
1845 directory, copies are put in that directory. If dest is a file,
1846 the source must be a single file.
1846 the source must be a single file.
1847
1847
1848 By default, this command copies the contents of files as they
1848 By default, this command copies the contents of files as they
1849 exist in the working directory. If invoked with -A/--after, the
1849 exist in the working directory. If invoked with -A/--after, the
1850 operation is recorded, but no copying is performed.
1850 operation is recorded, but no copying is performed.
1851
1851
1852 This command takes effect with the next commit. To undo a copy
1852 This command takes effect with the next commit. To undo a copy
1853 before that, see :hg:`revert`.
1853 before that, see :hg:`revert`.
1854
1854
1855 Returns 0 on success, 1 if errors are encountered.
1855 Returns 0 on success, 1 if errors are encountered.
1856 """
1856 """
1857 with repo.wlock(False):
1857 with repo.wlock(False):
1858 return cmdutil.copy(ui, repo, pats, opts)
1858 return cmdutil.copy(ui, repo, pats, opts)
1859
1859
1860 @command('^diff',
1860 @command('^diff',
1861 [('r', 'rev', [], _('revision'), _('REV')),
1861 [('r', 'rev', [], _('revision'), _('REV')),
1862 ('c', 'change', '', _('change made by revision'), _('REV'))
1862 ('c', 'change', '', _('change made by revision'), _('REV'))
1863 ] + diffopts + diffopts2 + walkopts + subrepoopts,
1863 ] + diffopts + diffopts2 + walkopts + subrepoopts,
1864 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
1864 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
1865 inferrepo=True)
1865 inferrepo=True)
1866 def diff(ui, repo, *pats, **opts):
1866 def diff(ui, repo, *pats, **opts):
1867 """diff repository (or selected files)
1867 """diff repository (or selected files)
1868
1868
1869 Show differences between revisions for the specified files.
1869 Show differences between revisions for the specified files.
1870
1870
1871 Differences between files are shown using the unified diff format.
1871 Differences between files are shown using the unified diff format.
1872
1872
1873 .. note::
1873 .. note::
1874
1874
1875 :hg:`diff` may generate unexpected results for merges, as it will
1875 :hg:`diff` may generate unexpected results for merges, as it will
1876 default to comparing against the working directory's first
1876 default to comparing against the working directory's first
1877 parent changeset if no revisions are specified.
1877 parent changeset if no revisions are specified.
1878
1878
1879 When two revision arguments are given, then changes are shown
1879 When two revision arguments are given, then changes are shown
1880 between those revisions. If only one revision is specified then
1880 between those revisions. If only one revision is specified then
1881 that revision is compared to the working directory, and, when no
1881 that revision is compared to the working directory, and, when no
1882 revisions are specified, the working directory files are compared
1882 revisions are specified, the working directory files are compared
1883 to its first parent.
1883 to its first parent.
1884
1884
1885 Alternatively you can specify -c/--change with a revision to see
1885 Alternatively you can specify -c/--change with a revision to see
1886 the changes in that changeset relative to its first parent.
1886 the changes in that changeset relative to its first parent.
1887
1887
1888 Without the -a/--text option, diff will avoid generating diffs of
1888 Without the -a/--text option, diff will avoid generating diffs of
1889 files it detects as binary. With -a, diff will generate a diff
1889 files it detects as binary. With -a, diff will generate a diff
1890 anyway, probably with undesirable results.
1890 anyway, probably with undesirable results.
1891
1891
1892 Use the -g/--git option to generate diffs in the git extended diff
1892 Use the -g/--git option to generate diffs in the git extended diff
1893 format. For more information, read :hg:`help diffs`.
1893 format. For more information, read :hg:`help diffs`.
1894
1894
1895 .. container:: verbose
1895 .. container:: verbose
1896
1896
1897 Examples:
1897 Examples:
1898
1898
1899 - compare a file in the current working directory to its parent::
1899 - compare a file in the current working directory to its parent::
1900
1900
1901 hg diff foo.c
1901 hg diff foo.c
1902
1902
1903 - compare two historical versions of a directory, with rename info::
1903 - compare two historical versions of a directory, with rename info::
1904
1904
1905 hg diff --git -r 1.0:1.2 lib/
1905 hg diff --git -r 1.0:1.2 lib/
1906
1906
1907 - get change stats relative to the last change on some date::
1907 - get change stats relative to the last change on some date::
1908
1908
1909 hg diff --stat -r "date('may 2')"
1909 hg diff --stat -r "date('may 2')"
1910
1910
1911 - diff all newly-added files that contain a keyword::
1911 - diff all newly-added files that contain a keyword::
1912
1912
1913 hg diff "set:added() and grep(GNU)"
1913 hg diff "set:added() and grep(GNU)"
1914
1914
1915 - compare a revision and its parents::
1915 - compare a revision and its parents::
1916
1916
1917 hg diff -c 9353 # compare against first parent
1917 hg diff -c 9353 # compare against first parent
1918 hg diff -r 9353^:9353 # same using revset syntax
1918 hg diff -r 9353^:9353 # same using revset syntax
1919 hg diff -r 9353^2:9353 # compare against the second parent
1919 hg diff -r 9353^2:9353 # compare against the second parent
1920
1920
1921 Returns 0 on success.
1921 Returns 0 on success.
1922 """
1922 """
1923
1923
1924 revs = opts.get('rev')
1924 revs = opts.get('rev')
1925 change = opts.get('change')
1925 change = opts.get('change')
1926 stat = opts.get('stat')
1926 stat = opts.get('stat')
1927 reverse = opts.get('reverse')
1927 reverse = opts.get('reverse')
1928
1928
1929 if revs and change:
1929 if revs and change:
1930 msg = _('cannot specify --rev and --change at the same time')
1930 msg = _('cannot specify --rev and --change at the same time')
1931 raise error.Abort(msg)
1931 raise error.Abort(msg)
1932 elif change:
1932 elif change:
1933 node2 = scmutil.revsingle(repo, change, None).node()
1933 node2 = scmutil.revsingle(repo, change, None).node()
1934 node1 = repo[node2].p1().node()
1934 node1 = repo[node2].p1().node()
1935 else:
1935 else:
1936 node1, node2 = scmutil.revpair(repo, revs)
1936 node1, node2 = scmutil.revpair(repo, revs)
1937
1937
1938 if reverse:
1938 if reverse:
1939 node1, node2 = node2, node1
1939 node1, node2 = node2, node1
1940
1940
1941 diffopts = patch.diffallopts(ui, opts)
1941 diffopts = patch.diffallopts(ui, opts)
1942 m = scmutil.match(repo[node2], pats, opts)
1942 m = scmutil.match(repo[node2], pats, opts)
1943 ui.pager('diff')
1943 ui.pager('diff')
1944 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
1944 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
1945 listsubrepos=opts.get('subrepos'),
1945 listsubrepos=opts.get('subrepos'),
1946 root=opts.get('root'))
1946 root=opts.get('root'))
1947
1947
1948 @command('^export',
1948 @command('^export',
1949 [('o', 'output', '',
1949 [('o', 'output', '',
1950 _('print output to file with formatted name'), _('FORMAT')),
1950 _('print output to file with formatted name'), _('FORMAT')),
1951 ('', 'switch-parent', None, _('diff against the second parent')),
1951 ('', 'switch-parent', None, _('diff against the second parent')),
1952 ('r', 'rev', [], _('revisions to export'), _('REV')),
1952 ('r', 'rev', [], _('revisions to export'), _('REV')),
1953 ] + diffopts,
1953 ] + diffopts,
1954 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
1954 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
1955 def export(ui, repo, *changesets, **opts):
1955 def export(ui, repo, *changesets, **opts):
1956 """dump the header and diffs for one or more changesets
1956 """dump the header and diffs for one or more changesets
1957
1957
1958 Print the changeset header and diffs for one or more revisions.
1958 Print the changeset header and diffs for one or more revisions.
1959 If no revision is given, the parent of the working directory is used.
1959 If no revision is given, the parent of the working directory is used.
1960
1960
1961 The information shown in the changeset header is: author, date,
1961 The information shown in the changeset header is: author, date,
1962 branch name (if non-default), changeset hash, parent(s) and commit
1962 branch name (if non-default), changeset hash, parent(s) and commit
1963 comment.
1963 comment.
1964
1964
1965 .. note::
1965 .. note::
1966
1966
1967 :hg:`export` may generate unexpected diff output for merge
1967 :hg:`export` may generate unexpected diff output for merge
1968 changesets, as it will compare the merge changeset against its
1968 changesets, as it will compare the merge changeset against its
1969 first parent only.
1969 first parent only.
1970
1970
1971 Output may be to a file, in which case the name of the file is
1971 Output may be to a file, in which case the name of the file is
1972 given using a format string. The formatting rules are as follows:
1972 given using a format string. The formatting rules are as follows:
1973
1973
1974 :``%%``: literal "%" character
1974 :``%%``: literal "%" character
1975 :``%H``: changeset hash (40 hexadecimal digits)
1975 :``%H``: changeset hash (40 hexadecimal digits)
1976 :``%N``: number of patches being generated
1976 :``%N``: number of patches being generated
1977 :``%R``: changeset revision number
1977 :``%R``: changeset revision number
1978 :``%b``: basename of the exporting repository
1978 :``%b``: basename of the exporting repository
1979 :``%h``: short-form changeset hash (12 hexadecimal digits)
1979 :``%h``: short-form changeset hash (12 hexadecimal digits)
1980 :``%m``: first line of the commit message (only alphanumeric characters)
1980 :``%m``: first line of the commit message (only alphanumeric characters)
1981 :``%n``: zero-padded sequence number, starting at 1
1981 :``%n``: zero-padded sequence number, starting at 1
1982 :``%r``: zero-padded changeset revision number
1982 :``%r``: zero-padded changeset revision number
1983
1983
1984 Without the -a/--text option, export will avoid generating diffs
1984 Without the -a/--text option, export will avoid generating diffs
1985 of files it detects as binary. With -a, export will generate a
1985 of files it detects as binary. With -a, export will generate a
1986 diff anyway, probably with undesirable results.
1986 diff anyway, probably with undesirable results.
1987
1987
1988 Use the -g/--git option to generate diffs in the git extended diff
1988 Use the -g/--git option to generate diffs in the git extended diff
1989 format. See :hg:`help diffs` for more information.
1989 format. See :hg:`help diffs` for more information.
1990
1990
1991 With the --switch-parent option, the diff will be against the
1991 With the --switch-parent option, the diff will be against the
1992 second parent. It can be useful to review a merge.
1992 second parent. It can be useful to review a merge.
1993
1993
1994 .. container:: verbose
1994 .. container:: verbose
1995
1995
1996 Examples:
1996 Examples:
1997
1997
1998 - use export and import to transplant a bugfix to the current
1998 - use export and import to transplant a bugfix to the current
1999 branch::
1999 branch::
2000
2000
2001 hg export -r 9353 | hg import -
2001 hg export -r 9353 | hg import -
2002
2002
2003 - export all the changesets between two revisions to a file with
2003 - export all the changesets between two revisions to a file with
2004 rename information::
2004 rename information::
2005
2005
2006 hg export --git -r 123:150 > changes.txt
2006 hg export --git -r 123:150 > changes.txt
2007
2007
2008 - split outgoing changes into a series of patches with
2008 - split outgoing changes into a series of patches with
2009 descriptive names::
2009 descriptive names::
2010
2010
2011 hg export -r "outgoing()" -o "%n-%m.patch"
2011 hg export -r "outgoing()" -o "%n-%m.patch"
2012
2012
2013 Returns 0 on success.
2013 Returns 0 on success.
2014 """
2014 """
2015 changesets += tuple(opts.get('rev', []))
2015 changesets += tuple(opts.get('rev', []))
2016 if not changesets:
2016 if not changesets:
2017 changesets = ['.']
2017 changesets = ['.']
2018 revs = scmutil.revrange(repo, changesets)
2018 revs = scmutil.revrange(repo, changesets)
2019 if not revs:
2019 if not revs:
2020 raise error.Abort(_("export requires at least one changeset"))
2020 raise error.Abort(_("export requires at least one changeset"))
2021 if len(revs) > 1:
2021 if len(revs) > 1:
2022 ui.note(_('exporting patches:\n'))
2022 ui.note(_('exporting patches:\n'))
2023 else:
2023 else:
2024 ui.note(_('exporting patch:\n'))
2024 ui.note(_('exporting patch:\n'))
2025 ui.pager('export')
2025 ui.pager('export')
2026 cmdutil.export(repo, revs, template=opts.get('output'),
2026 cmdutil.export(repo, revs, template=opts.get('output'),
2027 switch_parent=opts.get('switch_parent'),
2027 switch_parent=opts.get('switch_parent'),
2028 opts=patch.diffallopts(ui, opts))
2028 opts=patch.diffallopts(ui, opts))
2029
2029
2030 @command('files',
2030 @command('files',
2031 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
2031 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
2032 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
2032 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
2033 ] + walkopts + formatteropts + subrepoopts,
2033 ] + walkopts + formatteropts + subrepoopts,
2034 _('[OPTION]... [FILE]...'))
2034 _('[OPTION]... [FILE]...'))
2035 def files(ui, repo, *pats, **opts):
2035 def files(ui, repo, *pats, **opts):
2036 """list tracked files
2036 """list tracked files
2037
2037
2038 Print files under Mercurial control in the working directory or
2038 Print files under Mercurial control in the working directory or
2039 specified revision for given files (excluding removed files).
2039 specified revision for given files (excluding removed files).
2040 Files can be specified as filenames or filesets.
2040 Files can be specified as filenames or filesets.
2041
2041
2042 If no files are given to match, this command prints the names
2042 If no files are given to match, this command prints the names
2043 of all files under Mercurial control.
2043 of all files under Mercurial control.
2044
2044
2045 .. container:: verbose
2045 .. container:: verbose
2046
2046
2047 Examples:
2047 Examples:
2048
2048
2049 - list all files under the current directory::
2049 - list all files under the current directory::
2050
2050
2051 hg files .
2051 hg files .
2052
2052
2053 - shows sizes and flags for current revision::
2053 - shows sizes and flags for current revision::
2054
2054
2055 hg files -vr .
2055 hg files -vr .
2056
2056
2057 - list all files named README::
2057 - list all files named README::
2058
2058
2059 hg files -I "**/README"
2059 hg files -I "**/README"
2060
2060
2061 - list all binary files::
2061 - list all binary files::
2062
2062
2063 hg files "set:binary()"
2063 hg files "set:binary()"
2064
2064
2065 - find files containing a regular expression::
2065 - find files containing a regular expression::
2066
2066
2067 hg files "set:grep('bob')"
2067 hg files "set:grep('bob')"
2068
2068
2069 - search tracked file contents with xargs and grep::
2069 - search tracked file contents with xargs and grep::
2070
2070
2071 hg files -0 | xargs -0 grep foo
2071 hg files -0 | xargs -0 grep foo
2072
2072
2073 See :hg:`help patterns` and :hg:`help filesets` for more information
2073 See :hg:`help patterns` and :hg:`help filesets` for more information
2074 on specifying file patterns.
2074 on specifying file patterns.
2075
2075
2076 Returns 0 if a match is found, 1 otherwise.
2076 Returns 0 if a match is found, 1 otherwise.
2077
2077
2078 """
2078 """
2079 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2079 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2080
2080
2081 end = '\n'
2081 end = '\n'
2082 if opts.get('print0'):
2082 if opts.get('print0'):
2083 end = '\0'
2083 end = '\0'
2084 fmt = '%s' + end
2084 fmt = '%s' + end
2085
2085
2086 m = scmutil.match(ctx, pats, opts)
2086 m = scmutil.match(ctx, pats, opts)
2087 with ui.formatter('files', opts) as fm:
2087 with ui.formatter('files', opts) as fm:
2088 return cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
2088 return cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
2089
2089
2090 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
2090 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
2091 def forget(ui, repo, *pats, **opts):
2091 def forget(ui, repo, *pats, **opts):
2092 """forget the specified files on the next commit
2092 """forget the specified files on the next commit
2093
2093
2094 Mark the specified files so they will no longer be tracked
2094 Mark the specified files so they will no longer be tracked
2095 after the next commit.
2095 after the next commit.
2096
2096
2097 This only removes files from the current branch, not from the
2097 This only removes files from the current branch, not from the
2098 entire project history, and it does not delete them from the
2098 entire project history, and it does not delete them from the
2099 working directory.
2099 working directory.
2100
2100
2101 To delete the file from the working directory, see :hg:`remove`.
2101 To delete the file from the working directory, see :hg:`remove`.
2102
2102
2103 To undo a forget before the next commit, see :hg:`add`.
2103 To undo a forget before the next commit, see :hg:`add`.
2104
2104
2105 .. container:: verbose
2105 .. container:: verbose
2106
2106
2107 Examples:
2107 Examples:
2108
2108
2109 - forget newly-added binary files::
2109 - forget newly-added binary files::
2110
2110
2111 hg forget "set:added() and binary()"
2111 hg forget "set:added() and binary()"
2112
2112
2113 - forget files that would be excluded by .hgignore::
2113 - forget files that would be excluded by .hgignore::
2114
2114
2115 hg forget "set:hgignore()"
2115 hg forget "set:hgignore()"
2116
2116
2117 Returns 0 on success.
2117 Returns 0 on success.
2118 """
2118 """
2119
2119
2120 if not pats:
2120 if not pats:
2121 raise error.Abort(_('no files specified'))
2121 raise error.Abort(_('no files specified'))
2122
2122
2123 m = scmutil.match(repo[None], pats, opts)
2123 m = scmutil.match(repo[None], pats, opts)
2124 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2124 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2125 return rejected and 1 or 0
2125 return rejected and 1 or 0
2126
2126
2127 @command(
2127 @command(
2128 'graft',
2128 'graft',
2129 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2129 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2130 ('c', 'continue', False, _('resume interrupted graft')),
2130 ('c', 'continue', False, _('resume interrupted graft')),
2131 ('e', 'edit', False, _('invoke editor on commit messages')),
2131 ('e', 'edit', False, _('invoke editor on commit messages')),
2132 ('', 'log', None, _('append graft info to log message')),
2132 ('', 'log', None, _('append graft info to log message')),
2133 ('f', 'force', False, _('force graft')),
2133 ('f', 'force', False, _('force graft')),
2134 ('D', 'currentdate', False,
2134 ('D', 'currentdate', False,
2135 _('record the current date as commit date')),
2135 _('record the current date as commit date')),
2136 ('U', 'currentuser', False,
2136 ('U', 'currentuser', False,
2137 _('record the current user as committer'), _('DATE'))]
2137 _('record the current user as committer'), _('DATE'))]
2138 + commitopts2 + mergetoolopts + dryrunopts,
2138 + commitopts2 + mergetoolopts + dryrunopts,
2139 _('[OPTION]... [-r REV]... REV...'))
2139 _('[OPTION]... [-r REV]... REV...'))
2140 def graft(ui, repo, *revs, **opts):
2140 def graft(ui, repo, *revs, **opts):
2141 '''copy changes from other branches onto the current branch
2141 '''copy changes from other branches onto the current branch
2142
2142
2143 This command uses Mercurial's merge logic to copy individual
2143 This command uses Mercurial's merge logic to copy individual
2144 changes from other branches without merging branches in the
2144 changes from other branches without merging branches in the
2145 history graph. This is sometimes known as 'backporting' or
2145 history graph. This is sometimes known as 'backporting' or
2146 'cherry-picking'. By default, graft will copy user, date, and
2146 'cherry-picking'. By default, graft will copy user, date, and
2147 description from the source changesets.
2147 description from the source changesets.
2148
2148
2149 Changesets that are ancestors of the current revision, that have
2149 Changesets that are ancestors of the current revision, that have
2150 already been grafted, or that are merges will be skipped.
2150 already been grafted, or that are merges will be skipped.
2151
2151
2152 If --log is specified, log messages will have a comment appended
2152 If --log is specified, log messages will have a comment appended
2153 of the form::
2153 of the form::
2154
2154
2155 (grafted from CHANGESETHASH)
2155 (grafted from CHANGESETHASH)
2156
2156
2157 If --force is specified, revisions will be grafted even if they
2157 If --force is specified, revisions will be grafted even if they
2158 are already ancestors of or have been grafted to the destination.
2158 are already ancestors of or have been grafted to the destination.
2159 This is useful when the revisions have since been backed out.
2159 This is useful when the revisions have since been backed out.
2160
2160
2161 If a graft merge results in conflicts, the graft process is
2161 If a graft merge results in conflicts, the graft process is
2162 interrupted so that the current merge can be manually resolved.
2162 interrupted so that the current merge can be manually resolved.
2163 Once all conflicts are addressed, the graft process can be
2163 Once all conflicts are addressed, the graft process can be
2164 continued with the -c/--continue option.
2164 continued with the -c/--continue option.
2165
2165
2166 .. note::
2166 .. note::
2167
2167
2168 The -c/--continue option does not reapply earlier options, except
2168 The -c/--continue option does not reapply earlier options, except
2169 for --force.
2169 for --force.
2170
2170
2171 .. container:: verbose
2171 .. container:: verbose
2172
2172
2173 Examples:
2173 Examples:
2174
2174
2175 - copy a single change to the stable branch and edit its description::
2175 - copy a single change to the stable branch and edit its description::
2176
2176
2177 hg update stable
2177 hg update stable
2178 hg graft --edit 9393
2178 hg graft --edit 9393
2179
2179
2180 - graft a range of changesets with one exception, updating dates::
2180 - graft a range of changesets with one exception, updating dates::
2181
2181
2182 hg graft -D "2085::2093 and not 2091"
2182 hg graft -D "2085::2093 and not 2091"
2183
2183
2184 - continue a graft after resolving conflicts::
2184 - continue a graft after resolving conflicts::
2185
2185
2186 hg graft -c
2186 hg graft -c
2187
2187
2188 - show the source of a grafted changeset::
2188 - show the source of a grafted changeset::
2189
2189
2190 hg log --debug -r .
2190 hg log --debug -r .
2191
2191
2192 - show revisions sorted by date::
2192 - show revisions sorted by date::
2193
2193
2194 hg log -r "sort(all(), date)"
2194 hg log -r "sort(all(), date)"
2195
2195
2196 See :hg:`help revisions` for more about specifying revisions.
2196 See :hg:`help revisions` for more about specifying revisions.
2197
2197
2198 Returns 0 on successful completion.
2198 Returns 0 on successful completion.
2199 '''
2199 '''
2200 with repo.wlock():
2200 with repo.wlock():
2201 return _dograft(ui, repo, *revs, **opts)
2201 return _dograft(ui, repo, *revs, **opts)
2202
2202
2203 def _dograft(ui, repo, *revs, **opts):
2203 def _dograft(ui, repo, *revs, **opts):
2204 if revs and opts.get('rev'):
2204 if revs and opts.get('rev'):
2205 ui.warn(_('warning: inconsistent use of --rev might give unexpected '
2205 ui.warn(_('warning: inconsistent use of --rev might give unexpected '
2206 'revision ordering!\n'))
2206 'revision ordering!\n'))
2207
2207
2208 revs = list(revs)
2208 revs = list(revs)
2209 revs.extend(opts.get('rev'))
2209 revs.extend(opts.get('rev'))
2210
2210
2211 if not opts.get('user') and opts.get('currentuser'):
2211 if not opts.get('user') and opts.get('currentuser'):
2212 opts['user'] = ui.username()
2212 opts['user'] = ui.username()
2213 if not opts.get('date') and opts.get('currentdate'):
2213 if not opts.get('date') and opts.get('currentdate'):
2214 opts['date'] = "%d %d" % util.makedate()
2214 opts['date'] = "%d %d" % util.makedate()
2215
2215
2216 editor = cmdutil.getcommiteditor(editform='graft', **opts)
2216 editor = cmdutil.getcommiteditor(editform='graft', **opts)
2217
2217
2218 cont = False
2218 cont = False
2219 if opts.get('continue'):
2219 if opts.get('continue'):
2220 cont = True
2220 cont = True
2221 if revs:
2221 if revs:
2222 raise error.Abort(_("can't specify --continue and revisions"))
2222 raise error.Abort(_("can't specify --continue and revisions"))
2223 # read in unfinished revisions
2223 # read in unfinished revisions
2224 try:
2224 try:
2225 nodes = repo.vfs.read('graftstate').splitlines()
2225 nodes = repo.vfs.read('graftstate').splitlines()
2226 revs = [repo[node].rev() for node in nodes]
2226 revs = [repo[node].rev() for node in nodes]
2227 except IOError as inst:
2227 except IOError as inst:
2228 if inst.errno != errno.ENOENT:
2228 if inst.errno != errno.ENOENT:
2229 raise
2229 raise
2230 cmdutil.wrongtooltocontinue(repo, _('graft'))
2230 cmdutil.wrongtooltocontinue(repo, _('graft'))
2231 else:
2231 else:
2232 cmdutil.checkunfinished(repo)
2232 cmdutil.checkunfinished(repo)
2233 cmdutil.bailifchanged(repo)
2233 cmdutil.bailifchanged(repo)
2234 if not revs:
2234 if not revs:
2235 raise error.Abort(_('no revisions specified'))
2235 raise error.Abort(_('no revisions specified'))
2236 revs = scmutil.revrange(repo, revs)
2236 revs = scmutil.revrange(repo, revs)
2237
2237
2238 skipped = set()
2238 skipped = set()
2239 # check for merges
2239 # check for merges
2240 for rev in repo.revs('%ld and merge()', revs):
2240 for rev in repo.revs('%ld and merge()', revs):
2241 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2241 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2242 skipped.add(rev)
2242 skipped.add(rev)
2243 revs = [r for r in revs if r not in skipped]
2243 revs = [r for r in revs if r not in skipped]
2244 if not revs:
2244 if not revs:
2245 return -1
2245 return -1
2246
2246
2247 # Don't check in the --continue case, in effect retaining --force across
2247 # Don't check in the --continue case, in effect retaining --force across
2248 # --continues. That's because without --force, any revisions we decided to
2248 # --continues. That's because without --force, any revisions we decided to
2249 # skip would have been filtered out here, so they wouldn't have made their
2249 # skip would have been filtered out here, so they wouldn't have made their
2250 # way to the graftstate. With --force, any revisions we would have otherwise
2250 # way to the graftstate. With --force, any revisions we would have otherwise
2251 # skipped would not have been filtered out, and if they hadn't been applied
2251 # skipped would not have been filtered out, and if they hadn't been applied
2252 # already, they'd have been in the graftstate.
2252 # already, they'd have been in the graftstate.
2253 if not (cont or opts.get('force')):
2253 if not (cont or opts.get('force')):
2254 # check for ancestors of dest branch
2254 # check for ancestors of dest branch
2255 crev = repo['.'].rev()
2255 crev = repo['.'].rev()
2256 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2256 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2257 # XXX make this lazy in the future
2257 # XXX make this lazy in the future
2258 # don't mutate while iterating, create a copy
2258 # don't mutate while iterating, create a copy
2259 for rev in list(revs):
2259 for rev in list(revs):
2260 if rev in ancestors:
2260 if rev in ancestors:
2261 ui.warn(_('skipping ancestor revision %d:%s\n') %
2261 ui.warn(_('skipping ancestor revision %d:%s\n') %
2262 (rev, repo[rev]))
2262 (rev, repo[rev]))
2263 # XXX remove on list is slow
2263 # XXX remove on list is slow
2264 revs.remove(rev)
2264 revs.remove(rev)
2265 if not revs:
2265 if not revs:
2266 return -1
2266 return -1
2267
2267
2268 # analyze revs for earlier grafts
2268 # analyze revs for earlier grafts
2269 ids = {}
2269 ids = {}
2270 for ctx in repo.set("%ld", revs):
2270 for ctx in repo.set("%ld", revs):
2271 ids[ctx.hex()] = ctx.rev()
2271 ids[ctx.hex()] = ctx.rev()
2272 n = ctx.extra().get('source')
2272 n = ctx.extra().get('source')
2273 if n:
2273 if n:
2274 ids[n] = ctx.rev()
2274 ids[n] = ctx.rev()
2275
2275
2276 # check ancestors for earlier grafts
2276 # check ancestors for earlier grafts
2277 ui.debug('scanning for duplicate grafts\n')
2277 ui.debug('scanning for duplicate grafts\n')
2278
2278
2279 for rev in repo.changelog.findmissingrevs(revs, [crev]):
2279 for rev in repo.changelog.findmissingrevs(revs, [crev]):
2280 ctx = repo[rev]
2280 ctx = repo[rev]
2281 n = ctx.extra().get('source')
2281 n = ctx.extra().get('source')
2282 if n in ids:
2282 if n in ids:
2283 try:
2283 try:
2284 r = repo[n].rev()
2284 r = repo[n].rev()
2285 except error.RepoLookupError:
2285 except error.RepoLookupError:
2286 r = None
2286 r = None
2287 if r in revs:
2287 if r in revs:
2288 ui.warn(_('skipping revision %d:%s '
2288 ui.warn(_('skipping revision %d:%s '
2289 '(already grafted to %d:%s)\n')
2289 '(already grafted to %d:%s)\n')
2290 % (r, repo[r], rev, ctx))
2290 % (r, repo[r], rev, ctx))
2291 revs.remove(r)
2291 revs.remove(r)
2292 elif ids[n] in revs:
2292 elif ids[n] in revs:
2293 if r is None:
2293 if r is None:
2294 ui.warn(_('skipping already grafted revision %d:%s '
2294 ui.warn(_('skipping already grafted revision %d:%s '
2295 '(%d:%s also has unknown origin %s)\n')
2295 '(%d:%s also has unknown origin %s)\n')
2296 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
2296 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
2297 else:
2297 else:
2298 ui.warn(_('skipping already grafted revision %d:%s '
2298 ui.warn(_('skipping already grafted revision %d:%s '
2299 '(%d:%s also has origin %d:%s)\n')
2299 '(%d:%s also has origin %d:%s)\n')
2300 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
2300 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
2301 revs.remove(ids[n])
2301 revs.remove(ids[n])
2302 elif ctx.hex() in ids:
2302 elif ctx.hex() in ids:
2303 r = ids[ctx.hex()]
2303 r = ids[ctx.hex()]
2304 ui.warn(_('skipping already grafted revision %d:%s '
2304 ui.warn(_('skipping already grafted revision %d:%s '
2305 '(was grafted from %d:%s)\n') %
2305 '(was grafted from %d:%s)\n') %
2306 (r, repo[r], rev, ctx))
2306 (r, repo[r], rev, ctx))
2307 revs.remove(r)
2307 revs.remove(r)
2308 if not revs:
2308 if not revs:
2309 return -1
2309 return -1
2310
2310
2311 for pos, ctx in enumerate(repo.set("%ld", revs)):
2311 for pos, ctx in enumerate(repo.set("%ld", revs)):
2312 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
2312 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
2313 ctx.description().split('\n', 1)[0])
2313 ctx.description().split('\n', 1)[0])
2314 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
2314 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
2315 if names:
2315 if names:
2316 desc += ' (%s)' % ' '.join(names)
2316 desc += ' (%s)' % ' '.join(names)
2317 ui.status(_('grafting %s\n') % desc)
2317 ui.status(_('grafting %s\n') % desc)
2318 if opts.get('dry_run'):
2318 if opts.get('dry_run'):
2319 continue
2319 continue
2320
2320
2321 source = ctx.extra().get('source')
2321 source = ctx.extra().get('source')
2322 extra = {}
2322 extra = {}
2323 if source:
2323 if source:
2324 extra['source'] = source
2324 extra['source'] = source
2325 extra['intermediate-source'] = ctx.hex()
2325 extra['intermediate-source'] = ctx.hex()
2326 else:
2326 else:
2327 extra['source'] = ctx.hex()
2327 extra['source'] = ctx.hex()
2328 user = ctx.user()
2328 user = ctx.user()
2329 if opts.get('user'):
2329 if opts.get('user'):
2330 user = opts['user']
2330 user = opts['user']
2331 date = ctx.date()
2331 date = ctx.date()
2332 if opts.get('date'):
2332 if opts.get('date'):
2333 date = opts['date']
2333 date = opts['date']
2334 message = ctx.description()
2334 message = ctx.description()
2335 if opts.get('log'):
2335 if opts.get('log'):
2336 message += '\n(grafted from %s)' % ctx.hex()
2336 message += '\n(grafted from %s)' % ctx.hex()
2337
2337
2338 # we don't merge the first commit when continuing
2338 # we don't merge the first commit when continuing
2339 if not cont:
2339 if not cont:
2340 # perform the graft merge with p1(rev) as 'ancestor'
2340 # perform the graft merge with p1(rev) as 'ancestor'
2341 try:
2341 try:
2342 # ui.forcemerge is an internal variable, do not document
2342 # ui.forcemerge is an internal variable, do not document
2343 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
2343 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
2344 'graft')
2344 'graft')
2345 stats = mergemod.graft(repo, ctx, ctx.p1(),
2345 stats = mergemod.graft(repo, ctx, ctx.p1(),
2346 ['local', 'graft'])
2346 ['local', 'graft'])
2347 finally:
2347 finally:
2348 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
2348 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
2349 # report any conflicts
2349 # report any conflicts
2350 if stats and stats[3] > 0:
2350 if stats and stats[3] > 0:
2351 # write out state for --continue
2351 # write out state for --continue
2352 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2352 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2353 repo.vfs.write('graftstate', ''.join(nodelines))
2353 repo.vfs.write('graftstate', ''.join(nodelines))
2354 extra = ''
2354 extra = ''
2355 if opts.get('user'):
2355 if opts.get('user'):
2356 extra += ' --user %s' % util.shellquote(opts['user'])
2356 extra += ' --user %s' % util.shellquote(opts['user'])
2357 if opts.get('date'):
2357 if opts.get('date'):
2358 extra += ' --date %s' % util.shellquote(opts['date'])
2358 extra += ' --date %s' % util.shellquote(opts['date'])
2359 if opts.get('log'):
2359 if opts.get('log'):
2360 extra += ' --log'
2360 extra += ' --log'
2361 hint=_("use 'hg resolve' and 'hg graft --continue%s'") % extra
2361 hint=_("use 'hg resolve' and 'hg graft --continue%s'") % extra
2362 raise error.Abort(
2362 raise error.Abort(
2363 _("unresolved conflicts, can't continue"),
2363 _("unresolved conflicts, can't continue"),
2364 hint=hint)
2364 hint=hint)
2365 else:
2365 else:
2366 cont = False
2366 cont = False
2367
2367
2368 # commit
2368 # commit
2369 node = repo.commit(text=message, user=user,
2369 node = repo.commit(text=message, user=user,
2370 date=date, extra=extra, editor=editor)
2370 date=date, extra=extra, editor=editor)
2371 if node is None:
2371 if node is None:
2372 ui.warn(
2372 ui.warn(
2373 _('note: graft of %d:%s created no changes to commit\n') %
2373 _('note: graft of %d:%s created no changes to commit\n') %
2374 (ctx.rev(), ctx))
2374 (ctx.rev(), ctx))
2375
2375
2376 # remove state when we complete successfully
2376 # remove state when we complete successfully
2377 if not opts.get('dry_run'):
2377 if not opts.get('dry_run'):
2378 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
2378 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
2379
2379
2380 return 0
2380 return 0
2381
2381
2382 @command('grep',
2382 @command('grep',
2383 [('0', 'print0', None, _('end fields with NUL')),
2383 [('0', 'print0', None, _('end fields with NUL')),
2384 ('', 'all', None, _('print all revisions that match')),
2384 ('', 'all', None, _('print all revisions that match')),
2385 ('a', 'text', None, _('treat all files as text')),
2385 ('a', 'text', None, _('treat all files as text')),
2386 ('f', 'follow', None,
2386 ('f', 'follow', None,
2387 _('follow changeset history,'
2387 _('follow changeset history,'
2388 ' or file history across copies and renames')),
2388 ' or file history across copies and renames')),
2389 ('i', 'ignore-case', None, _('ignore case when matching')),
2389 ('i', 'ignore-case', None, _('ignore case when matching')),
2390 ('l', 'files-with-matches', None,
2390 ('l', 'files-with-matches', None,
2391 _('print only filenames and revisions that match')),
2391 _('print only filenames and revisions that match')),
2392 ('n', 'line-number', None, _('print matching line numbers')),
2392 ('n', 'line-number', None, _('print matching line numbers')),
2393 ('r', 'rev', [],
2393 ('r', 'rev', [],
2394 _('only search files changed within revision range'), _('REV')),
2394 _('only search files changed within revision range'), _('REV')),
2395 ('u', 'user', None, _('list the author (long with -v)')),
2395 ('u', 'user', None, _('list the author (long with -v)')),
2396 ('d', 'date', None, _('list the date (short with -q)')),
2396 ('d', 'date', None, _('list the date (short with -q)')),
2397 ] + formatteropts + walkopts,
2397 ] + formatteropts + walkopts,
2398 _('[OPTION]... PATTERN [FILE]...'),
2398 _('[OPTION]... PATTERN [FILE]...'),
2399 inferrepo=True)
2399 inferrepo=True)
2400 def grep(ui, repo, pattern, *pats, **opts):
2400 def grep(ui, repo, pattern, *pats, **opts):
2401 """search revision history for a pattern in specified files
2401 """search revision history for a pattern in specified files
2402
2402
2403 Search revision history for a regular expression in the specified
2403 Search revision history for a regular expression in the specified
2404 files or the entire project.
2404 files or the entire project.
2405
2405
2406 By default, grep prints the most recent revision number for each
2406 By default, grep prints the most recent revision number for each
2407 file in which it finds a match. To get it to print every revision
2407 file in which it finds a match. To get it to print every revision
2408 that contains a change in match status ("-" for a match that becomes
2408 that contains a change in match status ("-" for a match that becomes
2409 a non-match, or "+" for a non-match that becomes a match), use the
2409 a non-match, or "+" for a non-match that becomes a match), use the
2410 --all flag.
2410 --all flag.
2411
2411
2412 PATTERN can be any Python (roughly Perl-compatible) regular
2412 PATTERN can be any Python (roughly Perl-compatible) regular
2413 expression.
2413 expression.
2414
2414
2415 If no FILEs are specified (and -f/--follow isn't set), all files in
2415 If no FILEs are specified (and -f/--follow isn't set), all files in
2416 the repository are searched, including those that don't exist in the
2416 the repository are searched, including those that don't exist in the
2417 current branch or have been deleted in a prior changeset.
2417 current branch or have been deleted in a prior changeset.
2418
2418
2419 Returns 0 if a match is found, 1 otherwise.
2419 Returns 0 if a match is found, 1 otherwise.
2420 """
2420 """
2421 reflags = re.M
2421 reflags = re.M
2422 if opts.get('ignore_case'):
2422 if opts.get('ignore_case'):
2423 reflags |= re.I
2423 reflags |= re.I
2424 try:
2424 try:
2425 regexp = util.re.compile(pattern, reflags)
2425 regexp = util.re.compile(pattern, reflags)
2426 except re.error as inst:
2426 except re.error as inst:
2427 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2427 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2428 return 1
2428 return 1
2429 sep, eol = ':', '\n'
2429 sep, eol = ':', '\n'
2430 if opts.get('print0'):
2430 if opts.get('print0'):
2431 sep = eol = '\0'
2431 sep = eol = '\0'
2432
2432
2433 getfile = util.lrucachefunc(repo.file)
2433 getfile = util.lrucachefunc(repo.file)
2434
2434
2435 def matchlines(body):
2435 def matchlines(body):
2436 begin = 0
2436 begin = 0
2437 linenum = 0
2437 linenum = 0
2438 while begin < len(body):
2438 while begin < len(body):
2439 match = regexp.search(body, begin)
2439 match = regexp.search(body, begin)
2440 if not match:
2440 if not match:
2441 break
2441 break
2442 mstart, mend = match.span()
2442 mstart, mend = match.span()
2443 linenum += body.count('\n', begin, mstart) + 1
2443 linenum += body.count('\n', begin, mstart) + 1
2444 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2444 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2445 begin = body.find('\n', mend) + 1 or len(body) + 1
2445 begin = body.find('\n', mend) + 1 or len(body) + 1
2446 lend = begin - 1
2446 lend = begin - 1
2447 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2447 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2448
2448
2449 class linestate(object):
2449 class linestate(object):
2450 def __init__(self, line, linenum, colstart, colend):
2450 def __init__(self, line, linenum, colstart, colend):
2451 self.line = line
2451 self.line = line
2452 self.linenum = linenum
2452 self.linenum = linenum
2453 self.colstart = colstart
2453 self.colstart = colstart
2454 self.colend = colend
2454 self.colend = colend
2455
2455
2456 def __hash__(self):
2456 def __hash__(self):
2457 return hash((self.linenum, self.line))
2457 return hash((self.linenum, self.line))
2458
2458
2459 def __eq__(self, other):
2459 def __eq__(self, other):
2460 return self.line == other.line
2460 return self.line == other.line
2461
2461
2462 def findpos(self):
2462 def findpos(self):
2463 """Iterate all (start, end) indices of matches"""
2463 """Iterate all (start, end) indices of matches"""
2464 yield self.colstart, self.colend
2464 yield self.colstart, self.colend
2465 p = self.colend
2465 p = self.colend
2466 while p < len(self.line):
2466 while p < len(self.line):
2467 m = regexp.search(self.line, p)
2467 m = regexp.search(self.line, p)
2468 if not m:
2468 if not m:
2469 break
2469 break
2470 yield m.span()
2470 yield m.span()
2471 p = m.end()
2471 p = m.end()
2472
2472
2473 matches = {}
2473 matches = {}
2474 copies = {}
2474 copies = {}
2475 def grepbody(fn, rev, body):
2475 def grepbody(fn, rev, body):
2476 matches[rev].setdefault(fn, [])
2476 matches[rev].setdefault(fn, [])
2477 m = matches[rev][fn]
2477 m = matches[rev][fn]
2478 for lnum, cstart, cend, line in matchlines(body):
2478 for lnum, cstart, cend, line in matchlines(body):
2479 s = linestate(line, lnum, cstart, cend)
2479 s = linestate(line, lnum, cstart, cend)
2480 m.append(s)
2480 m.append(s)
2481
2481
2482 def difflinestates(a, b):
2482 def difflinestates(a, b):
2483 sm = difflib.SequenceMatcher(None, a, b)
2483 sm = difflib.SequenceMatcher(None, a, b)
2484 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2484 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2485 if tag == 'insert':
2485 if tag == 'insert':
2486 for i in xrange(blo, bhi):
2486 for i in xrange(blo, bhi):
2487 yield ('+', b[i])
2487 yield ('+', b[i])
2488 elif tag == 'delete':
2488 elif tag == 'delete':
2489 for i in xrange(alo, ahi):
2489 for i in xrange(alo, ahi):
2490 yield ('-', a[i])
2490 yield ('-', a[i])
2491 elif tag == 'replace':
2491 elif tag == 'replace':
2492 for i in xrange(alo, ahi):
2492 for i in xrange(alo, ahi):
2493 yield ('-', a[i])
2493 yield ('-', a[i])
2494 for i in xrange(blo, bhi):
2494 for i in xrange(blo, bhi):
2495 yield ('+', b[i])
2495 yield ('+', b[i])
2496
2496
2497 def display(fm, fn, ctx, pstates, states):
2497 def display(fm, fn, ctx, pstates, states):
2498 rev = ctx.rev()
2498 rev = ctx.rev()
2499 if fm.isplain():
2499 if fm.isplain():
2500 formatuser = ui.shortuser
2500 formatuser = ui.shortuser
2501 else:
2501 else:
2502 formatuser = str
2502 formatuser = str
2503 if ui.quiet:
2503 if ui.quiet:
2504 datefmt = '%Y-%m-%d'
2504 datefmt = '%Y-%m-%d'
2505 else:
2505 else:
2506 datefmt = '%a %b %d %H:%M:%S %Y %1%2'
2506 datefmt = '%a %b %d %H:%M:%S %Y %1%2'
2507 found = False
2507 found = False
2508 @util.cachefunc
2508 @util.cachefunc
2509 def binary():
2509 def binary():
2510 flog = getfile(fn)
2510 flog = getfile(fn)
2511 return util.binary(flog.read(ctx.filenode(fn)))
2511 return util.binary(flog.read(ctx.filenode(fn)))
2512
2512
2513 fieldnamemap = {'filename': 'file', 'linenumber': 'line_number'}
2513 fieldnamemap = {'filename': 'file', 'linenumber': 'line_number'}
2514 if opts.get('all'):
2514 if opts.get('all'):
2515 iter = difflinestates(pstates, states)
2515 iter = difflinestates(pstates, states)
2516 else:
2516 else:
2517 iter = [('', l) for l in states]
2517 iter = [('', l) for l in states]
2518 for change, l in iter:
2518 for change, l in iter:
2519 fm.startitem()
2519 fm.startitem()
2520 fm.data(node=fm.hexfunc(ctx.node()))
2520 fm.data(node=fm.hexfunc(ctx.node()))
2521 cols = [
2521 cols = [
2522 ('filename', fn, True),
2522 ('filename', fn, True),
2523 ('rev', rev, True),
2523 ('rev', rev, True),
2524 ('linenumber', l.linenum, opts.get('line_number')),
2524 ('linenumber', l.linenum, opts.get('line_number')),
2525 ]
2525 ]
2526 if opts.get('all'):
2526 if opts.get('all'):
2527 cols.append(('change', change, True))
2527 cols.append(('change', change, True))
2528 cols.extend([
2528 cols.extend([
2529 ('user', formatuser(ctx.user()), opts.get('user')),
2529 ('user', formatuser(ctx.user()), opts.get('user')),
2530 ('date', fm.formatdate(ctx.date(), datefmt), opts.get('date')),
2530 ('date', fm.formatdate(ctx.date(), datefmt), opts.get('date')),
2531 ])
2531 ])
2532 lastcol = next(name for name, data, cond in reversed(cols) if cond)
2532 lastcol = next(name for name, data, cond in reversed(cols) if cond)
2533 for name, data, cond in cols:
2533 for name, data, cond in cols:
2534 field = fieldnamemap.get(name, name)
2534 field = fieldnamemap.get(name, name)
2535 fm.condwrite(cond, field, '%s', data, label='grep.%s' % name)
2535 fm.condwrite(cond, field, '%s', data, label='grep.%s' % name)
2536 if cond and name != lastcol:
2536 if cond and name != lastcol:
2537 fm.plain(sep, label='grep.sep')
2537 fm.plain(sep, label='grep.sep')
2538 if not opts.get('files_with_matches'):
2538 if not opts.get('files_with_matches'):
2539 fm.plain(sep, label='grep.sep')
2539 fm.plain(sep, label='grep.sep')
2540 if not opts.get('text') and binary():
2540 if not opts.get('text') and binary():
2541 fm.plain(_(" Binary file matches"))
2541 fm.plain(_(" Binary file matches"))
2542 else:
2542 else:
2543 displaymatches(fm.nested('texts'), l)
2543 displaymatches(fm.nested('texts'), l)
2544 fm.plain(eol)
2544 fm.plain(eol)
2545 found = True
2545 found = True
2546 if opts.get('files_with_matches'):
2546 if opts.get('files_with_matches'):
2547 break
2547 break
2548 return found
2548 return found
2549
2549
2550 def displaymatches(fm, l):
2550 def displaymatches(fm, l):
2551 p = 0
2551 p = 0
2552 for s, e in l.findpos():
2552 for s, e in l.findpos():
2553 if p < s:
2553 if p < s:
2554 fm.startitem()
2554 fm.startitem()
2555 fm.write('text', '%s', l.line[p:s])
2555 fm.write('text', '%s', l.line[p:s])
2556 fm.data(matched=False)
2556 fm.data(matched=False)
2557 fm.startitem()
2557 fm.startitem()
2558 fm.write('text', '%s', l.line[s:e], label='grep.match')
2558 fm.write('text', '%s', l.line[s:e], label='grep.match')
2559 fm.data(matched=True)
2559 fm.data(matched=True)
2560 p = e
2560 p = e
2561 if p < len(l.line):
2561 if p < len(l.line):
2562 fm.startitem()
2562 fm.startitem()
2563 fm.write('text', '%s', l.line[p:])
2563 fm.write('text', '%s', l.line[p:])
2564 fm.data(matched=False)
2564 fm.data(matched=False)
2565 fm.end()
2565 fm.end()
2566
2566
2567 skip = {}
2567 skip = {}
2568 revfiles = {}
2568 revfiles = {}
2569 matchfn = scmutil.match(repo[None], pats, opts)
2569 matchfn = scmutil.match(repo[None], pats, opts)
2570 found = False
2570 found = False
2571 follow = opts.get('follow')
2571 follow = opts.get('follow')
2572
2572
2573 def prep(ctx, fns):
2573 def prep(ctx, fns):
2574 rev = ctx.rev()
2574 rev = ctx.rev()
2575 pctx = ctx.p1()
2575 pctx = ctx.p1()
2576 parent = pctx.rev()
2576 parent = pctx.rev()
2577 matches.setdefault(rev, {})
2577 matches.setdefault(rev, {})
2578 matches.setdefault(parent, {})
2578 matches.setdefault(parent, {})
2579 files = revfiles.setdefault(rev, [])
2579 files = revfiles.setdefault(rev, [])
2580 for fn in fns:
2580 for fn in fns:
2581 flog = getfile(fn)
2581 flog = getfile(fn)
2582 try:
2582 try:
2583 fnode = ctx.filenode(fn)
2583 fnode = ctx.filenode(fn)
2584 except error.LookupError:
2584 except error.LookupError:
2585 continue
2585 continue
2586
2586
2587 copied = flog.renamed(fnode)
2587 copied = flog.renamed(fnode)
2588 copy = follow and copied and copied[0]
2588 copy = follow and copied and copied[0]
2589 if copy:
2589 if copy:
2590 copies.setdefault(rev, {})[fn] = copy
2590 copies.setdefault(rev, {})[fn] = copy
2591 if fn in skip:
2591 if fn in skip:
2592 if copy:
2592 if copy:
2593 skip[copy] = True
2593 skip[copy] = True
2594 continue
2594 continue
2595 files.append(fn)
2595 files.append(fn)
2596
2596
2597 if fn not in matches[rev]:
2597 if fn not in matches[rev]:
2598 grepbody(fn, rev, flog.read(fnode))
2598 grepbody(fn, rev, flog.read(fnode))
2599
2599
2600 pfn = copy or fn
2600 pfn = copy or fn
2601 if pfn not in matches[parent]:
2601 if pfn not in matches[parent]:
2602 try:
2602 try:
2603 fnode = pctx.filenode(pfn)
2603 fnode = pctx.filenode(pfn)
2604 grepbody(pfn, parent, flog.read(fnode))
2604 grepbody(pfn, parent, flog.read(fnode))
2605 except error.LookupError:
2605 except error.LookupError:
2606 pass
2606 pass
2607
2607
2608 fm = ui.formatter('grep', opts)
2608 fm = ui.formatter('grep', opts)
2609 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2609 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2610 rev = ctx.rev()
2610 rev = ctx.rev()
2611 parent = ctx.p1().rev()
2611 parent = ctx.p1().rev()
2612 for fn in sorted(revfiles.get(rev, [])):
2612 for fn in sorted(revfiles.get(rev, [])):
2613 states = matches[rev][fn]
2613 states = matches[rev][fn]
2614 copy = copies.get(rev, {}).get(fn)
2614 copy = copies.get(rev, {}).get(fn)
2615 if fn in skip:
2615 if fn in skip:
2616 if copy:
2616 if copy:
2617 skip[copy] = True
2617 skip[copy] = True
2618 continue
2618 continue
2619 pstates = matches.get(parent, {}).get(copy or fn, [])
2619 pstates = matches.get(parent, {}).get(copy or fn, [])
2620 if pstates or states:
2620 if pstates or states:
2621 r = display(fm, fn, ctx, pstates, states)
2621 r = display(fm, fn, ctx, pstates, states)
2622 found = found or r
2622 found = found or r
2623 if r and not opts.get('all'):
2623 if r and not opts.get('all'):
2624 skip[fn] = True
2624 skip[fn] = True
2625 if copy:
2625 if copy:
2626 skip[copy] = True
2626 skip[copy] = True
2627 del matches[rev]
2627 del matches[rev]
2628 del revfiles[rev]
2628 del revfiles[rev]
2629 fm.end()
2629 fm.end()
2630
2630
2631 return not found
2631 return not found
2632
2632
2633 @command('heads',
2633 @command('heads',
2634 [('r', 'rev', '',
2634 [('r', 'rev', '',
2635 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2635 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2636 ('t', 'topo', False, _('show topological heads only')),
2636 ('t', 'topo', False, _('show topological heads only')),
2637 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2637 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2638 ('c', 'closed', False, _('show normal and closed branch heads')),
2638 ('c', 'closed', False, _('show normal and closed branch heads')),
2639 ] + templateopts,
2639 ] + templateopts,
2640 _('[-ct] [-r STARTREV] [REV]...'))
2640 _('[-ct] [-r STARTREV] [REV]...'))
2641 def heads(ui, repo, *branchrevs, **opts):
2641 def heads(ui, repo, *branchrevs, **opts):
2642 """show branch heads
2642 """show branch heads
2643
2643
2644 With no arguments, show all open branch heads in the repository.
2644 With no arguments, show all open branch heads in the repository.
2645 Branch heads are changesets that have no descendants on the
2645 Branch heads are changesets that have no descendants on the
2646 same branch. They are where development generally takes place and
2646 same branch. They are where development generally takes place and
2647 are the usual targets for update and merge operations.
2647 are the usual targets for update and merge operations.
2648
2648
2649 If one or more REVs are given, only open branch heads on the
2649 If one or more REVs are given, only open branch heads on the
2650 branches associated with the specified changesets are shown. This
2650 branches associated with the specified changesets are shown. This
2651 means that you can use :hg:`heads .` to see the heads on the
2651 means that you can use :hg:`heads .` to see the heads on the
2652 currently checked-out branch.
2652 currently checked-out branch.
2653
2653
2654 If -c/--closed is specified, also show branch heads marked closed
2654 If -c/--closed is specified, also show branch heads marked closed
2655 (see :hg:`commit --close-branch`).
2655 (see :hg:`commit --close-branch`).
2656
2656
2657 If STARTREV is specified, only those heads that are descendants of
2657 If STARTREV is specified, only those heads that are descendants of
2658 STARTREV will be displayed.
2658 STARTREV will be displayed.
2659
2659
2660 If -t/--topo is specified, named branch mechanics will be ignored and only
2660 If -t/--topo is specified, named branch mechanics will be ignored and only
2661 topological heads (changesets with no children) will be shown.
2661 topological heads (changesets with no children) will be shown.
2662
2662
2663 Returns 0 if matching heads are found, 1 if not.
2663 Returns 0 if matching heads are found, 1 if not.
2664 """
2664 """
2665
2665
2666 start = None
2666 start = None
2667 if 'rev' in opts:
2667 if 'rev' in opts:
2668 start = scmutil.revsingle(repo, opts['rev'], None).node()
2668 start = scmutil.revsingle(repo, opts['rev'], None).node()
2669
2669
2670 if opts.get('topo'):
2670 if opts.get('topo'):
2671 heads = [repo[h] for h in repo.heads(start)]
2671 heads = [repo[h] for h in repo.heads(start)]
2672 else:
2672 else:
2673 heads = []
2673 heads = []
2674 for branch in repo.branchmap():
2674 for branch in repo.branchmap():
2675 heads += repo.branchheads(branch, start, opts.get('closed'))
2675 heads += repo.branchheads(branch, start, opts.get('closed'))
2676 heads = [repo[h] for h in heads]
2676 heads = [repo[h] for h in heads]
2677
2677
2678 if branchrevs:
2678 if branchrevs:
2679 branches = set(repo[br].branch() for br in branchrevs)
2679 branches = set(repo[br].branch() for br in branchrevs)
2680 heads = [h for h in heads if h.branch() in branches]
2680 heads = [h for h in heads if h.branch() in branches]
2681
2681
2682 if opts.get('active') and branchrevs:
2682 if opts.get('active') and branchrevs:
2683 dagheads = repo.heads(start)
2683 dagheads = repo.heads(start)
2684 heads = [h for h in heads if h.node() in dagheads]
2684 heads = [h for h in heads if h.node() in dagheads]
2685
2685
2686 if branchrevs:
2686 if branchrevs:
2687 haveheads = set(h.branch() for h in heads)
2687 haveheads = set(h.branch() for h in heads)
2688 if branches - haveheads:
2688 if branches - haveheads:
2689 headless = ', '.join(b for b in branches - haveheads)
2689 headless = ', '.join(b for b in branches - haveheads)
2690 msg = _('no open branch heads found on branches %s')
2690 msg = _('no open branch heads found on branches %s')
2691 if opts.get('rev'):
2691 if opts.get('rev'):
2692 msg += _(' (started at %s)') % opts['rev']
2692 msg += _(' (started at %s)') % opts['rev']
2693 ui.warn((msg + '\n') % headless)
2693 ui.warn((msg + '\n') % headless)
2694
2694
2695 if not heads:
2695 if not heads:
2696 return 1
2696 return 1
2697
2697
2698 heads = sorted(heads, key=lambda x: -x.rev())
2698 heads = sorted(heads, key=lambda x: -x.rev())
2699 displayer = cmdutil.show_changeset(ui, repo, opts)
2699 displayer = cmdutil.show_changeset(ui, repo, opts)
2700 for ctx in heads:
2700 for ctx in heads:
2701 displayer.show(ctx)
2701 displayer.show(ctx)
2702 displayer.close()
2702 displayer.close()
2703
2703
2704 @command('help',
2704 @command('help',
2705 [('e', 'extension', None, _('show only help for extensions')),
2705 [('e', 'extension', None, _('show only help for extensions')),
2706 ('c', 'command', None, _('show only help for commands')),
2706 ('c', 'command', None, _('show only help for commands')),
2707 ('k', 'keyword', None, _('show topics matching keyword')),
2707 ('k', 'keyword', None, _('show topics matching keyword')),
2708 ('s', 'system', [], _('show help for specific platform(s)')),
2708 ('s', 'system', [], _('show help for specific platform(s)')),
2709 ],
2709 ],
2710 _('[-ecks] [TOPIC]'),
2710 _('[-ecks] [TOPIC]'),
2711 norepo=True)
2711 norepo=True)
2712 def help_(ui, name=None, **opts):
2712 def help_(ui, name=None, **opts):
2713 """show help for a given topic or a help overview
2713 """show help for a given topic or a help overview
2714
2714
2715 With no arguments, print a list of commands with short help messages.
2715 With no arguments, print a list of commands with short help messages.
2716
2716
2717 Given a topic, extension, or command name, print help for that
2717 Given a topic, extension, or command name, print help for that
2718 topic.
2718 topic.
2719
2719
2720 Returns 0 if successful.
2720 Returns 0 if successful.
2721 """
2721 """
2722
2722
2723 textwidth = ui.configint('ui', 'textwidth', 78)
2723 textwidth = ui.configint('ui', 'textwidth', 78)
2724 termwidth = ui.termwidth() - 2
2724 termwidth = ui.termwidth() - 2
2725 if textwidth <= 0 or termwidth < textwidth:
2725 if textwidth <= 0 or termwidth < textwidth:
2726 textwidth = termwidth
2726 textwidth = termwidth
2727
2727
2728 keep = opts.get('system') or []
2728 keep = opts.get('system') or []
2729 if len(keep) == 0:
2729 if len(keep) == 0:
2730 if pycompat.sysplatform.startswith('win'):
2730 if pycompat.sysplatform.startswith('win'):
2731 keep.append('windows')
2731 keep.append('windows')
2732 elif pycompat.sysplatform == 'OpenVMS':
2732 elif pycompat.sysplatform == 'OpenVMS':
2733 keep.append('vms')
2733 keep.append('vms')
2734 elif pycompat.sysplatform == 'plan9':
2734 elif pycompat.sysplatform == 'plan9':
2735 keep.append('plan9')
2735 keep.append('plan9')
2736 else:
2736 else:
2737 keep.append('unix')
2737 keep.append('unix')
2738 keep.append(pycompat.sysplatform.lower())
2738 keep.append(pycompat.sysplatform.lower())
2739 if ui.verbose:
2739 if ui.verbose:
2740 keep.append('verbose')
2740 keep.append('verbose')
2741
2741
2742 fullname = name
2742 fullname = name
2743 section = None
2743 section = None
2744 subtopic = None
2744 subtopic = None
2745 if name and '.' in name:
2745 if name and '.' in name:
2746 name, remaining = name.split('.', 1)
2746 name, remaining = name.split('.', 1)
2747 remaining = encoding.lower(remaining)
2747 remaining = encoding.lower(remaining)
2748 if '.' in remaining:
2748 if '.' in remaining:
2749 subtopic, section = remaining.split('.', 1)
2749 subtopic, section = remaining.split('.', 1)
2750 else:
2750 else:
2751 if name in help.subtopics:
2751 if name in help.subtopics:
2752 subtopic = remaining
2752 subtopic = remaining
2753 else:
2753 else:
2754 section = remaining
2754 section = remaining
2755
2755
2756 text = help.help_(ui, name, subtopic=subtopic, **opts)
2756 text = help.help_(ui, name, subtopic=subtopic, **opts)
2757
2757
2758 formatted, pruned = minirst.format(text, textwidth, keep=keep,
2758 formatted, pruned = minirst.format(text, textwidth, keep=keep,
2759 section=section)
2759 section=section)
2760
2760
2761 # We could have been given a weird ".foo" section without a name
2761 # We could have been given a weird ".foo" section without a name
2762 # to look for, or we could have simply failed to found "foo.bar"
2762 # to look for, or we could have simply failed to found "foo.bar"
2763 # because bar isn't a section of foo
2763 # because bar isn't a section of foo
2764 if section and not (formatted and name):
2764 if section and not (formatted and name):
2765 raise error.Abort(_("help section not found: %s") % fullname)
2765 raise error.Abort(_("help section not found: %s") % fullname)
2766
2766
2767 if 'verbose' in pruned:
2767 if 'verbose' in pruned:
2768 keep.append('omitted')
2768 keep.append('omitted')
2769 else:
2769 else:
2770 keep.append('notomitted')
2770 keep.append('notomitted')
2771 formatted, pruned = minirst.format(text, textwidth, keep=keep,
2771 formatted, pruned = minirst.format(text, textwidth, keep=keep,
2772 section=section)
2772 section=section)
2773 ui.write(formatted)
2773 ui.write(formatted)
2774
2774
2775
2775
2776 @command('identify|id',
2776 @command('identify|id',
2777 [('r', 'rev', '',
2777 [('r', 'rev', '',
2778 _('identify the specified revision'), _('REV')),
2778 _('identify the specified revision'), _('REV')),
2779 ('n', 'num', None, _('show local revision number')),
2779 ('n', 'num', None, _('show local revision number')),
2780 ('i', 'id', None, _('show global revision id')),
2780 ('i', 'id', None, _('show global revision id')),
2781 ('b', 'branch', None, _('show branch')),
2781 ('b', 'branch', None, _('show branch')),
2782 ('t', 'tags', None, _('show tags')),
2782 ('t', 'tags', None, _('show tags')),
2783 ('B', 'bookmarks', None, _('show bookmarks')),
2783 ('B', 'bookmarks', None, _('show bookmarks')),
2784 ] + remoteopts,
2784 ] + remoteopts,
2785 _('[-nibtB] [-r REV] [SOURCE]'),
2785 _('[-nibtB] [-r REV] [SOURCE]'),
2786 optionalrepo=True)
2786 optionalrepo=True)
2787 def identify(ui, repo, source=None, rev=None,
2787 def identify(ui, repo, source=None, rev=None,
2788 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
2788 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
2789 """identify the working directory or specified revision
2789 """identify the working directory or specified revision
2790
2790
2791 Print a summary identifying the repository state at REV using one or
2791 Print a summary identifying the repository state at REV using one or
2792 two parent hash identifiers, followed by a "+" if the working
2792 two parent hash identifiers, followed by a "+" if the working
2793 directory has uncommitted changes, the branch name (if not default),
2793 directory has uncommitted changes, the branch name (if not default),
2794 a list of tags, and a list of bookmarks.
2794 a list of tags, and a list of bookmarks.
2795
2795
2796 When REV is not given, print a summary of the current state of the
2796 When REV is not given, print a summary of the current state of the
2797 repository.
2797 repository.
2798
2798
2799 Specifying a path to a repository root or Mercurial bundle will
2799 Specifying a path to a repository root or Mercurial bundle will
2800 cause lookup to operate on that repository/bundle.
2800 cause lookup to operate on that repository/bundle.
2801
2801
2802 .. container:: verbose
2802 .. container:: verbose
2803
2803
2804 Examples:
2804 Examples:
2805
2805
2806 - generate a build identifier for the working directory::
2806 - generate a build identifier for the working directory::
2807
2807
2808 hg id --id > build-id.dat
2808 hg id --id > build-id.dat
2809
2809
2810 - find the revision corresponding to a tag::
2810 - find the revision corresponding to a tag::
2811
2811
2812 hg id -n -r 1.3
2812 hg id -n -r 1.3
2813
2813
2814 - check the most recent revision of a remote repository::
2814 - check the most recent revision of a remote repository::
2815
2815
2816 hg id -r tip https://www.mercurial-scm.org/repo/hg/
2816 hg id -r tip https://www.mercurial-scm.org/repo/hg/
2817
2817
2818 See :hg:`log` for generating more information about specific revisions,
2818 See :hg:`log` for generating more information about specific revisions,
2819 including full hash identifiers.
2819 including full hash identifiers.
2820
2820
2821 Returns 0 if successful.
2821 Returns 0 if successful.
2822 """
2822 """
2823
2823
2824 if not repo and not source:
2824 if not repo and not source:
2825 raise error.Abort(_("there is no Mercurial repository here "
2825 raise error.Abort(_("there is no Mercurial repository here "
2826 "(.hg not found)"))
2826 "(.hg not found)"))
2827
2827
2828 if ui.debugflag:
2828 if ui.debugflag:
2829 hexfunc = hex
2829 hexfunc = hex
2830 else:
2830 else:
2831 hexfunc = short
2831 hexfunc = short
2832 default = not (num or id or branch or tags or bookmarks)
2832 default = not (num or id or branch or tags or bookmarks)
2833 output = []
2833 output = []
2834 revs = []
2834 revs = []
2835
2835
2836 if source:
2836 if source:
2837 source, branches = hg.parseurl(ui.expandpath(source))
2837 source, branches = hg.parseurl(ui.expandpath(source))
2838 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
2838 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
2839 repo = peer.local()
2839 repo = peer.local()
2840 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
2840 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
2841
2841
2842 if not repo:
2842 if not repo:
2843 if num or branch or tags:
2843 if num or branch or tags:
2844 raise error.Abort(
2844 raise error.Abort(
2845 _("can't query remote revision number, branch, or tags"))
2845 _("can't query remote revision number, branch, or tags"))
2846 if not rev and revs:
2846 if not rev and revs:
2847 rev = revs[0]
2847 rev = revs[0]
2848 if not rev:
2848 if not rev:
2849 rev = "tip"
2849 rev = "tip"
2850
2850
2851 remoterev = peer.lookup(rev)
2851 remoterev = peer.lookup(rev)
2852 if default or id:
2852 if default or id:
2853 output = [hexfunc(remoterev)]
2853 output = [hexfunc(remoterev)]
2854
2854
2855 def getbms():
2855 def getbms():
2856 bms = []
2856 bms = []
2857
2857
2858 if 'bookmarks' in peer.listkeys('namespaces'):
2858 if 'bookmarks' in peer.listkeys('namespaces'):
2859 hexremoterev = hex(remoterev)
2859 hexremoterev = hex(remoterev)
2860 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
2860 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
2861 if bmr == hexremoterev]
2861 if bmr == hexremoterev]
2862
2862
2863 return sorted(bms)
2863 return sorted(bms)
2864
2864
2865 if bookmarks:
2865 if bookmarks:
2866 output.extend(getbms())
2866 output.extend(getbms())
2867 elif default and not ui.quiet:
2867 elif default and not ui.quiet:
2868 # multiple bookmarks for a single parent separated by '/'
2868 # multiple bookmarks for a single parent separated by '/'
2869 bm = '/'.join(getbms())
2869 bm = '/'.join(getbms())
2870 if bm:
2870 if bm:
2871 output.append(bm)
2871 output.append(bm)
2872 else:
2872 else:
2873 ctx = scmutil.revsingle(repo, rev, None)
2873 ctx = scmutil.revsingle(repo, rev, None)
2874
2874
2875 if ctx.rev() is None:
2875 if ctx.rev() is None:
2876 ctx = repo[None]
2876 ctx = repo[None]
2877 parents = ctx.parents()
2877 parents = ctx.parents()
2878 taglist = []
2878 taglist = []
2879 for p in parents:
2879 for p in parents:
2880 taglist.extend(p.tags())
2880 taglist.extend(p.tags())
2881
2881
2882 changed = ""
2882 changed = ""
2883 if default or id or num:
2883 if default or id or num:
2884 if (any(repo.status())
2884 if (any(repo.status())
2885 or any(ctx.sub(s).dirty() for s in ctx.substate)):
2885 or any(ctx.sub(s).dirty() for s in ctx.substate)):
2886 changed = '+'
2886 changed = '+'
2887 if default or id:
2887 if default or id:
2888 output = ["%s%s" %
2888 output = ["%s%s" %
2889 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
2889 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
2890 if num:
2890 if num:
2891 output.append("%s%s" %
2891 output.append("%s%s" %
2892 ('+'.join([str(p.rev()) for p in parents]), changed))
2892 ('+'.join([str(p.rev()) for p in parents]), changed))
2893 else:
2893 else:
2894 if default or id:
2894 if default or id:
2895 output = [hexfunc(ctx.node())]
2895 output = [hexfunc(ctx.node())]
2896 if num:
2896 if num:
2897 output.append(str(ctx.rev()))
2897 output.append(str(ctx.rev()))
2898 taglist = ctx.tags()
2898 taglist = ctx.tags()
2899
2899
2900 if default and not ui.quiet:
2900 if default and not ui.quiet:
2901 b = ctx.branch()
2901 b = ctx.branch()
2902 if b != 'default':
2902 if b != 'default':
2903 output.append("(%s)" % b)
2903 output.append("(%s)" % b)
2904
2904
2905 # multiple tags for a single parent separated by '/'
2905 # multiple tags for a single parent separated by '/'
2906 t = '/'.join(taglist)
2906 t = '/'.join(taglist)
2907 if t:
2907 if t:
2908 output.append(t)
2908 output.append(t)
2909
2909
2910 # multiple bookmarks for a single parent separated by '/'
2910 # multiple bookmarks for a single parent separated by '/'
2911 bm = '/'.join(ctx.bookmarks())
2911 bm = '/'.join(ctx.bookmarks())
2912 if bm:
2912 if bm:
2913 output.append(bm)
2913 output.append(bm)
2914 else:
2914 else:
2915 if branch:
2915 if branch:
2916 output.append(ctx.branch())
2916 output.append(ctx.branch())
2917
2917
2918 if tags:
2918 if tags:
2919 output.extend(taglist)
2919 output.extend(taglist)
2920
2920
2921 if bookmarks:
2921 if bookmarks:
2922 output.extend(ctx.bookmarks())
2922 output.extend(ctx.bookmarks())
2923
2923
2924 ui.write("%s\n" % ' '.join(output))
2924 ui.write("%s\n" % ' '.join(output))
2925
2925
2926 @command('import|patch',
2926 @command('import|patch',
2927 [('p', 'strip', 1,
2927 [('p', 'strip', 1,
2928 _('directory strip option for patch. This has the same '
2928 _('directory strip option for patch. This has the same '
2929 'meaning as the corresponding patch option'), _('NUM')),
2929 'meaning as the corresponding patch option'), _('NUM')),
2930 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
2930 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
2931 ('e', 'edit', False, _('invoke editor on commit messages')),
2931 ('e', 'edit', False, _('invoke editor on commit messages')),
2932 ('f', 'force', None,
2932 ('f', 'force', None,
2933 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
2933 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
2934 ('', 'no-commit', None,
2934 ('', 'no-commit', None,
2935 _("don't commit, just update the working directory")),
2935 _("don't commit, just update the working directory")),
2936 ('', 'bypass', None,
2936 ('', 'bypass', None,
2937 _("apply patch without touching the working directory")),
2937 _("apply patch without touching the working directory")),
2938 ('', 'partial', None,
2938 ('', 'partial', None,
2939 _('commit even if some hunks fail')),
2939 _('commit even if some hunks fail')),
2940 ('', 'exact', None,
2940 ('', 'exact', None,
2941 _('abort if patch would apply lossily')),
2941 _('abort if patch would apply lossily')),
2942 ('', 'prefix', '',
2942 ('', 'prefix', '',
2943 _('apply patch to subdirectory'), _('DIR')),
2943 _('apply patch to subdirectory'), _('DIR')),
2944 ('', 'import-branch', None,
2944 ('', 'import-branch', None,
2945 _('use any branch information in patch (implied by --exact)'))] +
2945 _('use any branch information in patch (implied by --exact)'))] +
2946 commitopts + commitopts2 + similarityopts,
2946 commitopts + commitopts2 + similarityopts,
2947 _('[OPTION]... PATCH...'))
2947 _('[OPTION]... PATCH...'))
2948 def import_(ui, repo, patch1=None, *patches, **opts):
2948 def import_(ui, repo, patch1=None, *patches, **opts):
2949 """import an ordered set of patches
2949 """import an ordered set of patches
2950
2950
2951 Import a list of patches and commit them individually (unless
2951 Import a list of patches and commit them individually (unless
2952 --no-commit is specified).
2952 --no-commit is specified).
2953
2953
2954 To read a patch from standard input (stdin), use "-" as the patch
2954 To read a patch from standard input (stdin), use "-" as the patch
2955 name. If a URL is specified, the patch will be downloaded from
2955 name. If a URL is specified, the patch will be downloaded from
2956 there.
2956 there.
2957
2957
2958 Import first applies changes to the working directory (unless
2958 Import first applies changes to the working directory (unless
2959 --bypass is specified), import will abort if there are outstanding
2959 --bypass is specified), import will abort if there are outstanding
2960 changes.
2960 changes.
2961
2961
2962 Use --bypass to apply and commit patches directly to the
2962 Use --bypass to apply and commit patches directly to the
2963 repository, without affecting the working directory. Without
2963 repository, without affecting the working directory. Without
2964 --exact, patches will be applied on top of the working directory
2964 --exact, patches will be applied on top of the working directory
2965 parent revision.
2965 parent revision.
2966
2966
2967 You can import a patch straight from a mail message. Even patches
2967 You can import a patch straight from a mail message. Even patches
2968 as attachments work (to use the body part, it must have type
2968 as attachments work (to use the body part, it must have type
2969 text/plain or text/x-patch). From and Subject headers of email
2969 text/plain or text/x-patch). From and Subject headers of email
2970 message are used as default committer and commit message. All
2970 message are used as default committer and commit message. All
2971 text/plain body parts before first diff are added to the commit
2971 text/plain body parts before first diff are added to the commit
2972 message.
2972 message.
2973
2973
2974 If the imported patch was generated by :hg:`export`, user and
2974 If the imported patch was generated by :hg:`export`, user and
2975 description from patch override values from message headers and
2975 description from patch override values from message headers and
2976 body. Values given on command line with -m/--message and -u/--user
2976 body. Values given on command line with -m/--message and -u/--user
2977 override these.
2977 override these.
2978
2978
2979 If --exact is specified, import will set the working directory to
2979 If --exact is specified, import will set the working directory to
2980 the parent of each patch before applying it, and will abort if the
2980 the parent of each patch before applying it, and will abort if the
2981 resulting changeset has a different ID than the one recorded in
2981 resulting changeset has a different ID than the one recorded in
2982 the patch. This will guard against various ways that portable
2982 the patch. This will guard against various ways that portable
2983 patch formats and mail systems might fail to transfer Mercurial
2983 patch formats and mail systems might fail to transfer Mercurial
2984 data or metadata. See :hg:`bundle` for lossless transmission.
2984 data or metadata. See :hg:`bundle` for lossless transmission.
2985
2985
2986 Use --partial to ensure a changeset will be created from the patch
2986 Use --partial to ensure a changeset will be created from the patch
2987 even if some hunks fail to apply. Hunks that fail to apply will be
2987 even if some hunks fail to apply. Hunks that fail to apply will be
2988 written to a <target-file>.rej file. Conflicts can then be resolved
2988 written to a <target-file>.rej file. Conflicts can then be resolved
2989 by hand before :hg:`commit --amend` is run to update the created
2989 by hand before :hg:`commit --amend` is run to update the created
2990 changeset. This flag exists to let people import patches that
2990 changeset. This flag exists to let people import patches that
2991 partially apply without losing the associated metadata (author,
2991 partially apply without losing the associated metadata (author,
2992 date, description, ...).
2992 date, description, ...).
2993
2993
2994 .. note::
2994 .. note::
2995
2995
2996 When no hunks apply cleanly, :hg:`import --partial` will create
2996 When no hunks apply cleanly, :hg:`import --partial` will create
2997 an empty changeset, importing only the patch metadata.
2997 an empty changeset, importing only the patch metadata.
2998
2998
2999 With -s/--similarity, hg will attempt to discover renames and
2999 With -s/--similarity, hg will attempt to discover renames and
3000 copies in the patch in the same way as :hg:`addremove`.
3000 copies in the patch in the same way as :hg:`addremove`.
3001
3001
3002 It is possible to use external patch programs to perform the patch
3002 It is possible to use external patch programs to perform the patch
3003 by setting the ``ui.patch`` configuration option. For the default
3003 by setting the ``ui.patch`` configuration option. For the default
3004 internal tool, the fuzz can also be configured via ``patch.fuzz``.
3004 internal tool, the fuzz can also be configured via ``patch.fuzz``.
3005 See :hg:`help config` for more information about configuration
3005 See :hg:`help config` for more information about configuration
3006 files and how to use these options.
3006 files and how to use these options.
3007
3007
3008 See :hg:`help dates` for a list of formats valid for -d/--date.
3008 See :hg:`help dates` for a list of formats valid for -d/--date.
3009
3009
3010 .. container:: verbose
3010 .. container:: verbose
3011
3011
3012 Examples:
3012 Examples:
3013
3013
3014 - import a traditional patch from a website and detect renames::
3014 - import a traditional patch from a website and detect renames::
3015
3015
3016 hg import -s 80 http://example.com/bugfix.patch
3016 hg import -s 80 http://example.com/bugfix.patch
3017
3017
3018 - import a changeset from an hgweb server::
3018 - import a changeset from an hgweb server::
3019
3019
3020 hg import https://www.mercurial-scm.org/repo/hg/rev/5ca8c111e9aa
3020 hg import https://www.mercurial-scm.org/repo/hg/rev/5ca8c111e9aa
3021
3021
3022 - import all the patches in an Unix-style mbox::
3022 - import all the patches in an Unix-style mbox::
3023
3023
3024 hg import incoming-patches.mbox
3024 hg import incoming-patches.mbox
3025
3025
3026 - import patches from stdin::
3026 - import patches from stdin::
3027
3027
3028 hg import -
3028 hg import -
3029
3029
3030 - attempt to exactly restore an exported changeset (not always
3030 - attempt to exactly restore an exported changeset (not always
3031 possible)::
3031 possible)::
3032
3032
3033 hg import --exact proposed-fix.patch
3033 hg import --exact proposed-fix.patch
3034
3034
3035 - use an external tool to apply a patch which is too fuzzy for
3035 - use an external tool to apply a patch which is too fuzzy for
3036 the default internal tool.
3036 the default internal tool.
3037
3037
3038 hg import --config ui.patch="patch --merge" fuzzy.patch
3038 hg import --config ui.patch="patch --merge" fuzzy.patch
3039
3039
3040 - change the default fuzzing from 2 to a less strict 7
3040 - change the default fuzzing from 2 to a less strict 7
3041
3041
3042 hg import --config ui.fuzz=7 fuzz.patch
3042 hg import --config ui.fuzz=7 fuzz.patch
3043
3043
3044 Returns 0 on success, 1 on partial success (see --partial).
3044 Returns 0 on success, 1 on partial success (see --partial).
3045 """
3045 """
3046
3046
3047 if not patch1:
3047 if not patch1:
3048 raise error.Abort(_('need at least one patch to import'))
3048 raise error.Abort(_('need at least one patch to import'))
3049
3049
3050 patches = (patch1,) + patches
3050 patches = (patch1,) + patches
3051
3051
3052 date = opts.get('date')
3052 date = opts.get('date')
3053 if date:
3053 if date:
3054 opts['date'] = util.parsedate(date)
3054 opts['date'] = util.parsedate(date)
3055
3055
3056 exact = opts.get('exact')
3056 exact = opts.get('exact')
3057 update = not opts.get('bypass')
3057 update = not opts.get('bypass')
3058 if not update and opts.get('no_commit'):
3058 if not update and opts.get('no_commit'):
3059 raise error.Abort(_('cannot use --no-commit with --bypass'))
3059 raise error.Abort(_('cannot use --no-commit with --bypass'))
3060 try:
3060 try:
3061 sim = float(opts.get('similarity') or 0)
3061 sim = float(opts.get('similarity') or 0)
3062 except ValueError:
3062 except ValueError:
3063 raise error.Abort(_('similarity must be a number'))
3063 raise error.Abort(_('similarity must be a number'))
3064 if sim < 0 or sim > 100:
3064 if sim < 0 or sim > 100:
3065 raise error.Abort(_('similarity must be between 0 and 100'))
3065 raise error.Abort(_('similarity must be between 0 and 100'))
3066 if sim and not update:
3066 if sim and not update:
3067 raise error.Abort(_('cannot use --similarity with --bypass'))
3067 raise error.Abort(_('cannot use --similarity with --bypass'))
3068 if exact:
3068 if exact:
3069 if opts.get('edit'):
3069 if opts.get('edit'):
3070 raise error.Abort(_('cannot use --exact with --edit'))
3070 raise error.Abort(_('cannot use --exact with --edit'))
3071 if opts.get('prefix'):
3071 if opts.get('prefix'):
3072 raise error.Abort(_('cannot use --exact with --prefix'))
3072 raise error.Abort(_('cannot use --exact with --prefix'))
3073
3073
3074 base = opts["base"]
3074 base = opts["base"]
3075 wlock = dsguard = lock = tr = None
3075 wlock = dsguard = lock = tr = None
3076 msgs = []
3076 msgs = []
3077 ret = 0
3077 ret = 0
3078
3078
3079
3079
3080 try:
3080 try:
3081 wlock = repo.wlock()
3081 wlock = repo.wlock()
3082
3082
3083 if update:
3083 if update:
3084 cmdutil.checkunfinished(repo)
3084 cmdutil.checkunfinished(repo)
3085 if (exact or not opts.get('force')):
3085 if (exact or not opts.get('force')):
3086 cmdutil.bailifchanged(repo)
3086 cmdutil.bailifchanged(repo)
3087
3087
3088 if not opts.get('no_commit'):
3088 if not opts.get('no_commit'):
3089 lock = repo.lock()
3089 lock = repo.lock()
3090 tr = repo.transaction('import')
3090 tr = repo.transaction('import')
3091 else:
3091 else:
3092 dsguard = dirstateguard.dirstateguard(repo, 'import')
3092 dsguard = dirstateguard.dirstateguard(repo, 'import')
3093 parents = repo[None].parents()
3093 parents = repo[None].parents()
3094 for patchurl in patches:
3094 for patchurl in patches:
3095 if patchurl == '-':
3095 if patchurl == '-':
3096 ui.status(_('applying patch from stdin\n'))
3096 ui.status(_('applying patch from stdin\n'))
3097 patchfile = ui.fin
3097 patchfile = ui.fin
3098 patchurl = 'stdin' # for error message
3098 patchurl = 'stdin' # for error message
3099 else:
3099 else:
3100 patchurl = os.path.join(base, patchurl)
3100 patchurl = os.path.join(base, patchurl)
3101 ui.status(_('applying %s\n') % patchurl)
3101 ui.status(_('applying %s\n') % patchurl)
3102 patchfile = hg.openpath(ui, patchurl)
3102 patchfile = hg.openpath(ui, patchurl)
3103
3103
3104 haspatch = False
3104 haspatch = False
3105 for hunk in patch.split(patchfile):
3105 for hunk in patch.split(patchfile):
3106 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
3106 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
3107 parents, opts,
3107 parents, opts,
3108 msgs, hg.clean)
3108 msgs, hg.clean)
3109 if msg:
3109 if msg:
3110 haspatch = True
3110 haspatch = True
3111 ui.note(msg + '\n')
3111 ui.note(msg + '\n')
3112 if update or exact:
3112 if update or exact:
3113 parents = repo[None].parents()
3113 parents = repo[None].parents()
3114 else:
3114 else:
3115 parents = [repo[node]]
3115 parents = [repo[node]]
3116 if rej:
3116 if rej:
3117 ui.write_err(_("patch applied partially\n"))
3117 ui.write_err(_("patch applied partially\n"))
3118 ui.write_err(_("(fix the .rej files and run "
3118 ui.write_err(_("(fix the .rej files and run "
3119 "`hg commit --amend`)\n"))
3119 "`hg commit --amend`)\n"))
3120 ret = 1
3120 ret = 1
3121 break
3121 break
3122
3122
3123 if not haspatch:
3123 if not haspatch:
3124 raise error.Abort(_('%s: no diffs found') % patchurl)
3124 raise error.Abort(_('%s: no diffs found') % patchurl)
3125
3125
3126 if tr:
3126 if tr:
3127 tr.close()
3127 tr.close()
3128 if msgs:
3128 if msgs:
3129 repo.savecommitmessage('\n* * *\n'.join(msgs))
3129 repo.savecommitmessage('\n* * *\n'.join(msgs))
3130 if dsguard:
3130 if dsguard:
3131 dsguard.close()
3131 dsguard.close()
3132 return ret
3132 return ret
3133 finally:
3133 finally:
3134 if tr:
3134 if tr:
3135 tr.release()
3135 tr.release()
3136 release(lock, dsguard, wlock)
3136 release(lock, dsguard, wlock)
3137
3137
3138 @command('incoming|in',
3138 @command('incoming|in',
3139 [('f', 'force', None,
3139 [('f', 'force', None,
3140 _('run even if remote repository is unrelated')),
3140 _('run even if remote repository is unrelated')),
3141 ('n', 'newest-first', None, _('show newest record first')),
3141 ('n', 'newest-first', None, _('show newest record first')),
3142 ('', 'bundle', '',
3142 ('', 'bundle', '',
3143 _('file to store the bundles into'), _('FILE')),
3143 _('file to store the bundles into'), _('FILE')),
3144 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3144 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3145 ('B', 'bookmarks', False, _("compare bookmarks")),
3145 ('B', 'bookmarks', False, _("compare bookmarks")),
3146 ('b', 'branch', [],
3146 ('b', 'branch', [],
3147 _('a specific branch you would like to pull'), _('BRANCH')),
3147 _('a specific branch you would like to pull'), _('BRANCH')),
3148 ] + logopts + remoteopts + subrepoopts,
3148 ] + logopts + remoteopts + subrepoopts,
3149 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3149 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3150 def incoming(ui, repo, source="default", **opts):
3150 def incoming(ui, repo, source="default", **opts):
3151 """show new changesets found in source
3151 """show new changesets found in source
3152
3152
3153 Show new changesets found in the specified path/URL or the default
3153 Show new changesets found in the specified path/URL or the default
3154 pull location. These are the changesets that would have been pulled
3154 pull location. These are the changesets that would have been pulled
3155 if a pull at the time you issued this command.
3155 if a pull at the time you issued this command.
3156
3156
3157 See pull for valid source format details.
3157 See pull for valid source format details.
3158
3158
3159 .. container:: verbose
3159 .. container:: verbose
3160
3160
3161 With -B/--bookmarks, the result of bookmark comparison between
3161 With -B/--bookmarks, the result of bookmark comparison between
3162 local and remote repositories is displayed. With -v/--verbose,
3162 local and remote repositories is displayed. With -v/--verbose,
3163 status is also displayed for each bookmark like below::
3163 status is also displayed for each bookmark like below::
3164
3164
3165 BM1 01234567890a added
3165 BM1 01234567890a added
3166 BM2 1234567890ab advanced
3166 BM2 1234567890ab advanced
3167 BM3 234567890abc diverged
3167 BM3 234567890abc diverged
3168 BM4 34567890abcd changed
3168 BM4 34567890abcd changed
3169
3169
3170 The action taken locally when pulling depends on the
3170 The action taken locally when pulling depends on the
3171 status of each bookmark:
3171 status of each bookmark:
3172
3172
3173 :``added``: pull will create it
3173 :``added``: pull will create it
3174 :``advanced``: pull will update it
3174 :``advanced``: pull will update it
3175 :``diverged``: pull will create a divergent bookmark
3175 :``diverged``: pull will create a divergent bookmark
3176 :``changed``: result depends on remote changesets
3176 :``changed``: result depends on remote changesets
3177
3177
3178 From the point of view of pulling behavior, bookmark
3178 From the point of view of pulling behavior, bookmark
3179 existing only in the remote repository are treated as ``added``,
3179 existing only in the remote repository are treated as ``added``,
3180 even if it is in fact locally deleted.
3180 even if it is in fact locally deleted.
3181
3181
3182 .. container:: verbose
3182 .. container:: verbose
3183
3183
3184 For remote repository, using --bundle avoids downloading the
3184 For remote repository, using --bundle avoids downloading the
3185 changesets twice if the incoming is followed by a pull.
3185 changesets twice if the incoming is followed by a pull.
3186
3186
3187 Examples:
3187 Examples:
3188
3188
3189 - show incoming changes with patches and full description::
3189 - show incoming changes with patches and full description::
3190
3190
3191 hg incoming -vp
3191 hg incoming -vp
3192
3192
3193 - show incoming changes excluding merges, store a bundle::
3193 - show incoming changes excluding merges, store a bundle::
3194
3194
3195 hg in -vpM --bundle incoming.hg
3195 hg in -vpM --bundle incoming.hg
3196 hg pull incoming.hg
3196 hg pull incoming.hg
3197
3197
3198 - briefly list changes inside a bundle::
3198 - briefly list changes inside a bundle::
3199
3199
3200 hg in changes.hg -T "{desc|firstline}\\n"
3200 hg in changes.hg -T "{desc|firstline}\\n"
3201
3201
3202 Returns 0 if there are incoming changes, 1 otherwise.
3202 Returns 0 if there are incoming changes, 1 otherwise.
3203 """
3203 """
3204 if opts.get('graph'):
3204 if opts.get('graph'):
3205 cmdutil.checkunsupportedgraphflags([], opts)
3205 cmdutil.checkunsupportedgraphflags([], opts)
3206 def display(other, chlist, displayer):
3206 def display(other, chlist, displayer):
3207 revdag = cmdutil.graphrevs(other, chlist, opts)
3207 revdag = cmdutil.graphrevs(other, chlist, opts)
3208 cmdutil.displaygraph(ui, repo, revdag, displayer,
3208 cmdutil.displaygraph(ui, repo, revdag, displayer,
3209 graphmod.asciiedges)
3209 graphmod.asciiedges)
3210
3210
3211 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3211 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3212 return 0
3212 return 0
3213
3213
3214 if opts.get('bundle') and opts.get('subrepos'):
3214 if opts.get('bundle') and opts.get('subrepos'):
3215 raise error.Abort(_('cannot combine --bundle and --subrepos'))
3215 raise error.Abort(_('cannot combine --bundle and --subrepos'))
3216
3216
3217 if opts.get('bookmarks'):
3217 if opts.get('bookmarks'):
3218 source, branches = hg.parseurl(ui.expandpath(source),
3218 source, branches = hg.parseurl(ui.expandpath(source),
3219 opts.get('branch'))
3219 opts.get('branch'))
3220 other = hg.peer(repo, opts, source)
3220 other = hg.peer(repo, opts, source)
3221 if 'bookmarks' not in other.listkeys('namespaces'):
3221 if 'bookmarks' not in other.listkeys('namespaces'):
3222 ui.warn(_("remote doesn't support bookmarks\n"))
3222 ui.warn(_("remote doesn't support bookmarks\n"))
3223 return 0
3223 return 0
3224 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3224 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3225 return bookmarks.incoming(ui, repo, other)
3225 return bookmarks.incoming(ui, repo, other)
3226
3226
3227 repo._subtoppath = ui.expandpath(source)
3227 repo._subtoppath = ui.expandpath(source)
3228 try:
3228 try:
3229 return hg.incoming(ui, repo, source, opts)
3229 return hg.incoming(ui, repo, source, opts)
3230 finally:
3230 finally:
3231 del repo._subtoppath
3231 del repo._subtoppath
3232
3232
3233
3233
3234 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
3234 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
3235 norepo=True)
3235 norepo=True)
3236 def init(ui, dest=".", **opts):
3236 def init(ui, dest=".", **opts):
3237 """create a new repository in the given directory
3237 """create a new repository in the given directory
3238
3238
3239 Initialize a new repository in the given directory. If the given
3239 Initialize a new repository in the given directory. If the given
3240 directory does not exist, it will be created.
3240 directory does not exist, it will be created.
3241
3241
3242 If no directory is given, the current directory is used.
3242 If no directory is given, the current directory is used.
3243
3243
3244 It is possible to specify an ``ssh://`` URL as the destination.
3244 It is possible to specify an ``ssh://`` URL as the destination.
3245 See :hg:`help urls` for more information.
3245 See :hg:`help urls` for more information.
3246
3246
3247 Returns 0 on success.
3247 Returns 0 on success.
3248 """
3248 """
3249 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3249 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3250
3250
3251 @command('locate',
3251 @command('locate',
3252 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3252 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3253 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3253 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3254 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3254 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3255 ] + walkopts,
3255 ] + walkopts,
3256 _('[OPTION]... [PATTERN]...'))
3256 _('[OPTION]... [PATTERN]...'))
3257 def locate(ui, repo, *pats, **opts):
3257 def locate(ui, repo, *pats, **opts):
3258 """locate files matching specific patterns (DEPRECATED)
3258 """locate files matching specific patterns (DEPRECATED)
3259
3259
3260 Print files under Mercurial control in the working directory whose
3260 Print files under Mercurial control in the working directory whose
3261 names match the given patterns.
3261 names match the given patterns.
3262
3262
3263 By default, this command searches all directories in the working
3263 By default, this command searches all directories in the working
3264 directory. To search just the current directory and its
3264 directory. To search just the current directory and its
3265 subdirectories, use "--include .".
3265 subdirectories, use "--include .".
3266
3266
3267 If no patterns are given to match, this command prints the names
3267 If no patterns are given to match, this command prints the names
3268 of all files under Mercurial control in the working directory.
3268 of all files under Mercurial control in the working directory.
3269
3269
3270 If you want to feed the output of this command into the "xargs"
3270 If you want to feed the output of this command into the "xargs"
3271 command, use the -0 option to both this command and "xargs". This
3271 command, use the -0 option to both this command and "xargs". This
3272 will avoid the problem of "xargs" treating single filenames that
3272 will avoid the problem of "xargs" treating single filenames that
3273 contain whitespace as multiple filenames.
3273 contain whitespace as multiple filenames.
3274
3274
3275 See :hg:`help files` for a more versatile command.
3275 See :hg:`help files` for a more versatile command.
3276
3276
3277 Returns 0 if a match is found, 1 otherwise.
3277 Returns 0 if a match is found, 1 otherwise.
3278 """
3278 """
3279 if opts.get('print0'):
3279 if opts.get('print0'):
3280 end = '\0'
3280 end = '\0'
3281 else:
3281 else:
3282 end = '\n'
3282 end = '\n'
3283 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3283 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3284
3284
3285 ret = 1
3285 ret = 1
3286 ctx = repo[rev]
3286 ctx = repo[rev]
3287 m = scmutil.match(ctx, pats, opts, default='relglob',
3287 m = scmutil.match(ctx, pats, opts, default='relglob',
3288 badfn=lambda x, y: False)
3288 badfn=lambda x, y: False)
3289
3289
3290 for abs in ctx.matches(m):
3290 for abs in ctx.matches(m):
3291 if opts.get('fullpath'):
3291 if opts.get('fullpath'):
3292 ui.write(repo.wjoin(abs), end)
3292 ui.write(repo.wjoin(abs), end)
3293 else:
3293 else:
3294 ui.write(((pats and m.rel(abs)) or abs), end)
3294 ui.write(((pats and m.rel(abs)) or abs), end)
3295 ret = 0
3295 ret = 0
3296
3296
3297 return ret
3297 return ret
3298
3298
3299 @command('^log|history',
3299 @command('^log|history',
3300 [('f', 'follow', None,
3300 [('f', 'follow', None,
3301 _('follow changeset history, or file history across copies and renames')),
3301 _('follow changeset history, or file history across copies and renames')),
3302 ('', 'follow-first', None,
3302 ('', 'follow-first', None,
3303 _('only follow the first parent of merge changesets (DEPRECATED)')),
3303 _('only follow the first parent of merge changesets (DEPRECATED)')),
3304 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3304 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3305 ('C', 'copies', None, _('show copied files')),
3305 ('C', 'copies', None, _('show copied files')),
3306 ('k', 'keyword', [],
3306 ('k', 'keyword', [],
3307 _('do case-insensitive search for a given text'), _('TEXT')),
3307 _('do case-insensitive search for a given text'), _('TEXT')),
3308 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
3308 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
3309 ('', 'removed', None, _('include revisions where files were removed')),
3309 ('', 'removed', None, _('include revisions where files were removed')),
3310 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3310 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3311 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3311 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3312 ('', 'only-branch', [],
3312 ('', 'only-branch', [],
3313 _('show only changesets within the given named branch (DEPRECATED)'),
3313 _('show only changesets within the given named branch (DEPRECATED)'),
3314 _('BRANCH')),
3314 _('BRANCH')),
3315 ('b', 'branch', [],
3315 ('b', 'branch', [],
3316 _('show changesets within the given named branch'), _('BRANCH')),
3316 _('show changesets within the given named branch'), _('BRANCH')),
3317 ('P', 'prune', [],
3317 ('P', 'prune', [],
3318 _('do not display revision or any of its ancestors'), _('REV')),
3318 _('do not display revision or any of its ancestors'), _('REV')),
3319 ] + logopts + walkopts,
3319 ] + logopts + walkopts,
3320 _('[OPTION]... [FILE]'),
3320 _('[OPTION]... [FILE]'),
3321 inferrepo=True)
3321 inferrepo=True)
3322 def log(ui, repo, *pats, **opts):
3322 def log(ui, repo, *pats, **opts):
3323 """show revision history of entire repository or files
3323 """show revision history of entire repository or files
3324
3324
3325 Print the revision history of the specified files or the entire
3325 Print the revision history of the specified files or the entire
3326 project.
3326 project.
3327
3327
3328 If no revision range is specified, the default is ``tip:0`` unless
3328 If no revision range is specified, the default is ``tip:0`` unless
3329 --follow is set, in which case the working directory parent is
3329 --follow is set, in which case the working directory parent is
3330 used as the starting revision.
3330 used as the starting revision.
3331
3331
3332 File history is shown without following rename or copy history of
3332 File history is shown without following rename or copy history of
3333 files. Use -f/--follow with a filename to follow history across
3333 files. Use -f/--follow with a filename to follow history across
3334 renames and copies. --follow without a filename will only show
3334 renames and copies. --follow without a filename will only show
3335 ancestors or descendants of the starting revision.
3335 ancestors or descendants of the starting revision.
3336
3336
3337 By default this command prints revision number and changeset id,
3337 By default this command prints revision number and changeset id,
3338 tags, non-trivial parents, user, date and time, and a summary for
3338 tags, non-trivial parents, user, date and time, and a summary for
3339 each commit. When the -v/--verbose switch is used, the list of
3339 each commit. When the -v/--verbose switch is used, the list of
3340 changed files and full commit message are shown.
3340 changed files and full commit message are shown.
3341
3341
3342 With --graph the revisions are shown as an ASCII art DAG with the most
3342 With --graph the revisions are shown as an ASCII art DAG with the most
3343 recent changeset at the top.
3343 recent changeset at the top.
3344 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
3344 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
3345 and '+' represents a fork where the changeset from the lines below is a
3345 and '+' represents a fork where the changeset from the lines below is a
3346 parent of the 'o' merge on the same line.
3346 parent of the 'o' merge on the same line.
3347
3347
3348 .. note::
3348 .. note::
3349
3349
3350 :hg:`log --patch` may generate unexpected diff output for merge
3350 :hg:`log --patch` may generate unexpected diff output for merge
3351 changesets, as it will only compare the merge changeset against
3351 changesets, as it will only compare the merge changeset against
3352 its first parent. Also, only files different from BOTH parents
3352 its first parent. Also, only files different from BOTH parents
3353 will appear in files:.
3353 will appear in files:.
3354
3354
3355 .. note::
3355 .. note::
3356
3356
3357 For performance reasons, :hg:`log FILE` may omit duplicate changes
3357 For performance reasons, :hg:`log FILE` may omit duplicate changes
3358 made on branches and will not show removals or mode changes. To
3358 made on branches and will not show removals or mode changes. To
3359 see all such changes, use the --removed switch.
3359 see all such changes, use the --removed switch.
3360
3360
3361 .. container:: verbose
3361 .. container:: verbose
3362
3362
3363 Some examples:
3363 Some examples:
3364
3364
3365 - changesets with full descriptions and file lists::
3365 - changesets with full descriptions and file lists::
3366
3366
3367 hg log -v
3367 hg log -v
3368
3368
3369 - changesets ancestral to the working directory::
3369 - changesets ancestral to the working directory::
3370
3370
3371 hg log -f
3371 hg log -f
3372
3372
3373 - last 10 commits on the current branch::
3373 - last 10 commits on the current branch::
3374
3374
3375 hg log -l 10 -b .
3375 hg log -l 10 -b .
3376
3376
3377 - changesets showing all modifications of a file, including removals::
3377 - changesets showing all modifications of a file, including removals::
3378
3378
3379 hg log --removed file.c
3379 hg log --removed file.c
3380
3380
3381 - all changesets that touch a directory, with diffs, excluding merges::
3381 - all changesets that touch a directory, with diffs, excluding merges::
3382
3382
3383 hg log -Mp lib/
3383 hg log -Mp lib/
3384
3384
3385 - all revision numbers that match a keyword::
3385 - all revision numbers that match a keyword::
3386
3386
3387 hg log -k bug --template "{rev}\\n"
3387 hg log -k bug --template "{rev}\\n"
3388
3388
3389 - the full hash identifier of the working directory parent::
3389 - the full hash identifier of the working directory parent::
3390
3390
3391 hg log -r . --template "{node}\\n"
3391 hg log -r . --template "{node}\\n"
3392
3392
3393 - list available log templates::
3393 - list available log templates::
3394
3394
3395 hg log -T list
3395 hg log -T list
3396
3396
3397 - check if a given changeset is included in a tagged release::
3397 - check if a given changeset is included in a tagged release::
3398
3398
3399 hg log -r "a21ccf and ancestor(1.9)"
3399 hg log -r "a21ccf and ancestor(1.9)"
3400
3400
3401 - find all changesets by some user in a date range::
3401 - find all changesets by some user in a date range::
3402
3402
3403 hg log -k alice -d "may 2008 to jul 2008"
3403 hg log -k alice -d "may 2008 to jul 2008"
3404
3404
3405 - summary of all changesets after the last tag::
3405 - summary of all changesets after the last tag::
3406
3406
3407 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3407 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3408
3408
3409 See :hg:`help dates` for a list of formats valid for -d/--date.
3409 See :hg:`help dates` for a list of formats valid for -d/--date.
3410
3410
3411 See :hg:`help revisions` for more about specifying and ordering
3411 See :hg:`help revisions` for more about specifying and ordering
3412 revisions.
3412 revisions.
3413
3413
3414 See :hg:`help templates` for more about pre-packaged styles and
3414 See :hg:`help templates` for more about pre-packaged styles and
3415 specifying custom templates.
3415 specifying custom templates.
3416
3416
3417 Returns 0 on success.
3417 Returns 0 on success.
3418
3418
3419 """
3419 """
3420 if opts.get('follow') and opts.get('rev'):
3420 if opts.get('follow') and opts.get('rev'):
3421 opts['rev'] = [revsetlang.formatspec('reverse(::%lr)', opts.get('rev'))]
3421 opts['rev'] = [revsetlang.formatspec('reverse(::%lr)', opts.get('rev'))]
3422 del opts['follow']
3422 del opts['follow']
3423
3423
3424 if opts.get('graph'):
3424 if opts.get('graph'):
3425 return cmdutil.graphlog(ui, repo, *pats, **opts)
3425 return cmdutil.graphlog(ui, repo, *pats, **opts)
3426
3426
3427 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
3427 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
3428 limit = cmdutil.loglimit(opts)
3428 limit = cmdutil.loglimit(opts)
3429 count = 0
3429 count = 0
3430
3430
3431 getrenamed = None
3431 getrenamed = None
3432 if opts.get('copies'):
3432 if opts.get('copies'):
3433 endrev = None
3433 endrev = None
3434 if opts.get('rev'):
3434 if opts.get('rev'):
3435 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
3435 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
3436 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3436 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3437
3437
3438 ui.pager('log')
3438 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
3439 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
3439 for rev in revs:
3440 for rev in revs:
3440 if count == limit:
3441 if count == limit:
3441 break
3442 break
3442 ctx = repo[rev]
3443 ctx = repo[rev]
3443 copies = None
3444 copies = None
3444 if getrenamed is not None and rev:
3445 if getrenamed is not None and rev:
3445 copies = []
3446 copies = []
3446 for fn in ctx.files():
3447 for fn in ctx.files():
3447 rename = getrenamed(fn, rev)
3448 rename = getrenamed(fn, rev)
3448 if rename:
3449 if rename:
3449 copies.append((fn, rename[0]))
3450 copies.append((fn, rename[0]))
3450 if filematcher:
3451 if filematcher:
3451 revmatchfn = filematcher(ctx.rev())
3452 revmatchfn = filematcher(ctx.rev())
3452 else:
3453 else:
3453 revmatchfn = None
3454 revmatchfn = None
3454 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
3455 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
3455 if displayer.flush(ctx):
3456 if displayer.flush(ctx):
3456 count += 1
3457 count += 1
3457
3458
3458 displayer.close()
3459 displayer.close()
3459
3460
3460 @command('manifest',
3461 @command('manifest',
3461 [('r', 'rev', '', _('revision to display'), _('REV')),
3462 [('r', 'rev', '', _('revision to display'), _('REV')),
3462 ('', 'all', False, _("list files from all revisions"))]
3463 ('', 'all', False, _("list files from all revisions"))]
3463 + formatteropts,
3464 + formatteropts,
3464 _('[-r REV]'))
3465 _('[-r REV]'))
3465 def manifest(ui, repo, node=None, rev=None, **opts):
3466 def manifest(ui, repo, node=None, rev=None, **opts):
3466 """output the current or given revision of the project manifest
3467 """output the current or given revision of the project manifest
3467
3468
3468 Print a list of version controlled files for the given revision.
3469 Print a list of version controlled files for the given revision.
3469 If no revision is given, the first parent of the working directory
3470 If no revision is given, the first parent of the working directory
3470 is used, or the null revision if no revision is checked out.
3471 is used, or the null revision if no revision is checked out.
3471
3472
3472 With -v, print file permissions, symlink and executable bits.
3473 With -v, print file permissions, symlink and executable bits.
3473 With --debug, print file revision hashes.
3474 With --debug, print file revision hashes.
3474
3475
3475 If option --all is specified, the list of all files from all revisions
3476 If option --all is specified, the list of all files from all revisions
3476 is printed. This includes deleted and renamed files.
3477 is printed. This includes deleted and renamed files.
3477
3478
3478 Returns 0 on success.
3479 Returns 0 on success.
3479 """
3480 """
3480
3481
3481 fm = ui.formatter('manifest', opts)
3482 fm = ui.formatter('manifest', opts)
3482
3483
3483 if opts.get('all'):
3484 if opts.get('all'):
3484 if rev or node:
3485 if rev or node:
3485 raise error.Abort(_("can't specify a revision with --all"))
3486 raise error.Abort(_("can't specify a revision with --all"))
3486
3487
3487 res = []
3488 res = []
3488 prefix = "data/"
3489 prefix = "data/"
3489 suffix = ".i"
3490 suffix = ".i"
3490 plen = len(prefix)
3491 plen = len(prefix)
3491 slen = len(suffix)
3492 slen = len(suffix)
3492 with repo.lock():
3493 with repo.lock():
3493 for fn, b, size in repo.store.datafiles():
3494 for fn, b, size in repo.store.datafiles():
3494 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
3495 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
3495 res.append(fn[plen:-slen])
3496 res.append(fn[plen:-slen])
3496 for f in res:
3497 for f in res:
3497 fm.startitem()
3498 fm.startitem()
3498 fm.write("path", '%s\n', f)
3499 fm.write("path", '%s\n', f)
3499 fm.end()
3500 fm.end()
3500 return
3501 return
3501
3502
3502 if rev and node:
3503 if rev and node:
3503 raise error.Abort(_("please specify just one revision"))
3504 raise error.Abort(_("please specify just one revision"))
3504
3505
3505 if not node:
3506 if not node:
3506 node = rev
3507 node = rev
3507
3508
3508 char = {'l': '@', 'x': '*', '': ''}
3509 char = {'l': '@', 'x': '*', '': ''}
3509 mode = {'l': '644', 'x': '755', '': '644'}
3510 mode = {'l': '644', 'x': '755', '': '644'}
3510 ctx = scmutil.revsingle(repo, node)
3511 ctx = scmutil.revsingle(repo, node)
3511 mf = ctx.manifest()
3512 mf = ctx.manifest()
3512 for f in ctx:
3513 for f in ctx:
3513 fm.startitem()
3514 fm.startitem()
3514 fl = ctx[f].flags()
3515 fl = ctx[f].flags()
3515 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
3516 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
3516 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
3517 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
3517 fm.write('path', '%s\n', f)
3518 fm.write('path', '%s\n', f)
3518 fm.end()
3519 fm.end()
3519
3520
3520 @command('^merge',
3521 @command('^merge',
3521 [('f', 'force', None,
3522 [('f', 'force', None,
3522 _('force a merge including outstanding changes (DEPRECATED)')),
3523 _('force a merge including outstanding changes (DEPRECATED)')),
3523 ('r', 'rev', '', _('revision to merge'), _('REV')),
3524 ('r', 'rev', '', _('revision to merge'), _('REV')),
3524 ('P', 'preview', None,
3525 ('P', 'preview', None,
3525 _('review revisions to merge (no merge is performed)'))
3526 _('review revisions to merge (no merge is performed)'))
3526 ] + mergetoolopts,
3527 ] + mergetoolopts,
3527 _('[-P] [[-r] REV]'))
3528 _('[-P] [[-r] REV]'))
3528 def merge(ui, repo, node=None, **opts):
3529 def merge(ui, repo, node=None, **opts):
3529 """merge another revision into working directory
3530 """merge another revision into working directory
3530
3531
3531 The current working directory is updated with all changes made in
3532 The current working directory is updated with all changes made in
3532 the requested revision since the last common predecessor revision.
3533 the requested revision since the last common predecessor revision.
3533
3534
3534 Files that changed between either parent are marked as changed for
3535 Files that changed between either parent are marked as changed for
3535 the next commit and a commit must be performed before any further
3536 the next commit and a commit must be performed before any further
3536 updates to the repository are allowed. The next commit will have
3537 updates to the repository are allowed. The next commit will have
3537 two parents.
3538 two parents.
3538
3539
3539 ``--tool`` can be used to specify the merge tool used for file
3540 ``--tool`` can be used to specify the merge tool used for file
3540 merges. It overrides the HGMERGE environment variable and your
3541 merges. It overrides the HGMERGE environment variable and your
3541 configuration files. See :hg:`help merge-tools` for options.
3542 configuration files. See :hg:`help merge-tools` for options.
3542
3543
3543 If no revision is specified, the working directory's parent is a
3544 If no revision is specified, the working directory's parent is a
3544 head revision, and the current branch contains exactly one other
3545 head revision, and the current branch contains exactly one other
3545 head, the other head is merged with by default. Otherwise, an
3546 head, the other head is merged with by default. Otherwise, an
3546 explicit revision with which to merge with must be provided.
3547 explicit revision with which to merge with must be provided.
3547
3548
3548 See :hg:`help resolve` for information on handling file conflicts.
3549 See :hg:`help resolve` for information on handling file conflicts.
3549
3550
3550 To undo an uncommitted merge, use :hg:`update --clean .` which
3551 To undo an uncommitted merge, use :hg:`update --clean .` which
3551 will check out a clean copy of the original merge parent, losing
3552 will check out a clean copy of the original merge parent, losing
3552 all changes.
3553 all changes.
3553
3554
3554 Returns 0 on success, 1 if there are unresolved files.
3555 Returns 0 on success, 1 if there are unresolved files.
3555 """
3556 """
3556
3557
3557 if opts.get('rev') and node:
3558 if opts.get('rev') and node:
3558 raise error.Abort(_("please specify just one revision"))
3559 raise error.Abort(_("please specify just one revision"))
3559 if not node:
3560 if not node:
3560 node = opts.get('rev')
3561 node = opts.get('rev')
3561
3562
3562 if node:
3563 if node:
3563 node = scmutil.revsingle(repo, node).node()
3564 node = scmutil.revsingle(repo, node).node()
3564
3565
3565 if not node:
3566 if not node:
3566 node = repo[destutil.destmerge(repo)].node()
3567 node = repo[destutil.destmerge(repo)].node()
3567
3568
3568 if opts.get('preview'):
3569 if opts.get('preview'):
3569 # find nodes that are ancestors of p2 but not of p1
3570 # find nodes that are ancestors of p2 but not of p1
3570 p1 = repo.lookup('.')
3571 p1 = repo.lookup('.')
3571 p2 = repo.lookup(node)
3572 p2 = repo.lookup(node)
3572 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
3573 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
3573
3574
3574 displayer = cmdutil.show_changeset(ui, repo, opts)
3575 displayer = cmdutil.show_changeset(ui, repo, opts)
3575 for node in nodes:
3576 for node in nodes:
3576 displayer.show(repo[node])
3577 displayer.show(repo[node])
3577 displayer.close()
3578 displayer.close()
3578 return 0
3579 return 0
3579
3580
3580 try:
3581 try:
3581 # ui.forcemerge is an internal variable, do not document
3582 # ui.forcemerge is an internal variable, do not document
3582 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
3583 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
3583 force = opts.get('force')
3584 force = opts.get('force')
3584 labels = ['working copy', 'merge rev']
3585 labels = ['working copy', 'merge rev']
3585 return hg.merge(repo, node, force=force, mergeforce=force,
3586 return hg.merge(repo, node, force=force, mergeforce=force,
3586 labels=labels)
3587 labels=labels)
3587 finally:
3588 finally:
3588 ui.setconfig('ui', 'forcemerge', '', 'merge')
3589 ui.setconfig('ui', 'forcemerge', '', 'merge')
3589
3590
3590 @command('outgoing|out',
3591 @command('outgoing|out',
3591 [('f', 'force', None, _('run even when the destination is unrelated')),
3592 [('f', 'force', None, _('run even when the destination is unrelated')),
3592 ('r', 'rev', [],
3593 ('r', 'rev', [],
3593 _('a changeset intended to be included in the destination'), _('REV')),
3594 _('a changeset intended to be included in the destination'), _('REV')),
3594 ('n', 'newest-first', None, _('show newest record first')),
3595 ('n', 'newest-first', None, _('show newest record first')),
3595 ('B', 'bookmarks', False, _('compare bookmarks')),
3596 ('B', 'bookmarks', False, _('compare bookmarks')),
3596 ('b', 'branch', [], _('a specific branch you would like to push'),
3597 ('b', 'branch', [], _('a specific branch you would like to push'),
3597 _('BRANCH')),
3598 _('BRANCH')),
3598 ] + logopts + remoteopts + subrepoopts,
3599 ] + logopts + remoteopts + subrepoopts,
3599 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
3600 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
3600 def outgoing(ui, repo, dest=None, **opts):
3601 def outgoing(ui, repo, dest=None, **opts):
3601 """show changesets not found in the destination
3602 """show changesets not found in the destination
3602
3603
3603 Show changesets not found in the specified destination repository
3604 Show changesets not found in the specified destination repository
3604 or the default push location. These are the changesets that would
3605 or the default push location. These are the changesets that would
3605 be pushed if a push was requested.
3606 be pushed if a push was requested.
3606
3607
3607 See pull for details of valid destination formats.
3608 See pull for details of valid destination formats.
3608
3609
3609 .. container:: verbose
3610 .. container:: verbose
3610
3611
3611 With -B/--bookmarks, the result of bookmark comparison between
3612 With -B/--bookmarks, the result of bookmark comparison between
3612 local and remote repositories is displayed. With -v/--verbose,
3613 local and remote repositories is displayed. With -v/--verbose,
3613 status is also displayed for each bookmark like below::
3614 status is also displayed for each bookmark like below::
3614
3615
3615 BM1 01234567890a added
3616 BM1 01234567890a added
3616 BM2 deleted
3617 BM2 deleted
3617 BM3 234567890abc advanced
3618 BM3 234567890abc advanced
3618 BM4 34567890abcd diverged
3619 BM4 34567890abcd diverged
3619 BM5 4567890abcde changed
3620 BM5 4567890abcde changed
3620
3621
3621 The action taken when pushing depends on the
3622 The action taken when pushing depends on the
3622 status of each bookmark:
3623 status of each bookmark:
3623
3624
3624 :``added``: push with ``-B`` will create it
3625 :``added``: push with ``-B`` will create it
3625 :``deleted``: push with ``-B`` will delete it
3626 :``deleted``: push with ``-B`` will delete it
3626 :``advanced``: push will update it
3627 :``advanced``: push will update it
3627 :``diverged``: push with ``-B`` will update it
3628 :``diverged``: push with ``-B`` will update it
3628 :``changed``: push with ``-B`` will update it
3629 :``changed``: push with ``-B`` will update it
3629
3630
3630 From the point of view of pushing behavior, bookmarks
3631 From the point of view of pushing behavior, bookmarks
3631 existing only in the remote repository are treated as
3632 existing only in the remote repository are treated as
3632 ``deleted``, even if it is in fact added remotely.
3633 ``deleted``, even if it is in fact added remotely.
3633
3634
3634 Returns 0 if there are outgoing changes, 1 otherwise.
3635 Returns 0 if there are outgoing changes, 1 otherwise.
3635 """
3636 """
3636 if opts.get('graph'):
3637 if opts.get('graph'):
3637 cmdutil.checkunsupportedgraphflags([], opts)
3638 cmdutil.checkunsupportedgraphflags([], opts)
3638 o, other = hg._outgoing(ui, repo, dest, opts)
3639 o, other = hg._outgoing(ui, repo, dest, opts)
3639 if not o:
3640 if not o:
3640 cmdutil.outgoinghooks(ui, repo, other, opts, o)
3641 cmdutil.outgoinghooks(ui, repo, other, opts, o)
3641 return
3642 return
3642
3643
3643 revdag = cmdutil.graphrevs(repo, o, opts)
3644 revdag = cmdutil.graphrevs(repo, o, opts)
3644 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
3645 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
3645 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
3646 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
3646 cmdutil.outgoinghooks(ui, repo, other, opts, o)
3647 cmdutil.outgoinghooks(ui, repo, other, opts, o)
3647 return 0
3648 return 0
3648
3649
3649 if opts.get('bookmarks'):
3650 if opts.get('bookmarks'):
3650 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3651 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3651 dest, branches = hg.parseurl(dest, opts.get('branch'))
3652 dest, branches = hg.parseurl(dest, opts.get('branch'))
3652 other = hg.peer(repo, opts, dest)
3653 other = hg.peer(repo, opts, dest)
3653 if 'bookmarks' not in other.listkeys('namespaces'):
3654 if 'bookmarks' not in other.listkeys('namespaces'):
3654 ui.warn(_("remote doesn't support bookmarks\n"))
3655 ui.warn(_("remote doesn't support bookmarks\n"))
3655 return 0
3656 return 0
3656 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
3657 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
3657 return bookmarks.outgoing(ui, repo, other)
3658 return bookmarks.outgoing(ui, repo, other)
3658
3659
3659 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
3660 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
3660 try:
3661 try:
3661 return hg.outgoing(ui, repo, dest, opts)
3662 return hg.outgoing(ui, repo, dest, opts)
3662 finally:
3663 finally:
3663 del repo._subtoppath
3664 del repo._subtoppath
3664
3665
3665 @command('parents',
3666 @command('parents',
3666 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
3667 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
3667 ] + templateopts,
3668 ] + templateopts,
3668 _('[-r REV] [FILE]'),
3669 _('[-r REV] [FILE]'),
3669 inferrepo=True)
3670 inferrepo=True)
3670 def parents(ui, repo, file_=None, **opts):
3671 def parents(ui, repo, file_=None, **opts):
3671 """show the parents of the working directory or revision (DEPRECATED)
3672 """show the parents of the working directory or revision (DEPRECATED)
3672
3673
3673 Print the working directory's parent revisions. If a revision is
3674 Print the working directory's parent revisions. If a revision is
3674 given via -r/--rev, the parent of that revision will be printed.
3675 given via -r/--rev, the parent of that revision will be printed.
3675 If a file argument is given, the revision in which the file was
3676 If a file argument is given, the revision in which the file was
3676 last changed (before the working directory revision or the
3677 last changed (before the working directory revision or the
3677 argument to --rev if given) is printed.
3678 argument to --rev if given) is printed.
3678
3679
3679 This command is equivalent to::
3680 This command is equivalent to::
3680
3681
3681 hg log -r "p1()+p2()" or
3682 hg log -r "p1()+p2()" or
3682 hg log -r "p1(REV)+p2(REV)" or
3683 hg log -r "p1(REV)+p2(REV)" or
3683 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
3684 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
3684 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
3685 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
3685
3686
3686 See :hg:`summary` and :hg:`help revsets` for related information.
3687 See :hg:`summary` and :hg:`help revsets` for related information.
3687
3688
3688 Returns 0 on success.
3689 Returns 0 on success.
3689 """
3690 """
3690
3691
3691 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3692 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3692
3693
3693 if file_:
3694 if file_:
3694 m = scmutil.match(ctx, (file_,), opts)
3695 m = scmutil.match(ctx, (file_,), opts)
3695 if m.anypats() or len(m.files()) != 1:
3696 if m.anypats() or len(m.files()) != 1:
3696 raise error.Abort(_('can only specify an explicit filename'))
3697 raise error.Abort(_('can only specify an explicit filename'))
3697 file_ = m.files()[0]
3698 file_ = m.files()[0]
3698 filenodes = []
3699 filenodes = []
3699 for cp in ctx.parents():
3700 for cp in ctx.parents():
3700 if not cp:
3701 if not cp:
3701 continue
3702 continue
3702 try:
3703 try:
3703 filenodes.append(cp.filenode(file_))
3704 filenodes.append(cp.filenode(file_))
3704 except error.LookupError:
3705 except error.LookupError:
3705 pass
3706 pass
3706 if not filenodes:
3707 if not filenodes:
3707 raise error.Abort(_("'%s' not found in manifest!") % file_)
3708 raise error.Abort(_("'%s' not found in manifest!") % file_)
3708 p = []
3709 p = []
3709 for fn in filenodes:
3710 for fn in filenodes:
3710 fctx = repo.filectx(file_, fileid=fn)
3711 fctx = repo.filectx(file_, fileid=fn)
3711 p.append(fctx.node())
3712 p.append(fctx.node())
3712 else:
3713 else:
3713 p = [cp.node() for cp in ctx.parents()]
3714 p = [cp.node() for cp in ctx.parents()]
3714
3715
3715 displayer = cmdutil.show_changeset(ui, repo, opts)
3716 displayer = cmdutil.show_changeset(ui, repo, opts)
3716 for n in p:
3717 for n in p:
3717 if n != nullid:
3718 if n != nullid:
3718 displayer.show(repo[n])
3719 displayer.show(repo[n])
3719 displayer.close()
3720 displayer.close()
3720
3721
3721 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True)
3722 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True)
3722 def paths(ui, repo, search=None, **opts):
3723 def paths(ui, repo, search=None, **opts):
3723 """show aliases for remote repositories
3724 """show aliases for remote repositories
3724
3725
3725 Show definition of symbolic path name NAME. If no name is given,
3726 Show definition of symbolic path name NAME. If no name is given,
3726 show definition of all available names.
3727 show definition of all available names.
3727
3728
3728 Option -q/--quiet suppresses all output when searching for NAME
3729 Option -q/--quiet suppresses all output when searching for NAME
3729 and shows only the path names when listing all definitions.
3730 and shows only the path names when listing all definitions.
3730
3731
3731 Path names are defined in the [paths] section of your
3732 Path names are defined in the [paths] section of your
3732 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
3733 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
3733 repository, ``.hg/hgrc`` is used, too.
3734 repository, ``.hg/hgrc`` is used, too.
3734
3735
3735 The path names ``default`` and ``default-push`` have a special
3736 The path names ``default`` and ``default-push`` have a special
3736 meaning. When performing a push or pull operation, they are used
3737 meaning. When performing a push or pull operation, they are used
3737 as fallbacks if no location is specified on the command-line.
3738 as fallbacks if no location is specified on the command-line.
3738 When ``default-push`` is set, it will be used for push and
3739 When ``default-push`` is set, it will be used for push and
3739 ``default`` will be used for pull; otherwise ``default`` is used
3740 ``default`` will be used for pull; otherwise ``default`` is used
3740 as the fallback for both. When cloning a repository, the clone
3741 as the fallback for both. When cloning a repository, the clone
3741 source is written as ``default`` in ``.hg/hgrc``.
3742 source is written as ``default`` in ``.hg/hgrc``.
3742
3743
3743 .. note::
3744 .. note::
3744
3745
3745 ``default`` and ``default-push`` apply to all inbound (e.g.
3746 ``default`` and ``default-push`` apply to all inbound (e.g.
3746 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
3747 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
3747 and :hg:`bundle`) operations.
3748 and :hg:`bundle`) operations.
3748
3749
3749 See :hg:`help urls` for more information.
3750 See :hg:`help urls` for more information.
3750
3751
3751 Returns 0 on success.
3752 Returns 0 on success.
3752 """
3753 """
3753 if search:
3754 if search:
3754 pathitems = [(name, path) for name, path in ui.paths.iteritems()
3755 pathitems = [(name, path) for name, path in ui.paths.iteritems()
3755 if name == search]
3756 if name == search]
3756 else:
3757 else:
3757 pathitems = sorted(ui.paths.iteritems())
3758 pathitems = sorted(ui.paths.iteritems())
3758
3759
3759 fm = ui.formatter('paths', opts)
3760 fm = ui.formatter('paths', opts)
3760 if fm.isplain():
3761 if fm.isplain():
3761 hidepassword = util.hidepassword
3762 hidepassword = util.hidepassword
3762 else:
3763 else:
3763 hidepassword = str
3764 hidepassword = str
3764 if ui.quiet:
3765 if ui.quiet:
3765 namefmt = '%s\n'
3766 namefmt = '%s\n'
3766 else:
3767 else:
3767 namefmt = '%s = '
3768 namefmt = '%s = '
3768 showsubopts = not search and not ui.quiet
3769 showsubopts = not search and not ui.quiet
3769
3770
3770 for name, path in pathitems:
3771 for name, path in pathitems:
3771 fm.startitem()
3772 fm.startitem()
3772 fm.condwrite(not search, 'name', namefmt, name)
3773 fm.condwrite(not search, 'name', namefmt, name)
3773 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
3774 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
3774 for subopt, value in sorted(path.suboptions.items()):
3775 for subopt, value in sorted(path.suboptions.items()):
3775 assert subopt not in ('name', 'url')
3776 assert subopt not in ('name', 'url')
3776 if showsubopts:
3777 if showsubopts:
3777 fm.plain('%s:%s = ' % (name, subopt))
3778 fm.plain('%s:%s = ' % (name, subopt))
3778 fm.condwrite(showsubopts, subopt, '%s\n', value)
3779 fm.condwrite(showsubopts, subopt, '%s\n', value)
3779
3780
3780 fm.end()
3781 fm.end()
3781
3782
3782 if search and not pathitems:
3783 if search and not pathitems:
3783 if not ui.quiet:
3784 if not ui.quiet:
3784 ui.warn(_("not found!\n"))
3785 ui.warn(_("not found!\n"))
3785 return 1
3786 return 1
3786 else:
3787 else:
3787 return 0
3788 return 0
3788
3789
3789 @command('phase',
3790 @command('phase',
3790 [('p', 'public', False, _('set changeset phase to public')),
3791 [('p', 'public', False, _('set changeset phase to public')),
3791 ('d', 'draft', False, _('set changeset phase to draft')),
3792 ('d', 'draft', False, _('set changeset phase to draft')),
3792 ('s', 'secret', False, _('set changeset phase to secret')),
3793 ('s', 'secret', False, _('set changeset phase to secret')),
3793 ('f', 'force', False, _('allow to move boundary backward')),
3794 ('f', 'force', False, _('allow to move boundary backward')),
3794 ('r', 'rev', [], _('target revision'), _('REV')),
3795 ('r', 'rev', [], _('target revision'), _('REV')),
3795 ],
3796 ],
3796 _('[-p|-d|-s] [-f] [-r] [REV...]'))
3797 _('[-p|-d|-s] [-f] [-r] [REV...]'))
3797 def phase(ui, repo, *revs, **opts):
3798 def phase(ui, repo, *revs, **opts):
3798 """set or show the current phase name
3799 """set or show the current phase name
3799
3800
3800 With no argument, show the phase name of the current revision(s).
3801 With no argument, show the phase name of the current revision(s).
3801
3802
3802 With one of -p/--public, -d/--draft or -s/--secret, change the
3803 With one of -p/--public, -d/--draft or -s/--secret, change the
3803 phase value of the specified revisions.
3804 phase value of the specified revisions.
3804
3805
3805 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
3806 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
3806 lower phase to an higher phase. Phases are ordered as follows::
3807 lower phase to an higher phase. Phases are ordered as follows::
3807
3808
3808 public < draft < secret
3809 public < draft < secret
3809
3810
3810 Returns 0 on success, 1 if some phases could not be changed.
3811 Returns 0 on success, 1 if some phases could not be changed.
3811
3812
3812 (For more information about the phases concept, see :hg:`help phases`.)
3813 (For more information about the phases concept, see :hg:`help phases`.)
3813 """
3814 """
3814 # search for a unique phase argument
3815 # search for a unique phase argument
3815 targetphase = None
3816 targetphase = None
3816 for idx, name in enumerate(phases.phasenames):
3817 for idx, name in enumerate(phases.phasenames):
3817 if opts[name]:
3818 if opts[name]:
3818 if targetphase is not None:
3819 if targetphase is not None:
3819 raise error.Abort(_('only one phase can be specified'))
3820 raise error.Abort(_('only one phase can be specified'))
3820 targetphase = idx
3821 targetphase = idx
3821
3822
3822 # look for specified revision
3823 # look for specified revision
3823 revs = list(revs)
3824 revs = list(revs)
3824 revs.extend(opts['rev'])
3825 revs.extend(opts['rev'])
3825 if not revs:
3826 if not revs:
3826 # display both parents as the second parent phase can influence
3827 # display both parents as the second parent phase can influence
3827 # the phase of a merge commit
3828 # the phase of a merge commit
3828 revs = [c.rev() for c in repo[None].parents()]
3829 revs = [c.rev() for c in repo[None].parents()]
3829
3830
3830 revs = scmutil.revrange(repo, revs)
3831 revs = scmutil.revrange(repo, revs)
3831
3832
3832 lock = None
3833 lock = None
3833 ret = 0
3834 ret = 0
3834 if targetphase is None:
3835 if targetphase is None:
3835 # display
3836 # display
3836 for r in revs:
3837 for r in revs:
3837 ctx = repo[r]
3838 ctx = repo[r]
3838 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
3839 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
3839 else:
3840 else:
3840 tr = None
3841 tr = None
3841 lock = repo.lock()
3842 lock = repo.lock()
3842 try:
3843 try:
3843 tr = repo.transaction("phase")
3844 tr = repo.transaction("phase")
3844 # set phase
3845 # set phase
3845 if not revs:
3846 if not revs:
3846 raise error.Abort(_('empty revision set'))
3847 raise error.Abort(_('empty revision set'))
3847 nodes = [repo[r].node() for r in revs]
3848 nodes = [repo[r].node() for r in revs]
3848 # moving revision from public to draft may hide them
3849 # moving revision from public to draft may hide them
3849 # We have to check result on an unfiltered repository
3850 # We have to check result on an unfiltered repository
3850 unfi = repo.unfiltered()
3851 unfi = repo.unfiltered()
3851 getphase = unfi._phasecache.phase
3852 getphase = unfi._phasecache.phase
3852 olddata = [getphase(unfi, r) for r in unfi]
3853 olddata = [getphase(unfi, r) for r in unfi]
3853 phases.advanceboundary(repo, tr, targetphase, nodes)
3854 phases.advanceboundary(repo, tr, targetphase, nodes)
3854 if opts['force']:
3855 if opts['force']:
3855 phases.retractboundary(repo, tr, targetphase, nodes)
3856 phases.retractboundary(repo, tr, targetphase, nodes)
3856 tr.close()
3857 tr.close()
3857 finally:
3858 finally:
3858 if tr is not None:
3859 if tr is not None:
3859 tr.release()
3860 tr.release()
3860 lock.release()
3861 lock.release()
3861 getphase = unfi._phasecache.phase
3862 getphase = unfi._phasecache.phase
3862 newdata = [getphase(unfi, r) for r in unfi]
3863 newdata = [getphase(unfi, r) for r in unfi]
3863 changes = sum(newdata[r] != olddata[r] for r in unfi)
3864 changes = sum(newdata[r] != olddata[r] for r in unfi)
3864 cl = unfi.changelog
3865 cl = unfi.changelog
3865 rejected = [n for n in nodes
3866 rejected = [n for n in nodes
3866 if newdata[cl.rev(n)] < targetphase]
3867 if newdata[cl.rev(n)] < targetphase]
3867 if rejected:
3868 if rejected:
3868 ui.warn(_('cannot move %i changesets to a higher '
3869 ui.warn(_('cannot move %i changesets to a higher '
3869 'phase, use --force\n') % len(rejected))
3870 'phase, use --force\n') % len(rejected))
3870 ret = 1
3871 ret = 1
3871 if changes:
3872 if changes:
3872 msg = _('phase changed for %i changesets\n') % changes
3873 msg = _('phase changed for %i changesets\n') % changes
3873 if ret:
3874 if ret:
3874 ui.status(msg)
3875 ui.status(msg)
3875 else:
3876 else:
3876 ui.note(msg)
3877 ui.note(msg)
3877 else:
3878 else:
3878 ui.warn(_('no phases changed\n'))
3879 ui.warn(_('no phases changed\n'))
3879 return ret
3880 return ret
3880
3881
3881 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
3882 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
3882 """Run after a changegroup has been added via pull/unbundle
3883 """Run after a changegroup has been added via pull/unbundle
3883
3884
3884 This takes arguments below:
3885 This takes arguments below:
3885
3886
3886 :modheads: change of heads by pull/unbundle
3887 :modheads: change of heads by pull/unbundle
3887 :optupdate: updating working directory is needed or not
3888 :optupdate: updating working directory is needed or not
3888 :checkout: update destination revision (or None to default destination)
3889 :checkout: update destination revision (or None to default destination)
3889 :brev: a name, which might be a bookmark to be activated after updating
3890 :brev: a name, which might be a bookmark to be activated after updating
3890 """
3891 """
3891 if modheads == 0:
3892 if modheads == 0:
3892 return
3893 return
3893 if optupdate:
3894 if optupdate:
3894 try:
3895 try:
3895 return hg.updatetotally(ui, repo, checkout, brev)
3896 return hg.updatetotally(ui, repo, checkout, brev)
3896 except error.UpdateAbort as inst:
3897 except error.UpdateAbort as inst:
3897 msg = _("not updating: %s") % str(inst)
3898 msg = _("not updating: %s") % str(inst)
3898 hint = inst.hint
3899 hint = inst.hint
3899 raise error.UpdateAbort(msg, hint=hint)
3900 raise error.UpdateAbort(msg, hint=hint)
3900 if modheads > 1:
3901 if modheads > 1:
3901 currentbranchheads = len(repo.branchheads())
3902 currentbranchheads = len(repo.branchheads())
3902 if currentbranchheads == modheads:
3903 if currentbranchheads == modheads:
3903 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
3904 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
3904 elif currentbranchheads > 1:
3905 elif currentbranchheads > 1:
3905 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
3906 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
3906 "merge)\n"))
3907 "merge)\n"))
3907 else:
3908 else:
3908 ui.status(_("(run 'hg heads' to see heads)\n"))
3909 ui.status(_("(run 'hg heads' to see heads)\n"))
3909 else:
3910 else:
3910 ui.status(_("(run 'hg update' to get a working copy)\n"))
3911 ui.status(_("(run 'hg update' to get a working copy)\n"))
3911
3912
3912 @command('^pull',
3913 @command('^pull',
3913 [('u', 'update', None,
3914 [('u', 'update', None,
3914 _('update to new branch head if changesets were pulled')),
3915 _('update to new branch head if changesets were pulled')),
3915 ('f', 'force', None, _('run even when remote repository is unrelated')),
3916 ('f', 'force', None, _('run even when remote repository is unrelated')),
3916 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3917 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3917 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
3918 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
3918 ('b', 'branch', [], _('a specific branch you would like to pull'),
3919 ('b', 'branch', [], _('a specific branch you would like to pull'),
3919 _('BRANCH')),
3920 _('BRANCH')),
3920 ] + remoteopts,
3921 ] + remoteopts,
3921 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
3922 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
3922 def pull(ui, repo, source="default", **opts):
3923 def pull(ui, repo, source="default", **opts):
3923 """pull changes from the specified source
3924 """pull changes from the specified source
3924
3925
3925 Pull changes from a remote repository to a local one.
3926 Pull changes from a remote repository to a local one.
3926
3927
3927 This finds all changes from the repository at the specified path
3928 This finds all changes from the repository at the specified path
3928 or URL and adds them to a local repository (the current one unless
3929 or URL and adds them to a local repository (the current one unless
3929 -R is specified). By default, this does not update the copy of the
3930 -R is specified). By default, this does not update the copy of the
3930 project in the working directory.
3931 project in the working directory.
3931
3932
3932 Use :hg:`incoming` if you want to see what would have been added
3933 Use :hg:`incoming` if you want to see what would have been added
3933 by a pull at the time you issued this command. If you then decide
3934 by a pull at the time you issued this command. If you then decide
3934 to add those changes to the repository, you should use :hg:`pull
3935 to add those changes to the repository, you should use :hg:`pull
3935 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
3936 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
3936
3937
3937 If SOURCE is omitted, the 'default' path will be used.
3938 If SOURCE is omitted, the 'default' path will be used.
3938 See :hg:`help urls` for more information.
3939 See :hg:`help urls` for more information.
3939
3940
3940 Specifying bookmark as ``.`` is equivalent to specifying the active
3941 Specifying bookmark as ``.`` is equivalent to specifying the active
3941 bookmark's name.
3942 bookmark's name.
3942
3943
3943 Returns 0 on success, 1 if an update had unresolved files.
3944 Returns 0 on success, 1 if an update had unresolved files.
3944 """
3945 """
3945 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
3946 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
3946 ui.status(_('pulling from %s\n') % util.hidepassword(source))
3947 ui.status(_('pulling from %s\n') % util.hidepassword(source))
3947 other = hg.peer(repo, opts, source)
3948 other = hg.peer(repo, opts, source)
3948 try:
3949 try:
3949 revs, checkout = hg.addbranchrevs(repo, other, branches,
3950 revs, checkout = hg.addbranchrevs(repo, other, branches,
3950 opts.get('rev'))
3951 opts.get('rev'))
3951
3952
3952
3953
3953 pullopargs = {}
3954 pullopargs = {}
3954 if opts.get('bookmark'):
3955 if opts.get('bookmark'):
3955 if not revs:
3956 if not revs:
3956 revs = []
3957 revs = []
3957 # The list of bookmark used here is not the one used to actually
3958 # The list of bookmark used here is not the one used to actually
3958 # update the bookmark name. This can result in the revision pulled
3959 # update the bookmark name. This can result in the revision pulled
3959 # not ending up with the name of the bookmark because of a race
3960 # not ending up with the name of the bookmark because of a race
3960 # condition on the server. (See issue 4689 for details)
3961 # condition on the server. (See issue 4689 for details)
3961 remotebookmarks = other.listkeys('bookmarks')
3962 remotebookmarks = other.listkeys('bookmarks')
3962 pullopargs['remotebookmarks'] = remotebookmarks
3963 pullopargs['remotebookmarks'] = remotebookmarks
3963 for b in opts['bookmark']:
3964 for b in opts['bookmark']:
3964 b = repo._bookmarks.expandname(b)
3965 b = repo._bookmarks.expandname(b)
3965 if b not in remotebookmarks:
3966 if b not in remotebookmarks:
3966 raise error.Abort(_('remote bookmark %s not found!') % b)
3967 raise error.Abort(_('remote bookmark %s not found!') % b)
3967 revs.append(remotebookmarks[b])
3968 revs.append(remotebookmarks[b])
3968
3969
3969 if revs:
3970 if revs:
3970 try:
3971 try:
3971 # When 'rev' is a bookmark name, we cannot guarantee that it
3972 # When 'rev' is a bookmark name, we cannot guarantee that it
3972 # will be updated with that name because of a race condition
3973 # will be updated with that name because of a race condition
3973 # server side. (See issue 4689 for details)
3974 # server side. (See issue 4689 for details)
3974 oldrevs = revs
3975 oldrevs = revs
3975 revs = [] # actually, nodes
3976 revs = [] # actually, nodes
3976 for r in oldrevs:
3977 for r in oldrevs:
3977 node = other.lookup(r)
3978 node = other.lookup(r)
3978 revs.append(node)
3979 revs.append(node)
3979 if r == checkout:
3980 if r == checkout:
3980 checkout = node
3981 checkout = node
3981 except error.CapabilityError:
3982 except error.CapabilityError:
3982 err = _("other repository doesn't support revision lookup, "
3983 err = _("other repository doesn't support revision lookup, "
3983 "so a rev cannot be specified.")
3984 "so a rev cannot be specified.")
3984 raise error.Abort(err)
3985 raise error.Abort(err)
3985
3986
3986 pullopargs.update(opts.get('opargs', {}))
3987 pullopargs.update(opts.get('opargs', {}))
3987 modheads = exchange.pull(repo, other, heads=revs,
3988 modheads = exchange.pull(repo, other, heads=revs,
3988 force=opts.get('force'),
3989 force=opts.get('force'),
3989 bookmarks=opts.get('bookmark', ()),
3990 bookmarks=opts.get('bookmark', ()),
3990 opargs=pullopargs).cgresult
3991 opargs=pullopargs).cgresult
3991
3992
3992 # brev is a name, which might be a bookmark to be activated at
3993 # brev is a name, which might be a bookmark to be activated at
3993 # the end of the update. In other words, it is an explicit
3994 # the end of the update. In other words, it is an explicit
3994 # destination of the update
3995 # destination of the update
3995 brev = None
3996 brev = None
3996
3997
3997 if checkout:
3998 if checkout:
3998 checkout = str(repo.changelog.rev(checkout))
3999 checkout = str(repo.changelog.rev(checkout))
3999
4000
4000 # order below depends on implementation of
4001 # order below depends on implementation of
4001 # hg.addbranchrevs(). opts['bookmark'] is ignored,
4002 # hg.addbranchrevs(). opts['bookmark'] is ignored,
4002 # because 'checkout' is determined without it.
4003 # because 'checkout' is determined without it.
4003 if opts.get('rev'):
4004 if opts.get('rev'):
4004 brev = opts['rev'][0]
4005 brev = opts['rev'][0]
4005 elif opts.get('branch'):
4006 elif opts.get('branch'):
4006 brev = opts['branch'][0]
4007 brev = opts['branch'][0]
4007 else:
4008 else:
4008 brev = branches[0]
4009 brev = branches[0]
4009 repo._subtoppath = source
4010 repo._subtoppath = source
4010 try:
4011 try:
4011 ret = postincoming(ui, repo, modheads, opts.get('update'),
4012 ret = postincoming(ui, repo, modheads, opts.get('update'),
4012 checkout, brev)
4013 checkout, brev)
4013
4014
4014 finally:
4015 finally:
4015 del repo._subtoppath
4016 del repo._subtoppath
4016
4017
4017 finally:
4018 finally:
4018 other.close()
4019 other.close()
4019 return ret
4020 return ret
4020
4021
4021 @command('^push',
4022 @command('^push',
4022 [('f', 'force', None, _('force push')),
4023 [('f', 'force', None, _('force push')),
4023 ('r', 'rev', [],
4024 ('r', 'rev', [],
4024 _('a changeset intended to be included in the destination'),
4025 _('a changeset intended to be included in the destination'),
4025 _('REV')),
4026 _('REV')),
4026 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4027 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4027 ('b', 'branch', [],
4028 ('b', 'branch', [],
4028 _('a specific branch you would like to push'), _('BRANCH')),
4029 _('a specific branch you would like to push'), _('BRANCH')),
4029 ('', 'new-branch', False, _('allow pushing a new branch')),
4030 ('', 'new-branch', False, _('allow pushing a new branch')),
4030 ] + remoteopts,
4031 ] + remoteopts,
4031 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4032 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4032 def push(ui, repo, dest=None, **opts):
4033 def push(ui, repo, dest=None, **opts):
4033 """push changes to the specified destination
4034 """push changes to the specified destination
4034
4035
4035 Push changesets from the local repository to the specified
4036 Push changesets from the local repository to the specified
4036 destination.
4037 destination.
4037
4038
4038 This operation is symmetrical to pull: it is identical to a pull
4039 This operation is symmetrical to pull: it is identical to a pull
4039 in the destination repository from the current one.
4040 in the destination repository from the current one.
4040
4041
4041 By default, push will not allow creation of new heads at the
4042 By default, push will not allow creation of new heads at the
4042 destination, since multiple heads would make it unclear which head
4043 destination, since multiple heads would make it unclear which head
4043 to use. In this situation, it is recommended to pull and merge
4044 to use. In this situation, it is recommended to pull and merge
4044 before pushing.
4045 before pushing.
4045
4046
4046 Use --new-branch if you want to allow push to create a new named
4047 Use --new-branch if you want to allow push to create a new named
4047 branch that is not present at the destination. This allows you to
4048 branch that is not present at the destination. This allows you to
4048 only create a new branch without forcing other changes.
4049 only create a new branch without forcing other changes.
4049
4050
4050 .. note::
4051 .. note::
4051
4052
4052 Extra care should be taken with the -f/--force option,
4053 Extra care should be taken with the -f/--force option,
4053 which will push all new heads on all branches, an action which will
4054 which will push all new heads on all branches, an action which will
4054 almost always cause confusion for collaborators.
4055 almost always cause confusion for collaborators.
4055
4056
4056 If -r/--rev is used, the specified revision and all its ancestors
4057 If -r/--rev is used, the specified revision and all its ancestors
4057 will be pushed to the remote repository.
4058 will be pushed to the remote repository.
4058
4059
4059 If -B/--bookmark is used, the specified bookmarked revision, its
4060 If -B/--bookmark is used, the specified bookmarked revision, its
4060 ancestors, and the bookmark will be pushed to the remote
4061 ancestors, and the bookmark will be pushed to the remote
4061 repository. Specifying ``.`` is equivalent to specifying the active
4062 repository. Specifying ``.`` is equivalent to specifying the active
4062 bookmark's name.
4063 bookmark's name.
4063
4064
4064 Please see :hg:`help urls` for important details about ``ssh://``
4065 Please see :hg:`help urls` for important details about ``ssh://``
4065 URLs. If DESTINATION is omitted, a default path will be used.
4066 URLs. If DESTINATION is omitted, a default path will be used.
4066
4067
4067 Returns 0 if push was successful, 1 if nothing to push.
4068 Returns 0 if push was successful, 1 if nothing to push.
4068 """
4069 """
4069
4070
4070 if opts.get('bookmark'):
4071 if opts.get('bookmark'):
4071 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
4072 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
4072 for b in opts['bookmark']:
4073 for b in opts['bookmark']:
4073 # translate -B options to -r so changesets get pushed
4074 # translate -B options to -r so changesets get pushed
4074 b = repo._bookmarks.expandname(b)
4075 b = repo._bookmarks.expandname(b)
4075 if b in repo._bookmarks:
4076 if b in repo._bookmarks:
4076 opts.setdefault('rev', []).append(b)
4077 opts.setdefault('rev', []).append(b)
4077 else:
4078 else:
4078 # if we try to push a deleted bookmark, translate it to null
4079 # if we try to push a deleted bookmark, translate it to null
4079 # this lets simultaneous -r, -b options continue working
4080 # this lets simultaneous -r, -b options continue working
4080 opts.setdefault('rev', []).append("null")
4081 opts.setdefault('rev', []).append("null")
4081
4082
4082 path = ui.paths.getpath(dest, default=('default-push', 'default'))
4083 path = ui.paths.getpath(dest, default=('default-push', 'default'))
4083 if not path:
4084 if not path:
4084 raise error.Abort(_('default repository not configured!'),
4085 raise error.Abort(_('default repository not configured!'),
4085 hint=_("see 'hg help config.paths'"))
4086 hint=_("see 'hg help config.paths'"))
4086 dest = path.pushloc or path.loc
4087 dest = path.pushloc or path.loc
4087 branches = (path.branch, opts.get('branch') or [])
4088 branches = (path.branch, opts.get('branch') or [])
4088 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4089 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4089 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4090 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4090 other = hg.peer(repo, opts, dest)
4091 other = hg.peer(repo, opts, dest)
4091
4092
4092 if revs:
4093 if revs:
4093 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4094 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4094 if not revs:
4095 if not revs:
4095 raise error.Abort(_("specified revisions evaluate to an empty set"),
4096 raise error.Abort(_("specified revisions evaluate to an empty set"),
4096 hint=_("use different revision arguments"))
4097 hint=_("use different revision arguments"))
4097 elif path.pushrev:
4098 elif path.pushrev:
4098 # It doesn't make any sense to specify ancestor revisions. So limit
4099 # It doesn't make any sense to specify ancestor revisions. So limit
4099 # to DAG heads to make discovery simpler.
4100 # to DAG heads to make discovery simpler.
4100 expr = revsetlang.formatspec('heads(%r)', path.pushrev)
4101 expr = revsetlang.formatspec('heads(%r)', path.pushrev)
4101 revs = scmutil.revrange(repo, [expr])
4102 revs = scmutil.revrange(repo, [expr])
4102 revs = [repo[rev].node() for rev in revs]
4103 revs = [repo[rev].node() for rev in revs]
4103 if not revs:
4104 if not revs:
4104 raise error.Abort(_('default push revset for path evaluates to an '
4105 raise error.Abort(_('default push revset for path evaluates to an '
4105 'empty set'))
4106 'empty set'))
4106
4107
4107 repo._subtoppath = dest
4108 repo._subtoppath = dest
4108 try:
4109 try:
4109 # push subrepos depth-first for coherent ordering
4110 # push subrepos depth-first for coherent ordering
4110 c = repo['']
4111 c = repo['']
4111 subs = c.substate # only repos that are committed
4112 subs = c.substate # only repos that are committed
4112 for s in sorted(subs):
4113 for s in sorted(subs):
4113 result = c.sub(s).push(opts)
4114 result = c.sub(s).push(opts)
4114 if result == 0:
4115 if result == 0:
4115 return not result
4116 return not result
4116 finally:
4117 finally:
4117 del repo._subtoppath
4118 del repo._subtoppath
4118 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
4119 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
4119 newbranch=opts.get('new_branch'),
4120 newbranch=opts.get('new_branch'),
4120 bookmarks=opts.get('bookmark', ()),
4121 bookmarks=opts.get('bookmark', ()),
4121 opargs=opts.get('opargs'))
4122 opargs=opts.get('opargs'))
4122
4123
4123 result = not pushop.cgresult
4124 result = not pushop.cgresult
4124
4125
4125 if pushop.bkresult is not None:
4126 if pushop.bkresult is not None:
4126 if pushop.bkresult == 2:
4127 if pushop.bkresult == 2:
4127 result = 2
4128 result = 2
4128 elif not result and pushop.bkresult:
4129 elif not result and pushop.bkresult:
4129 result = 2
4130 result = 2
4130
4131
4131 return result
4132 return result
4132
4133
4133 @command('recover', [])
4134 @command('recover', [])
4134 def recover(ui, repo):
4135 def recover(ui, repo):
4135 """roll back an interrupted transaction
4136 """roll back an interrupted transaction
4136
4137
4137 Recover from an interrupted commit or pull.
4138 Recover from an interrupted commit or pull.
4138
4139
4139 This command tries to fix the repository status after an
4140 This command tries to fix the repository status after an
4140 interrupted operation. It should only be necessary when Mercurial
4141 interrupted operation. It should only be necessary when Mercurial
4141 suggests it.
4142 suggests it.
4142
4143
4143 Returns 0 if successful, 1 if nothing to recover or verify fails.
4144 Returns 0 if successful, 1 if nothing to recover or verify fails.
4144 """
4145 """
4145 if repo.recover():
4146 if repo.recover():
4146 return hg.verify(repo)
4147 return hg.verify(repo)
4147 return 1
4148 return 1
4148
4149
4149 @command('^remove|rm',
4150 @command('^remove|rm',
4150 [('A', 'after', None, _('record delete for missing files')),
4151 [('A', 'after', None, _('record delete for missing files')),
4151 ('f', 'force', None,
4152 ('f', 'force', None,
4152 _('forget added files, delete modified files')),
4153 _('forget added files, delete modified files')),
4153 ] + subrepoopts + walkopts,
4154 ] + subrepoopts + walkopts,
4154 _('[OPTION]... FILE...'),
4155 _('[OPTION]... FILE...'),
4155 inferrepo=True)
4156 inferrepo=True)
4156 def remove(ui, repo, *pats, **opts):
4157 def remove(ui, repo, *pats, **opts):
4157 """remove the specified files on the next commit
4158 """remove the specified files on the next commit
4158
4159
4159 Schedule the indicated files for removal from the current branch.
4160 Schedule the indicated files for removal from the current branch.
4160
4161
4161 This command schedules the files to be removed at the next commit.
4162 This command schedules the files to be removed at the next commit.
4162 To undo a remove before that, see :hg:`revert`. To undo added
4163 To undo a remove before that, see :hg:`revert`. To undo added
4163 files, see :hg:`forget`.
4164 files, see :hg:`forget`.
4164
4165
4165 .. container:: verbose
4166 .. container:: verbose
4166
4167
4167 -A/--after can be used to remove only files that have already
4168 -A/--after can be used to remove only files that have already
4168 been deleted, -f/--force can be used to force deletion, and -Af
4169 been deleted, -f/--force can be used to force deletion, and -Af
4169 can be used to remove files from the next revision without
4170 can be used to remove files from the next revision without
4170 deleting them from the working directory.
4171 deleting them from the working directory.
4171
4172
4172 The following table details the behavior of remove for different
4173 The following table details the behavior of remove for different
4173 file states (columns) and option combinations (rows). The file
4174 file states (columns) and option combinations (rows). The file
4174 states are Added [A], Clean [C], Modified [M] and Missing [!]
4175 states are Added [A], Clean [C], Modified [M] and Missing [!]
4175 (as reported by :hg:`status`). The actions are Warn, Remove
4176 (as reported by :hg:`status`). The actions are Warn, Remove
4176 (from branch) and Delete (from disk):
4177 (from branch) and Delete (from disk):
4177
4178
4178 ========= == == == ==
4179 ========= == == == ==
4179 opt/state A C M !
4180 opt/state A C M !
4180 ========= == == == ==
4181 ========= == == == ==
4181 none W RD W R
4182 none W RD W R
4182 -f R RD RD R
4183 -f R RD RD R
4183 -A W W W R
4184 -A W W W R
4184 -Af R R R R
4185 -Af R R R R
4185 ========= == == == ==
4186 ========= == == == ==
4186
4187
4187 .. note::
4188 .. note::
4188
4189
4189 :hg:`remove` never deletes files in Added [A] state from the
4190 :hg:`remove` never deletes files in Added [A] state from the
4190 working directory, not even if ``--force`` is specified.
4191 working directory, not even if ``--force`` is specified.
4191
4192
4192 Returns 0 on success, 1 if any warnings encountered.
4193 Returns 0 on success, 1 if any warnings encountered.
4193 """
4194 """
4194
4195
4195 after, force = opts.get('after'), opts.get('force')
4196 after, force = opts.get('after'), opts.get('force')
4196 if not pats and not after:
4197 if not pats and not after:
4197 raise error.Abort(_('no files specified'))
4198 raise error.Abort(_('no files specified'))
4198
4199
4199 m = scmutil.match(repo[None], pats, opts)
4200 m = scmutil.match(repo[None], pats, opts)
4200 subrepos = opts.get('subrepos')
4201 subrepos = opts.get('subrepos')
4201 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
4202 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
4202
4203
4203 @command('rename|move|mv',
4204 @command('rename|move|mv',
4204 [('A', 'after', None, _('record a rename that has already occurred')),
4205 [('A', 'after', None, _('record a rename that has already occurred')),
4205 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4206 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4206 ] + walkopts + dryrunopts,
4207 ] + walkopts + dryrunopts,
4207 _('[OPTION]... SOURCE... DEST'))
4208 _('[OPTION]... SOURCE... DEST'))
4208 def rename(ui, repo, *pats, **opts):
4209 def rename(ui, repo, *pats, **opts):
4209 """rename files; equivalent of copy + remove
4210 """rename files; equivalent of copy + remove
4210
4211
4211 Mark dest as copies of sources; mark sources for deletion. If dest
4212 Mark dest as copies of sources; mark sources for deletion. If dest
4212 is a directory, copies are put in that directory. If dest is a
4213 is a directory, copies are put in that directory. If dest is a
4213 file, there can only be one source.
4214 file, there can only be one source.
4214
4215
4215 By default, this command copies the contents of files as they
4216 By default, this command copies the contents of files as they
4216 exist in the working directory. If invoked with -A/--after, the
4217 exist in the working directory. If invoked with -A/--after, the
4217 operation is recorded, but no copying is performed.
4218 operation is recorded, but no copying is performed.
4218
4219
4219 This command takes effect at the next commit. To undo a rename
4220 This command takes effect at the next commit. To undo a rename
4220 before that, see :hg:`revert`.
4221 before that, see :hg:`revert`.
4221
4222
4222 Returns 0 on success, 1 if errors are encountered.
4223 Returns 0 on success, 1 if errors are encountered.
4223 """
4224 """
4224 with repo.wlock(False):
4225 with repo.wlock(False):
4225 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4226 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4226
4227
4227 @command('resolve',
4228 @command('resolve',
4228 [('a', 'all', None, _('select all unresolved files')),
4229 [('a', 'all', None, _('select all unresolved files')),
4229 ('l', 'list', None, _('list state of files needing merge')),
4230 ('l', 'list', None, _('list state of files needing merge')),
4230 ('m', 'mark', None, _('mark files as resolved')),
4231 ('m', 'mark', None, _('mark files as resolved')),
4231 ('u', 'unmark', None, _('mark files as unresolved')),
4232 ('u', 'unmark', None, _('mark files as unresolved')),
4232 ('n', 'no-status', None, _('hide status prefix'))]
4233 ('n', 'no-status', None, _('hide status prefix'))]
4233 + mergetoolopts + walkopts + formatteropts,
4234 + mergetoolopts + walkopts + formatteropts,
4234 _('[OPTION]... [FILE]...'),
4235 _('[OPTION]... [FILE]...'),
4235 inferrepo=True)
4236 inferrepo=True)
4236 def resolve(ui, repo, *pats, **opts):
4237 def resolve(ui, repo, *pats, **opts):
4237 """redo merges or set/view the merge status of files
4238 """redo merges or set/view the merge status of files
4238
4239
4239 Merges with unresolved conflicts are often the result of
4240 Merges with unresolved conflicts are often the result of
4240 non-interactive merging using the ``internal:merge`` configuration
4241 non-interactive merging using the ``internal:merge`` configuration
4241 setting, or a command-line merge tool like ``diff3``. The resolve
4242 setting, or a command-line merge tool like ``diff3``. The resolve
4242 command is used to manage the files involved in a merge, after
4243 command is used to manage the files involved in a merge, after
4243 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4244 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4244 working directory must have two parents). See :hg:`help
4245 working directory must have two parents). See :hg:`help
4245 merge-tools` for information on configuring merge tools.
4246 merge-tools` for information on configuring merge tools.
4246
4247
4247 The resolve command can be used in the following ways:
4248 The resolve command can be used in the following ways:
4248
4249
4249 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4250 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4250 files, discarding any previous merge attempts. Re-merging is not
4251 files, discarding any previous merge attempts. Re-merging is not
4251 performed for files already marked as resolved. Use ``--all/-a``
4252 performed for files already marked as resolved. Use ``--all/-a``
4252 to select all unresolved files. ``--tool`` can be used to specify
4253 to select all unresolved files. ``--tool`` can be used to specify
4253 the merge tool used for the given files. It overrides the HGMERGE
4254 the merge tool used for the given files. It overrides the HGMERGE
4254 environment variable and your configuration files. Previous file
4255 environment variable and your configuration files. Previous file
4255 contents are saved with a ``.orig`` suffix.
4256 contents are saved with a ``.orig`` suffix.
4256
4257
4257 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4258 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4258 (e.g. after having manually fixed-up the files). The default is
4259 (e.g. after having manually fixed-up the files). The default is
4259 to mark all unresolved files.
4260 to mark all unresolved files.
4260
4261
4261 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4262 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4262 default is to mark all resolved files.
4263 default is to mark all resolved files.
4263
4264
4264 - :hg:`resolve -l`: list files which had or still have conflicts.
4265 - :hg:`resolve -l`: list files which had or still have conflicts.
4265 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4266 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4266 You can use ``set:unresolved()`` or ``set:resolved()`` to filter
4267 You can use ``set:unresolved()`` or ``set:resolved()`` to filter
4267 the list. See :hg:`help filesets` for details.
4268 the list. See :hg:`help filesets` for details.
4268
4269
4269 .. note::
4270 .. note::
4270
4271
4271 Mercurial will not let you commit files with unresolved merge
4272 Mercurial will not let you commit files with unresolved merge
4272 conflicts. You must use :hg:`resolve -m ...` before you can
4273 conflicts. You must use :hg:`resolve -m ...` before you can
4273 commit after a conflicting merge.
4274 commit after a conflicting merge.
4274
4275
4275 Returns 0 on success, 1 if any files fail a resolve attempt.
4276 Returns 0 on success, 1 if any files fail a resolve attempt.
4276 """
4277 """
4277
4278
4278 flaglist = 'all mark unmark list no_status'.split()
4279 flaglist = 'all mark unmark list no_status'.split()
4279 all, mark, unmark, show, nostatus = \
4280 all, mark, unmark, show, nostatus = \
4280 [opts.get(o) for o in flaglist]
4281 [opts.get(o) for o in flaglist]
4281
4282
4282 if (show and (mark or unmark)) or (mark and unmark):
4283 if (show and (mark or unmark)) or (mark and unmark):
4283 raise error.Abort(_("too many options specified"))
4284 raise error.Abort(_("too many options specified"))
4284 if pats and all:
4285 if pats and all:
4285 raise error.Abort(_("can't specify --all and patterns"))
4286 raise error.Abort(_("can't specify --all and patterns"))
4286 if not (all or pats or show or mark or unmark):
4287 if not (all or pats or show or mark or unmark):
4287 raise error.Abort(_('no files or directories specified'),
4288 raise error.Abort(_('no files or directories specified'),
4288 hint=('use --all to re-merge all unresolved files'))
4289 hint=('use --all to re-merge all unresolved files'))
4289
4290
4290 if show:
4291 if show:
4291 fm = ui.formatter('resolve', opts)
4292 fm = ui.formatter('resolve', opts)
4292 ms = mergemod.mergestate.read(repo)
4293 ms = mergemod.mergestate.read(repo)
4293 m = scmutil.match(repo[None], pats, opts)
4294 m = scmutil.match(repo[None], pats, opts)
4294 for f in ms:
4295 for f in ms:
4295 if not m(f):
4296 if not m(f):
4296 continue
4297 continue
4297 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
4298 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
4298 'd': 'driverresolved'}[ms[f]]
4299 'd': 'driverresolved'}[ms[f]]
4299 fm.startitem()
4300 fm.startitem()
4300 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
4301 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
4301 fm.write('path', '%s\n', f, label=l)
4302 fm.write('path', '%s\n', f, label=l)
4302 fm.end()
4303 fm.end()
4303 return 0
4304 return 0
4304
4305
4305 with repo.wlock():
4306 with repo.wlock():
4306 ms = mergemod.mergestate.read(repo)
4307 ms = mergemod.mergestate.read(repo)
4307
4308
4308 if not (ms.active() or repo.dirstate.p2() != nullid):
4309 if not (ms.active() or repo.dirstate.p2() != nullid):
4309 raise error.Abort(
4310 raise error.Abort(
4310 _('resolve command not applicable when not merging'))
4311 _('resolve command not applicable when not merging'))
4311
4312
4312 wctx = repo[None]
4313 wctx = repo[None]
4313
4314
4314 if ms.mergedriver and ms.mdstate() == 'u':
4315 if ms.mergedriver and ms.mdstate() == 'u':
4315 proceed = mergemod.driverpreprocess(repo, ms, wctx)
4316 proceed = mergemod.driverpreprocess(repo, ms, wctx)
4316 ms.commit()
4317 ms.commit()
4317 # allow mark and unmark to go through
4318 # allow mark and unmark to go through
4318 if not mark and not unmark and not proceed:
4319 if not mark and not unmark and not proceed:
4319 return 1
4320 return 1
4320
4321
4321 m = scmutil.match(wctx, pats, opts)
4322 m = scmutil.match(wctx, pats, opts)
4322 ret = 0
4323 ret = 0
4323 didwork = False
4324 didwork = False
4324 runconclude = False
4325 runconclude = False
4325
4326
4326 tocomplete = []
4327 tocomplete = []
4327 for f in ms:
4328 for f in ms:
4328 if not m(f):
4329 if not m(f):
4329 continue
4330 continue
4330
4331
4331 didwork = True
4332 didwork = True
4332
4333
4333 # don't let driver-resolved files be marked, and run the conclude
4334 # don't let driver-resolved files be marked, and run the conclude
4334 # step if asked to resolve
4335 # step if asked to resolve
4335 if ms[f] == "d":
4336 if ms[f] == "d":
4336 exact = m.exact(f)
4337 exact = m.exact(f)
4337 if mark:
4338 if mark:
4338 if exact:
4339 if exact:
4339 ui.warn(_('not marking %s as it is driver-resolved\n')
4340 ui.warn(_('not marking %s as it is driver-resolved\n')
4340 % f)
4341 % f)
4341 elif unmark:
4342 elif unmark:
4342 if exact:
4343 if exact:
4343 ui.warn(_('not unmarking %s as it is driver-resolved\n')
4344 ui.warn(_('not unmarking %s as it is driver-resolved\n')
4344 % f)
4345 % f)
4345 else:
4346 else:
4346 runconclude = True
4347 runconclude = True
4347 continue
4348 continue
4348
4349
4349 if mark:
4350 if mark:
4350 ms.mark(f, "r")
4351 ms.mark(f, "r")
4351 elif unmark:
4352 elif unmark:
4352 ms.mark(f, "u")
4353 ms.mark(f, "u")
4353 else:
4354 else:
4354 # backup pre-resolve (merge uses .orig for its own purposes)
4355 # backup pre-resolve (merge uses .orig for its own purposes)
4355 a = repo.wjoin(f)
4356 a = repo.wjoin(f)
4356 try:
4357 try:
4357 util.copyfile(a, a + ".resolve")
4358 util.copyfile(a, a + ".resolve")
4358 except (IOError, OSError) as inst:
4359 except (IOError, OSError) as inst:
4359 if inst.errno != errno.ENOENT:
4360 if inst.errno != errno.ENOENT:
4360 raise
4361 raise
4361
4362
4362 try:
4363 try:
4363 # preresolve file
4364 # preresolve file
4364 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4365 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4365 'resolve')
4366 'resolve')
4366 complete, r = ms.preresolve(f, wctx)
4367 complete, r = ms.preresolve(f, wctx)
4367 if not complete:
4368 if not complete:
4368 tocomplete.append(f)
4369 tocomplete.append(f)
4369 elif r:
4370 elif r:
4370 ret = 1
4371 ret = 1
4371 finally:
4372 finally:
4372 ui.setconfig('ui', 'forcemerge', '', 'resolve')
4373 ui.setconfig('ui', 'forcemerge', '', 'resolve')
4373 ms.commit()
4374 ms.commit()
4374
4375
4375 # replace filemerge's .orig file with our resolve file, but only
4376 # replace filemerge's .orig file with our resolve file, but only
4376 # for merges that are complete
4377 # for merges that are complete
4377 if complete:
4378 if complete:
4378 try:
4379 try:
4379 util.rename(a + ".resolve",
4380 util.rename(a + ".resolve",
4380 scmutil.origpath(ui, repo, a))
4381 scmutil.origpath(ui, repo, a))
4381 except OSError as inst:
4382 except OSError as inst:
4382 if inst.errno != errno.ENOENT:
4383 if inst.errno != errno.ENOENT:
4383 raise
4384 raise
4384
4385
4385 for f in tocomplete:
4386 for f in tocomplete:
4386 try:
4387 try:
4387 # resolve file
4388 # resolve file
4388 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4389 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4389 'resolve')
4390 'resolve')
4390 r = ms.resolve(f, wctx)
4391 r = ms.resolve(f, wctx)
4391 if r:
4392 if r:
4392 ret = 1
4393 ret = 1
4393 finally:
4394 finally:
4394 ui.setconfig('ui', 'forcemerge', '', 'resolve')
4395 ui.setconfig('ui', 'forcemerge', '', 'resolve')
4395 ms.commit()
4396 ms.commit()
4396
4397
4397 # replace filemerge's .orig file with our resolve file
4398 # replace filemerge's .orig file with our resolve file
4398 a = repo.wjoin(f)
4399 a = repo.wjoin(f)
4399 try:
4400 try:
4400 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
4401 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
4401 except OSError as inst:
4402 except OSError as inst:
4402 if inst.errno != errno.ENOENT:
4403 if inst.errno != errno.ENOENT:
4403 raise
4404 raise
4404
4405
4405 ms.commit()
4406 ms.commit()
4406 ms.recordactions()
4407 ms.recordactions()
4407
4408
4408 if not didwork and pats:
4409 if not didwork and pats:
4409 hint = None
4410 hint = None
4410 if not any([p for p in pats if p.find(':') >= 0]):
4411 if not any([p for p in pats if p.find(':') >= 0]):
4411 pats = ['path:%s' % p for p in pats]
4412 pats = ['path:%s' % p for p in pats]
4412 m = scmutil.match(wctx, pats, opts)
4413 m = scmutil.match(wctx, pats, opts)
4413 for f in ms:
4414 for f in ms:
4414 if not m(f):
4415 if not m(f):
4415 continue
4416 continue
4416 flags = ''.join(['-%s ' % o[0] for o in flaglist
4417 flags = ''.join(['-%s ' % o[0] for o in flaglist
4417 if opts.get(o)])
4418 if opts.get(o)])
4418 hint = _("(try: hg resolve %s%s)\n") % (
4419 hint = _("(try: hg resolve %s%s)\n") % (
4419 flags,
4420 flags,
4420 ' '.join(pats))
4421 ' '.join(pats))
4421 break
4422 break
4422 ui.warn(_("arguments do not match paths that need resolving\n"))
4423 ui.warn(_("arguments do not match paths that need resolving\n"))
4423 if hint:
4424 if hint:
4424 ui.warn(hint)
4425 ui.warn(hint)
4425 elif ms.mergedriver and ms.mdstate() != 's':
4426 elif ms.mergedriver and ms.mdstate() != 's':
4426 # run conclude step when either a driver-resolved file is requested
4427 # run conclude step when either a driver-resolved file is requested
4427 # or there are no driver-resolved files
4428 # or there are no driver-resolved files
4428 # we can't use 'ret' to determine whether any files are unresolved
4429 # we can't use 'ret' to determine whether any files are unresolved
4429 # because we might not have tried to resolve some
4430 # because we might not have tried to resolve some
4430 if ((runconclude or not list(ms.driverresolved()))
4431 if ((runconclude or not list(ms.driverresolved()))
4431 and not list(ms.unresolved())):
4432 and not list(ms.unresolved())):
4432 proceed = mergemod.driverconclude(repo, ms, wctx)
4433 proceed = mergemod.driverconclude(repo, ms, wctx)
4433 ms.commit()
4434 ms.commit()
4434 if not proceed:
4435 if not proceed:
4435 return 1
4436 return 1
4436
4437
4437 # Nudge users into finishing an unfinished operation
4438 # Nudge users into finishing an unfinished operation
4438 unresolvedf = list(ms.unresolved())
4439 unresolvedf = list(ms.unresolved())
4439 driverresolvedf = list(ms.driverresolved())
4440 driverresolvedf = list(ms.driverresolved())
4440 if not unresolvedf and not driverresolvedf:
4441 if not unresolvedf and not driverresolvedf:
4441 ui.status(_('(no more unresolved files)\n'))
4442 ui.status(_('(no more unresolved files)\n'))
4442 cmdutil.checkafterresolved(repo)
4443 cmdutil.checkafterresolved(repo)
4443 elif not unresolvedf:
4444 elif not unresolvedf:
4444 ui.status(_('(no more unresolved files -- '
4445 ui.status(_('(no more unresolved files -- '
4445 'run "hg resolve --all" to conclude)\n'))
4446 'run "hg resolve --all" to conclude)\n'))
4446
4447
4447 return ret
4448 return ret
4448
4449
4449 @command('revert',
4450 @command('revert',
4450 [('a', 'all', None, _('revert all changes when no arguments given')),
4451 [('a', 'all', None, _('revert all changes when no arguments given')),
4451 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4452 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4452 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4453 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4453 ('C', 'no-backup', None, _('do not save backup copies of files')),
4454 ('C', 'no-backup', None, _('do not save backup copies of files')),
4454 ('i', 'interactive', None,
4455 ('i', 'interactive', None,
4455 _('interactively select the changes (EXPERIMENTAL)')),
4456 _('interactively select the changes (EXPERIMENTAL)')),
4456 ] + walkopts + dryrunopts,
4457 ] + walkopts + dryrunopts,
4457 _('[OPTION]... [-r REV] [NAME]...'))
4458 _('[OPTION]... [-r REV] [NAME]...'))
4458 def revert(ui, repo, *pats, **opts):
4459 def revert(ui, repo, *pats, **opts):
4459 """restore files to their checkout state
4460 """restore files to their checkout state
4460
4461
4461 .. note::
4462 .. note::
4462
4463
4463 To check out earlier revisions, you should use :hg:`update REV`.
4464 To check out earlier revisions, you should use :hg:`update REV`.
4464 To cancel an uncommitted merge (and lose your changes),
4465 To cancel an uncommitted merge (and lose your changes),
4465 use :hg:`update --clean .`.
4466 use :hg:`update --clean .`.
4466
4467
4467 With no revision specified, revert the specified files or directories
4468 With no revision specified, revert the specified files or directories
4468 to the contents they had in the parent of the working directory.
4469 to the contents they had in the parent of the working directory.
4469 This restores the contents of files to an unmodified
4470 This restores the contents of files to an unmodified
4470 state and unschedules adds, removes, copies, and renames. If the
4471 state and unschedules adds, removes, copies, and renames. If the
4471 working directory has two parents, you must explicitly specify a
4472 working directory has two parents, you must explicitly specify a
4472 revision.
4473 revision.
4473
4474
4474 Using the -r/--rev or -d/--date options, revert the given files or
4475 Using the -r/--rev or -d/--date options, revert the given files or
4475 directories to their states as of a specific revision. Because
4476 directories to their states as of a specific revision. Because
4476 revert does not change the working directory parents, this will
4477 revert does not change the working directory parents, this will
4477 cause these files to appear modified. This can be helpful to "back
4478 cause these files to appear modified. This can be helpful to "back
4478 out" some or all of an earlier change. See :hg:`backout` for a
4479 out" some or all of an earlier change. See :hg:`backout` for a
4479 related method.
4480 related method.
4480
4481
4481 Modified files are saved with a .orig suffix before reverting.
4482 Modified files are saved with a .orig suffix before reverting.
4482 To disable these backups, use --no-backup. It is possible to store
4483 To disable these backups, use --no-backup. It is possible to store
4483 the backup files in a custom directory relative to the root of the
4484 the backup files in a custom directory relative to the root of the
4484 repository by setting the ``ui.origbackuppath`` configuration
4485 repository by setting the ``ui.origbackuppath`` configuration
4485 option.
4486 option.
4486
4487
4487 See :hg:`help dates` for a list of formats valid for -d/--date.
4488 See :hg:`help dates` for a list of formats valid for -d/--date.
4488
4489
4489 See :hg:`help backout` for a way to reverse the effect of an
4490 See :hg:`help backout` for a way to reverse the effect of an
4490 earlier changeset.
4491 earlier changeset.
4491
4492
4492 Returns 0 on success.
4493 Returns 0 on success.
4493 """
4494 """
4494
4495
4495 if opts.get("date"):
4496 if opts.get("date"):
4496 if opts.get("rev"):
4497 if opts.get("rev"):
4497 raise error.Abort(_("you can't specify a revision and a date"))
4498 raise error.Abort(_("you can't specify a revision and a date"))
4498 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4499 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4499
4500
4500 parent, p2 = repo.dirstate.parents()
4501 parent, p2 = repo.dirstate.parents()
4501 if not opts.get('rev') and p2 != nullid:
4502 if not opts.get('rev') and p2 != nullid:
4502 # revert after merge is a trap for new users (issue2915)
4503 # revert after merge is a trap for new users (issue2915)
4503 raise error.Abort(_('uncommitted merge with no revision specified'),
4504 raise error.Abort(_('uncommitted merge with no revision specified'),
4504 hint=_("use 'hg update' or see 'hg help revert'"))
4505 hint=_("use 'hg update' or see 'hg help revert'"))
4505
4506
4506 ctx = scmutil.revsingle(repo, opts.get('rev'))
4507 ctx = scmutil.revsingle(repo, opts.get('rev'))
4507
4508
4508 if (not (pats or opts.get('include') or opts.get('exclude') or
4509 if (not (pats or opts.get('include') or opts.get('exclude') or
4509 opts.get('all') or opts.get('interactive'))):
4510 opts.get('all') or opts.get('interactive'))):
4510 msg = _("no files or directories specified")
4511 msg = _("no files or directories specified")
4511 if p2 != nullid:
4512 if p2 != nullid:
4512 hint = _("uncommitted merge, use --all to discard all changes,"
4513 hint = _("uncommitted merge, use --all to discard all changes,"
4513 " or 'hg update -C .' to abort the merge")
4514 " or 'hg update -C .' to abort the merge")
4514 raise error.Abort(msg, hint=hint)
4515 raise error.Abort(msg, hint=hint)
4515 dirty = any(repo.status())
4516 dirty = any(repo.status())
4516 node = ctx.node()
4517 node = ctx.node()
4517 if node != parent:
4518 if node != parent:
4518 if dirty:
4519 if dirty:
4519 hint = _("uncommitted changes, use --all to discard all"
4520 hint = _("uncommitted changes, use --all to discard all"
4520 " changes, or 'hg update %s' to update") % ctx.rev()
4521 " changes, or 'hg update %s' to update") % ctx.rev()
4521 else:
4522 else:
4522 hint = _("use --all to revert all files,"
4523 hint = _("use --all to revert all files,"
4523 " or 'hg update %s' to update") % ctx.rev()
4524 " or 'hg update %s' to update") % ctx.rev()
4524 elif dirty:
4525 elif dirty:
4525 hint = _("uncommitted changes, use --all to discard all changes")
4526 hint = _("uncommitted changes, use --all to discard all changes")
4526 else:
4527 else:
4527 hint = _("use --all to revert all files")
4528 hint = _("use --all to revert all files")
4528 raise error.Abort(msg, hint=hint)
4529 raise error.Abort(msg, hint=hint)
4529
4530
4530 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
4531 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
4531
4532
4532 @command('rollback', dryrunopts +
4533 @command('rollback', dryrunopts +
4533 [('f', 'force', False, _('ignore safety measures'))])
4534 [('f', 'force', False, _('ignore safety measures'))])
4534 def rollback(ui, repo, **opts):
4535 def rollback(ui, repo, **opts):
4535 """roll back the last transaction (DANGEROUS) (DEPRECATED)
4536 """roll back the last transaction (DANGEROUS) (DEPRECATED)
4536
4537
4537 Please use :hg:`commit --amend` instead of rollback to correct
4538 Please use :hg:`commit --amend` instead of rollback to correct
4538 mistakes in the last commit.
4539 mistakes in the last commit.
4539
4540
4540 This command should be used with care. There is only one level of
4541 This command should be used with care. There is only one level of
4541 rollback, and there is no way to undo a rollback. It will also
4542 rollback, and there is no way to undo a rollback. It will also
4542 restore the dirstate at the time of the last transaction, losing
4543 restore the dirstate at the time of the last transaction, losing
4543 any dirstate changes since that time. This command does not alter
4544 any dirstate changes since that time. This command does not alter
4544 the working directory.
4545 the working directory.
4545
4546
4546 Transactions are used to encapsulate the effects of all commands
4547 Transactions are used to encapsulate the effects of all commands
4547 that create new changesets or propagate existing changesets into a
4548 that create new changesets or propagate existing changesets into a
4548 repository.
4549 repository.
4549
4550
4550 .. container:: verbose
4551 .. container:: verbose
4551
4552
4552 For example, the following commands are transactional, and their
4553 For example, the following commands are transactional, and their
4553 effects can be rolled back:
4554 effects can be rolled back:
4554
4555
4555 - commit
4556 - commit
4556 - import
4557 - import
4557 - pull
4558 - pull
4558 - push (with this repository as the destination)
4559 - push (with this repository as the destination)
4559 - unbundle
4560 - unbundle
4560
4561
4561 To avoid permanent data loss, rollback will refuse to rollback a
4562 To avoid permanent data loss, rollback will refuse to rollback a
4562 commit transaction if it isn't checked out. Use --force to
4563 commit transaction if it isn't checked out. Use --force to
4563 override this protection.
4564 override this protection.
4564
4565
4565 The rollback command can be entirely disabled by setting the
4566 The rollback command can be entirely disabled by setting the
4566 ``ui.rollback`` configuration setting to false. If you're here
4567 ``ui.rollback`` configuration setting to false. If you're here
4567 because you want to use rollback and it's disabled, you can
4568 because you want to use rollback and it's disabled, you can
4568 re-enable the command by setting ``ui.rollback`` to true.
4569 re-enable the command by setting ``ui.rollback`` to true.
4569
4570
4570 This command is not intended for use on public repositories. Once
4571 This command is not intended for use on public repositories. Once
4571 changes are visible for pull by other users, rolling a transaction
4572 changes are visible for pull by other users, rolling a transaction
4572 back locally is ineffective (someone else may already have pulled
4573 back locally is ineffective (someone else may already have pulled
4573 the changes). Furthermore, a race is possible with readers of the
4574 the changes). Furthermore, a race is possible with readers of the
4574 repository; for example an in-progress pull from the repository
4575 repository; for example an in-progress pull from the repository
4575 may fail if a rollback is performed.
4576 may fail if a rollback is performed.
4576
4577
4577 Returns 0 on success, 1 if no rollback data is available.
4578 Returns 0 on success, 1 if no rollback data is available.
4578 """
4579 """
4579 if not ui.configbool('ui', 'rollback', True):
4580 if not ui.configbool('ui', 'rollback', True):
4580 raise error.Abort(_('rollback is disabled because it is unsafe'),
4581 raise error.Abort(_('rollback is disabled because it is unsafe'),
4581 hint=('see `hg help -v rollback` for information'))
4582 hint=('see `hg help -v rollback` for information'))
4582 return repo.rollback(dryrun=opts.get('dry_run'),
4583 return repo.rollback(dryrun=opts.get('dry_run'),
4583 force=opts.get('force'))
4584 force=opts.get('force'))
4584
4585
4585 @command('root', [])
4586 @command('root', [])
4586 def root(ui, repo):
4587 def root(ui, repo):
4587 """print the root (top) of the current working directory
4588 """print the root (top) of the current working directory
4588
4589
4589 Print the root directory of the current repository.
4590 Print the root directory of the current repository.
4590
4591
4591 Returns 0 on success.
4592 Returns 0 on success.
4592 """
4593 """
4593 ui.write(repo.root + "\n")
4594 ui.write(repo.root + "\n")
4594
4595
4595 @command('^serve',
4596 @command('^serve',
4596 [('A', 'accesslog', '', _('name of access log file to write to'),
4597 [('A', 'accesslog', '', _('name of access log file to write to'),
4597 _('FILE')),
4598 _('FILE')),
4598 ('d', 'daemon', None, _('run server in background')),
4599 ('d', 'daemon', None, _('run server in background')),
4599 ('', 'daemon-postexec', [], _('used internally by daemon mode')),
4600 ('', 'daemon-postexec', [], _('used internally by daemon mode')),
4600 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4601 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4601 # use string type, then we can check if something was passed
4602 # use string type, then we can check if something was passed
4602 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4603 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4603 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4604 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4604 _('ADDR')),
4605 _('ADDR')),
4605 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4606 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4606 _('PREFIX')),
4607 _('PREFIX')),
4607 ('n', 'name', '',
4608 ('n', 'name', '',
4608 _('name to show in web pages (default: working directory)'), _('NAME')),
4609 _('name to show in web pages (default: working directory)'), _('NAME')),
4609 ('', 'web-conf', '',
4610 ('', 'web-conf', '',
4610 _("name of the hgweb config file (see 'hg help hgweb')"), _('FILE')),
4611 _("name of the hgweb config file (see 'hg help hgweb')"), _('FILE')),
4611 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4612 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4612 _('FILE')),
4613 _('FILE')),
4613 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4614 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4614 ('', 'stdio', None, _('for remote clients')),
4615 ('', 'stdio', None, _('for remote clients')),
4615 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
4616 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
4616 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4617 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4617 ('', 'style', '', _('template style to use'), _('STYLE')),
4618 ('', 'style', '', _('template style to use'), _('STYLE')),
4618 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4619 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4619 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
4620 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
4620 _('[OPTION]...'),
4621 _('[OPTION]...'),
4621 optionalrepo=True)
4622 optionalrepo=True)
4622 def serve(ui, repo, **opts):
4623 def serve(ui, repo, **opts):
4623 """start stand-alone webserver
4624 """start stand-alone webserver
4624
4625
4625 Start a local HTTP repository browser and pull server. You can use
4626 Start a local HTTP repository browser and pull server. You can use
4626 this for ad-hoc sharing and browsing of repositories. It is
4627 this for ad-hoc sharing and browsing of repositories. It is
4627 recommended to use a real web server to serve a repository for
4628 recommended to use a real web server to serve a repository for
4628 longer periods of time.
4629 longer periods of time.
4629
4630
4630 Please note that the server does not implement access control.
4631 Please note that the server does not implement access control.
4631 This means that, by default, anybody can read from the server and
4632 This means that, by default, anybody can read from the server and
4632 nobody can write to it by default. Set the ``web.allow_push``
4633 nobody can write to it by default. Set the ``web.allow_push``
4633 option to ``*`` to allow everybody to push to the server. You
4634 option to ``*`` to allow everybody to push to the server. You
4634 should use a real web server if you need to authenticate users.
4635 should use a real web server if you need to authenticate users.
4635
4636
4636 By default, the server logs accesses to stdout and errors to
4637 By default, the server logs accesses to stdout and errors to
4637 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
4638 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
4638 files.
4639 files.
4639
4640
4640 To have the server choose a free port number to listen on, specify
4641 To have the server choose a free port number to listen on, specify
4641 a port number of 0; in this case, the server will print the port
4642 a port number of 0; in this case, the server will print the port
4642 number it uses.
4643 number it uses.
4643
4644
4644 Returns 0 on success.
4645 Returns 0 on success.
4645 """
4646 """
4646
4647
4647 if opts["stdio"] and opts["cmdserver"]:
4648 if opts["stdio"] and opts["cmdserver"]:
4648 raise error.Abort(_("cannot use --stdio with --cmdserver"))
4649 raise error.Abort(_("cannot use --stdio with --cmdserver"))
4649
4650
4650 if opts["stdio"]:
4651 if opts["stdio"]:
4651 if repo is None:
4652 if repo is None:
4652 raise error.RepoError(_("there is no Mercurial repository here"
4653 raise error.RepoError(_("there is no Mercurial repository here"
4653 " (.hg not found)"))
4654 " (.hg not found)"))
4654 s = sshserver.sshserver(ui, repo)
4655 s = sshserver.sshserver(ui, repo)
4655 s.serve_forever()
4656 s.serve_forever()
4656
4657
4657 service = server.createservice(ui, repo, opts)
4658 service = server.createservice(ui, repo, opts)
4658 return server.runservice(opts, initfn=service.init, runfn=service.run)
4659 return server.runservice(opts, initfn=service.init, runfn=service.run)
4659
4660
4660 @command('^status|st',
4661 @command('^status|st',
4661 [('A', 'all', None, _('show status of all files')),
4662 [('A', 'all', None, _('show status of all files')),
4662 ('m', 'modified', None, _('show only modified files')),
4663 ('m', 'modified', None, _('show only modified files')),
4663 ('a', 'added', None, _('show only added files')),
4664 ('a', 'added', None, _('show only added files')),
4664 ('r', 'removed', None, _('show only removed files')),
4665 ('r', 'removed', None, _('show only removed files')),
4665 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4666 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4666 ('c', 'clean', None, _('show only files without changes')),
4667 ('c', 'clean', None, _('show only files without changes')),
4667 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4668 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4668 ('i', 'ignored', None, _('show only ignored files')),
4669 ('i', 'ignored', None, _('show only ignored files')),
4669 ('n', 'no-status', None, _('hide status prefix')),
4670 ('n', 'no-status', None, _('hide status prefix')),
4670 ('C', 'copies', None, _('show source of copied files')),
4671 ('C', 'copies', None, _('show source of copied files')),
4671 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4672 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4672 ('', 'rev', [], _('show difference from revision'), _('REV')),
4673 ('', 'rev', [], _('show difference from revision'), _('REV')),
4673 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
4674 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
4674 ] + walkopts + subrepoopts + formatteropts,
4675 ] + walkopts + subrepoopts + formatteropts,
4675 _('[OPTION]... [FILE]...'),
4676 _('[OPTION]... [FILE]...'),
4676 inferrepo=True)
4677 inferrepo=True)
4677 def status(ui, repo, *pats, **opts):
4678 def status(ui, repo, *pats, **opts):
4678 """show changed files in the working directory
4679 """show changed files in the working directory
4679
4680
4680 Show status of files in the repository. If names are given, only
4681 Show status of files in the repository. If names are given, only
4681 files that match are shown. Files that are clean or ignored or
4682 files that match are shown. Files that are clean or ignored or
4682 the source of a copy/move operation, are not listed unless
4683 the source of a copy/move operation, are not listed unless
4683 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
4684 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
4684 Unless options described with "show only ..." are given, the
4685 Unless options described with "show only ..." are given, the
4685 options -mardu are used.
4686 options -mardu are used.
4686
4687
4687 Option -q/--quiet hides untracked (unknown and ignored) files
4688 Option -q/--quiet hides untracked (unknown and ignored) files
4688 unless explicitly requested with -u/--unknown or -i/--ignored.
4689 unless explicitly requested with -u/--unknown or -i/--ignored.
4689
4690
4690 .. note::
4691 .. note::
4691
4692
4692 :hg:`status` may appear to disagree with diff if permissions have
4693 :hg:`status` may appear to disagree with diff if permissions have
4693 changed or a merge has occurred. The standard diff format does
4694 changed or a merge has occurred. The standard diff format does
4694 not report permission changes and diff only reports changes
4695 not report permission changes and diff only reports changes
4695 relative to one merge parent.
4696 relative to one merge parent.
4696
4697
4697 If one revision is given, it is used as the base revision.
4698 If one revision is given, it is used as the base revision.
4698 If two revisions are given, the differences between them are
4699 If two revisions are given, the differences between them are
4699 shown. The --change option can also be used as a shortcut to list
4700 shown. The --change option can also be used as a shortcut to list
4700 the changed files of a revision from its first parent.
4701 the changed files of a revision from its first parent.
4701
4702
4702 The codes used to show the status of files are::
4703 The codes used to show the status of files are::
4703
4704
4704 M = modified
4705 M = modified
4705 A = added
4706 A = added
4706 R = removed
4707 R = removed
4707 C = clean
4708 C = clean
4708 ! = missing (deleted by non-hg command, but still tracked)
4709 ! = missing (deleted by non-hg command, but still tracked)
4709 ? = not tracked
4710 ? = not tracked
4710 I = ignored
4711 I = ignored
4711 = origin of the previous file (with --copies)
4712 = origin of the previous file (with --copies)
4712
4713
4713 .. container:: verbose
4714 .. container:: verbose
4714
4715
4715 Examples:
4716 Examples:
4716
4717
4717 - show changes in the working directory relative to a
4718 - show changes in the working directory relative to a
4718 changeset::
4719 changeset::
4719
4720
4720 hg status --rev 9353
4721 hg status --rev 9353
4721
4722
4722 - show changes in the working directory relative to the
4723 - show changes in the working directory relative to the
4723 current directory (see :hg:`help patterns` for more information)::
4724 current directory (see :hg:`help patterns` for more information)::
4724
4725
4725 hg status re:
4726 hg status re:
4726
4727
4727 - show all changes including copies in an existing changeset::
4728 - show all changes including copies in an existing changeset::
4728
4729
4729 hg status --copies --change 9353
4730 hg status --copies --change 9353
4730
4731
4731 - get a NUL separated list of added files, suitable for xargs::
4732 - get a NUL separated list of added files, suitable for xargs::
4732
4733
4733 hg status -an0
4734 hg status -an0
4734
4735
4735 Returns 0 on success.
4736 Returns 0 on success.
4736 """
4737 """
4737
4738
4738 revs = opts.get('rev')
4739 revs = opts.get('rev')
4739 change = opts.get('change')
4740 change = opts.get('change')
4740
4741
4741 if revs and change:
4742 if revs and change:
4742 msg = _('cannot specify --rev and --change at the same time')
4743 msg = _('cannot specify --rev and --change at the same time')
4743 raise error.Abort(msg)
4744 raise error.Abort(msg)
4744 elif change:
4745 elif change:
4745 node2 = scmutil.revsingle(repo, change, None).node()
4746 node2 = scmutil.revsingle(repo, change, None).node()
4746 node1 = repo[node2].p1().node()
4747 node1 = repo[node2].p1().node()
4747 else:
4748 else:
4748 node1, node2 = scmutil.revpair(repo, revs)
4749 node1, node2 = scmutil.revpair(repo, revs)
4749
4750
4750 if pats:
4751 if pats:
4751 cwd = repo.getcwd()
4752 cwd = repo.getcwd()
4752 else:
4753 else:
4753 cwd = ''
4754 cwd = ''
4754
4755
4755 if opts.get('print0'):
4756 if opts.get('print0'):
4756 end = '\0'
4757 end = '\0'
4757 else:
4758 else:
4758 end = '\n'
4759 end = '\n'
4759 copy = {}
4760 copy = {}
4760 states = 'modified added removed deleted unknown ignored clean'.split()
4761 states = 'modified added removed deleted unknown ignored clean'.split()
4761 show = [k for k in states if opts.get(k)]
4762 show = [k for k in states if opts.get(k)]
4762 if opts.get('all'):
4763 if opts.get('all'):
4763 show += ui.quiet and (states[:4] + ['clean']) or states
4764 show += ui.quiet and (states[:4] + ['clean']) or states
4764 if not show:
4765 if not show:
4765 if ui.quiet:
4766 if ui.quiet:
4766 show = states[:4]
4767 show = states[:4]
4767 else:
4768 else:
4768 show = states[:5]
4769 show = states[:5]
4769
4770
4770 m = scmutil.match(repo[node2], pats, opts)
4771 m = scmutil.match(repo[node2], pats, opts)
4771 stat = repo.status(node1, node2, m,
4772 stat = repo.status(node1, node2, m,
4772 'ignored' in show, 'clean' in show, 'unknown' in show,
4773 'ignored' in show, 'clean' in show, 'unknown' in show,
4773 opts.get('subrepos'))
4774 opts.get('subrepos'))
4774 changestates = zip(states, 'MAR!?IC', stat)
4775 changestates = zip(states, 'MAR!?IC', stat)
4775
4776
4776 if (opts.get('all') or opts.get('copies')
4777 if (opts.get('all') or opts.get('copies')
4777 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
4778 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
4778 copy = copies.pathcopies(repo[node1], repo[node2], m)
4779 copy = copies.pathcopies(repo[node1], repo[node2], m)
4779
4780
4780 fm = ui.formatter('status', opts)
4781 fm = ui.formatter('status', opts)
4781 fmt = '%s' + end
4782 fmt = '%s' + end
4782 showchar = not opts.get('no_status')
4783 showchar = not opts.get('no_status')
4783
4784
4784 for state, char, files in changestates:
4785 for state, char, files in changestates:
4785 if state in show:
4786 if state in show:
4786 label = 'status.' + state
4787 label = 'status.' + state
4787 for f in files:
4788 for f in files:
4788 fm.startitem()
4789 fm.startitem()
4789 fm.condwrite(showchar, 'status', '%s ', char, label=label)
4790 fm.condwrite(showchar, 'status', '%s ', char, label=label)
4790 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
4791 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
4791 if f in copy:
4792 if f in copy:
4792 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
4793 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
4793 label='status.copied')
4794 label='status.copied')
4794 fm.end()
4795 fm.end()
4795
4796
4796 @command('^summary|sum',
4797 @command('^summary|sum',
4797 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
4798 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
4798 def summary(ui, repo, **opts):
4799 def summary(ui, repo, **opts):
4799 """summarize working directory state
4800 """summarize working directory state
4800
4801
4801 This generates a brief summary of the working directory state,
4802 This generates a brief summary of the working directory state,
4802 including parents, branch, commit status, phase and available updates.
4803 including parents, branch, commit status, phase and available updates.
4803
4804
4804 With the --remote option, this will check the default paths for
4805 With the --remote option, this will check the default paths for
4805 incoming and outgoing changes. This can be time-consuming.
4806 incoming and outgoing changes. This can be time-consuming.
4806
4807
4807 Returns 0 on success.
4808 Returns 0 on success.
4808 """
4809 """
4809
4810
4810 ctx = repo[None]
4811 ctx = repo[None]
4811 parents = ctx.parents()
4812 parents = ctx.parents()
4812 pnode = parents[0].node()
4813 pnode = parents[0].node()
4813 marks = []
4814 marks = []
4814
4815
4815 ms = None
4816 ms = None
4816 try:
4817 try:
4817 ms = mergemod.mergestate.read(repo)
4818 ms = mergemod.mergestate.read(repo)
4818 except error.UnsupportedMergeRecords as e:
4819 except error.UnsupportedMergeRecords as e:
4819 s = ' '.join(e.recordtypes)
4820 s = ' '.join(e.recordtypes)
4820 ui.warn(
4821 ui.warn(
4821 _('warning: merge state has unsupported record types: %s\n') % s)
4822 _('warning: merge state has unsupported record types: %s\n') % s)
4822 unresolved = 0
4823 unresolved = 0
4823 else:
4824 else:
4824 unresolved = [f for f in ms if ms[f] == 'u']
4825 unresolved = [f for f in ms if ms[f] == 'u']
4825
4826
4826 for p in parents:
4827 for p in parents:
4827 # label with log.changeset (instead of log.parent) since this
4828 # label with log.changeset (instead of log.parent) since this
4828 # shows a working directory parent *changeset*:
4829 # shows a working directory parent *changeset*:
4829 # i18n: column positioning for "hg summary"
4830 # i18n: column positioning for "hg summary"
4830 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
4831 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
4831 label=cmdutil._changesetlabels(p))
4832 label=cmdutil._changesetlabels(p))
4832 ui.write(' '.join(p.tags()), label='log.tag')
4833 ui.write(' '.join(p.tags()), label='log.tag')
4833 if p.bookmarks():
4834 if p.bookmarks():
4834 marks.extend(p.bookmarks())
4835 marks.extend(p.bookmarks())
4835 if p.rev() == -1:
4836 if p.rev() == -1:
4836 if not len(repo):
4837 if not len(repo):
4837 ui.write(_(' (empty repository)'))
4838 ui.write(_(' (empty repository)'))
4838 else:
4839 else:
4839 ui.write(_(' (no revision checked out)'))
4840 ui.write(_(' (no revision checked out)'))
4840 if p.troubled():
4841 if p.troubled():
4841 ui.write(' ('
4842 ui.write(' ('
4842 + ', '.join(ui.label(trouble, 'trouble.%s' % trouble)
4843 + ', '.join(ui.label(trouble, 'trouble.%s' % trouble)
4843 for trouble in p.troubles())
4844 for trouble in p.troubles())
4844 + ')')
4845 + ')')
4845 ui.write('\n')
4846 ui.write('\n')
4846 if p.description():
4847 if p.description():
4847 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
4848 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
4848 label='log.summary')
4849 label='log.summary')
4849
4850
4850 branch = ctx.branch()
4851 branch = ctx.branch()
4851 bheads = repo.branchheads(branch)
4852 bheads = repo.branchheads(branch)
4852 # i18n: column positioning for "hg summary"
4853 # i18n: column positioning for "hg summary"
4853 m = _('branch: %s\n') % branch
4854 m = _('branch: %s\n') % branch
4854 if branch != 'default':
4855 if branch != 'default':
4855 ui.write(m, label='log.branch')
4856 ui.write(m, label='log.branch')
4856 else:
4857 else:
4857 ui.status(m, label='log.branch')
4858 ui.status(m, label='log.branch')
4858
4859
4859 if marks:
4860 if marks:
4860 active = repo._activebookmark
4861 active = repo._activebookmark
4861 # i18n: column positioning for "hg summary"
4862 # i18n: column positioning for "hg summary"
4862 ui.write(_('bookmarks:'), label='log.bookmark')
4863 ui.write(_('bookmarks:'), label='log.bookmark')
4863 if active is not None:
4864 if active is not None:
4864 if active in marks:
4865 if active in marks:
4865 ui.write(' *' + active, label=activebookmarklabel)
4866 ui.write(' *' + active, label=activebookmarklabel)
4866 marks.remove(active)
4867 marks.remove(active)
4867 else:
4868 else:
4868 ui.write(' [%s]' % active, label=activebookmarklabel)
4869 ui.write(' [%s]' % active, label=activebookmarklabel)
4869 for m in marks:
4870 for m in marks:
4870 ui.write(' ' + m, label='log.bookmark')
4871 ui.write(' ' + m, label='log.bookmark')
4871 ui.write('\n', label='log.bookmark')
4872 ui.write('\n', label='log.bookmark')
4872
4873
4873 status = repo.status(unknown=True)
4874 status = repo.status(unknown=True)
4874
4875
4875 c = repo.dirstate.copies()
4876 c = repo.dirstate.copies()
4876 copied, renamed = [], []
4877 copied, renamed = [], []
4877 for d, s in c.iteritems():
4878 for d, s in c.iteritems():
4878 if s in status.removed:
4879 if s in status.removed:
4879 status.removed.remove(s)
4880 status.removed.remove(s)
4880 renamed.append(d)
4881 renamed.append(d)
4881 else:
4882 else:
4882 copied.append(d)
4883 copied.append(d)
4883 if d in status.added:
4884 if d in status.added:
4884 status.added.remove(d)
4885 status.added.remove(d)
4885
4886
4886 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
4887 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
4887
4888
4888 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
4889 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
4889 (ui.label(_('%d added'), 'status.added'), status.added),
4890 (ui.label(_('%d added'), 'status.added'), status.added),
4890 (ui.label(_('%d removed'), 'status.removed'), status.removed),
4891 (ui.label(_('%d removed'), 'status.removed'), status.removed),
4891 (ui.label(_('%d renamed'), 'status.copied'), renamed),
4892 (ui.label(_('%d renamed'), 'status.copied'), renamed),
4892 (ui.label(_('%d copied'), 'status.copied'), copied),
4893 (ui.label(_('%d copied'), 'status.copied'), copied),
4893 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
4894 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
4894 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
4895 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
4895 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
4896 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
4896 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
4897 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
4897 t = []
4898 t = []
4898 for l, s in labels:
4899 for l, s in labels:
4899 if s:
4900 if s:
4900 t.append(l % len(s))
4901 t.append(l % len(s))
4901
4902
4902 t = ', '.join(t)
4903 t = ', '.join(t)
4903 cleanworkdir = False
4904 cleanworkdir = False
4904
4905
4905 if repo.vfs.exists('graftstate'):
4906 if repo.vfs.exists('graftstate'):
4906 t += _(' (graft in progress)')
4907 t += _(' (graft in progress)')
4907 if repo.vfs.exists('updatestate'):
4908 if repo.vfs.exists('updatestate'):
4908 t += _(' (interrupted update)')
4909 t += _(' (interrupted update)')
4909 elif len(parents) > 1:
4910 elif len(parents) > 1:
4910 t += _(' (merge)')
4911 t += _(' (merge)')
4911 elif branch != parents[0].branch():
4912 elif branch != parents[0].branch():
4912 t += _(' (new branch)')
4913 t += _(' (new branch)')
4913 elif (parents[0].closesbranch() and
4914 elif (parents[0].closesbranch() and
4914 pnode in repo.branchheads(branch, closed=True)):
4915 pnode in repo.branchheads(branch, closed=True)):
4915 t += _(' (head closed)')
4916 t += _(' (head closed)')
4916 elif not (status.modified or status.added or status.removed or renamed or
4917 elif not (status.modified or status.added or status.removed or renamed or
4917 copied or subs):
4918 copied or subs):
4918 t += _(' (clean)')
4919 t += _(' (clean)')
4919 cleanworkdir = True
4920 cleanworkdir = True
4920 elif pnode not in bheads:
4921 elif pnode not in bheads:
4921 t += _(' (new branch head)')
4922 t += _(' (new branch head)')
4922
4923
4923 if parents:
4924 if parents:
4924 pendingphase = max(p.phase() for p in parents)
4925 pendingphase = max(p.phase() for p in parents)
4925 else:
4926 else:
4926 pendingphase = phases.public
4927 pendingphase = phases.public
4927
4928
4928 if pendingphase > phases.newcommitphase(ui):
4929 if pendingphase > phases.newcommitphase(ui):
4929 t += ' (%s)' % phases.phasenames[pendingphase]
4930 t += ' (%s)' % phases.phasenames[pendingphase]
4930
4931
4931 if cleanworkdir:
4932 if cleanworkdir:
4932 # i18n: column positioning for "hg summary"
4933 # i18n: column positioning for "hg summary"
4933 ui.status(_('commit: %s\n') % t.strip())
4934 ui.status(_('commit: %s\n') % t.strip())
4934 else:
4935 else:
4935 # i18n: column positioning for "hg summary"
4936 # i18n: column positioning for "hg summary"
4936 ui.write(_('commit: %s\n') % t.strip())
4937 ui.write(_('commit: %s\n') % t.strip())
4937
4938
4938 # all ancestors of branch heads - all ancestors of parent = new csets
4939 # all ancestors of branch heads - all ancestors of parent = new csets
4939 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
4940 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
4940 bheads))
4941 bheads))
4941
4942
4942 if new == 0:
4943 if new == 0:
4943 # i18n: column positioning for "hg summary"
4944 # i18n: column positioning for "hg summary"
4944 ui.status(_('update: (current)\n'))
4945 ui.status(_('update: (current)\n'))
4945 elif pnode not in bheads:
4946 elif pnode not in bheads:
4946 # i18n: column positioning for "hg summary"
4947 # i18n: column positioning for "hg summary"
4947 ui.write(_('update: %d new changesets (update)\n') % new)
4948 ui.write(_('update: %d new changesets (update)\n') % new)
4948 else:
4949 else:
4949 # i18n: column positioning for "hg summary"
4950 # i18n: column positioning for "hg summary"
4950 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
4951 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
4951 (new, len(bheads)))
4952 (new, len(bheads)))
4952
4953
4953 t = []
4954 t = []
4954 draft = len(repo.revs('draft()'))
4955 draft = len(repo.revs('draft()'))
4955 if draft:
4956 if draft:
4956 t.append(_('%d draft') % draft)
4957 t.append(_('%d draft') % draft)
4957 secret = len(repo.revs('secret()'))
4958 secret = len(repo.revs('secret()'))
4958 if secret:
4959 if secret:
4959 t.append(_('%d secret') % secret)
4960 t.append(_('%d secret') % secret)
4960
4961
4961 if draft or secret:
4962 if draft or secret:
4962 ui.status(_('phases: %s\n') % ', '.join(t))
4963 ui.status(_('phases: %s\n') % ', '.join(t))
4963
4964
4964 if obsolete.isenabled(repo, obsolete.createmarkersopt):
4965 if obsolete.isenabled(repo, obsolete.createmarkersopt):
4965 for trouble in ("unstable", "divergent", "bumped"):
4966 for trouble in ("unstable", "divergent", "bumped"):
4966 numtrouble = len(repo.revs(trouble + "()"))
4967 numtrouble = len(repo.revs(trouble + "()"))
4967 # We write all the possibilities to ease translation
4968 # We write all the possibilities to ease translation
4968 troublemsg = {
4969 troublemsg = {
4969 "unstable": _("unstable: %d changesets"),
4970 "unstable": _("unstable: %d changesets"),
4970 "divergent": _("divergent: %d changesets"),
4971 "divergent": _("divergent: %d changesets"),
4971 "bumped": _("bumped: %d changesets"),
4972 "bumped": _("bumped: %d changesets"),
4972 }
4973 }
4973 if numtrouble > 0:
4974 if numtrouble > 0:
4974 ui.status(troublemsg[trouble] % numtrouble + "\n")
4975 ui.status(troublemsg[trouble] % numtrouble + "\n")
4975
4976
4976 cmdutil.summaryhooks(ui, repo)
4977 cmdutil.summaryhooks(ui, repo)
4977
4978
4978 if opts.get('remote'):
4979 if opts.get('remote'):
4979 needsincoming, needsoutgoing = True, True
4980 needsincoming, needsoutgoing = True, True
4980 else:
4981 else:
4981 needsincoming, needsoutgoing = False, False
4982 needsincoming, needsoutgoing = False, False
4982 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
4983 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
4983 if i:
4984 if i:
4984 needsincoming = True
4985 needsincoming = True
4985 if o:
4986 if o:
4986 needsoutgoing = True
4987 needsoutgoing = True
4987 if not needsincoming and not needsoutgoing:
4988 if not needsincoming and not needsoutgoing:
4988 return
4989 return
4989
4990
4990 def getincoming():
4991 def getincoming():
4991 source, branches = hg.parseurl(ui.expandpath('default'))
4992 source, branches = hg.parseurl(ui.expandpath('default'))
4992 sbranch = branches[0]
4993 sbranch = branches[0]
4993 try:
4994 try:
4994 other = hg.peer(repo, {}, source)
4995 other = hg.peer(repo, {}, source)
4995 except error.RepoError:
4996 except error.RepoError:
4996 if opts.get('remote'):
4997 if opts.get('remote'):
4997 raise
4998 raise
4998 return source, sbranch, None, None, None
4999 return source, sbranch, None, None, None
4999 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5000 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5000 if revs:
5001 if revs:
5001 revs = [other.lookup(rev) for rev in revs]
5002 revs = [other.lookup(rev) for rev in revs]
5002 ui.debug('comparing with %s\n' % util.hidepassword(source))
5003 ui.debug('comparing with %s\n' % util.hidepassword(source))
5003 repo.ui.pushbuffer()
5004 repo.ui.pushbuffer()
5004 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5005 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5005 repo.ui.popbuffer()
5006 repo.ui.popbuffer()
5006 return source, sbranch, other, commoninc, commoninc[1]
5007 return source, sbranch, other, commoninc, commoninc[1]
5007
5008
5008 if needsincoming:
5009 if needsincoming:
5009 source, sbranch, sother, commoninc, incoming = getincoming()
5010 source, sbranch, sother, commoninc, incoming = getincoming()
5010 else:
5011 else:
5011 source = sbranch = sother = commoninc = incoming = None
5012 source = sbranch = sother = commoninc = incoming = None
5012
5013
5013 def getoutgoing():
5014 def getoutgoing():
5014 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5015 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5015 dbranch = branches[0]
5016 dbranch = branches[0]
5016 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5017 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5017 if source != dest:
5018 if source != dest:
5018 try:
5019 try:
5019 dother = hg.peer(repo, {}, dest)
5020 dother = hg.peer(repo, {}, dest)
5020 except error.RepoError:
5021 except error.RepoError:
5021 if opts.get('remote'):
5022 if opts.get('remote'):
5022 raise
5023 raise
5023 return dest, dbranch, None, None
5024 return dest, dbranch, None, None
5024 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5025 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5025 elif sother is None:
5026 elif sother is None:
5026 # there is no explicit destination peer, but source one is invalid
5027 # there is no explicit destination peer, but source one is invalid
5027 return dest, dbranch, None, None
5028 return dest, dbranch, None, None
5028 else:
5029 else:
5029 dother = sother
5030 dother = sother
5030 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5031 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5031 common = None
5032 common = None
5032 else:
5033 else:
5033 common = commoninc
5034 common = commoninc
5034 if revs:
5035 if revs:
5035 revs = [repo.lookup(rev) for rev in revs]
5036 revs = [repo.lookup(rev) for rev in revs]
5036 repo.ui.pushbuffer()
5037 repo.ui.pushbuffer()
5037 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5038 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5038 commoninc=common)
5039 commoninc=common)
5039 repo.ui.popbuffer()
5040 repo.ui.popbuffer()
5040 return dest, dbranch, dother, outgoing
5041 return dest, dbranch, dother, outgoing
5041
5042
5042 if needsoutgoing:
5043 if needsoutgoing:
5043 dest, dbranch, dother, outgoing = getoutgoing()
5044 dest, dbranch, dother, outgoing = getoutgoing()
5044 else:
5045 else:
5045 dest = dbranch = dother = outgoing = None
5046 dest = dbranch = dother = outgoing = None
5046
5047
5047 if opts.get('remote'):
5048 if opts.get('remote'):
5048 t = []
5049 t = []
5049 if incoming:
5050 if incoming:
5050 t.append(_('1 or more incoming'))
5051 t.append(_('1 or more incoming'))
5051 o = outgoing.missing
5052 o = outgoing.missing
5052 if o:
5053 if o:
5053 t.append(_('%d outgoing') % len(o))
5054 t.append(_('%d outgoing') % len(o))
5054 other = dother or sother
5055 other = dother or sother
5055 if 'bookmarks' in other.listkeys('namespaces'):
5056 if 'bookmarks' in other.listkeys('namespaces'):
5056 counts = bookmarks.summary(repo, other)
5057 counts = bookmarks.summary(repo, other)
5057 if counts[0] > 0:
5058 if counts[0] > 0:
5058 t.append(_('%d incoming bookmarks') % counts[0])
5059 t.append(_('%d incoming bookmarks') % counts[0])
5059 if counts[1] > 0:
5060 if counts[1] > 0:
5060 t.append(_('%d outgoing bookmarks') % counts[1])
5061 t.append(_('%d outgoing bookmarks') % counts[1])
5061
5062
5062 if t:
5063 if t:
5063 # i18n: column positioning for "hg summary"
5064 # i18n: column positioning for "hg summary"
5064 ui.write(_('remote: %s\n') % (', '.join(t)))
5065 ui.write(_('remote: %s\n') % (', '.join(t)))
5065 else:
5066 else:
5066 # i18n: column positioning for "hg summary"
5067 # i18n: column positioning for "hg summary"
5067 ui.status(_('remote: (synced)\n'))
5068 ui.status(_('remote: (synced)\n'))
5068
5069
5069 cmdutil.summaryremotehooks(ui, repo, opts,
5070 cmdutil.summaryremotehooks(ui, repo, opts,
5070 ((source, sbranch, sother, commoninc),
5071 ((source, sbranch, sother, commoninc),
5071 (dest, dbranch, dother, outgoing)))
5072 (dest, dbranch, dother, outgoing)))
5072
5073
5073 @command('tag',
5074 @command('tag',
5074 [('f', 'force', None, _('force tag')),
5075 [('f', 'force', None, _('force tag')),
5075 ('l', 'local', None, _('make the tag local')),
5076 ('l', 'local', None, _('make the tag local')),
5076 ('r', 'rev', '', _('revision to tag'), _('REV')),
5077 ('r', 'rev', '', _('revision to tag'), _('REV')),
5077 ('', 'remove', None, _('remove a tag')),
5078 ('', 'remove', None, _('remove a tag')),
5078 # -l/--local is already there, commitopts cannot be used
5079 # -l/--local is already there, commitopts cannot be used
5079 ('e', 'edit', None, _('invoke editor on commit messages')),
5080 ('e', 'edit', None, _('invoke editor on commit messages')),
5080 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5081 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5081 ] + commitopts2,
5082 ] + commitopts2,
5082 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5083 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5083 def tag(ui, repo, name1, *names, **opts):
5084 def tag(ui, repo, name1, *names, **opts):
5084 """add one or more tags for the current or given revision
5085 """add one or more tags for the current or given revision
5085
5086
5086 Name a particular revision using <name>.
5087 Name a particular revision using <name>.
5087
5088
5088 Tags are used to name particular revisions of the repository and are
5089 Tags are used to name particular revisions of the repository and are
5089 very useful to compare different revisions, to go back to significant
5090 very useful to compare different revisions, to go back to significant
5090 earlier versions or to mark branch points as releases, etc. Changing
5091 earlier versions or to mark branch points as releases, etc. Changing
5091 an existing tag is normally disallowed; use -f/--force to override.
5092 an existing tag is normally disallowed; use -f/--force to override.
5092
5093
5093 If no revision is given, the parent of the working directory is
5094 If no revision is given, the parent of the working directory is
5094 used.
5095 used.
5095
5096
5096 To facilitate version control, distribution, and merging of tags,
5097 To facilitate version control, distribution, and merging of tags,
5097 they are stored as a file named ".hgtags" which is managed similarly
5098 they are stored as a file named ".hgtags" which is managed similarly
5098 to other project files and can be hand-edited if necessary. This
5099 to other project files and can be hand-edited if necessary. This
5099 also means that tagging creates a new commit. The file
5100 also means that tagging creates a new commit. The file
5100 ".hg/localtags" is used for local tags (not shared among
5101 ".hg/localtags" is used for local tags (not shared among
5101 repositories).
5102 repositories).
5102
5103
5103 Tag commits are usually made at the head of a branch. If the parent
5104 Tag commits are usually made at the head of a branch. If the parent
5104 of the working directory is not a branch head, :hg:`tag` aborts; use
5105 of the working directory is not a branch head, :hg:`tag` aborts; use
5105 -f/--force to force the tag commit to be based on a non-head
5106 -f/--force to force the tag commit to be based on a non-head
5106 changeset.
5107 changeset.
5107
5108
5108 See :hg:`help dates` for a list of formats valid for -d/--date.
5109 See :hg:`help dates` for a list of formats valid for -d/--date.
5109
5110
5110 Since tag names have priority over branch names during revision
5111 Since tag names have priority over branch names during revision
5111 lookup, using an existing branch name as a tag name is discouraged.
5112 lookup, using an existing branch name as a tag name is discouraged.
5112
5113
5113 Returns 0 on success.
5114 Returns 0 on success.
5114 """
5115 """
5115 wlock = lock = None
5116 wlock = lock = None
5116 try:
5117 try:
5117 wlock = repo.wlock()
5118 wlock = repo.wlock()
5118 lock = repo.lock()
5119 lock = repo.lock()
5119 rev_ = "."
5120 rev_ = "."
5120 names = [t.strip() for t in (name1,) + names]
5121 names = [t.strip() for t in (name1,) + names]
5121 if len(names) != len(set(names)):
5122 if len(names) != len(set(names)):
5122 raise error.Abort(_('tag names must be unique'))
5123 raise error.Abort(_('tag names must be unique'))
5123 for n in names:
5124 for n in names:
5124 scmutil.checknewlabel(repo, n, 'tag')
5125 scmutil.checknewlabel(repo, n, 'tag')
5125 if not n:
5126 if not n:
5126 raise error.Abort(_('tag names cannot consist entirely of '
5127 raise error.Abort(_('tag names cannot consist entirely of '
5127 'whitespace'))
5128 'whitespace'))
5128 if opts.get('rev') and opts.get('remove'):
5129 if opts.get('rev') and opts.get('remove'):
5129 raise error.Abort(_("--rev and --remove are incompatible"))
5130 raise error.Abort(_("--rev and --remove are incompatible"))
5130 if opts.get('rev'):
5131 if opts.get('rev'):
5131 rev_ = opts['rev']
5132 rev_ = opts['rev']
5132 message = opts.get('message')
5133 message = opts.get('message')
5133 if opts.get('remove'):
5134 if opts.get('remove'):
5134 if opts.get('local'):
5135 if opts.get('local'):
5135 expectedtype = 'local'
5136 expectedtype = 'local'
5136 else:
5137 else:
5137 expectedtype = 'global'
5138 expectedtype = 'global'
5138
5139
5139 for n in names:
5140 for n in names:
5140 if not repo.tagtype(n):
5141 if not repo.tagtype(n):
5141 raise error.Abort(_("tag '%s' does not exist") % n)
5142 raise error.Abort(_("tag '%s' does not exist") % n)
5142 if repo.tagtype(n) != expectedtype:
5143 if repo.tagtype(n) != expectedtype:
5143 if expectedtype == 'global':
5144 if expectedtype == 'global':
5144 raise error.Abort(_("tag '%s' is not a global tag") % n)
5145 raise error.Abort(_("tag '%s' is not a global tag") % n)
5145 else:
5146 else:
5146 raise error.Abort(_("tag '%s' is not a local tag") % n)
5147 raise error.Abort(_("tag '%s' is not a local tag") % n)
5147 rev_ = 'null'
5148 rev_ = 'null'
5148 if not message:
5149 if not message:
5149 # we don't translate commit messages
5150 # we don't translate commit messages
5150 message = 'Removed tag %s' % ', '.join(names)
5151 message = 'Removed tag %s' % ', '.join(names)
5151 elif not opts.get('force'):
5152 elif not opts.get('force'):
5152 for n in names:
5153 for n in names:
5153 if n in repo.tags():
5154 if n in repo.tags():
5154 raise error.Abort(_("tag '%s' already exists "
5155 raise error.Abort(_("tag '%s' already exists "
5155 "(use -f to force)") % n)
5156 "(use -f to force)") % n)
5156 if not opts.get('local'):
5157 if not opts.get('local'):
5157 p1, p2 = repo.dirstate.parents()
5158 p1, p2 = repo.dirstate.parents()
5158 if p2 != nullid:
5159 if p2 != nullid:
5159 raise error.Abort(_('uncommitted merge'))
5160 raise error.Abort(_('uncommitted merge'))
5160 bheads = repo.branchheads()
5161 bheads = repo.branchheads()
5161 if not opts.get('force') and bheads and p1 not in bheads:
5162 if not opts.get('force') and bheads and p1 not in bheads:
5162 raise error.Abort(_('working directory is not at a branch head '
5163 raise error.Abort(_('working directory is not at a branch head '
5163 '(use -f to force)'))
5164 '(use -f to force)'))
5164 r = scmutil.revsingle(repo, rev_).node()
5165 r = scmutil.revsingle(repo, rev_).node()
5165
5166
5166 if not message:
5167 if not message:
5167 # we don't translate commit messages
5168 # we don't translate commit messages
5168 message = ('Added tag %s for changeset %s' %
5169 message = ('Added tag %s for changeset %s' %
5169 (', '.join(names), short(r)))
5170 (', '.join(names), short(r)))
5170
5171
5171 date = opts.get('date')
5172 date = opts.get('date')
5172 if date:
5173 if date:
5173 date = util.parsedate(date)
5174 date = util.parsedate(date)
5174
5175
5175 if opts.get('remove'):
5176 if opts.get('remove'):
5176 editform = 'tag.remove'
5177 editform = 'tag.remove'
5177 else:
5178 else:
5178 editform = 'tag.add'
5179 editform = 'tag.add'
5179 editor = cmdutil.getcommiteditor(editform=editform, **opts)
5180 editor = cmdutil.getcommiteditor(editform=editform, **opts)
5180
5181
5181 # don't allow tagging the null rev
5182 # don't allow tagging the null rev
5182 if (not opts.get('remove') and
5183 if (not opts.get('remove') and
5183 scmutil.revsingle(repo, rev_).rev() == nullrev):
5184 scmutil.revsingle(repo, rev_).rev() == nullrev):
5184 raise error.Abort(_("cannot tag null revision"))
5185 raise error.Abort(_("cannot tag null revision"))
5185
5186
5186 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
5187 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
5187 editor=editor)
5188 editor=editor)
5188 finally:
5189 finally:
5189 release(lock, wlock)
5190 release(lock, wlock)
5190
5191
5191 @command('tags', formatteropts, '')
5192 @command('tags', formatteropts, '')
5192 def tags(ui, repo, **opts):
5193 def tags(ui, repo, **opts):
5193 """list repository tags
5194 """list repository tags
5194
5195
5195 This lists both regular and local tags. When the -v/--verbose
5196 This lists both regular and local tags. When the -v/--verbose
5196 switch is used, a third column "local" is printed for local tags.
5197 switch is used, a third column "local" is printed for local tags.
5197 When the -q/--quiet switch is used, only the tag name is printed.
5198 When the -q/--quiet switch is used, only the tag name is printed.
5198
5199
5199 Returns 0 on success.
5200 Returns 0 on success.
5200 """
5201 """
5201
5202
5202 fm = ui.formatter('tags', opts)
5203 fm = ui.formatter('tags', opts)
5203 hexfunc = fm.hexfunc
5204 hexfunc = fm.hexfunc
5204 tagtype = ""
5205 tagtype = ""
5205
5206
5206 for t, n in reversed(repo.tagslist()):
5207 for t, n in reversed(repo.tagslist()):
5207 hn = hexfunc(n)
5208 hn = hexfunc(n)
5208 label = 'tags.normal'
5209 label = 'tags.normal'
5209 tagtype = ''
5210 tagtype = ''
5210 if repo.tagtype(t) == 'local':
5211 if repo.tagtype(t) == 'local':
5211 label = 'tags.local'
5212 label = 'tags.local'
5212 tagtype = 'local'
5213 tagtype = 'local'
5213
5214
5214 fm.startitem()
5215 fm.startitem()
5215 fm.write('tag', '%s', t, label=label)
5216 fm.write('tag', '%s', t, label=label)
5216 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5217 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5217 fm.condwrite(not ui.quiet, 'rev node', fmt,
5218 fm.condwrite(not ui.quiet, 'rev node', fmt,
5218 repo.changelog.rev(n), hn, label=label)
5219 repo.changelog.rev(n), hn, label=label)
5219 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5220 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5220 tagtype, label=label)
5221 tagtype, label=label)
5221 fm.plain('\n')
5222 fm.plain('\n')
5222 fm.end()
5223 fm.end()
5223
5224
5224 @command('tip',
5225 @command('tip',
5225 [('p', 'patch', None, _('show patch')),
5226 [('p', 'patch', None, _('show patch')),
5226 ('g', 'git', None, _('use git extended diff format')),
5227 ('g', 'git', None, _('use git extended diff format')),
5227 ] + templateopts,
5228 ] + templateopts,
5228 _('[-p] [-g]'))
5229 _('[-p] [-g]'))
5229 def tip(ui, repo, **opts):
5230 def tip(ui, repo, **opts):
5230 """show the tip revision (DEPRECATED)
5231 """show the tip revision (DEPRECATED)
5231
5232
5232 The tip revision (usually just called the tip) is the changeset
5233 The tip revision (usually just called the tip) is the changeset
5233 most recently added to the repository (and therefore the most
5234 most recently added to the repository (and therefore the most
5234 recently changed head).
5235 recently changed head).
5235
5236
5236 If you have just made a commit, that commit will be the tip. If
5237 If you have just made a commit, that commit will be the tip. If
5237 you have just pulled changes from another repository, the tip of
5238 you have just pulled changes from another repository, the tip of
5238 that repository becomes the current tip. The "tip" tag is special
5239 that repository becomes the current tip. The "tip" tag is special
5239 and cannot be renamed or assigned to a different changeset.
5240 and cannot be renamed or assigned to a different changeset.
5240
5241
5241 This command is deprecated, please use :hg:`heads` instead.
5242 This command is deprecated, please use :hg:`heads` instead.
5242
5243
5243 Returns 0 on success.
5244 Returns 0 on success.
5244 """
5245 """
5245 displayer = cmdutil.show_changeset(ui, repo, opts)
5246 displayer = cmdutil.show_changeset(ui, repo, opts)
5246 displayer.show(repo['tip'])
5247 displayer.show(repo['tip'])
5247 displayer.close()
5248 displayer.close()
5248
5249
5249 @command('unbundle',
5250 @command('unbundle',
5250 [('u', 'update', None,
5251 [('u', 'update', None,
5251 _('update to new branch head if changesets were unbundled'))],
5252 _('update to new branch head if changesets were unbundled'))],
5252 _('[-u] FILE...'))
5253 _('[-u] FILE...'))
5253 def unbundle(ui, repo, fname1, *fnames, **opts):
5254 def unbundle(ui, repo, fname1, *fnames, **opts):
5254 """apply one or more changegroup files
5255 """apply one or more changegroup files
5255
5256
5256 Apply one or more compressed changegroup files generated by the
5257 Apply one or more compressed changegroup files generated by the
5257 bundle command.
5258 bundle command.
5258
5259
5259 Returns 0 on success, 1 if an update has unresolved files.
5260 Returns 0 on success, 1 if an update has unresolved files.
5260 """
5261 """
5261 fnames = (fname1,) + fnames
5262 fnames = (fname1,) + fnames
5262
5263
5263 with repo.lock():
5264 with repo.lock():
5264 for fname in fnames:
5265 for fname in fnames:
5265 f = hg.openpath(ui, fname)
5266 f = hg.openpath(ui, fname)
5266 gen = exchange.readbundle(ui, f, fname)
5267 gen = exchange.readbundle(ui, f, fname)
5267 if isinstance(gen, bundle2.unbundle20):
5268 if isinstance(gen, bundle2.unbundle20):
5268 tr = repo.transaction('unbundle')
5269 tr = repo.transaction('unbundle')
5269 try:
5270 try:
5270 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
5271 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
5271 url='bundle:' + fname)
5272 url='bundle:' + fname)
5272 tr.close()
5273 tr.close()
5273 except error.BundleUnknownFeatureError as exc:
5274 except error.BundleUnknownFeatureError as exc:
5274 raise error.Abort(_('%s: unknown bundle feature, %s')
5275 raise error.Abort(_('%s: unknown bundle feature, %s')
5275 % (fname, exc),
5276 % (fname, exc),
5276 hint=_("see https://mercurial-scm.org/"
5277 hint=_("see https://mercurial-scm.org/"
5277 "wiki/BundleFeature for more "
5278 "wiki/BundleFeature for more "
5278 "information"))
5279 "information"))
5279 finally:
5280 finally:
5280 if tr:
5281 if tr:
5281 tr.release()
5282 tr.release()
5282 changes = [r.get('return', 0)
5283 changes = [r.get('return', 0)
5283 for r in op.records['changegroup']]
5284 for r in op.records['changegroup']]
5284 modheads = changegroup.combineresults(changes)
5285 modheads = changegroup.combineresults(changes)
5285 elif isinstance(gen, streamclone.streamcloneapplier):
5286 elif isinstance(gen, streamclone.streamcloneapplier):
5286 raise error.Abort(
5287 raise error.Abort(
5287 _('packed bundles cannot be applied with '
5288 _('packed bundles cannot be applied with '
5288 '"hg unbundle"'),
5289 '"hg unbundle"'),
5289 hint=_('use "hg debugapplystreamclonebundle"'))
5290 hint=_('use "hg debugapplystreamclonebundle"'))
5290 else:
5291 else:
5291 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
5292 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
5292
5293
5293 return postincoming(ui, repo, modheads, opts.get('update'), None, None)
5294 return postincoming(ui, repo, modheads, opts.get('update'), None, None)
5294
5295
5295 @command('^update|up|checkout|co',
5296 @command('^update|up|checkout|co',
5296 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5297 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5297 ('c', 'check', None, _('require clean working directory')),
5298 ('c', 'check', None, _('require clean working directory')),
5298 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5299 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5299 ('r', 'rev', '', _('revision'), _('REV'))
5300 ('r', 'rev', '', _('revision'), _('REV'))
5300 ] + mergetoolopts,
5301 ] + mergetoolopts,
5301 _('[-C|-c] [-d DATE] [[-r] REV]'))
5302 _('[-C|-c] [-d DATE] [[-r] REV]'))
5302 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
5303 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
5303 tool=None):
5304 tool=None):
5304 """update working directory (or switch revisions)
5305 """update working directory (or switch revisions)
5305
5306
5306 Update the repository's working directory to the specified
5307 Update the repository's working directory to the specified
5307 changeset. If no changeset is specified, update to the tip of the
5308 changeset. If no changeset is specified, update to the tip of the
5308 current named branch and move the active bookmark (see :hg:`help
5309 current named branch and move the active bookmark (see :hg:`help
5309 bookmarks`).
5310 bookmarks`).
5310
5311
5311 Update sets the working directory's parent revision to the specified
5312 Update sets the working directory's parent revision to the specified
5312 changeset (see :hg:`help parents`).
5313 changeset (see :hg:`help parents`).
5313
5314
5314 If the changeset is not a descendant or ancestor of the working
5315 If the changeset is not a descendant or ancestor of the working
5315 directory's parent and there are uncommitted changes, the update is
5316 directory's parent and there are uncommitted changes, the update is
5316 aborted. With the -c/--check option, the working directory is checked
5317 aborted. With the -c/--check option, the working directory is checked
5317 for uncommitted changes; if none are found, the working directory is
5318 for uncommitted changes; if none are found, the working directory is
5318 updated to the specified changeset.
5319 updated to the specified changeset.
5319
5320
5320 .. container:: verbose
5321 .. container:: verbose
5321
5322
5322 The -C/--clean and -c/--check options control what happens if the
5323 The -C/--clean and -c/--check options control what happens if the
5323 working directory contains uncommitted changes.
5324 working directory contains uncommitted changes.
5324 At most of one of them can be specified.
5325 At most of one of them can be specified.
5325
5326
5326 1. If no option is specified, and if
5327 1. If no option is specified, and if
5327 the requested changeset is an ancestor or descendant of
5328 the requested changeset is an ancestor or descendant of
5328 the working directory's parent, the uncommitted changes
5329 the working directory's parent, the uncommitted changes
5329 are merged into the requested changeset and the merged
5330 are merged into the requested changeset and the merged
5330 result is left uncommitted. If the requested changeset is
5331 result is left uncommitted. If the requested changeset is
5331 not an ancestor or descendant (that is, it is on another
5332 not an ancestor or descendant (that is, it is on another
5332 branch), the update is aborted and the uncommitted changes
5333 branch), the update is aborted and the uncommitted changes
5333 are preserved.
5334 are preserved.
5334
5335
5335 2. With the -c/--check option, the update is aborted and the
5336 2. With the -c/--check option, the update is aborted and the
5336 uncommitted changes are preserved.
5337 uncommitted changes are preserved.
5337
5338
5338 3. With the -C/--clean option, uncommitted changes are discarded and
5339 3. With the -C/--clean option, uncommitted changes are discarded and
5339 the working directory is updated to the requested changeset.
5340 the working directory is updated to the requested changeset.
5340
5341
5341 To cancel an uncommitted merge (and lose your changes), use
5342 To cancel an uncommitted merge (and lose your changes), use
5342 :hg:`update --clean .`.
5343 :hg:`update --clean .`.
5343
5344
5344 Use null as the changeset to remove the working directory (like
5345 Use null as the changeset to remove the working directory (like
5345 :hg:`clone -U`).
5346 :hg:`clone -U`).
5346
5347
5347 If you want to revert just one file to an older revision, use
5348 If you want to revert just one file to an older revision, use
5348 :hg:`revert [-r REV] NAME`.
5349 :hg:`revert [-r REV] NAME`.
5349
5350
5350 See :hg:`help dates` for a list of formats valid for -d/--date.
5351 See :hg:`help dates` for a list of formats valid for -d/--date.
5351
5352
5352 Returns 0 on success, 1 if there are unresolved files.
5353 Returns 0 on success, 1 if there are unresolved files.
5353 """
5354 """
5354 if rev and node:
5355 if rev and node:
5355 raise error.Abort(_("please specify just one revision"))
5356 raise error.Abort(_("please specify just one revision"))
5356
5357
5357 if rev is None or rev == '':
5358 if rev is None or rev == '':
5358 rev = node
5359 rev = node
5359
5360
5360 if date and rev is not None:
5361 if date and rev is not None:
5361 raise error.Abort(_("you can't specify a revision and a date"))
5362 raise error.Abort(_("you can't specify a revision and a date"))
5362
5363
5363 if check and clean:
5364 if check and clean:
5364 raise error.Abort(_("cannot specify both -c/--check and -C/--clean"))
5365 raise error.Abort(_("cannot specify both -c/--check and -C/--clean"))
5365
5366
5366 with repo.wlock():
5367 with repo.wlock():
5367 cmdutil.clearunfinished(repo)
5368 cmdutil.clearunfinished(repo)
5368
5369
5369 if date:
5370 if date:
5370 rev = cmdutil.finddate(ui, repo, date)
5371 rev = cmdutil.finddate(ui, repo, date)
5371
5372
5372 # if we defined a bookmark, we have to remember the original name
5373 # if we defined a bookmark, we have to remember the original name
5373 brev = rev
5374 brev = rev
5374 rev = scmutil.revsingle(repo, rev, rev).rev()
5375 rev = scmutil.revsingle(repo, rev, rev).rev()
5375
5376
5376 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
5377 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
5377
5378
5378 return hg.updatetotally(ui, repo, rev, brev, clean=clean, check=check)
5379 return hg.updatetotally(ui, repo, rev, brev, clean=clean, check=check)
5379
5380
5380 @command('verify', [])
5381 @command('verify', [])
5381 def verify(ui, repo):
5382 def verify(ui, repo):
5382 """verify the integrity of the repository
5383 """verify the integrity of the repository
5383
5384
5384 Verify the integrity of the current repository.
5385 Verify the integrity of the current repository.
5385
5386
5386 This will perform an extensive check of the repository's
5387 This will perform an extensive check of the repository's
5387 integrity, validating the hashes and checksums of each entry in
5388 integrity, validating the hashes and checksums of each entry in
5388 the changelog, manifest, and tracked files, as well as the
5389 the changelog, manifest, and tracked files, as well as the
5389 integrity of their crosslinks and indices.
5390 integrity of their crosslinks and indices.
5390
5391
5391 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
5392 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
5392 for more information about recovery from corruption of the
5393 for more information about recovery from corruption of the
5393 repository.
5394 repository.
5394
5395
5395 Returns 0 on success, 1 if errors are encountered.
5396 Returns 0 on success, 1 if errors are encountered.
5396 """
5397 """
5397 return hg.verify(repo)
5398 return hg.verify(repo)
5398
5399
5399 @command('version', [] + formatteropts, norepo=True)
5400 @command('version', [] + formatteropts, norepo=True)
5400 def version_(ui, **opts):
5401 def version_(ui, **opts):
5401 """output version and copyright information"""
5402 """output version and copyright information"""
5402 fm = ui.formatter("version", opts)
5403 fm = ui.formatter("version", opts)
5403 fm.startitem()
5404 fm.startitem()
5404 fm.write("ver", _("Mercurial Distributed SCM (version %s)\n"),
5405 fm.write("ver", _("Mercurial Distributed SCM (version %s)\n"),
5405 util.version())
5406 util.version())
5406 license = _(
5407 license = _(
5407 "(see https://mercurial-scm.org for more information)\n"
5408 "(see https://mercurial-scm.org for more information)\n"
5408 "\nCopyright (C) 2005-2017 Matt Mackall and others\n"
5409 "\nCopyright (C) 2005-2017 Matt Mackall and others\n"
5409 "This is free software; see the source for copying conditions. "
5410 "This is free software; see the source for copying conditions. "
5410 "There is NO\nwarranty; "
5411 "There is NO\nwarranty; "
5411 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5412 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5412 )
5413 )
5413 if not ui.quiet:
5414 if not ui.quiet:
5414 fm.plain(license)
5415 fm.plain(license)
5415
5416
5416 if ui.verbose:
5417 if ui.verbose:
5417 fm.plain(_("\nEnabled extensions:\n\n"))
5418 fm.plain(_("\nEnabled extensions:\n\n"))
5418 # format names and versions into columns
5419 # format names and versions into columns
5419 names = []
5420 names = []
5420 vers = []
5421 vers = []
5421 isinternals = []
5422 isinternals = []
5422 for name, module in extensions.extensions():
5423 for name, module in extensions.extensions():
5423 names.append(name)
5424 names.append(name)
5424 vers.append(extensions.moduleversion(module) or None)
5425 vers.append(extensions.moduleversion(module) or None)
5425 isinternals.append(extensions.ismoduleinternal(module))
5426 isinternals.append(extensions.ismoduleinternal(module))
5426 fn = fm.nested("extensions")
5427 fn = fm.nested("extensions")
5427 if names:
5428 if names:
5428 namefmt = " %%-%ds " % max(len(n) for n in names)
5429 namefmt = " %%-%ds " % max(len(n) for n in names)
5429 places = [_("external"), _("internal")]
5430 places = [_("external"), _("internal")]
5430 for n, v, p in zip(names, vers, isinternals):
5431 for n, v, p in zip(names, vers, isinternals):
5431 fn.startitem()
5432 fn.startitem()
5432 fn.condwrite(ui.verbose, "name", namefmt, n)
5433 fn.condwrite(ui.verbose, "name", namefmt, n)
5433 if ui.verbose:
5434 if ui.verbose:
5434 fn.plain("%s " % places[p])
5435 fn.plain("%s " % places[p])
5435 fn.data(bundled=p)
5436 fn.data(bundled=p)
5436 fn.condwrite(ui.verbose and v, "ver", "%s", v)
5437 fn.condwrite(ui.verbose and v, "ver", "%s", v)
5437 if ui.verbose:
5438 if ui.verbose:
5438 fn.plain("\n")
5439 fn.plain("\n")
5439 fn.end()
5440 fn.end()
5440 fm.end()
5441 fm.end()
5441
5442
5442 def loadcmdtable(ui, name, cmdtable):
5443 def loadcmdtable(ui, name, cmdtable):
5443 """Load command functions from specified cmdtable
5444 """Load command functions from specified cmdtable
5444 """
5445 """
5445 overrides = [cmd for cmd in cmdtable if cmd in table]
5446 overrides = [cmd for cmd in cmdtable if cmd in table]
5446 if overrides:
5447 if overrides:
5447 ui.warn(_("extension '%s' overrides commands: %s\n")
5448 ui.warn(_("extension '%s' overrides commands: %s\n")
5448 % (name, " ".join(overrides)))
5449 % (name, " ".join(overrides)))
5449 table.update(cmdtable)
5450 table.update(cmdtable)
General Comments 0
You need to be logged in to leave comments. Login now