##// END OF EJS Templates
merge with stable
Martin Geisler -
r13234:0935ff76 merge default
parent child Browse files
Show More
@@ -1,1099 +1,1100 b''
1 ======
1 ======
2 hgrc
2 hgrc
3 ======
3 ======
4
4
5 ---------------------------------
5 ---------------------------------
6 configuration files for Mercurial
6 configuration files for Mercurial
7 ---------------------------------
7 ---------------------------------
8
8
9 :Author: Bryan O'Sullivan <bos@serpentine.com>
9 :Author: Bryan O'Sullivan <bos@serpentine.com>
10 :Organization: Mercurial
10 :Organization: Mercurial
11 :Manual section: 5
11 :Manual section: 5
12 :Manual group: Mercurial Manual
12 :Manual group: Mercurial Manual
13
13
14 .. contents::
14 .. contents::
15 :backlinks: top
15 :backlinks: top
16 :class: htmlonly
16 :class: htmlonly
17
17
18
18
19 Synopsis
19 Synopsis
20 --------
20 --------
21
21
22 The Mercurial system uses a set of configuration files to control
22 The Mercurial system uses a set of configuration files to control
23 aspects of its behavior.
23 aspects of its behavior.
24
24
25 Files
25 Files
26 -----
26 -----
27
27
28 Mercurial reads configuration data from several files, if they exist.
28 Mercurial reads configuration data from several files, if they exist.
29 The names of these files depend on the system on which Mercurial is
29 The names of these files depend on the system on which Mercurial is
30 installed. ``*.rc`` files from a single directory are read in
30 installed. ``*.rc`` files from a single directory are read in
31 alphabetical order, later ones overriding earlier ones. Where multiple
31 alphabetical order, later ones overriding earlier ones. Where multiple
32 paths are given below, settings from earlier paths override later
32 paths are given below, settings from earlier paths override later
33 ones.
33 ones.
34
34
35 | (Unix, Windows) ``<repo>/.hg/hgrc``
35 | (Unix, Windows) ``<repo>/.hg/hgrc``
36
36
37 Per-repository configuration options that only apply in a
37 Per-repository configuration options that only apply in a
38 particular repository. This file is not version-controlled, and
38 particular repository. This file is not version-controlled, and
39 will not get transferred during a "clone" operation. Options in
39 will not get transferred during a "clone" operation. Options in
40 this file override options in all other configuration files. On
40 this file override options in all other configuration files. On
41 Unix, most of this file will be ignored if it doesn't belong to a
41 Unix, most of this file will be ignored if it doesn't belong to a
42 trusted user or to a trusted group. See the documentation for the
42 trusted user or to a trusted group. See the documentation for the
43 trusted_ section below for more details.
43 trusted_ section below for more details.
44
44
45 | (Unix) ``$HOME/.hgrc``
45 | (Unix) ``$HOME/.hgrc``
46 | (Windows) ``%USERPROFILE%\.hgrc``
46 | (Windows) ``%USERPROFILE%\.hgrc``
47 | (Windows) ``%USERPROFILE%\Mercurial.ini``
47 | (Windows) ``%USERPROFILE%\Mercurial.ini``
48 | (Windows) ``%HOME%\.hgrc``
48 | (Windows) ``%HOME%\.hgrc``
49 | (Windows) ``%HOME%\Mercurial.ini``
49 | (Windows) ``%HOME%\Mercurial.ini``
50
50
51 Per-user configuration file(s), for the user running Mercurial. On
51 Per-user configuration file(s), for the user running Mercurial. On
52 Windows 9x, ``%HOME%`` is replaced by ``%APPDATA%``. Options in these
52 Windows 9x, ``%HOME%`` is replaced by ``%APPDATA%``. Options in these
53 files apply to all Mercurial commands executed by this user in any
53 files apply to all Mercurial commands executed by this user in any
54 directory. Options in these files override per-system and per-installation
54 directory. Options in these files override per-system and per-installation
55 options.
55 options.
56
56
57 | (Unix) ``/etc/mercurial/hgrc``
57 | (Unix) ``/etc/mercurial/hgrc``
58 | (Unix) ``/etc/mercurial/hgrc.d/*.rc``
58 | (Unix) ``/etc/mercurial/hgrc.d/*.rc``
59
59
60 Per-system configuration files, for the system on which Mercurial
60 Per-system configuration files, for the system on which Mercurial
61 is running. Options in these files apply to all Mercurial commands
61 is running. Options in these files apply to all Mercurial commands
62 executed by any user in any directory. Options in these files
62 executed by any user in any directory. Options in these files
63 override per-installation options.
63 override per-installation options.
64
64
65 | (Unix) ``<install-root>/etc/mercurial/hgrc``
65 | (Unix) ``<install-root>/etc/mercurial/hgrc``
66 | (Unix) ``<install-root>/etc/mercurial/hgrc.d/*.rc``
66 | (Unix) ``<install-root>/etc/mercurial/hgrc.d/*.rc``
67
67
68 Per-installation configuration files, searched for in the
68 Per-installation configuration files, searched for in the
69 directory where Mercurial is installed. ``<install-root>`` is the
69 directory where Mercurial is installed. ``<install-root>`` is the
70 parent directory of the **hg** executable (or symlink) being run. For
70 parent directory of the **hg** executable (or symlink) being run. For
71 example, if installed in ``/shared/tools/bin/hg``, Mercurial will look
71 example, if installed in ``/shared/tools/bin/hg``, Mercurial will look
72 in ``/shared/tools/etc/mercurial/hgrc``. Options in these files apply
72 in ``/shared/tools/etc/mercurial/hgrc``. Options in these files apply
73 to all Mercurial commands executed by any user in any directory.
73 to all Mercurial commands executed by any user in any directory.
74
74
75 | (Windows) ``<install-dir>\Mercurial.ini``
75 | (Windows) ``<install-dir>\Mercurial.ini``
76 | (Windows) ``<install-dir>\hgrc.d\*.rc``
76 | (Windows) ``<install-dir>\hgrc.d\*.rc``
77 | (Windows) ``HKEY_LOCAL_MACHINE\SOFTWARE\Mercurial``
77 | (Windows) ``HKEY_LOCAL_MACHINE\SOFTWARE\Mercurial``
78
78
79 Per-installation/system configuration files, for the system on
79 Per-installation/system configuration files, for the system on
80 which Mercurial is running. Options in these files apply to all
80 which Mercurial is running. Options in these files apply to all
81 Mercurial commands executed by any user in any directory. Registry
81 Mercurial commands executed by any user in any directory. Registry
82 keys contain PATH-like strings, every part of which must reference
82 keys contain PATH-like strings, every part of which must reference
83 a ``Mercurial.ini`` file or be a directory where ``*.rc`` files will
83 a ``Mercurial.ini`` file or be a directory where ``*.rc`` files will
84 be read. Mercurial checks each of these locations in the specified
84 be read. Mercurial checks each of these locations in the specified
85 order until one or more configuration files are detected. If the
85 order until one or more configuration files are detected. If the
86 pywin32 extensions are not installed, Mercurial will only look for
86 pywin32 extensions are not installed, Mercurial will only look for
87 site-wide configuration in ``C:\Mercurial\Mercurial.ini``.
87 site-wide configuration in ``C:\Mercurial\Mercurial.ini``.
88
88
89 Syntax
89 Syntax
90 ------
90 ------
91
91
92 A configuration file consists of sections, led by a ``[section]`` header
92 A configuration file consists of sections, led by a ``[section]`` header
93 and followed by ``name = value`` entries (sometimes called
93 and followed by ``name = value`` entries (sometimes called
94 ``configuration keys``)::
94 ``configuration keys``)::
95
95
96 [spam]
96 [spam]
97 eggs=ham
97 eggs=ham
98 green=
98 green=
99 eggs
99 eggs
100
100
101 Each line contains one entry. If the lines that follow are indented,
101 Each line contains one entry. If the lines that follow are indented,
102 they are treated as continuations of that entry. Leading whitespace is
102 they are treated as continuations of that entry. Leading whitespace is
103 removed from values. Empty lines are skipped. Lines beginning with
103 removed from values. Empty lines are skipped. Lines beginning with
104 ``#`` or ``;`` are ignored and may be used to provide comments.
104 ``#`` or ``;`` are ignored and may be used to provide comments.
105
105
106 Configuration keys can be set multiple times, in which case mercurial
106 Configuration keys can be set multiple times, in which case mercurial
107 will use the value that was configured last. As an example::
107 will use the value that was configured last. As an example::
108
108
109 [spam]
109 [spam]
110 eggs=large
110 eggs=large
111 ham=serrano
111 ham=serrano
112 eggs=small
112 eggs=small
113
113
114 This would set the configuration key named ``eggs`` to ``small``.
114 This would set the configuration key named ``eggs`` to ``small``.
115
115
116 It is also possible to define a section multiple times. A section can
116 It is also possible to define a section multiple times. A section can
117 be redefined on the same and/or on different hgrc files. For example::
117 be redefined on the same and/or on different hgrc files. For example::
118
118
119 [foo]
119 [foo]
120 eggs=large
120 eggs=large
121 ham=serrano
121 ham=serrano
122 eggs=small
122 eggs=small
123
123
124 [bar]
124 [bar]
125 eggs=ham
125 eggs=ham
126 green=
126 green=
127 eggs
127 eggs
128
128
129 [foo]
129 [foo]
130 ham=prosciutto
130 ham=prosciutto
131 eggs=medium
131 eggs=medium
132 bread=toasted
132 bread=toasted
133
133
134 This would set the ``eggs``, ``ham``, and ``bread`` configuration keys
134 This would set the ``eggs``, ``ham``, and ``bread`` configuration keys
135 of the ``foo`` section to ``medium``, ``prosciutto``, and ``toasted``,
135 of the ``foo`` section to ``medium``, ``prosciutto``, and ``toasted``,
136 respectively. As you can see there only thing that matters is the last
136 respectively. As you can see there only thing that matters is the last
137 value that was set for each of the configuration keys.
137 value that was set for each of the configuration keys.
138
138
139 If a configuration key is set multiple times in different
139 If a configuration key is set multiple times in different
140 configuration files the final value will depend on the order in which
140 configuration files the final value will depend on the order in which
141 the different configuration files are read, with settings from earlier
141 the different configuration files are read, with settings from earlier
142 paths overriding later ones as described on the ``Files`` section
142 paths overriding later ones as described on the ``Files`` section
143 above.
143 above.
144
144
145 A line of the form ``%include file`` will include ``file`` into the
145 A line of the form ``%include file`` will include ``file`` into the
146 current configuration file. The inclusion is recursive, which means
146 current configuration file. The inclusion is recursive, which means
147 that included files can include other files. Filenames are relative to
147 that included files can include other files. Filenames are relative to
148 the configuration file in which the ``%include`` directive is found.
148 the configuration file in which the ``%include`` directive is found.
149 Environment variables and ``~user`` constructs are expanded in
149 Environment variables and ``~user`` constructs are expanded in
150 ``file``. This lets you do something like::
150 ``file``. This lets you do something like::
151
151
152 %include ~/.hgrc.d/$HOST.rc
152 %include ~/.hgrc.d/$HOST.rc
153
153
154 to include a different configuration file on each computer you use.
154 to include a different configuration file on each computer you use.
155
155
156 A line with ``%unset name`` will remove ``name`` from the current
156 A line with ``%unset name`` will remove ``name`` from the current
157 section, if it has been set previously.
157 section, if it has been set previously.
158
158
159 The values are either free-form text strings, lists of text strings,
159 The values are either free-form text strings, lists of text strings,
160 or Boolean values. Boolean values can be set to true using any of "1",
160 or Boolean values. Boolean values can be set to true using any of "1",
161 "yes", "true", or "on" and to false using "0", "no", "false", or "off"
161 "yes", "true", or "on" and to false using "0", "no", "false", or "off"
162 (all case insensitive).
162 (all case insensitive).
163
163
164 List values are separated by whitespace or comma, except when values are
164 List values are separated by whitespace or comma, except when values are
165 placed in double quotation marks::
165 placed in double quotation marks::
166
166
167 allow_read = "John Doe, PhD", brian, betty
167 allow_read = "John Doe, PhD", brian, betty
168
168
169 Quotation marks can be escaped by prefixing them with a backslash. Only
169 Quotation marks can be escaped by prefixing them with a backslash. Only
170 quotation marks at the beginning of a word is counted as a quotation
170 quotation marks at the beginning of a word is counted as a quotation
171 (e.g., ``foo"bar baz`` is the list of ``foo"bar`` and ``baz``).
171 (e.g., ``foo"bar baz`` is the list of ``foo"bar`` and ``baz``).
172
172
173 Sections
173 Sections
174 --------
174 --------
175
175
176 This section describes the different sections that may appear in a
176 This section describes the different sections that may appear in a
177 Mercurial "hgrc" file, the purpose of each section, its possible keys,
177 Mercurial "hgrc" file, the purpose of each section, its possible keys,
178 and their possible values.
178 and their possible values.
179
179
180 ``alias``
180 ``alias``
181 """""""""
181 """""""""
182 Defines command aliases.
182 Defines command aliases.
183 Aliases allow you to define your own commands in terms of other
183 Aliases allow you to define your own commands in terms of other
184 commands (or aliases), optionally including arguments.
184 commands (or aliases), optionally including arguments.
185
185
186 Alias definitions consist of lines of the form::
186 Alias definitions consist of lines of the form::
187
187
188 <alias> = <command> [<argument]...
188 <alias> = <command> [<argument]...
189
189
190 For example, this definition::
190 For example, this definition::
191
191
192 latest = log --limit 5
192 latest = log --limit 5
193
193
194 creates a new command ``latest`` that shows only the five most recent
194 creates a new command ``latest`` that shows only the five most recent
195 changesets. You can define subsequent aliases using earlier ones::
195 changesets. You can define subsequent aliases using earlier ones::
196
196
197 stable5 = latest -b stable
197 stable5 = latest -b stable
198
198
199 .. note:: It is possible to create aliases with the same names as
199 .. note:: It is possible to create aliases with the same names as
200 existing commands, which will then override the original
200 existing commands, which will then override the original
201 definitions. This is almost always a bad idea!
201 definitions. This is almost always a bad idea!
202
202
203
203
204 ``auth``
204 ``auth``
205 """"""""
205 """"""""
206
206
207 Authentication credentials for HTTP authentication. This section
207 Authentication credentials for HTTP authentication. This section
208 allows you to store usernames and passwords for use when logging
208 allows you to store usernames and passwords for use when logging
209 *into* HTTP servers. See the web_ configuration section if you want to
209 *into* HTTP servers. See the web_ configuration section if you want to
210 configure *who* can login to your HTTP server.
210 configure *who* can login to your HTTP server.
211
211
212 Each line has the following format::
212 Each line has the following format::
213
213
214 <name>.<argument> = <value>
214 <name>.<argument> = <value>
215
215
216 where ``<name>`` is used to group arguments into authentication
216 where ``<name>`` is used to group arguments into authentication
217 entries. Example::
217 entries. Example::
218
218
219 foo.prefix = hg.intevation.org/mercurial
219 foo.prefix = hg.intevation.org/mercurial
220 foo.username = foo
220 foo.username = foo
221 foo.password = bar
221 foo.password = bar
222 foo.schemes = http https
222 foo.schemes = http https
223
223
224 bar.prefix = secure.example.org
224 bar.prefix = secure.example.org
225 bar.key = path/to/file.key
225 bar.key = path/to/file.key
226 bar.cert = path/to/file.cert
226 bar.cert = path/to/file.cert
227 bar.schemes = https
227 bar.schemes = https
228
228
229 Supported arguments:
229 Supported arguments:
230
230
231 ``prefix``
231 ``prefix``
232 Either ``*`` or a URI prefix with or without the scheme part.
232 Either ``*`` or a URI prefix with or without the scheme part.
233 The authentication entry with the longest matching prefix is used
233 The authentication entry with the longest matching prefix is used
234 (where ``*`` matches everything and counts as a match of length
234 (where ``*`` matches everything and counts as a match of length
235 1). If the prefix doesn't include a scheme, the match is performed
235 1). If the prefix doesn't include a scheme, the match is performed
236 against the URI with its scheme stripped as well, and the schemes
236 against the URI with its scheme stripped as well, and the schemes
237 argument, q.v., is then subsequently consulted.
237 argument, q.v., is then subsequently consulted.
238 ``username``
238 ``username``
239 Optional. Username to authenticate with. If not given, and the
239 Optional. Username to authenticate with. If not given, and the
240 remote site requires basic or digest authentication, the user will
240 remote site requires basic or digest authentication, the user will
241 be prompted for it. Environment variables are expanded in the
241 be prompted for it. Environment variables are expanded in the
242 username letting you do ``foo.username = $USER``.
242 username letting you do ``foo.username = $USER``.
243 ``password``
243 ``password``
244 Optional. Password to authenticate with. If not given, and the
244 Optional. Password to authenticate with. If not given, and the
245 remote site requires basic or digest authentication, the user
245 remote site requires basic or digest authentication, the user
246 will be prompted for it.
246 will be prompted for it.
247 ``key``
247 ``key``
248 Optional. PEM encoded client certificate key file. Environment
248 Optional. PEM encoded client certificate key file. Environment
249 variables are expanded in the filename.
249 variables are expanded in the filename.
250 ``cert``
250 ``cert``
251 Optional. PEM encoded client certificate chain file. Environment
251 Optional. PEM encoded client certificate chain file. Environment
252 variables are expanded in the filename.
252 variables are expanded in the filename.
253 ``schemes``
253 ``schemes``
254 Optional. Space separated list of URI schemes to use this
254 Optional. Space separated list of URI schemes to use this
255 authentication entry with. Only used if the prefix doesn't include
255 authentication entry with. Only used if the prefix doesn't include
256 a scheme. Supported schemes are http and https. They will match
256 a scheme. Supported schemes are http and https. They will match
257 static-http and static-https respectively, as well.
257 static-http and static-https respectively, as well.
258 Default: https.
258 Default: https.
259
259
260 If no suitable authentication entry is found, the user is prompted
260 If no suitable authentication entry is found, the user is prompted
261 for credentials as usual if required by the remote.
261 for credentials as usual if required by the remote.
262
262
263
263
264 ``decode/encode``
264 ``decode/encode``
265 """""""""""""""""
265 """""""""""""""""
266 Filters for transforming files on checkout/checkin. This would
266 Filters for transforming files on checkout/checkin. This would
267 typically be used for newline processing or other
267 typically be used for newline processing or other
268 localization/canonicalization of files.
268 localization/canonicalization of files.
269
269
270 Filters consist of a filter pattern followed by a filter command.
270 Filters consist of a filter pattern followed by a filter command.
271 Filter patterns are globs by default, rooted at the repository root.
271 Filter patterns are globs by default, rooted at the repository root.
272 For example, to match any file ending in ``.txt`` in the root
272 For example, to match any file ending in ``.txt`` in the root
273 directory only, use the pattern ``*.txt``. To match any file ending
273 directory only, use the pattern ``*.txt``. To match any file ending
274 in ``.c`` anywhere in the repository, use the pattern ``**.c``.
274 in ``.c`` anywhere in the repository, use the pattern ``**.c``.
275 For each file only the first matching filter applies.
275 For each file only the first matching filter applies.
276
276
277 The filter command can start with a specifier, either ``pipe:`` or
277 The filter command can start with a specifier, either ``pipe:`` or
278 ``tempfile:``. If no specifier is given, ``pipe:`` is used by default.
278 ``tempfile:``. If no specifier is given, ``pipe:`` is used by default.
279
279
280 A ``pipe:`` command must accept data on stdin and return the transformed
280 A ``pipe:`` command must accept data on stdin and return the transformed
281 data on stdout.
281 data on stdout.
282
282
283 Pipe example::
283 Pipe example::
284
284
285 [encode]
285 [encode]
286 # uncompress gzip files on checkin to improve delta compression
286 # uncompress gzip files on checkin to improve delta compression
287 # note: not necessarily a good idea, just an example
287 # note: not necessarily a good idea, just an example
288 *.gz = pipe: gunzip
288 *.gz = pipe: gunzip
289
289
290 [decode]
290 [decode]
291 # recompress gzip files when writing them to the working dir (we
291 # recompress gzip files when writing them to the working dir (we
292 # can safely omit "pipe:", because it's the default)
292 # can safely omit "pipe:", because it's the default)
293 *.gz = gzip
293 *.gz = gzip
294
294
295 A ``tempfile:`` command is a template. The string ``INFILE`` is replaced
295 A ``tempfile:`` command is a template. The string ``INFILE`` is replaced
296 with the name of a temporary file that contains the data to be
296 with the name of a temporary file that contains the data to be
297 filtered by the command. The string ``OUTFILE`` is replaced with the name
297 filtered by the command. The string ``OUTFILE`` is replaced with the name
298 of an empty temporary file, where the filtered data must be written by
298 of an empty temporary file, where the filtered data must be written by
299 the command.
299 the command.
300
300
301 .. note:: The tempfile mechanism is recommended for Windows systems,
301 .. note:: The tempfile mechanism is recommended for Windows systems,
302 where the standard shell I/O redirection operators often have
302 where the standard shell I/O redirection operators often have
303 strange effects and may corrupt the contents of your files.
303 strange effects and may corrupt the contents of your files.
304
304
305 This filter mechanism is used internally by the ``eol`` extension to
305 This filter mechanism is used internally by the ``eol`` extension to
306 translate line ending characters between Windows (CRLF) and Unix (LF)
306 translate line ending characters between Windows (CRLF) and Unix (LF)
307 format. We suggest you use the ``eol`` extension for convenience.
307 format. We suggest you use the ``eol`` extension for convenience.
308
308
309
309
310 ``defaults``
310 ``defaults``
311 """"""""""""
311 """"""""""""
312
312
313 (defaults are deprecated. Don't use them. Use aliases instead)
313 (defaults are deprecated. Don't use them. Use aliases instead)
314
314
315 Use the ``[defaults]`` section to define command defaults, i.e. the
315 Use the ``[defaults]`` section to define command defaults, i.e. the
316 default options/arguments to pass to the specified commands.
316 default options/arguments to pass to the specified commands.
317
317
318 The following example makes :hg:`log` run in verbose mode, and
318 The following example makes :hg:`log` run in verbose mode, and
319 :hg:`status` show only the modified files, by default::
319 :hg:`status` show only the modified files, by default::
320
320
321 [defaults]
321 [defaults]
322 log = -v
322 log = -v
323 status = -m
323 status = -m
324
324
325 The actual commands, instead of their aliases, must be used when
325 The actual commands, instead of their aliases, must be used when
326 defining command defaults. The command defaults will also be applied
326 defining command defaults. The command defaults will also be applied
327 to the aliases of the commands defined.
327 to the aliases of the commands defined.
328
328
329
329
330 ``diff``
330 ``diff``
331 """"""""
331 """"""""
332
332
333 Settings used when displaying diffs. They are all Boolean and
333 Settings used when displaying diffs. They are all Boolean and
334 defaults to False.
334 defaults to False.
335
335
336 ``git``
336 ``git``
337 Use git extended diff format.
337 Use git extended diff format.
338 ``nodates``
338 ``nodates``
339 Don't include dates in diff headers.
339 Don't include dates in diff headers.
340 ``showfunc``
340 ``showfunc``
341 Show which function each change is in.
341 Show which function each change is in.
342 ``ignorews``
342 ``ignorews``
343 Ignore white space when comparing lines.
343 Ignore white space when comparing lines.
344 ``ignorewsamount``
344 ``ignorewsamount``
345 Ignore changes in the amount of white space.
345 Ignore changes in the amount of white space.
346 ``ignoreblanklines``
346 ``ignoreblanklines``
347 Ignore changes whose lines are all blank.
347 Ignore changes whose lines are all blank.
348
348
349 ``email``
349 ``email``
350 """""""""
350 """""""""
351 Settings for extensions that send email messages.
351 Settings for extensions that send email messages.
352
352
353 ``from``
353 ``from``
354 Optional. Email address to use in "From" header and SMTP envelope
354 Optional. Email address to use in "From" header and SMTP envelope
355 of outgoing messages.
355 of outgoing messages.
356 ``to``
356 ``to``
357 Optional. Comma-separated list of recipients' email addresses.
357 Optional. Comma-separated list of recipients' email addresses.
358 ``cc``
358 ``cc``
359 Optional. Comma-separated list of carbon copy recipients'
359 Optional. Comma-separated list of carbon copy recipients'
360 email addresses.
360 email addresses.
361 ``bcc``
361 ``bcc``
362 Optional. Comma-separated list of blind carbon copy recipients'
362 Optional. Comma-separated list of blind carbon copy recipients'
363 email addresses.
363 email addresses.
364 ``method``
364 ``method``
365 Optional. Method to use to send email messages. If value is ``smtp``
365 Optional. Method to use to send email messages. If value is ``smtp``
366 (default), use SMTP (see the SMTP_ section for configuration).
366 (default), use SMTP (see the SMTP_ section for configuration).
367 Otherwise, use as name of program to run that acts like sendmail
367 Otherwise, use as name of program to run that acts like sendmail
368 (takes ``-f`` option for sender, list of recipients on command line,
368 (takes ``-f`` option for sender, list of recipients on command line,
369 message on stdin). Normally, setting this to ``sendmail`` or
369 message on stdin). Normally, setting this to ``sendmail`` or
370 ``/usr/sbin/sendmail`` is enough to use sendmail to send messages.
370 ``/usr/sbin/sendmail`` is enough to use sendmail to send messages.
371 ``charsets``
371 ``charsets``
372 Optional. Comma-separated list of character sets considered
372 Optional. Comma-separated list of character sets considered
373 convenient for recipients. Addresses, headers, and parts not
373 convenient for recipients. Addresses, headers, and parts not
374 containing patches of outgoing messages will be encoded in the
374 containing patches of outgoing messages will be encoded in the
375 first character set to which conversion from local encoding
375 first character set to which conversion from local encoding
376 (``$HGENCODING``, ``ui.fallbackencoding``) succeeds. If correct
376 (``$HGENCODING``, ``ui.fallbackencoding``) succeeds. If correct
377 conversion fails, the text in question is sent as is. Defaults to
377 conversion fails, the text in question is sent as is. Defaults to
378 empty (explicit) list.
378 empty (explicit) list.
379
379
380 Order of outgoing email character sets:
380 Order of outgoing email character sets:
381
381
382 1. ``us-ascii``: always first, regardless of settings
382 1. ``us-ascii``: always first, regardless of settings
383 2. ``email.charsets``: in order given by user
383 2. ``email.charsets``: in order given by user
384 3. ``ui.fallbackencoding``: if not in email.charsets
384 3. ``ui.fallbackencoding``: if not in email.charsets
385 4. ``$HGENCODING``: if not in email.charsets
385 4. ``$HGENCODING``: if not in email.charsets
386 5. ``utf-8``: always last, regardless of settings
386 5. ``utf-8``: always last, regardless of settings
387
387
388 Email example::
388 Email example::
389
389
390 [email]
390 [email]
391 from = Joseph User <joe.user@example.com>
391 from = Joseph User <joe.user@example.com>
392 method = /usr/sbin/sendmail
392 method = /usr/sbin/sendmail
393 # charsets for western Europeans
393 # charsets for western Europeans
394 # us-ascii, utf-8 omitted, as they are tried first and last
394 # us-ascii, utf-8 omitted, as they are tried first and last
395 charsets = iso-8859-1, iso-8859-15, windows-1252
395 charsets = iso-8859-1, iso-8859-15, windows-1252
396
396
397
397
398 ``extensions``
398 ``extensions``
399 """"""""""""""
399 """"""""""""""
400
400
401 Mercurial has an extension mechanism for adding new features. To
401 Mercurial has an extension mechanism for adding new features. To
402 enable an extension, create an entry for it in this section.
402 enable an extension, create an entry for it in this section.
403
403
404 If you know that the extension is already in Python's search path,
404 If you know that the extension is already in Python's search path,
405 you can give the name of the module, followed by ``=``, with nothing
405 you can give the name of the module, followed by ``=``, with nothing
406 after the ``=``.
406 after the ``=``.
407
407
408 Otherwise, give a name that you choose, followed by ``=``, followed by
408 Otherwise, give a name that you choose, followed by ``=``, followed by
409 the path to the ``.py`` file (including the file name extension) that
409 the path to the ``.py`` file (including the file name extension) that
410 defines the extension.
410 defines the extension.
411
411
412 To explicitly disable an extension that is enabled in an hgrc of
412 To explicitly disable an extension that is enabled in an hgrc of
413 broader scope, prepend its path with ``!``, as in
413 broader scope, prepend its path with ``!``, as in
414 ``hgext.foo = !/ext/path`` or ``hgext.foo = !`` when path is not
414 ``hgext.foo = !/ext/path`` or ``hgext.foo = !`` when path is not
415 supplied.
415 supplied.
416
416
417 Example for ``~/.hgrc``::
417 Example for ``~/.hgrc``::
418
418
419 [extensions]
419 [extensions]
420 # (the mq extension will get loaded from Mercurial's path)
420 # (the mq extension will get loaded from Mercurial's path)
421 hgext.mq =
421 hgext.mq =
422 # (this extension will get loaded from the file specified)
422 # (this extension will get loaded from the file specified)
423 myfeature = ~/.hgext/myfeature.py
423 myfeature = ~/.hgext/myfeature.py
424
424
425
425
426 ``format``
426 ``format``
427 """"""""""
427 """"""""""
428
428
429 ``usestore``
429 ``usestore``
430 Enable or disable the "store" repository format which improves
430 Enable or disable the "store" repository format which improves
431 compatibility with systems that fold case or otherwise mangle
431 compatibility with systems that fold case or otherwise mangle
432 filenames. Enabled by default. Disabling this option will allow
432 filenames. Enabled by default. Disabling this option will allow
433 you to store longer filenames in some situations at the expense of
433 you to store longer filenames in some situations at the expense of
434 compatibility and ensures that the on-disk format of newly created
434 compatibility and ensures that the on-disk format of newly created
435 repositories will be compatible with Mercurial before version 0.9.4.
435 repositories will be compatible with Mercurial before version 0.9.4.
436
436
437 ``usefncache``
437 ``usefncache``
438 Enable or disable the "fncache" repository format which enhances
438 Enable or disable the "fncache" repository format which enhances
439 the "store" repository format (which has to be enabled to use
439 the "store" repository format (which has to be enabled to use
440 fncache) to allow longer filenames and avoids using Windows
440 fncache) to allow longer filenames and avoids using Windows
441 reserved names, e.g. "nul". Enabled by default. Disabling this
441 reserved names, e.g. "nul". Enabled by default. Disabling this
442 option ensures that the on-disk format of newly created
442 option ensures that the on-disk format of newly created
443 repositories will be compatible with Mercurial before version 1.1.
443 repositories will be compatible with Mercurial before version 1.1.
444
444
445 ``dotencode``
445 ``dotencode``
446 Enable or disable the "dotencode" repository format which enhances
446 Enable or disable the "dotencode" repository format which enhances
447 the "fncache" repository format (which has to be enabled to use
447 the "fncache" repository format (which has to be enabled to use
448 dotencode) to avoid issues with filenames starting with ._ on
448 dotencode) to avoid issues with filenames starting with ._ on
449 Mac OS X and spaces on Windows. Enabled by default. Disabling this
449 Mac OS X and spaces on Windows. Enabled by default. Disabling this
450 option ensures that the on-disk format of newly created
450 option ensures that the on-disk format of newly created
451 repositories will be compatible with Mercurial before version 1.7.
451 repositories will be compatible with Mercurial before version 1.7.
452
452
453 ``merge-patterns``
453 ``merge-patterns``
454 """"""""""""""""""
454 """"""""""""""""""
455
455
456 This section specifies merge tools to associate with particular file
456 This section specifies merge tools to associate with particular file
457 patterns. Tools matched here will take precedence over the default
457 patterns. Tools matched here will take precedence over the default
458 merge tool. Patterns are globs by default, rooted at the repository
458 merge tool. Patterns are globs by default, rooted at the repository
459 root.
459 root.
460
460
461 Example::
461 Example::
462
462
463 [merge-patterns]
463 [merge-patterns]
464 **.c = kdiff3
464 **.c = kdiff3
465 **.jpg = myimgmerge
465 **.jpg = myimgmerge
466
466
467 ``merge-tools``
467 ``merge-tools``
468 """""""""""""""
468 """""""""""""""
469
469
470 This section configures external merge tools to use for file-level
470 This section configures external merge tools to use for file-level
471 merges.
471 merges.
472
472
473 Example ``~/.hgrc``::
473 Example ``~/.hgrc``::
474
474
475 [merge-tools]
475 [merge-tools]
476 # Override stock tool location
476 # Override stock tool location
477 kdiff3.executable = ~/bin/kdiff3
477 kdiff3.executable = ~/bin/kdiff3
478 # Specify command line
478 # Specify command line
479 kdiff3.args = $base $local $other -o $output
479 kdiff3.args = $base $local $other -o $output
480 # Give higher priority
480 # Give higher priority
481 kdiff3.priority = 1
481 kdiff3.priority = 1
482
482
483 # Define new tool
483 # Define new tool
484 myHtmlTool.args = -m $local $other $base $output
484 myHtmlTool.args = -m $local $other $base $output
485 myHtmlTool.regkey = Software\FooSoftware\HtmlMerge
485 myHtmlTool.regkey = Software\FooSoftware\HtmlMerge
486 myHtmlTool.priority = 1
486 myHtmlTool.priority = 1
487
487
488 Supported arguments:
488 Supported arguments:
489
489
490 ``priority``
490 ``priority``
491 The priority in which to evaluate this tool.
491 The priority in which to evaluate this tool.
492 Default: 0.
492 Default: 0.
493 ``executable``
493 ``executable``
494 Either just the name of the executable or its pathname. On Windows,
494 Either just the name of the executable or its pathname. On Windows,
495 the path can use environment variables with ${ProgramFiles} syntax.
495 the path can use environment variables with ${ProgramFiles} syntax.
496 Default: the tool name.
496 Default: the tool name.
497 ``args``
497 ``args``
498 The arguments to pass to the tool executable. You can refer to the
498 The arguments to pass to the tool executable. You can refer to the
499 files being merged as well as the output file through these
499 files being merged as well as the output file through these
500 variables: ``$base``, ``$local``, ``$other``, ``$output``.
500 variables: ``$base``, ``$local``, ``$other``, ``$output``.
501 Default: ``$local $base $other``
501 Default: ``$local $base $other``
502 ``premerge``
502 ``premerge``
503 Attempt to run internal non-interactive 3-way merge tool before
503 Attempt to run internal non-interactive 3-way merge tool before
504 launching external tool. Options are ``true``, ``false``, or ``keep``
504 launching external tool. Options are ``true``, ``false``, or ``keep``
505 to leave markers in the file if the premerge fails.
505 to leave markers in the file if the premerge fails.
506 Default: True
506 Default: True
507 ``binary``
507 ``binary``
508 This tool can merge binary files. Defaults to False, unless tool
508 This tool can merge binary files. Defaults to False, unless tool
509 was selected by file pattern match.
509 was selected by file pattern match.
510 ``symlink``
510 ``symlink``
511 This tool can merge symlinks. Defaults to False, even if tool was
511 This tool can merge symlinks. Defaults to False, even if tool was
512 selected by file pattern match.
512 selected by file pattern match.
513 ``check``
513 ``check``
514 A list of merge success-checking options:
514 A list of merge success-checking options:
515
515
516 ``changed``
516 ``changed``
517 Ask whether merge was successful when the merged file shows no changes.
517 Ask whether merge was successful when the merged file shows no changes.
518 ``conflicts``
518 ``conflicts``
519 Check whether there are conflicts even though the tool reported success.
519 Check whether there are conflicts even though the tool reported success.
520 ``prompt``
520 ``prompt``
521 Always prompt for merge success, regardless of success reported by tool.
521 Always prompt for merge success, regardless of success reported by tool.
522
522
523 ``checkchanged``
523 ``checkchanged``
524 True is equivalent to ``check = changed``.
524 True is equivalent to ``check = changed``.
525 Default: False
525 Default: False
526 ``checkconflicts``
526 ``checkconflicts``
527 True is equivalent to ``check = conflicts``.
527 True is equivalent to ``check = conflicts``.
528 Default: False
528 Default: False
529 ``fixeol``
529 ``fixeol``
530 Attempt to fix up EOL changes caused by the merge tool.
530 Attempt to fix up EOL changes caused by the merge tool.
531 Default: False
531 Default: False
532 ``gui``
532 ``gui``
533 This tool requires a graphical interface to run. Default: False
533 This tool requires a graphical interface to run. Default: False
534 ``regkey``
534 ``regkey``
535 Windows registry key which describes install location of this
535 Windows registry key which describes install location of this
536 tool. Mercurial will search for this key first under
536 tool. Mercurial will search for this key first under
537 ``HKEY_CURRENT_USER`` and then under ``HKEY_LOCAL_MACHINE``.
537 ``HKEY_CURRENT_USER`` and then under ``HKEY_LOCAL_MACHINE``.
538 Default: None
538 Default: None
539 ``regname``
539 ``regname``
540 Name of value to read from specified registry key. Defaults to the
540 Name of value to read from specified registry key. Defaults to the
541 unnamed (default) value.
541 unnamed (default) value.
542 ``regappend``
542 ``regappend``
543 String to append to the value read from the registry, typically
543 String to append to the value read from the registry, typically
544 the executable name of the tool.
544 the executable name of the tool.
545 Default: None
545 Default: None
546
546
547
547
548 ``hooks``
548 ``hooks``
549 """""""""
549 """""""""
550 Commands or Python functions that get automatically executed by
550 Commands or Python functions that get automatically executed by
551 various actions such as starting or finishing a commit. Multiple
551 various actions such as starting or finishing a commit. Multiple
552 hooks can be run for the same action by appending a suffix to the
552 hooks can be run for the same action by appending a suffix to the
553 action. Overriding a site-wide hook can be done by changing its
553 action. Overriding a site-wide hook can be done by changing its
554 value or setting it to an empty string.
554 value or setting it to an empty string.
555
555
556 Example ``.hg/hgrc``::
556 Example ``.hg/hgrc``::
557
557
558 [hooks]
558 [hooks]
559 # update working directory after adding changesets
559 # update working directory after adding changesets
560 changegroup.update = hg update
560 changegroup.update = hg update
561 # do not use the site-wide hook
561 # do not use the site-wide hook
562 incoming =
562 incoming =
563 incoming.email = /my/email/hook
563 incoming.email = /my/email/hook
564 incoming.autobuild = /my/build/hook
564 incoming.autobuild = /my/build/hook
565
565
566 Most hooks are run with environment variables set that give useful
566 Most hooks are run with environment variables set that give useful
567 additional information. For each hook below, the environment
567 additional information. For each hook below, the environment
568 variables it is passed are listed with names of the form ``$HG_foo``.
568 variables it is passed are listed with names of the form ``$HG_foo``.
569
569
570 ``changegroup``
570 ``changegroup``
571 Run after a changegroup has been added via push, pull or unbundle.
571 Run after a changegroup has been added via push, pull or unbundle.
572 ID of the first new changeset is in ``$HG_NODE``. URL from which
572 ID of the first new changeset is in ``$HG_NODE``. URL from which
573 changes came is in ``$HG_URL``.
573 changes came is in ``$HG_URL``.
574 ``commit``
574 ``commit``
575 Run after a changeset has been created in the local repository. ID
575 Run after a changeset has been created in the local repository. ID
576 of the newly created changeset is in ``$HG_NODE``. Parent changeset
576 of the newly created changeset is in ``$HG_NODE``. Parent changeset
577 IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
577 IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
578 ``incoming``
578 ``incoming``
579 Run after a changeset has been pulled, pushed, or unbundled into
579 Run after a changeset has been pulled, pushed, or unbundled into
580 the local repository. The ID of the newly arrived changeset is in
580 the local repository. The ID of the newly arrived changeset is in
581 ``$HG_NODE``. URL that was source of changes came is in ``$HG_URL``.
581 ``$HG_NODE``. URL that was source of changes came is in ``$HG_URL``.
582 ``outgoing``
582 ``outgoing``
583 Run after sending changes from local repository to another. ID of
583 Run after sending changes from local repository to another. ID of
584 first changeset sent is in ``$HG_NODE``. Source of operation is in
584 first changeset sent is in ``$HG_NODE``. Source of operation is in
585 ``$HG_SOURCE``; see "preoutgoing" hook for description.
585 ``$HG_SOURCE``; see "preoutgoing" hook for description.
586 ``post-<command>``
586 ``post-<command>``
587 Run after successful invocations of the associated command. The
587 Run after successful invocations of the associated command. The
588 contents of the command line are passed as ``$HG_ARGS`` and the result
588 contents of the command line are passed as ``$HG_ARGS`` and the result
589 code in ``$HG_RESULT``. Parsed command line arguments are passed as
589 code in ``$HG_RESULT``. Parsed command line arguments are passed as
590 ``$HG_PATS`` and ``$HG_OPTS``. These contain string representations of
590 ``$HG_PATS`` and ``$HG_OPTS``. These contain string representations of
591 the python data internally passed to <command>. ``$HG_OPTS`` is a
591 the python data internally passed to <command>. ``$HG_OPTS`` is a
592 dictionary of options (with unspecified options set to their defaults).
592 dictionary of options (with unspecified options set to their defaults).
593 ``$HG_PATS`` is a list of arguments. Hook failure is ignored.
593 ``$HG_PATS`` is a list of arguments. Hook failure is ignored.
594 ``pre-<command>``
594 ``pre-<command>``
595 Run before executing the associated command. The contents of the
595 Run before executing the associated command. The contents of the
596 command line are passed as ``$HG_ARGS``. Parsed command line arguments
596 command line are passed as ``$HG_ARGS``. Parsed command line arguments
597 are passed as ``$HG_PATS`` and ``$HG_OPTS``. These contain string
597 are passed as ``$HG_PATS`` and ``$HG_OPTS``. These contain string
598 representations of the data internally passed to <command>. ``$HG_OPTS``
598 representations of the data internally passed to <command>. ``$HG_OPTS``
599 is a dictionary of options (with unspecified options set to their
599 is a dictionary of options (with unspecified options set to their
600 defaults). ``$HG_PATS`` is a list of arguments. If the hook returns
600 defaults). ``$HG_PATS`` is a list of arguments. If the hook returns
601 failure, the command doesn't execute and Mercurial returns the failure
601 failure, the command doesn't execute and Mercurial returns the failure
602 code.
602 code.
603 ``prechangegroup``
603 ``prechangegroup``
604 Run before a changegroup is added via push, pull or unbundle. Exit
604 Run before a changegroup is added via push, pull or unbundle. Exit
605 status 0 allows the changegroup to proceed. Non-zero status will
605 status 0 allows the changegroup to proceed. Non-zero status will
606 cause the push, pull or unbundle to fail. URL from which changes
606 cause the push, pull or unbundle to fail. URL from which changes
607 will come is in ``$HG_URL``.
607 will come is in ``$HG_URL``.
608 ``precommit``
608 ``precommit``
609 Run before starting a local commit. Exit status 0 allows the
609 Run before starting a local commit. Exit status 0 allows the
610 commit to proceed. Non-zero status will cause the commit to fail.
610 commit to proceed. Non-zero status will cause the commit to fail.
611 Parent changeset IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
611 Parent changeset IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
612 ``preoutgoing``
612 ``preoutgoing``
613 Run before collecting changes to send from the local repository to
613 Run before collecting changes to send from the local repository to
614 another. Non-zero status will cause failure. This lets you prevent
614 another. Non-zero status will cause failure. This lets you prevent
615 pull over HTTP or SSH. Also prevents against local pull, push
615 pull over HTTP or SSH. Also prevents against local pull, push
616 (outbound) or bundle commands, but not effective, since you can
616 (outbound) or bundle commands, but not effective, since you can
617 just copy files instead then. Source of operation is in
617 just copy files instead then. Source of operation is in
618 ``$HG_SOURCE``. If "serve", operation is happening on behalf of remote
618 ``$HG_SOURCE``. If "serve", operation is happening on behalf of remote
619 SSH or HTTP repository. If "push", "pull" or "bundle", operation
619 SSH or HTTP repository. If "push", "pull" or "bundle", operation
620 is happening on behalf of repository on same system.
620 is happening on behalf of repository on same system.
621 ``pretag``
621 ``pretag``
622 Run before creating a tag. Exit status 0 allows the tag to be
622 Run before creating a tag. Exit status 0 allows the tag to be
623 created. Non-zero status will cause the tag to fail. ID of
623 created. Non-zero status will cause the tag to fail. ID of
624 changeset to tag is in ``$HG_NODE``. Name of tag is in ``$HG_TAG``. Tag is
624 changeset to tag is in ``$HG_NODE``. Name of tag is in ``$HG_TAG``. Tag is
625 local if ``$HG_LOCAL=1``, in repository if ``$HG_LOCAL=0``.
625 local if ``$HG_LOCAL=1``, in repository if ``$HG_LOCAL=0``.
626 ``pretxnchangegroup``
626 ``pretxnchangegroup``
627 Run after a changegroup has been added via push, pull or unbundle,
627 Run after a changegroup has been added via push, pull or unbundle,
628 but before the transaction has been committed. Changegroup is
628 but before the transaction has been committed. Changegroup is
629 visible to hook program. This lets you validate incoming changes
629 visible to hook program. This lets you validate incoming changes
630 before accepting them. Passed the ID of the first new changeset in
630 before accepting them. Passed the ID of the first new changeset in
631 ``$HG_NODE``. Exit status 0 allows the transaction to commit. Non-zero
631 ``$HG_NODE``. Exit status 0 allows the transaction to commit. Non-zero
632 status will cause the transaction to be rolled back and the push,
632 status will cause the transaction to be rolled back and the push,
633 pull or unbundle will fail. URL that was source of changes is in
633 pull or unbundle will fail. URL that was source of changes is in
634 ``$HG_URL``.
634 ``$HG_URL``.
635 ``pretxncommit``
635 ``pretxncommit``
636 Run after a changeset has been created but the transaction not yet
636 Run after a changeset has been created but the transaction not yet
637 committed. Changeset is visible to hook program. This lets you
637 committed. Changeset is visible to hook program. This lets you
638 validate commit message and changes. Exit status 0 allows the
638 validate commit message and changes. Exit status 0 allows the
639 commit to proceed. Non-zero status will cause the transaction to
639 commit to proceed. Non-zero status will cause the transaction to
640 be rolled back. ID of changeset is in ``$HG_NODE``. Parent changeset
640 be rolled back. ID of changeset is in ``$HG_NODE``. Parent changeset
641 IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
641 IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
642 ``preupdate``
642 ``preupdate``
643 Run before updating the working directory. Exit status 0 allows
643 Run before updating the working directory. Exit status 0 allows
644 the update to proceed. Non-zero status will prevent the update.
644 the update to proceed. Non-zero status will prevent the update.
645 Changeset ID of first new parent is in ``$HG_PARENT1``. If merge, ID
645 Changeset ID of first new parent is in ``$HG_PARENT1``. If merge, ID
646 of second new parent is in ``$HG_PARENT2``.
646 of second new parent is in ``$HG_PARENT2``.
647 ``tag``
647 ``tag``
648 Run after a tag is created. ID of tagged changeset is in ``$HG_NODE``.
648 Run after a tag is created. ID of tagged changeset is in ``$HG_NODE``.
649 Name of tag is in ``$HG_TAG``. Tag is local if ``$HG_LOCAL=1``, in
649 Name of tag is in ``$HG_TAG``. Tag is local if ``$HG_LOCAL=1``, in
650 repository if ``$HG_LOCAL=0``.
650 repository if ``$HG_LOCAL=0``.
651 ``update``
651 ``update``
652 Run after updating the working directory. Changeset ID of first
652 Run after updating the working directory. Changeset ID of first
653 new parent is in ``$HG_PARENT1``. If merge, ID of second new parent is
653 new parent is in ``$HG_PARENT1``. If merge, ID of second new parent is
654 in ``$HG_PARENT2``. If the update succeeded, ``$HG_ERROR=0``. If the
654 in ``$HG_PARENT2``. If the update succeeded, ``$HG_ERROR=0``. If the
655 update failed (e.g. because conflicts not resolved), ``$HG_ERROR=1``.
655 update failed (e.g. because conflicts not resolved), ``$HG_ERROR=1``.
656
656
657 .. note:: It is generally better to use standard hooks rather than the
657 .. note:: It is generally better to use standard hooks rather than the
658 generic pre- and post- command hooks as they are guaranteed to be
658 generic pre- and post- command hooks as they are guaranteed to be
659 called in the appropriate contexts for influencing transactions.
659 called in the appropriate contexts for influencing transactions.
660 Also, hooks like "commit" will be called in all contexts that
660 Also, hooks like "commit" will be called in all contexts that
661 generate a commit (e.g. tag) and not just the commit command.
661 generate a commit (e.g. tag) and not just the commit command.
662
662
663 .. note:: Environment variables with empty values may not be passed to
663 .. note:: Environment variables with empty values may not be passed to
664 hooks on platforms such as Windows. As an example, ``$HG_PARENT2``
664 hooks on platforms such as Windows. As an example, ``$HG_PARENT2``
665 will have an empty value under Unix-like platforms for non-merge
665 will have an empty value under Unix-like platforms for non-merge
666 changesets, while it will not be available at all under Windows.
666 changesets, while it will not be available at all under Windows.
667
667
668 The syntax for Python hooks is as follows::
668 The syntax for Python hooks is as follows::
669
669
670 hookname = python:modulename.submodule.callable
670 hookname = python:modulename.submodule.callable
671 hookname = python:/path/to/python/module.py:callable
671 hookname = python:/path/to/python/module.py:callable
672
672
673 Python hooks are run within the Mercurial process. Each hook is
673 Python hooks are run within the Mercurial process. Each hook is
674 called with at least three keyword arguments: a ui object (keyword
674 called with at least three keyword arguments: a ui object (keyword
675 ``ui``), a repository object (keyword ``repo``), and a ``hooktype``
675 ``ui``), a repository object (keyword ``repo``), and a ``hooktype``
676 keyword that tells what kind of hook is used. Arguments listed as
676 keyword that tells what kind of hook is used. Arguments listed as
677 environment variables above are passed as keyword arguments, with no
677 environment variables above are passed as keyword arguments, with no
678 ``HG_`` prefix, and names in lower case.
678 ``HG_`` prefix, and names in lower case.
679
679
680 If a Python hook returns a "true" value or raises an exception, this
680 If a Python hook returns a "true" value or raises an exception, this
681 is treated as a failure.
681 is treated as a failure.
682
682
683
683
684 ``http_proxy``
684 ``http_proxy``
685 """"""""""""""
685 """"""""""""""
686 Used to access web-based Mercurial repositories through a HTTP
686 Used to access web-based Mercurial repositories through a HTTP
687 proxy.
687 proxy.
688
688
689 ``host``
689 ``host``
690 Host name and (optional) port of the proxy server, for example
690 Host name and (optional) port of the proxy server, for example
691 "myproxy:8000".
691 "myproxy:8000".
692 ``no``
692 ``no``
693 Optional. Comma-separated list of host names that should bypass
693 Optional. Comma-separated list of host names that should bypass
694 the proxy.
694 the proxy.
695 ``passwd``
695 ``passwd``
696 Optional. Password to authenticate with at the proxy server.
696 Optional. Password to authenticate with at the proxy server.
697 ``user``
697 ``user``
698 Optional. User name to authenticate with at the proxy server.
698 Optional. User name to authenticate with at the proxy server.
699 ``always``
699 ``always``
700 Optional. Always use the proxy, even for localhost and any entries
700 Optional. Always use the proxy, even for localhost and any entries
701 in ``http_proxy.no``. True or False. Default: False.
701 in ``http_proxy.no``. True or False. Default: False.
702
702
703 ``smtp``
703 ``smtp``
704 """"""""
704 """"""""
705 Configuration for extensions that need to send email messages.
705 Configuration for extensions that need to send email messages.
706
706
707 ``host``
707 ``host``
708 Host name of mail server, e.g. "mail.example.com".
708 Host name of mail server, e.g. "mail.example.com".
709 ``port``
709 ``port``
710 Optional. Port to connect to on mail server. Default: 25.
710 Optional. Port to connect to on mail server. Default: 25.
711 ``tls``
711 ``tls``
712 Optional. Method to enable TLS when connecting to mail server: starttls,
712 Optional. Method to enable TLS when connecting to mail server: starttls,
713 smtps or none. Default: none.
713 smtps or none. Default: none.
714 ``username``
714 ``username``
715 Optional. User name for authenticating with the SMTP server.
715 Optional. User name for authenticating with the SMTP server.
716 Default: none.
716 Default: none.
717 ``password``
717 ``password``
718 Optional. Password for authenticating with the SMTP server. If not
718 Optional. Password for authenticating with the SMTP server. If not
719 specified, interactive sessions will prompt the user for a
719 specified, interactive sessions will prompt the user for a
720 password; non-interactive sessions will fail. Default: none.
720 password; non-interactive sessions will fail. Default: none.
721 ``local_hostname``
721 ``local_hostname``
722 Optional. It's the hostname that the sender can use to identify
722 Optional. It's the hostname that the sender can use to identify
723 itself to the MTA.
723 itself to the MTA.
724
724
725
725
726 ``patch``
726 ``patch``
727 """""""""
727 """""""""
728 Settings used when applying patches, for instance through the 'import'
728 Settings used when applying patches, for instance through the 'import'
729 command or with Mercurial Queues extension.
729 command or with Mercurial Queues extension.
730
730
731 ``eol``
731 ``eol``
732 When set to 'strict' patch content and patched files end of lines
732 When set to 'strict' patch content and patched files end of lines
733 are preserved. When set to ``lf`` or ``crlf``, both files end of
733 are preserved. When set to ``lf`` or ``crlf``, both files end of
734 lines are ignored when patching and the result line endings are
734 lines are ignored when patching and the result line endings are
735 normalized to either LF (Unix) or CRLF (Windows). When set to
735 normalized to either LF (Unix) or CRLF (Windows). When set to
736 ``auto``, end of lines are again ignored while patching but line
736 ``auto``, end of lines are again ignored while patching but line
737 endings in patched files are normalized to their original setting
737 endings in patched files are normalized to their original setting
738 on a per-file basis. If target file does not exist or has no end
738 on a per-file basis. If target file does not exist or has no end
739 of line, patch line endings are preserved.
739 of line, patch line endings are preserved.
740 Default: strict.
740 Default: strict.
741
741
742
742
743 ``paths``
743 ``paths``
744 """""""""
744 """""""""
745 Assigns symbolic names to repositories. The left side is the
745 Assigns symbolic names to repositories. The left side is the
746 symbolic name, and the right gives the directory or URL that is the
746 symbolic name, and the right gives the directory or URL that is the
747 location of the repository. Default paths can be declared by setting
747 location of the repository. Default paths can be declared by setting
748 the following entries.
748 the following entries.
749
749
750 ``default``
750 ``default``
751 Directory or URL to use when pulling if no source is specified.
751 Directory or URL to use when pulling if no source is specified.
752 Default is set to repository from which the current repository was
752 Default is set to repository from which the current repository was
753 cloned.
753 cloned.
754 ``default-push``
754 ``default-push``
755 Optional. Directory or URL to use when pushing if no destination
755 Optional. Directory or URL to use when pushing if no destination
756 is specified.
756 is specified.
757
757
758
758
759 ``profiling``
759 ``profiling``
760 """""""""""""
760 """""""""""""
761 Specifies profiling format and file output. In this section
761 Specifies profiling format and file output. In this section
762 description, 'profiling data' stands for the raw data collected
762 description, 'profiling data' stands for the raw data collected
763 during profiling, while 'profiling report' stands for a statistical
763 during profiling, while 'profiling report' stands for a statistical
764 text report generated from the profiling data. The profiling is done
764 text report generated from the profiling data. The profiling is done
765 using lsprof.
765 using lsprof.
766
766
767 ``format``
767 ``format``
768 Profiling format.
768 Profiling format.
769 Default: text.
769 Default: text.
770
770
771 ``text``
771 ``text``
772 Generate a profiling report. When saving to a file, it should be
772 Generate a profiling report. When saving to a file, it should be
773 noted that only the report is saved, and the profiling data is
773 noted that only the report is saved, and the profiling data is
774 not kept.
774 not kept.
775 ``kcachegrind``
775 ``kcachegrind``
776 Format profiling data for kcachegrind use: when saving to a
776 Format profiling data for kcachegrind use: when saving to a
777 file, the generated file can directly be loaded into
777 file, the generated file can directly be loaded into
778 kcachegrind.
778 kcachegrind.
779 ``output``
779 ``output``
780 File path where profiling data or report should be saved. If the
780 File path where profiling data or report should be saved. If the
781 file exists, it is replaced. Default: None, data is printed on
781 file exists, it is replaced. Default: None, data is printed on
782 stderr
782 stderr
783
783
784 ``server``
784 ``server``
785 """"""""""
785 """"""""""
786 Controls generic server settings.
786 Controls generic server settings.
787
787
788 ``uncompressed``
788 ``uncompressed``
789 Whether to allow clients to clone a repository using the
789 Whether to allow clients to clone a repository using the
790 uncompressed streaming protocol. This transfers about 40% more
790 uncompressed streaming protocol. This transfers about 40% more
791 data than a regular clone, but uses less memory and CPU on both
791 data than a regular clone, but uses less memory and CPU on both
792 server and client. Over a LAN (100 Mbps or better) or a very fast
792 server and client. Over a LAN (100 Mbps or better) or a very fast
793 WAN, an uncompressed streaming clone is a lot faster (~10x) than a
793 WAN, an uncompressed streaming clone is a lot faster (~10x) than a
794 regular clone. Over most WAN connections (anything slower than
794 regular clone. Over most WAN connections (anything slower than
795 about 6 Mbps), uncompressed streaming is slower, because of the
795 about 6 Mbps), uncompressed streaming is slower, because of the
796 extra data transfer overhead. This mode will also temporarily hold
796 extra data transfer overhead. This mode will also temporarily hold
797 the write lock while determining what data to transfer.
797 the write lock while determining what data to transfer.
798 Default is True.
798 Default is True.
799
799
800 ``validate``
800 ``validate``
801 Whether to validate the completeness of pushed changesets by
801 Whether to validate the completeness of pushed changesets by
802 checking that all new file revisions specified in manifests are
802 checking that all new file revisions specified in manifests are
803 present. Default is False.
803 present. Default is False.
804
804
805 ``subpaths``
805 ``subpaths``
806 """"""""""""
806 """"""""""""
807 Defines subrepositories source locations rewriting rules of the form::
807 Defines subrepositories source locations rewriting rules of the form::
808
808
809 <pattern> = <replacement>
809 <pattern> = <replacement>
810
810
811 Where ``pattern`` is a regular expression matching the source and
811 Where ``pattern`` is a regular expression matching the source and
812 ``replacement`` is the replacement string used to rewrite it. Groups
812 ``replacement`` is the replacement string used to rewrite it. Groups
813 can be matched in ``pattern`` and referenced in ``replacements``. For
813 can be matched in ``pattern`` and referenced in ``replacements``. For
814 instance::
814 instance::
815
815
816 http://server/(.*)-hg/ = http://hg.server/\1/
816 http://server/(.*)-hg/ = http://hg.server/\1/
817
817
818 rewrites ``http://server/foo-hg/`` into ``http://hg.server/foo/``.
818 rewrites ``http://server/foo-hg/`` into ``http://hg.server/foo/``.
819
819
820 All patterns are applied in definition order.
820 All patterns are applied in definition order.
821
821
822 ``trusted``
822 ``trusted``
823 """""""""""
823 """""""""""
824
824
825 Mercurial will not use the settings in the
825 Mercurial will not use the settings in the
826 ``.hg/hgrc`` file from a repository if it doesn't belong to a trusted
826 ``.hg/hgrc`` file from a repository if it doesn't belong to a trusted
827 user or to a trusted group, as various hgrc features allow arbitrary
827 user or to a trusted group, as various hgrc features allow arbitrary
828 commands to be run. This issue is often encountered when configuring
828 commands to be run. This issue is often encountered when configuring
829 hooks or extensions for shared repositories or servers. However,
829 hooks or extensions for shared repositories or servers. However,
830 the web interface will use some safe settings from the ``[web]``
830 the web interface will use some safe settings from the ``[web]``
831 section.
831 section.
832
832
833 This section specifies what users and groups are trusted. The
833 This section specifies what users and groups are trusted. The
834 current user is always trusted. To trust everybody, list a user or a
834 current user is always trusted. To trust everybody, list a user or a
835 group with name ``*``. These settings must be placed in an
835 group with name ``*``. These settings must be placed in an
836 *already-trusted file* to take effect, such as ``$HOME/.hgrc`` of the
836 *already-trusted file* to take effect, such as ``$HOME/.hgrc`` of the
837 user or service running Mercurial.
837 user or service running Mercurial.
838
838
839 ``users``
839 ``users``
840 Comma-separated list of trusted users.
840 Comma-separated list of trusted users.
841 ``groups``
841 ``groups``
842 Comma-separated list of trusted groups.
842 Comma-separated list of trusted groups.
843
843
844
844
845 ``ui``
845 ``ui``
846 """"""
846 """"""
847
847
848 User interface controls.
848 User interface controls.
849
849
850 ``archivemeta``
850 ``archivemeta``
851 Whether to include the .hg_archival.txt file containing meta data
851 Whether to include the .hg_archival.txt file containing meta data
852 (hashes for the repository base and for tip) in archives created
852 (hashes for the repository base and for tip) in archives created
853 by the :hg:`archive` command or downloaded via hgweb.
853 by the :hg:`archive` command or downloaded via hgweb.
854 Default is True.
854 Default is True.
855 ``askusername``
855 ``askusername``
856 Whether to prompt for a username when committing. If True, and
856 Whether to prompt for a username when committing. If True, and
857 neither ``$HGUSER`` nor ``$EMAIL`` has been specified, then the user will
857 neither ``$HGUSER`` nor ``$EMAIL`` has been specified, then the user will
858 be prompted to enter a username. If no username is entered, the
858 be prompted to enter a username. If no username is entered, the
859 default ``USER@HOST`` is used instead.
859 default ``USER@HOST`` is used instead.
860 Default is False.
860 Default is False.
861 ``debug``
861 ``debug``
862 Print debugging information. True or False. Default is False.
862 Print debugging information. True or False. Default is False.
863 ``editor``
863 ``editor``
864 The editor to use during a commit. Default is ``$EDITOR`` or ``vi``.
864 The editor to use during a commit. Default is ``$EDITOR`` or ``vi``.
865 ``fallbackencoding``
865 ``fallbackencoding``
866 Encoding to try if it's not possible to decode the changelog using
866 Encoding to try if it's not possible to decode the changelog using
867 UTF-8. Default is ISO-8859-1.
867 UTF-8. Default is ISO-8859-1.
868 ``ignore``
868 ``ignore``
869 A file to read per-user ignore patterns from. This file should be
869 A file to read per-user ignore patterns from. This file should be
870 in the same format as a repository-wide .hgignore file. This
870 in the same format as a repository-wide .hgignore file. This
871 option supports hook syntax, so if you want to specify multiple
871 option supports hook syntax, so if you want to specify multiple
872 ignore files, you can do so by setting something like
872 ignore files, you can do so by setting something like
873 ``ignore.other = ~/.hgignore2``. For details of the ignore file
873 ``ignore.other = ~/.hgignore2``. For details of the ignore file
874 format, see the |hgignore(5)|_ man page.
874 format, see the |hgignore(5)|_ man page.
875 ``interactive``
875 ``interactive``
876 Allow to prompt the user. True or False. Default is True.
876 Allow to prompt the user. True or False. Default is True.
877 ``logtemplate``
877 ``logtemplate``
878 Template string for commands that print changesets.
878 Template string for commands that print changesets.
879 ``merge``
879 ``merge``
880 The conflict resolution program to use during a manual merge.
880 The conflict resolution program to use during a manual merge.
881 For more information on merge tools see :hg:`help merge-tools`.
881 For more information on merge tools see :hg:`help merge-tools`.
882 For configuring merge tools see the merge-tools_ section.
882 For configuring merge tools see the merge-tools_ section.
883 ``patch``
883 ``patch``
884 command to use to apply patches. Look for ``gpatch`` or ``patch`` in
884 command to use to apply patches. Look for ``gpatch`` or ``patch`` in
885 PATH if unset.
885 PATH if unset.
886 ``quiet``
886 ``quiet``
887 Reduce the amount of output printed. True or False. Default is False.
887 Reduce the amount of output printed. True or False. Default is False.
888 ``remotecmd``
888 ``remotecmd``
889 remote command to use for clone/push/pull operations. Default is ``hg``.
889 remote command to use for clone/push/pull operations. Default is ``hg``.
890 ``report_untrusted``
890 ``report_untrusted``
891 Warn if a ``.hg/hgrc`` file is ignored due to not being owned by a
891 Warn if a ``.hg/hgrc`` file is ignored due to not being owned by a
892 trusted user or group. True or False. Default is True.
892 trusted user or group. True or False. Default is True.
893 ``slash``
893 ``slash``
894 Display paths using a slash (``/``) as the path separator. This
894 Display paths using a slash (``/``) as the path separator. This
895 only makes a difference on systems where the default path
895 only makes a difference on systems where the default path
896 separator is not the slash character (e.g. Windows uses the
896 separator is not the slash character (e.g. Windows uses the
897 backslash character (``\``)).
897 backslash character (``\``)).
898 Default is False.
898 Default is False.
899 ``ssh``
899 ``ssh``
900 command to use for SSH connections. Default is ``ssh``.
900 command to use for SSH connections. Default is ``ssh``.
901 ``strict``
901 ``strict``
902 Require exact command names, instead of allowing unambiguous
902 Require exact command names, instead of allowing unambiguous
903 abbreviations. True or False. Default is False.
903 abbreviations. True or False. Default is False.
904 ``style``
904 ``style``
905 Name of style to use for command output.
905 Name of style to use for command output.
906 ``timeout``
906 ``timeout``
907 The timeout used when a lock is held (in seconds), a negative value
907 The timeout used when a lock is held (in seconds), a negative value
908 means no timeout. Default is 600.
908 means no timeout. Default is 600.
909 ``traceback``
909 ``traceback``
910 Mercurial always prints a traceback when an unknown exception
910 Mercurial always prints a traceback when an unknown exception
911 occurs. Setting this to True will make Mercurial print a traceback
911 occurs. Setting this to True will make Mercurial print a traceback
912 on all exceptions, even those recognized by Mercurial (such as
912 on all exceptions, even those recognized by Mercurial (such as
913 IOError or MemoryError). Default is False.
913 IOError or MemoryError). Default is False.
914 ``username``
914 ``username``
915 The committer of a changeset created when running "commit".
915 The committer of a changeset created when running "commit".
916 Typically a person's name and email address, e.g. ``Fred Widget
916 Typically a person's name and email address, e.g. ``Fred Widget
917 <fred@example.com>``. Default is ``$EMAIL`` or ``username@hostname``. If
917 <fred@example.com>``. Default is ``$EMAIL`` or ``username@hostname``. If
918 the username in hgrc is empty, it has to be specified manually or
918 the username in hgrc is empty, it has to be specified manually or
919 in a different hgrc file (e.g. ``$HOME/.hgrc``, if the admin set
919 in a different hgrc file (e.g. ``$HOME/.hgrc``, if the admin set
920 ``username =`` in the system hgrc). Environment variables in the
920 ``username =`` in the system hgrc). Environment variables in the
921 username are expanded.
921 username are expanded.
922 ``verbose``
922 ``verbose``
923 Increase the amount of output printed. True or False. Default is False.
923 Increase the amount of output printed. True or False. Default is False.
924
924
925
925
926 ``web``
926 ``web``
927 """""""
927 """""""
928
928
929 Web interface configuration. The settings in this section apply to
929 Web interface configuration. The settings in this section apply to
930 both the builtin webserver (started by :hg:`serve`) and the script you
930 both the builtin webserver (started by :hg:`serve`) and the script you
931 run through a webserver (``hgweb.cgi`` and the derivatives for FastCGI
931 run through a webserver (``hgweb.cgi`` and the derivatives for FastCGI
932 and WSGI).
932 and WSGI).
933
933
934 The Mercurial webserver does no authentication (it does not prompt for
934 The Mercurial webserver does no authentication (it does not prompt for
935 usernames and passwords to validate *who* users are), but it does do
935 usernames and passwords to validate *who* users are), but it does do
936 authorization (it grants or denies access for *authenticated users*
936 authorization (it grants or denies access for *authenticated users*
937 based on settings in this section). You must either configure your
937 based on settings in this section). You must either configure your
938 webserver to do authentication for you, or disable the authorization
938 webserver to do authentication for you, or disable the authorization
939 checks.
939 checks.
940
940
941 For a quick setup in a trusted environment, e.g., a private LAN, where
941 For a quick setup in a trusted environment, e.g., a private LAN, where
942 you want it to accept pushes from anybody, you can use the following
942 you want it to accept pushes from anybody, you can use the following
943 command line::
943 command line::
944
944
945 $ hg --config web.allow_push=* --config web.push_ssl=False serve
945 $ hg --config web.allow_push=* --config web.push_ssl=False serve
946
946
947 Note that this will allow anybody to push anything to the server and
947 Note that this will allow anybody to push anything to the server and
948 that this should not be used for public servers.
948 that this should not be used for public servers.
949
949
950 The full set of options is:
950 The full set of options is:
951
951
952 ``accesslog``
952 ``accesslog``
953 Where to output the access log. Default is stdout.
953 Where to output the access log. Default is stdout.
954 ``address``
954 ``address``
955 Interface address to bind to. Default is all.
955 Interface address to bind to. Default is all.
956 ``allow_archive``
956 ``allow_archive``
957 List of archive format (bz2, gz, zip) allowed for downloading.
957 List of archive format (bz2, gz, zip) allowed for downloading.
958 Default is empty.
958 Default is empty.
959 ``allowbz2``
959 ``allowbz2``
960 (DEPRECATED) Whether to allow .tar.bz2 downloading of repository
960 (DEPRECATED) Whether to allow .tar.bz2 downloading of repository
961 revisions.
961 revisions.
962 Default is False.
962 Default is False.
963 ``allowgz``
963 ``allowgz``
964 (DEPRECATED) Whether to allow .tar.gz downloading of repository
964 (DEPRECATED) Whether to allow .tar.gz downloading of repository
965 revisions.
965 revisions.
966 Default is False.
966 Default is False.
967 ``allowpull``
967 ``allowpull``
968 Whether to allow pulling from the repository. Default is True.
968 Whether to allow pulling from the repository. Default is True.
969 ``allow_push``
969 ``allow_push``
970 Whether to allow pushing to the repository. If empty or not set,
970 Whether to allow pushing to the repository. If empty or not set,
971 push is not allowed. If the special value ``*``, any remote user can
971 push is not allowed. If the special value ``*``, any remote user can
972 push, including unauthenticated users. Otherwise, the remote user
972 push, including unauthenticated users. Otherwise, the remote user
973 must have been authenticated, and the authenticated user name must
973 must have been authenticated, and the authenticated user name must
974 be present in this list. The contents of the allow_push list are
974 be present in this list. The contents of the allow_push list are
975 examined after the deny_push list.
975 examined after the deny_push list.
976 ``allow_read``
976 ``allow_read``
977 If the user has not already been denied repository access due to
977 If the user has not already been denied repository access due to
978 the contents of deny_read, this list determines whether to grant
978 the contents of deny_read, this list determines whether to grant
979 repository access to the user. If this list is not empty, and the
979 repository access to the user. If this list is not empty, and the
980 user is unauthenticated or not present in the list, then access is
980 user is unauthenticated or not present in the list, then access is
981 denied for the user. If the list is empty or not set, then access
981 denied for the user. If the list is empty or not set, then access
982 is permitted to all users by default. Setting allow_read to the
982 is permitted to all users by default. Setting allow_read to the
983 special value ``*`` is equivalent to it not being set (i.e. access
983 special value ``*`` is equivalent to it not being set (i.e. access
984 is permitted to all users). The contents of the allow_read list are
984 is permitted to all users). The contents of the allow_read list are
985 examined after the deny_read list.
985 examined after the deny_read list.
986 ``allowzip``
986 ``allowzip``
987 (DEPRECATED) Whether to allow .zip downloading of repository
987 (DEPRECATED) Whether to allow .zip downloading of repository
988 revisions. Default is False. This feature creates temporary files.
988 revisions. Default is False. This feature creates temporary files.
989 ``baseurl``
989 ``baseurl``
990 Base URL to use when publishing URLs in other locations, so
990 Base URL to use when publishing URLs in other locations, so
991 third-party tools like email notification hooks can construct
991 third-party tools like email notification hooks can construct
992 URLs. Example: ``http://hgserver/repos/``.
992 URLs. Example: ``http://hgserver/repos/``.
993 ``cacerts``
993 ``cacerts``
994 Path to file containing a list of PEM encoded certificate authority
994 Path to file containing a list of PEM encoded certificate
995 certificates. If specified on the client, then it will verify the identity
995 authority certificates. Environment variables and ``~user``
996 of remote HTTPS servers with these certificates. The form must be
996 constructs are expanded in the filename. If specified on the
997 as follows::
997 client, then it will verify the identity of remote HTTPS servers
998 with these certificates. The form must be as follows::
998
999
999 -----BEGIN CERTIFICATE-----
1000 -----BEGIN CERTIFICATE-----
1000 ... (certificate in base64 PEM encoding) ...
1001 ... (certificate in base64 PEM encoding) ...
1001 -----END CERTIFICATE-----
1002 -----END CERTIFICATE-----
1002 -----BEGIN CERTIFICATE-----
1003 -----BEGIN CERTIFICATE-----
1003 ... (certificate in base64 PEM encoding) ...
1004 ... (certificate in base64 PEM encoding) ...
1004 -----END CERTIFICATE-----
1005 -----END CERTIFICATE-----
1005
1006
1006 This feature is only supported when using Python 2.6 or later. If you wish
1007 This feature is only supported when using Python 2.6 or later. If you wish
1007 to use it with earlier versions of Python, install the backported
1008 to use it with earlier versions of Python, install the backported
1008 version of the ssl library that is available from
1009 version of the ssl library that is available from
1009 ``http://pypi.python.org``.
1010 ``http://pypi.python.org``.
1010
1011
1011 You can use OpenSSL's CA certificate file if your platform has one.
1012 You can use OpenSSL's CA certificate file if your platform has one.
1012 On most Linux systems this will be ``/etc/ssl/certs/ca-certificates.crt``.
1013 On most Linux systems this will be ``/etc/ssl/certs/ca-certificates.crt``.
1013 Otherwise you will have to generate this file manually.
1014 Otherwise you will have to generate this file manually.
1014 ``contact``
1015 ``contact``
1015 Name or email address of the person in charge of the repository.
1016 Name or email address of the person in charge of the repository.
1016 Defaults to ui.username or ``$EMAIL`` or "unknown" if unset or empty.
1017 Defaults to ui.username or ``$EMAIL`` or "unknown" if unset or empty.
1017 ``deny_push``
1018 ``deny_push``
1018 Whether to deny pushing to the repository. If empty or not set,
1019 Whether to deny pushing to the repository. If empty or not set,
1019 push is not denied. If the special value ``*``, all remote users are
1020 push is not denied. If the special value ``*``, all remote users are
1020 denied push. Otherwise, unauthenticated users are all denied, and
1021 denied push. Otherwise, unauthenticated users are all denied, and
1021 any authenticated user name present in this list is also denied. The
1022 any authenticated user name present in this list is also denied. The
1022 contents of the deny_push list are examined before the allow_push list.
1023 contents of the deny_push list are examined before the allow_push list.
1023 ``deny_read``
1024 ``deny_read``
1024 Whether to deny reading/viewing of the repository. If this list is
1025 Whether to deny reading/viewing of the repository. If this list is
1025 not empty, unauthenticated users are all denied, and any
1026 not empty, unauthenticated users are all denied, and any
1026 authenticated user name present in this list is also denied access to
1027 authenticated user name present in this list is also denied access to
1027 the repository. If set to the special value ``*``, all remote users
1028 the repository. If set to the special value ``*``, all remote users
1028 are denied access (rarely needed ;). If deny_read is empty or not set,
1029 are denied access (rarely needed ;). If deny_read is empty or not set,
1029 the determination of repository access depends on the presence and
1030 the determination of repository access depends on the presence and
1030 content of the allow_read list (see description). If both
1031 content of the allow_read list (see description). If both
1031 deny_read and allow_read are empty or not set, then access is
1032 deny_read and allow_read are empty or not set, then access is
1032 permitted to all users by default. If the repository is being
1033 permitted to all users by default. If the repository is being
1033 served via hgwebdir, denied users will not be able to see it in
1034 served via hgwebdir, denied users will not be able to see it in
1034 the list of repositories. The contents of the deny_read list have
1035 the list of repositories. The contents of the deny_read list have
1035 priority over (are examined before) the contents of the allow_read
1036 priority over (are examined before) the contents of the allow_read
1036 list.
1037 list.
1037 ``descend``
1038 ``descend``
1038 hgwebdir indexes will not descend into subdirectories. Only repositories
1039 hgwebdir indexes will not descend into subdirectories. Only repositories
1039 directly in the current path will be shown (other repositories are still
1040 directly in the current path will be shown (other repositories are still
1040 available from the index corresponding to their containing path).
1041 available from the index corresponding to their containing path).
1041 ``description``
1042 ``description``
1042 Textual description of the repository's purpose or contents.
1043 Textual description of the repository's purpose or contents.
1043 Default is "unknown".
1044 Default is "unknown".
1044 ``encoding``
1045 ``encoding``
1045 Character encoding name. Default is the current locale charset.
1046 Character encoding name. Default is the current locale charset.
1046 Example: "UTF-8"
1047 Example: "UTF-8"
1047 ``errorlog``
1048 ``errorlog``
1048 Where to output the error log. Default is stderr.
1049 Where to output the error log. Default is stderr.
1049 ``hidden``
1050 ``hidden``
1050 Whether to hide the repository in the hgwebdir index.
1051 Whether to hide the repository in the hgwebdir index.
1051 Default is False.
1052 Default is False.
1052 ``ipv6``
1053 ``ipv6``
1053 Whether to use IPv6. Default is False.
1054 Whether to use IPv6. Default is False.
1054 ``name``
1055 ``name``
1055 Repository name to use in the web interface. Default is current
1056 Repository name to use in the web interface. Default is current
1056 working directory.
1057 working directory.
1057 ``maxchanges``
1058 ``maxchanges``
1058 Maximum number of changes to list on the changelog. Default is 10.
1059 Maximum number of changes to list on the changelog. Default is 10.
1059 ``maxfiles``
1060 ``maxfiles``
1060 Maximum number of files to list per changeset. Default is 10.
1061 Maximum number of files to list per changeset. Default is 10.
1061 ``port``
1062 ``port``
1062 Port to listen on. Default is 8000.
1063 Port to listen on. Default is 8000.
1063 ``prefix``
1064 ``prefix``
1064 Prefix path to serve from. Default is '' (server root).
1065 Prefix path to serve from. Default is '' (server root).
1065 ``push_ssl``
1066 ``push_ssl``
1066 Whether to require that inbound pushes be transported over SSL to
1067 Whether to require that inbound pushes be transported over SSL to
1067 prevent password sniffing. Default is True.
1068 prevent password sniffing. Default is True.
1068 ``staticurl``
1069 ``staticurl``
1069 Base URL to use for static files. If unset, static files (e.g. the
1070 Base URL to use for static files. If unset, static files (e.g. the
1070 hgicon.png favicon) will be served by the CGI script itself. Use
1071 hgicon.png favicon) will be served by the CGI script itself. Use
1071 this setting to serve them directly with the HTTP server.
1072 this setting to serve them directly with the HTTP server.
1072 Example: ``http://hgserver/static/``.
1073 Example: ``http://hgserver/static/``.
1073 ``stripes``
1074 ``stripes``
1074 How many lines a "zebra stripe" should span in multiline output.
1075 How many lines a "zebra stripe" should span in multiline output.
1075 Default is 1; set to 0 to disable.
1076 Default is 1; set to 0 to disable.
1076 ``style``
1077 ``style``
1077 Which template map style to use.
1078 Which template map style to use.
1078 ``templates``
1079 ``templates``
1079 Where to find the HTML templates. Default is install path.
1080 Where to find the HTML templates. Default is install path.
1080
1081
1081
1082
1082 Author
1083 Author
1083 ------
1084 ------
1084 Bryan O'Sullivan <bos@serpentine.com>.
1085 Bryan O'Sullivan <bos@serpentine.com>.
1085
1086
1086 Mercurial was written by Matt Mackall <mpm@selenic.com>.
1087 Mercurial was written by Matt Mackall <mpm@selenic.com>.
1087
1088
1088 See Also
1089 See Also
1089 --------
1090 --------
1090 |hg(1)|_, |hgignore(5)|_
1091 |hg(1)|_, |hgignore(5)|_
1091
1092
1092 Copying
1093 Copying
1093 -------
1094 -------
1094 This manual page is copyright 2005 Bryan O'Sullivan.
1095 This manual page is copyright 2005 Bryan O'Sullivan.
1095 Mercurial is copyright 2005-2010 Matt Mackall.
1096 Mercurial is copyright 2005-2010 Matt Mackall.
1096 Free use of this software is granted under the terms of the GNU General
1097 Free use of this software is granted under the terms of the GNU General
1097 Public License version 2 or any later version.
1098 Public License version 2 or any later version.
1098
1099
1099 .. include:: common.txt
1100 .. include:: common.txt
@@ -1,4535 +1,4535 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 node import hex, nullid, nullrev, short
8 from node import hex, nullid, nullrev, short
9 from lock import release
9 from lock import release
10 from i18n import _, gettext
10 from i18n import _, gettext
11 import os, re, sys, difflib, time, tempfile
11 import os, re, sys, difflib, time, tempfile
12 import hg, util, revlog, extensions, copies, error
12 import hg, util, revlog, extensions, copies, error
13 import patch, help, mdiff, url, encoding, templatekw, discovery
13 import patch, help, mdiff, url, encoding, templatekw, discovery
14 import archival, changegroup, cmdutil, sshserver, hbisect, hgweb, hgweb.server
14 import archival, changegroup, cmdutil, sshserver, hbisect, hgweb, hgweb.server
15 import merge as mergemod
15 import merge as mergemod
16 import minirst, revset
16 import minirst, revset
17 import dagparser
17 import dagparser
18
18
19 # Commands start here, listed alphabetically
19 # Commands start here, listed alphabetically
20
20
21 def add(ui, repo, *pats, **opts):
21 def add(ui, repo, *pats, **opts):
22 """add the specified files on the next commit
22 """add the specified files on the next commit
23
23
24 Schedule files to be version controlled and added to the
24 Schedule files to be version controlled and added to the
25 repository.
25 repository.
26
26
27 The files will be added to the repository at the next commit. To
27 The files will be added to the repository at the next commit. To
28 undo an add before that, see :hg:`forget`.
28 undo an add before that, see :hg:`forget`.
29
29
30 If no names are given, add all files to the repository.
30 If no names are given, add all files to the repository.
31
31
32 .. container:: verbose
32 .. container:: verbose
33
33
34 An example showing how new (unknown) files are added
34 An example showing how new (unknown) files are added
35 automatically by :hg:`add`::
35 automatically by :hg:`add`::
36
36
37 $ ls
37 $ ls
38 foo.c
38 foo.c
39 $ hg status
39 $ hg status
40 ? foo.c
40 ? foo.c
41 $ hg add
41 $ hg add
42 adding foo.c
42 adding foo.c
43 $ hg status
43 $ hg status
44 A foo.c
44 A foo.c
45
45
46 Returns 0 if all files are successfully added.
46 Returns 0 if all files are successfully added.
47 """
47 """
48
48
49 m = cmdutil.match(repo, pats, opts)
49 m = cmdutil.match(repo, pats, opts)
50 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
50 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
51 opts.get('subrepos'), prefix="")
51 opts.get('subrepos'), prefix="")
52 return rejected and 1 or 0
52 return rejected and 1 or 0
53
53
54 def addremove(ui, repo, *pats, **opts):
54 def addremove(ui, repo, *pats, **opts):
55 """add all new files, delete all missing files
55 """add all new files, delete all missing files
56
56
57 Add all new files and remove all missing files from the
57 Add all new files and remove all missing files from the
58 repository.
58 repository.
59
59
60 New files are ignored if they match any of the patterns in
60 New files are ignored if they match any of the patterns in
61 .hgignore. As with add, these changes take effect at the next
61 .hgignore. As with add, these changes take effect at the next
62 commit.
62 commit.
63
63
64 Use the -s/--similarity option to detect renamed files. With a
64 Use the -s/--similarity option to detect renamed files. With a
65 parameter greater than 0, this compares every removed file with
65 parameter greater than 0, this compares every removed file with
66 every added file and records those similar enough as renames. This
66 every added file and records those similar enough as renames. This
67 option takes a percentage between 0 (disabled) and 100 (files must
67 option takes a percentage between 0 (disabled) and 100 (files must
68 be identical) as its parameter. Detecting renamed files this way
68 be identical) as its parameter. Detecting renamed files this way
69 can be expensive. After using this option, :hg:`status -C` can be
69 can be expensive. After using this option, :hg:`status -C` can be
70 used to check which files were identified as moved or renamed.
70 used to check which files were identified as moved or renamed.
71
71
72 Returns 0 if all files are successfully added.
72 Returns 0 if all files are successfully added.
73 """
73 """
74 try:
74 try:
75 sim = float(opts.get('similarity') or 100)
75 sim = float(opts.get('similarity') or 100)
76 except ValueError:
76 except ValueError:
77 raise util.Abort(_('similarity must be a number'))
77 raise util.Abort(_('similarity must be a number'))
78 if sim < 0 or sim > 100:
78 if sim < 0 or sim > 100:
79 raise util.Abort(_('similarity must be between 0 and 100'))
79 raise util.Abort(_('similarity must be between 0 and 100'))
80 return cmdutil.addremove(repo, pats, opts, similarity=sim / 100.0)
80 return cmdutil.addremove(repo, pats, opts, similarity=sim / 100.0)
81
81
82 def annotate(ui, repo, *pats, **opts):
82 def annotate(ui, repo, *pats, **opts):
83 """show changeset information by line for each file
83 """show changeset information by line for each file
84
84
85 List changes in files, showing the revision id responsible for
85 List changes in files, showing the revision id responsible for
86 each line
86 each line
87
87
88 This command is useful for discovering when a change was made and
88 This command is useful for discovering when a change was made and
89 by whom.
89 by whom.
90
90
91 Without the -a/--text option, annotate will avoid processing files
91 Without the -a/--text option, annotate will avoid processing files
92 it detects as binary. With -a, annotate will annotate the file
92 it detects as binary. With -a, annotate will annotate the file
93 anyway, although the results will probably be neither useful
93 anyway, although the results will probably be neither useful
94 nor desirable.
94 nor desirable.
95
95
96 Returns 0 on success.
96 Returns 0 on success.
97 """
97 """
98 if opts.get('follow'):
98 if opts.get('follow'):
99 # --follow is deprecated and now just an alias for -f/--file
99 # --follow is deprecated and now just an alias for -f/--file
100 # to mimic the behavior of Mercurial before version 1.5
100 # to mimic the behavior of Mercurial before version 1.5
101 opts['file'] = 1
101 opts['file'] = 1
102
102
103 datefunc = ui.quiet and util.shortdate or util.datestr
103 datefunc = ui.quiet and util.shortdate or util.datestr
104 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
104 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
105
105
106 if not pats:
106 if not pats:
107 raise util.Abort(_('at least one filename or pattern is required'))
107 raise util.Abort(_('at least one filename or pattern is required'))
108
108
109 opmap = [('user', lambda x: ui.shortuser(x[0].user())),
109 opmap = [('user', lambda x: ui.shortuser(x[0].user())),
110 ('number', lambda x: str(x[0].rev())),
110 ('number', lambda x: str(x[0].rev())),
111 ('changeset', lambda x: short(x[0].node())),
111 ('changeset', lambda x: short(x[0].node())),
112 ('date', getdate),
112 ('date', getdate),
113 ('file', lambda x: x[0].path()),
113 ('file', lambda x: x[0].path()),
114 ]
114 ]
115
115
116 if (not opts.get('user') and not opts.get('changeset')
116 if (not opts.get('user') and not opts.get('changeset')
117 and not opts.get('date') and not opts.get('file')):
117 and not opts.get('date') and not opts.get('file')):
118 opts['number'] = 1
118 opts['number'] = 1
119
119
120 linenumber = opts.get('line_number') is not None
120 linenumber = opts.get('line_number') is not None
121 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
121 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
122 raise util.Abort(_('at least one of -n/-c is required for -l'))
122 raise util.Abort(_('at least one of -n/-c is required for -l'))
123
123
124 funcmap = [func for op, func in opmap if opts.get(op)]
124 funcmap = [func for op, func in opmap if opts.get(op)]
125 if linenumber:
125 if linenumber:
126 lastfunc = funcmap[-1]
126 lastfunc = funcmap[-1]
127 funcmap[-1] = lambda x: "%s:%s" % (lastfunc(x), x[1])
127 funcmap[-1] = lambda x: "%s:%s" % (lastfunc(x), x[1])
128
128
129 ctx = cmdutil.revsingle(repo, opts.get('rev'))
129 ctx = cmdutil.revsingle(repo, opts.get('rev'))
130 m = cmdutil.match(repo, pats, opts)
130 m = cmdutil.match(repo, pats, opts)
131 follow = not opts.get('no_follow')
131 follow = not opts.get('no_follow')
132 for abs in ctx.walk(m):
132 for abs in ctx.walk(m):
133 fctx = ctx[abs]
133 fctx = ctx[abs]
134 if not opts.get('text') and util.binary(fctx.data()):
134 if not opts.get('text') and util.binary(fctx.data()):
135 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
135 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
136 continue
136 continue
137
137
138 lines = fctx.annotate(follow=follow, linenumber=linenumber)
138 lines = fctx.annotate(follow=follow, linenumber=linenumber)
139 pieces = []
139 pieces = []
140
140
141 for f in funcmap:
141 for f in funcmap:
142 l = [f(n) for n, dummy in lines]
142 l = [f(n) for n, dummy in lines]
143 if l:
143 if l:
144 sized = [(x, encoding.colwidth(x)) for x in l]
144 sized = [(x, encoding.colwidth(x)) for x in l]
145 ml = max([w for x, w in sized])
145 ml = max([w for x, w in sized])
146 pieces.append(["%s%s" % (' ' * (ml - w), x) for x, w in sized])
146 pieces.append(["%s%s" % (' ' * (ml - w), x) for x, w in sized])
147
147
148 if pieces:
148 if pieces:
149 for p, l in zip(zip(*pieces), lines):
149 for p, l in zip(zip(*pieces), lines):
150 ui.write("%s: %s" % (" ".join(p), l[1]))
150 ui.write("%s: %s" % (" ".join(p), l[1]))
151
151
152 def archive(ui, repo, dest, **opts):
152 def archive(ui, repo, dest, **opts):
153 '''create an unversioned archive of a repository revision
153 '''create an unversioned archive of a repository revision
154
154
155 By default, the revision used is the parent of the working
155 By default, the revision used is the parent of the working
156 directory; use -r/--rev to specify a different revision.
156 directory; use -r/--rev to specify a different revision.
157
157
158 The archive type is automatically detected based on file
158 The archive type is automatically detected based on file
159 extension (or override using -t/--type).
159 extension (or override using -t/--type).
160
160
161 Valid types are:
161 Valid types are:
162
162
163 :``files``: a directory full of files (default)
163 :``files``: a directory full of files (default)
164 :``tar``: tar archive, uncompressed
164 :``tar``: tar archive, uncompressed
165 :``tbz2``: tar archive, compressed using bzip2
165 :``tbz2``: tar archive, compressed using bzip2
166 :``tgz``: tar archive, compressed using gzip
166 :``tgz``: tar archive, compressed using gzip
167 :``uzip``: zip archive, uncompressed
167 :``uzip``: zip archive, uncompressed
168 :``zip``: zip archive, compressed using deflate
168 :``zip``: zip archive, compressed using deflate
169
169
170 The exact name of the destination archive or directory is given
170 The exact name of the destination archive or directory is given
171 using a format string; see :hg:`help export` for details.
171 using a format string; see :hg:`help export` for details.
172
172
173 Each member added to an archive file has a directory prefix
173 Each member added to an archive file has a directory prefix
174 prepended. Use -p/--prefix to specify a format string for the
174 prepended. Use -p/--prefix to specify a format string for the
175 prefix. The default is the basename of the archive, with suffixes
175 prefix. The default is the basename of the archive, with suffixes
176 removed.
176 removed.
177
177
178 Returns 0 on success.
178 Returns 0 on success.
179 '''
179 '''
180
180
181 ctx = cmdutil.revsingle(repo, opts.get('rev'))
181 ctx = cmdutil.revsingle(repo, opts.get('rev'))
182 if not ctx:
182 if not ctx:
183 raise util.Abort(_('no working directory: please specify a revision'))
183 raise util.Abort(_('no working directory: please specify a revision'))
184 node = ctx.node()
184 node = ctx.node()
185 dest = cmdutil.make_filename(repo, dest, node)
185 dest = cmdutil.make_filename(repo, dest, node)
186 if os.path.realpath(dest) == repo.root:
186 if os.path.realpath(dest) == repo.root:
187 raise util.Abort(_('repository root cannot be destination'))
187 raise util.Abort(_('repository root cannot be destination'))
188
188
189 kind = opts.get('type') or archival.guesskind(dest) or 'files'
189 kind = opts.get('type') or archival.guesskind(dest) or 'files'
190 prefix = opts.get('prefix')
190 prefix = opts.get('prefix')
191
191
192 if dest == '-':
192 if dest == '-':
193 if kind == 'files':
193 if kind == 'files':
194 raise util.Abort(_('cannot archive plain files to stdout'))
194 raise util.Abort(_('cannot archive plain files to stdout'))
195 dest = sys.stdout
195 dest = sys.stdout
196 if not prefix:
196 if not prefix:
197 prefix = os.path.basename(repo.root) + '-%h'
197 prefix = os.path.basename(repo.root) + '-%h'
198
198
199 prefix = cmdutil.make_filename(repo, prefix, node)
199 prefix = cmdutil.make_filename(repo, prefix, node)
200 matchfn = cmdutil.match(repo, [], opts)
200 matchfn = cmdutil.match(repo, [], opts)
201 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
201 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
202 matchfn, prefix, subrepos=opts.get('subrepos'))
202 matchfn, prefix, subrepos=opts.get('subrepos'))
203
203
204 def backout(ui, repo, node=None, rev=None, **opts):
204 def backout(ui, repo, node=None, rev=None, **opts):
205 '''reverse effect of earlier changeset
205 '''reverse effect of earlier changeset
206
206
207 The backout command merges the reverse effect of the reverted
207 The backout command merges the reverse effect of the reverted
208 changeset into the working directory.
208 changeset into the working directory.
209
209
210 With the --merge option, it first commits the reverted changes
210 With the --merge option, it first commits the reverted changes
211 as a new changeset. This new changeset is a child of the reverted
211 as a new changeset. This new changeset is a child of the reverted
212 changeset.
212 changeset.
213 The --merge option remembers the parent of the working directory
213 The --merge option remembers the parent of the working directory
214 before starting the backout, then merges the new head with that
214 before starting the backout, then merges the new head with that
215 changeset afterwards.
215 changeset afterwards.
216 This will result in an explicit merge in the history.
216 This will result in an explicit merge in the history.
217
217
218 If you backout a changeset other than the original parent of the
218 If you backout a changeset other than the original parent of the
219 working directory, the result of this merge is not committed,
219 working directory, the result of this merge is not committed,
220 as with a normal merge. Otherwise, no merge is needed and the
220 as with a normal merge. Otherwise, no merge is needed and the
221 commit is automatic.
221 commit is automatic.
222
222
223 Note that the default behavior (without --merge) has changed in
223 Note that the default behavior (without --merge) has changed in
224 version 1.7. To restore the previous default behavior, use
224 version 1.7. To restore the previous default behavior, use
225 :hg:`backout --merge` and then :hg:`update --clean .` to get rid of
225 :hg:`backout --merge` and then :hg:`update --clean .` to get rid of
226 the ongoing merge.
226 the ongoing merge.
227
227
228 See :hg:`help dates` for a list of formats valid for -d/--date.
228 See :hg:`help dates` for a list of formats valid for -d/--date.
229
229
230 Returns 0 on success.
230 Returns 0 on success.
231 '''
231 '''
232 if rev and node:
232 if rev and node:
233 raise util.Abort(_("please specify just one revision"))
233 raise util.Abort(_("please specify just one revision"))
234
234
235 if not rev:
235 if not rev:
236 rev = node
236 rev = node
237
237
238 if not rev:
238 if not rev:
239 raise util.Abort(_("please specify a revision to backout"))
239 raise util.Abort(_("please specify a revision to backout"))
240
240
241 date = opts.get('date')
241 date = opts.get('date')
242 if date:
242 if date:
243 opts['date'] = util.parsedate(date)
243 opts['date'] = util.parsedate(date)
244
244
245 cmdutil.bail_if_changed(repo)
245 cmdutil.bail_if_changed(repo)
246 node = cmdutil.revsingle(repo, rev).node()
246 node = cmdutil.revsingle(repo, rev).node()
247
247
248 op1, op2 = repo.dirstate.parents()
248 op1, op2 = repo.dirstate.parents()
249 a = repo.changelog.ancestor(op1, node)
249 a = repo.changelog.ancestor(op1, node)
250 if a != node:
250 if a != node:
251 raise util.Abort(_('cannot backout change on a different branch'))
251 raise util.Abort(_('cannot backout change on a different branch'))
252
252
253 p1, p2 = repo.changelog.parents(node)
253 p1, p2 = repo.changelog.parents(node)
254 if p1 == nullid:
254 if p1 == nullid:
255 raise util.Abort(_('cannot backout a change with no parents'))
255 raise util.Abort(_('cannot backout a change with no parents'))
256 if p2 != nullid:
256 if p2 != nullid:
257 if not opts.get('parent'):
257 if not opts.get('parent'):
258 raise util.Abort(_('cannot backout a merge changeset without '
258 raise util.Abort(_('cannot backout a merge changeset without '
259 '--parent'))
259 '--parent'))
260 p = repo.lookup(opts['parent'])
260 p = repo.lookup(opts['parent'])
261 if p not in (p1, p2):
261 if p not in (p1, p2):
262 raise util.Abort(_('%s is not a parent of %s') %
262 raise util.Abort(_('%s is not a parent of %s') %
263 (short(p), short(node)))
263 (short(p), short(node)))
264 parent = p
264 parent = p
265 else:
265 else:
266 if opts.get('parent'):
266 if opts.get('parent'):
267 raise util.Abort(_('cannot use --parent on non-merge changeset'))
267 raise util.Abort(_('cannot use --parent on non-merge changeset'))
268 parent = p1
268 parent = p1
269
269
270 # the backout should appear on the same branch
270 # the backout should appear on the same branch
271 branch = repo.dirstate.branch()
271 branch = repo.dirstate.branch()
272 hg.clean(repo, node, show_stats=False)
272 hg.clean(repo, node, show_stats=False)
273 repo.dirstate.setbranch(branch)
273 repo.dirstate.setbranch(branch)
274 revert_opts = opts.copy()
274 revert_opts = opts.copy()
275 revert_opts['date'] = None
275 revert_opts['date'] = None
276 revert_opts['all'] = True
276 revert_opts['all'] = True
277 revert_opts['rev'] = hex(parent)
277 revert_opts['rev'] = hex(parent)
278 revert_opts['no_backup'] = None
278 revert_opts['no_backup'] = None
279 revert(ui, repo, **revert_opts)
279 revert(ui, repo, **revert_opts)
280 if not opts.get('merge') and op1 != node:
280 if not opts.get('merge') and op1 != node:
281 try:
281 try:
282 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
282 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
283 return hg.update(repo, op1)
283 return hg.update(repo, op1)
284 finally:
284 finally:
285 ui.setconfig('ui', 'forcemerge', '')
285 ui.setconfig('ui', 'forcemerge', '')
286
286
287 commit_opts = opts.copy()
287 commit_opts = opts.copy()
288 commit_opts['addremove'] = False
288 commit_opts['addremove'] = False
289 if not commit_opts['message'] and not commit_opts['logfile']:
289 if not commit_opts['message'] and not commit_opts['logfile']:
290 # we don't translate commit messages
290 # we don't translate commit messages
291 commit_opts['message'] = "Backed out changeset %s" % short(node)
291 commit_opts['message'] = "Backed out changeset %s" % short(node)
292 commit_opts['force_editor'] = True
292 commit_opts['force_editor'] = True
293 commit(ui, repo, **commit_opts)
293 commit(ui, repo, **commit_opts)
294 def nice(node):
294 def nice(node):
295 return '%d:%s' % (repo.changelog.rev(node), short(node))
295 return '%d:%s' % (repo.changelog.rev(node), short(node))
296 ui.status(_('changeset %s backs out changeset %s\n') %
296 ui.status(_('changeset %s backs out changeset %s\n') %
297 (nice(repo.changelog.tip()), nice(node)))
297 (nice(repo.changelog.tip()), nice(node)))
298 if opts.get('merge') and op1 != node:
298 if opts.get('merge') and op1 != node:
299 hg.clean(repo, op1, show_stats=False)
299 hg.clean(repo, op1, show_stats=False)
300 ui.status(_('merging with changeset %s\n')
300 ui.status(_('merging with changeset %s\n')
301 % nice(repo.changelog.tip()))
301 % nice(repo.changelog.tip()))
302 try:
302 try:
303 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
303 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
304 return hg.merge(repo, hex(repo.changelog.tip()))
304 return hg.merge(repo, hex(repo.changelog.tip()))
305 finally:
305 finally:
306 ui.setconfig('ui', 'forcemerge', '')
306 ui.setconfig('ui', 'forcemerge', '')
307 return 0
307 return 0
308
308
309 def bisect(ui, repo, rev=None, extra=None, command=None,
309 def bisect(ui, repo, rev=None, extra=None, command=None,
310 reset=None, good=None, bad=None, skip=None, noupdate=None):
310 reset=None, good=None, bad=None, skip=None, noupdate=None):
311 """subdivision search of changesets
311 """subdivision search of changesets
312
312
313 This command helps to find changesets which introduce problems. To
313 This command helps to find changesets which introduce problems. To
314 use, mark the earliest changeset you know exhibits the problem as
314 use, mark the earliest changeset you know exhibits the problem as
315 bad, then mark the latest changeset which is free from the problem
315 bad, then mark the latest changeset which is free from the problem
316 as good. Bisect will update your working directory to a revision
316 as good. Bisect will update your working directory to a revision
317 for testing (unless the -U/--noupdate option is specified). Once
317 for testing (unless the -U/--noupdate option is specified). Once
318 you have performed tests, mark the working directory as good or
318 you have performed tests, mark the working directory as good or
319 bad, and bisect will either update to another candidate changeset
319 bad, and bisect will either update to another candidate changeset
320 or announce that it has found the bad revision.
320 or announce that it has found the bad revision.
321
321
322 As a shortcut, you can also use the revision argument to mark a
322 As a shortcut, you can also use the revision argument to mark a
323 revision as good or bad without checking it out first.
323 revision as good or bad without checking it out first.
324
324
325 If you supply a command, it will be used for automatic bisection.
325 If you supply a command, it will be used for automatic bisection.
326 Its exit status will be used to mark revisions as good or bad:
326 Its exit status will be used to mark revisions as good or bad:
327 status 0 means good, 125 means to skip the revision, 127
327 status 0 means good, 125 means to skip the revision, 127
328 (command not found) will abort the bisection, and any other
328 (command not found) will abort the bisection, and any other
329 non-zero exit status means the revision is bad.
329 non-zero exit status means the revision is bad.
330
330
331 Returns 0 on success.
331 Returns 0 on success.
332 """
332 """
333 def print_result(nodes, good):
333 def print_result(nodes, good):
334 displayer = cmdutil.show_changeset(ui, repo, {})
334 displayer = cmdutil.show_changeset(ui, repo, {})
335 if len(nodes) == 1:
335 if len(nodes) == 1:
336 # narrowed it down to a single revision
336 # narrowed it down to a single revision
337 if good:
337 if good:
338 ui.write(_("The first good revision is:\n"))
338 ui.write(_("The first good revision is:\n"))
339 else:
339 else:
340 ui.write(_("The first bad revision is:\n"))
340 ui.write(_("The first bad revision is:\n"))
341 displayer.show(repo[nodes[0]])
341 displayer.show(repo[nodes[0]])
342 parents = repo[nodes[0]].parents()
342 parents = repo[nodes[0]].parents()
343 if len(parents) > 1:
343 if len(parents) > 1:
344 side = good and state['bad'] or state['good']
344 side = good and state['bad'] or state['good']
345 num = len(set(i.node() for i in parents) & set(side))
345 num = len(set(i.node() for i in parents) & set(side))
346 if num == 1:
346 if num == 1:
347 common = parents[0].ancestor(parents[1])
347 common = parents[0].ancestor(parents[1])
348 ui.write(_('Not all ancestors of this changeset have been'
348 ui.write(_('Not all ancestors of this changeset have been'
349 ' checked.\nTo check the other ancestors, start'
349 ' checked.\nTo check the other ancestors, start'
350 ' from the common ancestor, %s.\n' % common))
350 ' from the common ancestor, %s.\n' % common))
351 else:
351 else:
352 # multiple possible revisions
352 # multiple possible revisions
353 if good:
353 if good:
354 ui.write(_("Due to skipped revisions, the first "
354 ui.write(_("Due to skipped revisions, the first "
355 "good revision could be any of:\n"))
355 "good revision could be any of:\n"))
356 else:
356 else:
357 ui.write(_("Due to skipped revisions, the first "
357 ui.write(_("Due to skipped revisions, the first "
358 "bad revision could be any of:\n"))
358 "bad revision could be any of:\n"))
359 for n in nodes:
359 for n in nodes:
360 displayer.show(repo[n])
360 displayer.show(repo[n])
361 displayer.close()
361 displayer.close()
362
362
363 def check_state(state, interactive=True):
363 def check_state(state, interactive=True):
364 if not state['good'] or not state['bad']:
364 if not state['good'] or not state['bad']:
365 if (good or bad or skip or reset) and interactive:
365 if (good or bad or skip or reset) and interactive:
366 return
366 return
367 if not state['good']:
367 if not state['good']:
368 raise util.Abort(_('cannot bisect (no known good revisions)'))
368 raise util.Abort(_('cannot bisect (no known good revisions)'))
369 else:
369 else:
370 raise util.Abort(_('cannot bisect (no known bad revisions)'))
370 raise util.Abort(_('cannot bisect (no known bad revisions)'))
371 return True
371 return True
372
372
373 # backward compatibility
373 # backward compatibility
374 if rev in "good bad reset init".split():
374 if rev in "good bad reset init".split():
375 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
375 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
376 cmd, rev, extra = rev, extra, None
376 cmd, rev, extra = rev, extra, None
377 if cmd == "good":
377 if cmd == "good":
378 good = True
378 good = True
379 elif cmd == "bad":
379 elif cmd == "bad":
380 bad = True
380 bad = True
381 else:
381 else:
382 reset = True
382 reset = True
383 elif extra or good + bad + skip + reset + bool(command) > 1:
383 elif extra or good + bad + skip + reset + bool(command) > 1:
384 raise util.Abort(_('incompatible arguments'))
384 raise util.Abort(_('incompatible arguments'))
385
385
386 if reset:
386 if reset:
387 p = repo.join("bisect.state")
387 p = repo.join("bisect.state")
388 if os.path.exists(p):
388 if os.path.exists(p):
389 os.unlink(p)
389 os.unlink(p)
390 return
390 return
391
391
392 state = hbisect.load_state(repo)
392 state = hbisect.load_state(repo)
393
393
394 if command:
394 if command:
395 changesets = 1
395 changesets = 1
396 try:
396 try:
397 while changesets:
397 while changesets:
398 # update state
398 # update state
399 status = util.system(command)
399 status = util.system(command)
400 if status == 125:
400 if status == 125:
401 transition = "skip"
401 transition = "skip"
402 elif status == 0:
402 elif status == 0:
403 transition = "good"
403 transition = "good"
404 # status < 0 means process was killed
404 # status < 0 means process was killed
405 elif status == 127:
405 elif status == 127:
406 raise util.Abort(_("failed to execute %s") % command)
406 raise util.Abort(_("failed to execute %s") % command)
407 elif status < 0:
407 elif status < 0:
408 raise util.Abort(_("%s killed") % command)
408 raise util.Abort(_("%s killed") % command)
409 else:
409 else:
410 transition = "bad"
410 transition = "bad"
411 ctx = cmdutil.revsingle(repo, rev)
411 ctx = cmdutil.revsingle(repo, rev)
412 rev = None # clear for future iterations
412 rev = None # clear for future iterations
413 state[transition].append(ctx.node())
413 state[transition].append(ctx.node())
414 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
414 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
415 check_state(state, interactive=False)
415 check_state(state, interactive=False)
416 # bisect
416 # bisect
417 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
417 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
418 # update to next check
418 # update to next check
419 cmdutil.bail_if_changed(repo)
419 cmdutil.bail_if_changed(repo)
420 hg.clean(repo, nodes[0], show_stats=False)
420 hg.clean(repo, nodes[0], show_stats=False)
421 finally:
421 finally:
422 hbisect.save_state(repo, state)
422 hbisect.save_state(repo, state)
423 print_result(nodes, good)
423 print_result(nodes, good)
424 return
424 return
425
425
426 # update state
426 # update state
427
427
428 if rev:
428 if rev:
429 nodes = [repo.lookup(i) for i in cmdutil.revrange(repo, [rev])]
429 nodes = [repo.lookup(i) for i in cmdutil.revrange(repo, [rev])]
430 else:
430 else:
431 nodes = [repo.lookup('.')]
431 nodes = [repo.lookup('.')]
432
432
433 if good or bad or skip:
433 if good or bad or skip:
434 if good:
434 if good:
435 state['good'] += nodes
435 state['good'] += nodes
436 elif bad:
436 elif bad:
437 state['bad'] += nodes
437 state['bad'] += nodes
438 elif skip:
438 elif skip:
439 state['skip'] += nodes
439 state['skip'] += nodes
440 hbisect.save_state(repo, state)
440 hbisect.save_state(repo, state)
441
441
442 if not check_state(state):
442 if not check_state(state):
443 return
443 return
444
444
445 # actually bisect
445 # actually bisect
446 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
446 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
447 if changesets == 0:
447 if changesets == 0:
448 print_result(nodes, good)
448 print_result(nodes, good)
449 else:
449 else:
450 assert len(nodes) == 1 # only a single node can be tested next
450 assert len(nodes) == 1 # only a single node can be tested next
451 node = nodes[0]
451 node = nodes[0]
452 # compute the approximate number of remaining tests
452 # compute the approximate number of remaining tests
453 tests, size = 0, 2
453 tests, size = 0, 2
454 while size <= changesets:
454 while size <= changesets:
455 tests, size = tests + 1, size * 2
455 tests, size = tests + 1, size * 2
456 rev = repo.changelog.rev(node)
456 rev = repo.changelog.rev(node)
457 ui.write(_("Testing changeset %d:%s "
457 ui.write(_("Testing changeset %d:%s "
458 "(%d changesets remaining, ~%d tests)\n")
458 "(%d changesets remaining, ~%d tests)\n")
459 % (rev, short(node), changesets, tests))
459 % (rev, short(node), changesets, tests))
460 if not noupdate:
460 if not noupdate:
461 cmdutil.bail_if_changed(repo)
461 cmdutil.bail_if_changed(repo)
462 return hg.clean(repo, node)
462 return hg.clean(repo, node)
463
463
464 def branch(ui, repo, label=None, **opts):
464 def branch(ui, repo, label=None, **opts):
465 """set or show the current branch name
465 """set or show the current branch name
466
466
467 With no argument, show the current branch name. With one argument,
467 With no argument, show the current branch name. With one argument,
468 set the working directory branch name (the branch will not exist
468 set the working directory branch name (the branch will not exist
469 in the repository until the next commit). Standard practice
469 in the repository until the next commit). Standard practice
470 recommends that primary development take place on the 'default'
470 recommends that primary development take place on the 'default'
471 branch.
471 branch.
472
472
473 Unless -f/--force is specified, branch will not let you set a
473 Unless -f/--force is specified, branch will not let you set a
474 branch name that already exists, even if it's inactive.
474 branch name that already exists, even if it's inactive.
475
475
476 Use -C/--clean to reset the working directory branch to that of
476 Use -C/--clean to reset the working directory branch to that of
477 the parent of the working directory, negating a previous branch
477 the parent of the working directory, negating a previous branch
478 change.
478 change.
479
479
480 Use the command :hg:`update` to switch to an existing branch. Use
480 Use the command :hg:`update` to switch to an existing branch. Use
481 :hg:`commit --close-branch` to mark this branch as closed.
481 :hg:`commit --close-branch` to mark this branch as closed.
482
482
483 Returns 0 on success.
483 Returns 0 on success.
484 """
484 """
485
485
486 if opts.get('clean'):
486 if opts.get('clean'):
487 label = repo[None].parents()[0].branch()
487 label = repo[None].parents()[0].branch()
488 repo.dirstate.setbranch(label)
488 repo.dirstate.setbranch(label)
489 ui.status(_('reset working directory to branch %s\n') % label)
489 ui.status(_('reset working directory to branch %s\n') % label)
490 elif label:
490 elif label:
491 if not opts.get('force') and label in repo.branchtags():
491 if not opts.get('force') and label in repo.branchtags():
492 if label not in [p.branch() for p in repo.parents()]:
492 if label not in [p.branch() for p in repo.parents()]:
493 raise util.Abort(_('a branch of the same name already exists'
493 raise util.Abort(_('a branch of the same name already exists'
494 " (use 'hg update' to switch to it)"))
494 " (use 'hg update' to switch to it)"))
495 repo.dirstate.setbranch(label)
495 repo.dirstate.setbranch(label)
496 ui.status(_('marked working directory as branch %s\n') % label)
496 ui.status(_('marked working directory as branch %s\n') % label)
497 else:
497 else:
498 ui.write("%s\n" % repo.dirstate.branch())
498 ui.write("%s\n" % repo.dirstate.branch())
499
499
500 def branches(ui, repo, active=False, closed=False):
500 def branches(ui, repo, active=False, closed=False):
501 """list repository named branches
501 """list repository named branches
502
502
503 List the repository's named branches, indicating which ones are
503 List the repository's named branches, indicating which ones are
504 inactive. If -c/--closed is specified, also list branches which have
504 inactive. If -c/--closed is specified, also list branches which have
505 been marked closed (see :hg:`commit --close-branch`).
505 been marked closed (see :hg:`commit --close-branch`).
506
506
507 If -a/--active is specified, only show active branches. A branch
507 If -a/--active is specified, only show active branches. A branch
508 is considered active if it contains repository heads.
508 is considered active if it contains repository heads.
509
509
510 Use the command :hg:`update` to switch to an existing branch.
510 Use the command :hg:`update` to switch to an existing branch.
511
511
512 Returns 0.
512 Returns 0.
513 """
513 """
514
514
515 hexfunc = ui.debugflag and hex or short
515 hexfunc = ui.debugflag and hex or short
516 activebranches = [repo[n].branch() for n in repo.heads()]
516 activebranches = [repo[n].branch() for n in repo.heads()]
517 def testactive(tag, node):
517 def testactive(tag, node):
518 realhead = tag in activebranches
518 realhead = tag in activebranches
519 open = node in repo.branchheads(tag, closed=False)
519 open = node in repo.branchheads(tag, closed=False)
520 return realhead and open
520 return realhead and open
521 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
521 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
522 for tag, node in repo.branchtags().items()],
522 for tag, node in repo.branchtags().items()],
523 reverse=True)
523 reverse=True)
524
524
525 for isactive, node, tag in branches:
525 for isactive, node, tag in branches:
526 if (not active) or isactive:
526 if (not active) or isactive:
527 if ui.quiet:
527 if ui.quiet:
528 ui.write("%s\n" % tag)
528 ui.write("%s\n" % tag)
529 else:
529 else:
530 hn = repo.lookup(node)
530 hn = repo.lookup(node)
531 if isactive:
531 if isactive:
532 label = 'branches.active'
532 label = 'branches.active'
533 notice = ''
533 notice = ''
534 elif hn not in repo.branchheads(tag, closed=False):
534 elif hn not in repo.branchheads(tag, closed=False):
535 if not closed:
535 if not closed:
536 continue
536 continue
537 label = 'branches.closed'
537 label = 'branches.closed'
538 notice = _(' (closed)')
538 notice = _(' (closed)')
539 else:
539 else:
540 label = 'branches.inactive'
540 label = 'branches.inactive'
541 notice = _(' (inactive)')
541 notice = _(' (inactive)')
542 if tag == repo.dirstate.branch():
542 if tag == repo.dirstate.branch():
543 label = 'branches.current'
543 label = 'branches.current'
544 rev = str(node).rjust(31 - encoding.colwidth(tag))
544 rev = str(node).rjust(31 - encoding.colwidth(tag))
545 rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
545 rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
546 tag = ui.label(tag, label)
546 tag = ui.label(tag, label)
547 ui.write("%s %s%s\n" % (tag, rev, notice))
547 ui.write("%s %s%s\n" % (tag, rev, notice))
548
548
549 def bundle(ui, repo, fname, dest=None, **opts):
549 def bundle(ui, repo, fname, dest=None, **opts):
550 """create a changegroup file
550 """create a changegroup file
551
551
552 Generate a compressed changegroup file collecting changesets not
552 Generate a compressed changegroup file collecting changesets not
553 known to be in another repository.
553 known to be in another repository.
554
554
555 If you omit the destination repository, then hg assumes the
555 If you omit the destination repository, then hg assumes the
556 destination will have all the nodes you specify with --base
556 destination will have all the nodes you specify with --base
557 parameters. To create a bundle containing all changesets, use
557 parameters. To create a bundle containing all changesets, use
558 -a/--all (or --base null).
558 -a/--all (or --base null).
559
559
560 You can change compression method with the -t/--type option.
560 You can change compression method with the -t/--type option.
561 The available compression methods are: none, bzip2, and
561 The available compression methods are: none, bzip2, and
562 gzip (by default, bundles are compressed using bzip2).
562 gzip (by default, bundles are compressed using bzip2).
563
563
564 The bundle file can then be transferred using conventional means
564 The bundle file can then be transferred using conventional means
565 and applied to another repository with the unbundle or pull
565 and applied to another repository with the unbundle or pull
566 command. This is useful when direct push and pull are not
566 command. This is useful when direct push and pull are not
567 available or when exporting an entire repository is undesirable.
567 available or when exporting an entire repository is undesirable.
568
568
569 Applying bundles preserves all changeset contents including
569 Applying bundles preserves all changeset contents including
570 permissions, copy/rename information, and revision history.
570 permissions, copy/rename information, and revision history.
571
571
572 Returns 0 on success, 1 if no changes found.
572 Returns 0 on success, 1 if no changes found.
573 """
573 """
574 revs = None
574 revs = None
575 if 'rev' in opts:
575 if 'rev' in opts:
576 revs = cmdutil.revrange(repo, opts['rev'])
576 revs = cmdutil.revrange(repo, opts['rev'])
577
577
578 if opts.get('all'):
578 if opts.get('all'):
579 base = ['null']
579 base = ['null']
580 else:
580 else:
581 base = cmdutil.revrange(repo, opts.get('base'))
581 base = cmdutil.revrange(repo, opts.get('base'))
582 if base:
582 if base:
583 if dest:
583 if dest:
584 raise util.Abort(_("--base is incompatible with specifying "
584 raise util.Abort(_("--base is incompatible with specifying "
585 "a destination"))
585 "a destination"))
586 base = [repo.lookup(rev) for rev in base]
586 base = [repo.lookup(rev) for rev in base]
587 # create the right base
587 # create the right base
588 # XXX: nodesbetween / changegroup* should be "fixed" instead
588 # XXX: nodesbetween / changegroup* should be "fixed" instead
589 o = []
589 o = []
590 has = set((nullid,))
590 has = set((nullid,))
591 for n in base:
591 for n in base:
592 has.update(repo.changelog.reachable(n))
592 has.update(repo.changelog.reachable(n))
593 if revs:
593 if revs:
594 revs = [repo.lookup(rev) for rev in revs]
594 revs = [repo.lookup(rev) for rev in revs]
595 visit = revs[:]
595 visit = revs[:]
596 has.difference_update(visit)
596 has.difference_update(visit)
597 else:
597 else:
598 visit = repo.changelog.heads()
598 visit = repo.changelog.heads()
599 seen = {}
599 seen = {}
600 while visit:
600 while visit:
601 n = visit.pop(0)
601 n = visit.pop(0)
602 parents = [p for p in repo.changelog.parents(n) if p not in has]
602 parents = [p for p in repo.changelog.parents(n) if p not in has]
603 if len(parents) == 0:
603 if len(parents) == 0:
604 if n not in has:
604 if n not in has:
605 o.append(n)
605 o.append(n)
606 else:
606 else:
607 for p in parents:
607 for p in parents:
608 if p not in seen:
608 if p not in seen:
609 seen[p] = 1
609 seen[p] = 1
610 visit.append(p)
610 visit.append(p)
611 else:
611 else:
612 dest = ui.expandpath(dest or 'default-push', dest or 'default')
612 dest = ui.expandpath(dest or 'default-push', dest or 'default')
613 dest, branches = hg.parseurl(dest, opts.get('branch'))
613 dest, branches = hg.parseurl(dest, opts.get('branch'))
614 other = hg.repository(hg.remoteui(repo, opts), dest)
614 other = hg.repository(hg.remoteui(repo, opts), dest)
615 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
615 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
616 if revs:
616 if revs:
617 revs = [repo.lookup(rev) for rev in revs]
617 revs = [repo.lookup(rev) for rev in revs]
618 o = discovery.findoutgoing(repo, other, force=opts.get('force'))
618 o = discovery.findoutgoing(repo, other, force=opts.get('force'))
619
619
620 if not o:
620 if not o:
621 ui.status(_("no changes found\n"))
621 ui.status(_("no changes found\n"))
622 return 1
622 return 1
623
623
624 if revs:
624 if revs:
625 cg = repo.changegroupsubset(o, revs, 'bundle')
625 cg = repo.changegroupsubset(o, revs, 'bundle')
626 else:
626 else:
627 cg = repo.changegroup(o, 'bundle')
627 cg = repo.changegroup(o, 'bundle')
628
628
629 bundletype = opts.get('type', 'bzip2').lower()
629 bundletype = opts.get('type', 'bzip2').lower()
630 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
630 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
631 bundletype = btypes.get(bundletype)
631 bundletype = btypes.get(bundletype)
632 if bundletype not in changegroup.bundletypes:
632 if bundletype not in changegroup.bundletypes:
633 raise util.Abort(_('unknown bundle type specified with --type'))
633 raise util.Abort(_('unknown bundle type specified with --type'))
634
634
635 changegroup.writebundle(cg, fname, bundletype)
635 changegroup.writebundle(cg, fname, bundletype)
636
636
637 def cat(ui, repo, file1, *pats, **opts):
637 def cat(ui, repo, file1, *pats, **opts):
638 """output the current or given revision of files
638 """output the current or given revision of files
639
639
640 Print the specified files as they were at the given revision. If
640 Print the specified files as they were at the given revision. If
641 no revision is given, the parent of the working directory is used,
641 no revision is given, the parent of the working directory is used,
642 or tip if no revision is checked out.
642 or tip if no revision is checked out.
643
643
644 Output may be to a file, in which case the name of the file is
644 Output may be to a file, in which case the name of the file is
645 given using a format string. The formatting rules are the same as
645 given using a format string. The formatting rules are the same as
646 for the export command, with the following additions:
646 for the export command, with the following additions:
647
647
648 :``%s``: basename of file being printed
648 :``%s``: basename of file being printed
649 :``%d``: dirname of file being printed, or '.' if in repository root
649 :``%d``: dirname of file being printed, or '.' if in repository root
650 :``%p``: root-relative path name of file being printed
650 :``%p``: root-relative path name of file being printed
651
651
652 Returns 0 on success.
652 Returns 0 on success.
653 """
653 """
654 ctx = cmdutil.revsingle(repo, opts.get('rev'))
654 ctx = cmdutil.revsingle(repo, opts.get('rev'))
655 err = 1
655 err = 1
656 m = cmdutil.match(repo, (file1,) + pats, opts)
656 m = cmdutil.match(repo, (file1,) + pats, opts)
657 for abs in ctx.walk(m):
657 for abs in ctx.walk(m):
658 fp = cmdutil.make_file(repo, opts.get('output'), ctx.node(), pathname=abs)
658 fp = cmdutil.make_file(repo, opts.get('output'), ctx.node(), pathname=abs)
659 data = ctx[abs].data()
659 data = ctx[abs].data()
660 if opts.get('decode'):
660 if opts.get('decode'):
661 data = repo.wwritedata(abs, data)
661 data = repo.wwritedata(abs, data)
662 fp.write(data)
662 fp.write(data)
663 err = 0
663 err = 0
664 return err
664 return err
665
665
666 def clone(ui, source, dest=None, **opts):
666 def clone(ui, source, dest=None, **opts):
667 """make a copy of an existing repository
667 """make a copy of an existing repository
668
668
669 Create a copy of an existing repository in a new directory.
669 Create a copy of an existing repository in a new directory.
670
670
671 If no destination directory name is specified, it defaults to the
671 If no destination directory name is specified, it defaults to the
672 basename of the source.
672 basename of the source.
673
673
674 The location of the source is added to the new repository's
674 The location of the source is added to the new repository's
675 .hg/hgrc file, as the default to be used for future pulls.
675 .hg/hgrc file, as the default to be used for future pulls.
676
676
677 See :hg:`help urls` for valid source format details.
677 See :hg:`help urls` for valid source format details.
678
678
679 It is possible to specify an ``ssh://`` URL as the destination, but no
679 It is possible to specify an ``ssh://`` URL as the destination, but no
680 .hg/hgrc and working directory will be created on the remote side.
680 .hg/hgrc and working directory will be created on the remote side.
681 Please see :hg:`help urls` for important details about ``ssh://`` URLs.
681 Please see :hg:`help urls` for important details about ``ssh://`` URLs.
682
682
683 A set of changesets (tags, or branch names) to pull may be specified
683 A set of changesets (tags, or branch names) to pull may be specified
684 by listing each changeset (tag, or branch name) with -r/--rev.
684 by listing each changeset (tag, or branch name) with -r/--rev.
685 If -r/--rev is used, the cloned repository will contain only a subset
685 If -r/--rev is used, the cloned repository will contain only a subset
686 of the changesets of the source repository. Only the set of changesets
686 of the changesets of the source repository. Only the set of changesets
687 defined by all -r/--rev options (including all their ancestors)
687 defined by all -r/--rev options (including all their ancestors)
688 will be pulled into the destination repository.
688 will be pulled into the destination repository.
689 No subsequent changesets (including subsequent tags) will be present
689 No subsequent changesets (including subsequent tags) will be present
690 in the destination.
690 in the destination.
691
691
692 Using -r/--rev (or 'clone src#rev dest') implies --pull, even for
692 Using -r/--rev (or 'clone src#rev dest') implies --pull, even for
693 local source repositories.
693 local source repositories.
694
694
695 For efficiency, hardlinks are used for cloning whenever the source
695 For efficiency, hardlinks are used for cloning whenever the source
696 and destination are on the same filesystem (note this applies only
696 and destination are on the same filesystem (note this applies only
697 to the repository data, not to the working directory). Some
697 to the repository data, not to the working directory). Some
698 filesystems, such as AFS, implement hardlinking incorrectly, but
698 filesystems, such as AFS, implement hardlinking incorrectly, but
699 do not report errors. In these cases, use the --pull option to
699 do not report errors. In these cases, use the --pull option to
700 avoid hardlinking.
700 avoid hardlinking.
701
701
702 In some cases, you can clone repositories and the working directory
702 In some cases, you can clone repositories and the working directory
703 using full hardlinks with ::
703 using full hardlinks with ::
704
704
705 $ cp -al REPO REPOCLONE
705 $ cp -al REPO REPOCLONE
706
706
707 This is the fastest way to clone, but it is not always safe. The
707 This is the fastest way to clone, but it is not always safe. The
708 operation is not atomic (making sure REPO is not modified during
708 operation is not atomic (making sure REPO is not modified during
709 the operation is up to you) and you have to make sure your editor
709 the operation is up to you) and you have to make sure your editor
710 breaks hardlinks (Emacs and most Linux Kernel tools do so). Also,
710 breaks hardlinks (Emacs and most Linux Kernel tools do so). Also,
711 this is not compatible with certain extensions that place their
711 this is not compatible with certain extensions that place their
712 metadata under the .hg directory, such as mq.
712 metadata under the .hg directory, such as mq.
713
713
714 Mercurial will update the working directory to the first applicable
714 Mercurial will update the working directory to the first applicable
715 revision from this list:
715 revision from this list:
716
716
717 a) null if -U or the source repository has no changesets
717 a) null if -U or the source repository has no changesets
718 b) if -u . and the source repository is local, the first parent of
718 b) if -u . and the source repository is local, the first parent of
719 the source repository's working directory
719 the source repository's working directory
720 c) the changeset specified with -u (if a branch name, this means the
720 c) the changeset specified with -u (if a branch name, this means the
721 latest head of that branch)
721 latest head of that branch)
722 d) the changeset specified with -r
722 d) the changeset specified with -r
723 e) the tipmost head specified with -b
723 e) the tipmost head specified with -b
724 f) the tipmost head specified with the url#branch source syntax
724 f) the tipmost head specified with the url#branch source syntax
725 g) the tipmost head of the default branch
725 g) the tipmost head of the default branch
726 h) tip
726 h) tip
727
727
728 Returns 0 on success.
728 Returns 0 on success.
729 """
729 """
730 if opts.get('noupdate') and opts.get('updaterev'):
730 if opts.get('noupdate') and opts.get('updaterev'):
731 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
731 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
732
732
733 r = hg.clone(hg.remoteui(ui, opts), source, dest,
733 r = hg.clone(hg.remoteui(ui, opts), source, dest,
734 pull=opts.get('pull'),
734 pull=opts.get('pull'),
735 stream=opts.get('uncompressed'),
735 stream=opts.get('uncompressed'),
736 rev=opts.get('rev'),
736 rev=opts.get('rev'),
737 update=opts.get('updaterev') or not opts.get('noupdate'),
737 update=opts.get('updaterev') or not opts.get('noupdate'),
738 branch=opts.get('branch'))
738 branch=opts.get('branch'))
739
739
740 return r is None
740 return r is None
741
741
742 def commit(ui, repo, *pats, **opts):
742 def commit(ui, repo, *pats, **opts):
743 """commit the specified files or all outstanding changes
743 """commit the specified files or all outstanding changes
744
744
745 Commit changes to the given files into the repository. Unlike a
745 Commit changes to the given files into the repository. Unlike a
746 centralized RCS, this operation is a local operation. See
746 centralized RCS, this operation is a local operation. See
747 :hg:`push` for a way to actively distribute your changes.
747 :hg:`push` for a way to actively distribute your changes.
748
748
749 If a list of files is omitted, all changes reported by :hg:`status`
749 If a list of files is omitted, all changes reported by :hg:`status`
750 will be committed.
750 will be committed.
751
751
752 If you are committing the result of a merge, do not provide any
752 If you are committing the result of a merge, do not provide any
753 filenames or -I/-X filters.
753 filenames or -I/-X filters.
754
754
755 If no commit message is specified, Mercurial starts your
755 If no commit message is specified, Mercurial starts your
756 configured editor where you can enter a message. In case your
756 configured editor where you can enter a message. In case your
757 commit fails, you will find a backup of your message in
757 commit fails, you will find a backup of your message in
758 ``.hg/last-message.txt``.
758 ``.hg/last-message.txt``.
759
759
760 See :hg:`help dates` for a list of formats valid for -d/--date.
760 See :hg:`help dates` for a list of formats valid for -d/--date.
761
761
762 Returns 0 on success, 1 if nothing changed.
762 Returns 0 on success, 1 if nothing changed.
763 """
763 """
764 extra = {}
764 extra = {}
765 if opts.get('close_branch'):
765 if opts.get('close_branch'):
766 if repo['.'].node() not in repo.branchheads():
766 if repo['.'].node() not in repo.branchheads():
767 # The topo heads set is included in the branch heads set of the
767 # The topo heads set is included in the branch heads set of the
768 # current branch, so it's sufficient to test branchheads
768 # current branch, so it's sufficient to test branchheads
769 raise util.Abort(_('can only close branch heads'))
769 raise util.Abort(_('can only close branch heads'))
770 extra['close'] = 1
770 extra['close'] = 1
771 e = cmdutil.commiteditor
771 e = cmdutil.commiteditor
772 if opts.get('force_editor'):
772 if opts.get('force_editor'):
773 e = cmdutil.commitforceeditor
773 e = cmdutil.commitforceeditor
774
774
775 def commitfunc(ui, repo, message, match, opts):
775 def commitfunc(ui, repo, message, match, opts):
776 return repo.commit(message, opts.get('user'), opts.get('date'), match,
776 return repo.commit(message, opts.get('user'), opts.get('date'), match,
777 editor=e, extra=extra)
777 editor=e, extra=extra)
778
778
779 branch = repo[None].branch()
779 branch = repo[None].branch()
780 bheads = repo.branchheads(branch)
780 bheads = repo.branchheads(branch)
781
781
782 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
782 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
783 if not node:
783 if not node:
784 ui.status(_("nothing changed\n"))
784 ui.status(_("nothing changed\n"))
785 return 1
785 return 1
786
786
787 ctx = repo[node]
787 ctx = repo[node]
788 parents = ctx.parents()
788 parents = ctx.parents()
789
789
790 if bheads and not [x for x in parents
790 if bheads and not [x for x in parents
791 if x.node() in bheads and x.branch() == branch]:
791 if x.node() in bheads and x.branch() == branch]:
792 ui.status(_('created new head\n'))
792 ui.status(_('created new head\n'))
793 # The message is not printed for initial roots. For the other
793 # The message is not printed for initial roots. For the other
794 # changesets, it is printed in the following situations:
794 # changesets, it is printed in the following situations:
795 #
795 #
796 # Par column: for the 2 parents with ...
796 # Par column: for the 2 parents with ...
797 # N: null or no parent
797 # N: null or no parent
798 # B: parent is on another named branch
798 # B: parent is on another named branch
799 # C: parent is a regular non head changeset
799 # C: parent is a regular non head changeset
800 # H: parent was a branch head of the current branch
800 # H: parent was a branch head of the current branch
801 # Msg column: whether we print "created new head" message
801 # Msg column: whether we print "created new head" message
802 # In the following, it is assumed that there already exists some
802 # In the following, it is assumed that there already exists some
803 # initial branch heads of the current branch, otherwise nothing is
803 # initial branch heads of the current branch, otherwise nothing is
804 # printed anyway.
804 # printed anyway.
805 #
805 #
806 # Par Msg Comment
806 # Par Msg Comment
807 # NN y additional topo root
807 # NN y additional topo root
808 #
808 #
809 # BN y additional branch root
809 # BN y additional branch root
810 # CN y additional topo head
810 # CN y additional topo head
811 # HN n usual case
811 # HN n usual case
812 #
812 #
813 # BB y weird additional branch root
813 # BB y weird additional branch root
814 # CB y branch merge
814 # CB y branch merge
815 # HB n merge with named branch
815 # HB n merge with named branch
816 #
816 #
817 # CC y additional head from merge
817 # CC y additional head from merge
818 # CH n merge with a head
818 # CH n merge with a head
819 #
819 #
820 # HH n head merge: head count decreases
820 # HH n head merge: head count decreases
821
821
822 if not opts.get('close_branch'):
822 if not opts.get('close_branch'):
823 for r in parents:
823 for r in parents:
824 if r.extra().get('close') and r.branch() == branch:
824 if r.extra().get('close') and r.branch() == branch:
825 ui.status(_('reopening closed branch head %d\n') % r)
825 ui.status(_('reopening closed branch head %d\n') % r)
826
826
827 if ui.debugflag:
827 if ui.debugflag:
828 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
828 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
829 elif ui.verbose:
829 elif ui.verbose:
830 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
830 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
831
831
832 def copy(ui, repo, *pats, **opts):
832 def copy(ui, repo, *pats, **opts):
833 """mark files as copied for the next commit
833 """mark files as copied for the next commit
834
834
835 Mark dest as having copies of source files. If dest is a
835 Mark dest as having copies of source files. If dest is a
836 directory, copies are put in that directory. If dest is a file,
836 directory, copies are put in that directory. If dest is a file,
837 the source must be a single file.
837 the source must be a single file.
838
838
839 By default, this command copies the contents of files as they
839 By default, this command copies the contents of files as they
840 exist in the working directory. If invoked with -A/--after, the
840 exist in the working directory. If invoked with -A/--after, the
841 operation is recorded, but no copying is performed.
841 operation is recorded, but no copying is performed.
842
842
843 This command takes effect with the next commit. To undo a copy
843 This command takes effect with the next commit. To undo a copy
844 before that, see :hg:`revert`.
844 before that, see :hg:`revert`.
845
845
846 Returns 0 on success, 1 if errors are encountered.
846 Returns 0 on success, 1 if errors are encountered.
847 """
847 """
848 wlock = repo.wlock(False)
848 wlock = repo.wlock(False)
849 try:
849 try:
850 return cmdutil.copy(ui, repo, pats, opts)
850 return cmdutil.copy(ui, repo, pats, opts)
851 finally:
851 finally:
852 wlock.release()
852 wlock.release()
853
853
854 def debugancestor(ui, repo, *args):
854 def debugancestor(ui, repo, *args):
855 """find the ancestor revision of two revisions in a given index"""
855 """find the ancestor revision of two revisions in a given index"""
856 if len(args) == 3:
856 if len(args) == 3:
857 index, rev1, rev2 = args
857 index, rev1, rev2 = args
858 r = revlog.revlog(util.opener(os.getcwd(), audit=False), index)
858 r = revlog.revlog(util.opener(os.getcwd(), audit=False), index)
859 lookup = r.lookup
859 lookup = r.lookup
860 elif len(args) == 2:
860 elif len(args) == 2:
861 if not repo:
861 if not repo:
862 raise util.Abort(_("there is no Mercurial repository here "
862 raise util.Abort(_("there is no Mercurial repository here "
863 "(.hg not found)"))
863 "(.hg not found)"))
864 rev1, rev2 = args
864 rev1, rev2 = args
865 r = repo.changelog
865 r = repo.changelog
866 lookup = repo.lookup
866 lookup = repo.lookup
867 else:
867 else:
868 raise util.Abort(_('either two or three arguments required'))
868 raise util.Abort(_('either two or three arguments required'))
869 a = r.ancestor(lookup(rev1), lookup(rev2))
869 a = r.ancestor(lookup(rev1), lookup(rev2))
870 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
870 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
871
871
872 def debugbuilddag(ui, repo, text,
872 def debugbuilddag(ui, repo, text,
873 mergeable_file=False,
873 mergeable_file=False,
874 appended_file=False,
874 appended_file=False,
875 overwritten_file=False,
875 overwritten_file=False,
876 new_file=False):
876 new_file=False):
877 """builds a repo with a given dag from scratch in the current empty repo
877 """builds a repo with a given dag from scratch in the current empty repo
878
878
879 Elements:
879 Elements:
880
880
881 - "+n" is a linear run of n nodes based on the current default parent
881 - "+n" is a linear run of n nodes based on the current default parent
882 - "." is a single node based on the current default parent
882 - "." is a single node based on the current default parent
883 - "$" resets the default parent to null (implied at the start);
883 - "$" resets the default parent to null (implied at the start);
884 otherwise the default parent is always the last node created
884 otherwise the default parent is always the last node created
885 - "<p" sets the default parent to the backref p
885 - "<p" sets the default parent to the backref p
886 - "*p" is a fork at parent p, which is a backref
886 - "*p" is a fork at parent p, which is a backref
887 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
887 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
888 - "/p2" is a merge of the preceding node and p2
888 - "/p2" is a merge of the preceding node and p2
889 - ":tag" defines a local tag for the preceding node
889 - ":tag" defines a local tag for the preceding node
890 - "@branch" sets the named branch for subsequent nodes
890 - "@branch" sets the named branch for subsequent nodes
891 - "!command" runs the command using your shell
891 - "!command" runs the command using your shell
892 - "!!my command\\n" is like "!", but to the end of the line
892 - "!!my command\\n" is like "!", but to the end of the line
893 - "#...\\n" is a comment up to the end of the line
893 - "#...\\n" is a comment up to the end of the line
894
894
895 Whitespace between the above elements is ignored.
895 Whitespace between the above elements is ignored.
896
896
897 A backref is either
897 A backref is either
898
898
899 - a number n, which references the node curr-n, where curr is the current
899 - a number n, which references the node curr-n, where curr is the current
900 node, or
900 node, or
901 - the name of a local tag you placed earlier using ":tag", or
901 - the name of a local tag you placed earlier using ":tag", or
902 - empty to denote the default parent.
902 - empty to denote the default parent.
903
903
904 All string valued-elements are either strictly alphanumeric, or must
904 All string valued-elements are either strictly alphanumeric, or must
905 be enclosed in double quotes ("..."), with "\\" as escape character.
905 be enclosed in double quotes ("..."), with "\\" as escape character.
906
906
907 Note that the --overwritten-file and --appended-file options imply the
907 Note that the --overwritten-file and --appended-file options imply the
908 use of "HGMERGE=internal:local" during DAG buildup.
908 use of "HGMERGE=internal:local" during DAG buildup.
909 """
909 """
910
910
911 if not (mergeable_file or appended_file or overwritten_file or new_file):
911 if not (mergeable_file or appended_file or overwritten_file or new_file):
912 raise util.Abort(_('need at least one of -m, -a, -o, -n'))
912 raise util.Abort(_('need at least one of -m, -a, -o, -n'))
913
913
914 if len(repo.changelog) > 0:
914 if len(repo.changelog) > 0:
915 raise util.Abort(_('repository is not empty'))
915 raise util.Abort(_('repository is not empty'))
916
916
917 if overwritten_file or appended_file:
917 if overwritten_file or appended_file:
918 # we don't want to fail in merges during buildup
918 # we don't want to fail in merges during buildup
919 os.environ['HGMERGE'] = 'internal:local'
919 os.environ['HGMERGE'] = 'internal:local'
920
920
921 def writefile(fname, text, fmode="wb"):
921 def writefile(fname, text, fmode="wb"):
922 f = open(fname, fmode)
922 f = open(fname, fmode)
923 try:
923 try:
924 f.write(text)
924 f.write(text)
925 finally:
925 finally:
926 f.close()
926 f.close()
927
927
928 if mergeable_file:
928 if mergeable_file:
929 linesperrev = 2
929 linesperrev = 2
930 # determine number of revs in DAG
930 # determine number of revs in DAG
931 n = 0
931 n = 0
932 for type, data in dagparser.parsedag(text):
932 for type, data in dagparser.parsedag(text):
933 if type == 'n':
933 if type == 'n':
934 n += 1
934 n += 1
935 # make a file with k lines per rev
935 # make a file with k lines per rev
936 writefile("mf", "\n".join(str(i) for i in xrange(0, n * linesperrev))
936 writefile("mf", "\n".join(str(i) for i in xrange(0, n * linesperrev))
937 + "\n")
937 + "\n")
938
938
939 at = -1
939 at = -1
940 atbranch = 'default'
940 atbranch = 'default'
941 for type, data in dagparser.parsedag(text):
941 for type, data in dagparser.parsedag(text):
942 if type == 'n':
942 if type == 'n':
943 ui.status('node %s\n' % str(data))
943 ui.status('node %s\n' % str(data))
944 id, ps = data
944 id, ps = data
945 p1 = ps[0]
945 p1 = ps[0]
946 if p1 != at:
946 if p1 != at:
947 update(ui, repo, node=str(p1), clean=True)
947 update(ui, repo, node=str(p1), clean=True)
948 at = p1
948 at = p1
949 if repo.dirstate.branch() != atbranch:
949 if repo.dirstate.branch() != atbranch:
950 branch(ui, repo, atbranch, force=True)
950 branch(ui, repo, atbranch, force=True)
951 if len(ps) > 1:
951 if len(ps) > 1:
952 p2 = ps[1]
952 p2 = ps[1]
953 merge(ui, repo, node=p2)
953 merge(ui, repo, node=p2)
954
954
955 if mergeable_file:
955 if mergeable_file:
956 f = open("mf", "rb+")
956 f = open("mf", "rb+")
957 try:
957 try:
958 lines = f.read().split("\n")
958 lines = f.read().split("\n")
959 lines[id * linesperrev] += " r%i" % id
959 lines[id * linesperrev] += " r%i" % id
960 f.seek(0)
960 f.seek(0)
961 f.write("\n".join(lines))
961 f.write("\n".join(lines))
962 finally:
962 finally:
963 f.close()
963 f.close()
964
964
965 if appended_file:
965 if appended_file:
966 writefile("af", "r%i\n" % id, "ab")
966 writefile("af", "r%i\n" % id, "ab")
967
967
968 if overwritten_file:
968 if overwritten_file:
969 writefile("of", "r%i\n" % id)
969 writefile("of", "r%i\n" % id)
970
970
971 if new_file:
971 if new_file:
972 writefile("nf%i" % id, "r%i\n" % id)
972 writefile("nf%i" % id, "r%i\n" % id)
973
973
974 commit(ui, repo, addremove=True, message="r%i" % id, date=(id, 0))
974 commit(ui, repo, addremove=True, message="r%i" % id, date=(id, 0))
975 at = id
975 at = id
976 elif type == 'l':
976 elif type == 'l':
977 id, name = data
977 id, name = data
978 ui.status('tag %s\n' % name)
978 ui.status('tag %s\n' % name)
979 tag(ui, repo, name, local=True)
979 tag(ui, repo, name, local=True)
980 elif type == 'a':
980 elif type == 'a':
981 ui.status('branch %s\n' % data)
981 ui.status('branch %s\n' % data)
982 atbranch = data
982 atbranch = data
983 elif type in 'cC':
983 elif type in 'cC':
984 r = util.system(data, cwd=repo.root)
984 r = util.system(data, cwd=repo.root)
985 if r:
985 if r:
986 desc, r = util.explain_exit(r)
986 desc, r = util.explain_exit(r)
987 raise util.Abort(_('%s command %s') % (data, desc))
987 raise util.Abort(_('%s command %s') % (data, desc))
988
988
989 def debugcommands(ui, cmd='', *args):
989 def debugcommands(ui, cmd='', *args):
990 """list all available commands and options"""
990 """list all available commands and options"""
991 for cmd, vals in sorted(table.iteritems()):
991 for cmd, vals in sorted(table.iteritems()):
992 cmd = cmd.split('|')[0].strip('^')
992 cmd = cmd.split('|')[0].strip('^')
993 opts = ', '.join([i[1] for i in vals[1]])
993 opts = ', '.join([i[1] for i in vals[1]])
994 ui.write('%s: %s\n' % (cmd, opts))
994 ui.write('%s: %s\n' % (cmd, opts))
995
995
996 def debugcomplete(ui, cmd='', **opts):
996 def debugcomplete(ui, cmd='', **opts):
997 """returns the completion list associated with the given command"""
997 """returns the completion list associated with the given command"""
998
998
999 if opts.get('options'):
999 if opts.get('options'):
1000 options = []
1000 options = []
1001 otables = [globalopts]
1001 otables = [globalopts]
1002 if cmd:
1002 if cmd:
1003 aliases, entry = cmdutil.findcmd(cmd, table, False)
1003 aliases, entry = cmdutil.findcmd(cmd, table, False)
1004 otables.append(entry[1])
1004 otables.append(entry[1])
1005 for t in otables:
1005 for t in otables:
1006 for o in t:
1006 for o in t:
1007 if "(DEPRECATED)" in o[3]:
1007 if "(DEPRECATED)" in o[3]:
1008 continue
1008 continue
1009 if o[0]:
1009 if o[0]:
1010 options.append('-%s' % o[0])
1010 options.append('-%s' % o[0])
1011 options.append('--%s' % o[1])
1011 options.append('--%s' % o[1])
1012 ui.write("%s\n" % "\n".join(options))
1012 ui.write("%s\n" % "\n".join(options))
1013 return
1013 return
1014
1014
1015 cmdlist = cmdutil.findpossible(cmd, table)
1015 cmdlist = cmdutil.findpossible(cmd, table)
1016 if ui.verbose:
1016 if ui.verbose:
1017 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1017 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1018 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1018 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1019
1019
1020 def debugfsinfo(ui, path = "."):
1020 def debugfsinfo(ui, path = "."):
1021 """show information detected about current filesystem"""
1021 """show information detected about current filesystem"""
1022 open('.debugfsinfo', 'w').write('')
1022 open('.debugfsinfo', 'w').write('')
1023 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1023 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1024 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1024 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1025 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1025 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1026 and 'yes' or 'no'))
1026 and 'yes' or 'no'))
1027 os.unlink('.debugfsinfo')
1027 os.unlink('.debugfsinfo')
1028
1028
1029 def debugrebuildstate(ui, repo, rev="tip"):
1029 def debugrebuildstate(ui, repo, rev="tip"):
1030 """rebuild the dirstate as it would look like for the given revision"""
1030 """rebuild the dirstate as it would look like for the given revision"""
1031 ctx = cmdutil.revsingle(repo, rev)
1031 ctx = cmdutil.revsingle(repo, rev)
1032 wlock = repo.wlock()
1032 wlock = repo.wlock()
1033 try:
1033 try:
1034 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1034 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1035 finally:
1035 finally:
1036 wlock.release()
1036 wlock.release()
1037
1037
1038 def debugcheckstate(ui, repo):
1038 def debugcheckstate(ui, repo):
1039 """validate the correctness of the current dirstate"""
1039 """validate the correctness of the current dirstate"""
1040 parent1, parent2 = repo.dirstate.parents()
1040 parent1, parent2 = repo.dirstate.parents()
1041 m1 = repo[parent1].manifest()
1041 m1 = repo[parent1].manifest()
1042 m2 = repo[parent2].manifest()
1042 m2 = repo[parent2].manifest()
1043 errors = 0
1043 errors = 0
1044 for f in repo.dirstate:
1044 for f in repo.dirstate:
1045 state = repo.dirstate[f]
1045 state = repo.dirstate[f]
1046 if state in "nr" and f not in m1:
1046 if state in "nr" and f not in m1:
1047 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1047 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1048 errors += 1
1048 errors += 1
1049 if state in "a" and f in m1:
1049 if state in "a" and f in m1:
1050 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1050 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1051 errors += 1
1051 errors += 1
1052 if state in "m" and f not in m1 and f not in m2:
1052 if state in "m" and f not in m1 and f not in m2:
1053 ui.warn(_("%s in state %s, but not in either manifest\n") %
1053 ui.warn(_("%s in state %s, but not in either manifest\n") %
1054 (f, state))
1054 (f, state))
1055 errors += 1
1055 errors += 1
1056 for f in m1:
1056 for f in m1:
1057 state = repo.dirstate[f]
1057 state = repo.dirstate[f]
1058 if state not in "nrm":
1058 if state not in "nrm":
1059 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1059 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1060 errors += 1
1060 errors += 1
1061 if errors:
1061 if errors:
1062 error = _(".hg/dirstate inconsistent with current parent's manifest")
1062 error = _(".hg/dirstate inconsistent with current parent's manifest")
1063 raise util.Abort(error)
1063 raise util.Abort(error)
1064
1064
1065 def showconfig(ui, repo, *values, **opts):
1065 def showconfig(ui, repo, *values, **opts):
1066 """show combined config settings from all hgrc files
1066 """show combined config settings from all hgrc files
1067
1067
1068 With no arguments, print names and values of all config items.
1068 With no arguments, print names and values of all config items.
1069
1069
1070 With one argument of the form section.name, print just the value
1070 With one argument of the form section.name, print just the value
1071 of that config item.
1071 of that config item.
1072
1072
1073 With multiple arguments, print names and values of all config
1073 With multiple arguments, print names and values of all config
1074 items with matching section names.
1074 items with matching section names.
1075
1075
1076 With --debug, the source (filename and line number) is printed
1076 With --debug, the source (filename and line number) is printed
1077 for each config item.
1077 for each config item.
1078
1078
1079 Returns 0 on success.
1079 Returns 0 on success.
1080 """
1080 """
1081
1081
1082 for f in util.rcpath():
1082 for f in util.rcpath():
1083 ui.debug(_('read config from: %s\n') % f)
1083 ui.debug(_('read config from: %s\n') % f)
1084 untrusted = bool(opts.get('untrusted'))
1084 untrusted = bool(opts.get('untrusted'))
1085 if values:
1085 if values:
1086 sections = [v for v in values if '.' not in v]
1086 sections = [v for v in values if '.' not in v]
1087 items = [v for v in values if '.' in v]
1087 items = [v for v in values if '.' in v]
1088 if len(items) > 1 or items and sections:
1088 if len(items) > 1 or items and sections:
1089 raise util.Abort(_('only one config item permitted'))
1089 raise util.Abort(_('only one config item permitted'))
1090 for section, name, value in ui.walkconfig(untrusted=untrusted):
1090 for section, name, value in ui.walkconfig(untrusted=untrusted):
1091 sectname = section + '.' + name
1091 sectname = section + '.' + name
1092 if values:
1092 if values:
1093 for v in values:
1093 for v in values:
1094 if v == section:
1094 if v == section:
1095 ui.debug('%s: ' %
1095 ui.debug('%s: ' %
1096 ui.configsource(section, name, untrusted))
1096 ui.configsource(section, name, untrusted))
1097 ui.write('%s=%s\n' % (sectname, value))
1097 ui.write('%s=%s\n' % (sectname, value))
1098 elif v == sectname:
1098 elif v == sectname:
1099 ui.debug('%s: ' %
1099 ui.debug('%s: ' %
1100 ui.configsource(section, name, untrusted))
1100 ui.configsource(section, name, untrusted))
1101 ui.write(value, '\n')
1101 ui.write(value, '\n')
1102 else:
1102 else:
1103 ui.debug('%s: ' %
1103 ui.debug('%s: ' %
1104 ui.configsource(section, name, untrusted))
1104 ui.configsource(section, name, untrusted))
1105 ui.write('%s=%s\n' % (sectname, value))
1105 ui.write('%s=%s\n' % (sectname, value))
1106
1106
1107 def debugpushkey(ui, repopath, namespace, *keyinfo):
1107 def debugpushkey(ui, repopath, namespace, *keyinfo):
1108 '''access the pushkey key/value protocol
1108 '''access the pushkey key/value protocol
1109
1109
1110 With two args, list the keys in the given namespace.
1110 With two args, list the keys in the given namespace.
1111
1111
1112 With five args, set a key to new if it currently is set to old.
1112 With five args, set a key to new if it currently is set to old.
1113 Reports success or failure.
1113 Reports success or failure.
1114 '''
1114 '''
1115
1115
1116 target = hg.repository(ui, repopath)
1116 target = hg.repository(ui, repopath)
1117 if keyinfo:
1117 if keyinfo:
1118 key, old, new = keyinfo
1118 key, old, new = keyinfo
1119 r = target.pushkey(namespace, key, old, new)
1119 r = target.pushkey(namespace, key, old, new)
1120 ui.status(str(r) + '\n')
1120 ui.status(str(r) + '\n')
1121 return not r
1121 return not r
1122 else:
1122 else:
1123 for k, v in target.listkeys(namespace).iteritems():
1123 for k, v in target.listkeys(namespace).iteritems():
1124 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1124 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1125 v.encode('string-escape')))
1125 v.encode('string-escape')))
1126
1126
1127 def debugrevspec(ui, repo, expr):
1127 def debugrevspec(ui, repo, expr):
1128 '''parse and apply a revision specification'''
1128 '''parse and apply a revision specification'''
1129 if ui.verbose:
1129 if ui.verbose:
1130 tree = revset.parse(expr)
1130 tree = revset.parse(expr)
1131 ui.note(tree, "\n")
1131 ui.note(tree, "\n")
1132 func = revset.match(expr)
1132 func = revset.match(expr)
1133 for c in func(repo, range(len(repo))):
1133 for c in func(repo, range(len(repo))):
1134 ui.write("%s\n" % c)
1134 ui.write("%s\n" % c)
1135
1135
1136 def debugsetparents(ui, repo, rev1, rev2=None):
1136 def debugsetparents(ui, repo, rev1, rev2=None):
1137 """manually set the parents of the current working directory
1137 """manually set the parents of the current working directory
1138
1138
1139 This is useful for writing repository conversion tools, but should
1139 This is useful for writing repository conversion tools, but should
1140 be used with care.
1140 be used with care.
1141
1141
1142 Returns 0 on success.
1142 Returns 0 on success.
1143 """
1143 """
1144
1144
1145 r1 = cmdutil.revsingle(repo, rev1).node()
1145 r1 = cmdutil.revsingle(repo, rev1).node()
1146 r2 = cmdutil.revsingle(repo, rev2, 'null').node()
1146 r2 = cmdutil.revsingle(repo, rev2, 'null').node()
1147
1147
1148 wlock = repo.wlock()
1148 wlock = repo.wlock()
1149 try:
1149 try:
1150 repo.dirstate.setparents(r1, r2)
1150 repo.dirstate.setparents(r1, r2)
1151 finally:
1151 finally:
1152 wlock.release()
1152 wlock.release()
1153
1153
1154 def debugstate(ui, repo, nodates=None):
1154 def debugstate(ui, repo, nodates=None):
1155 """show the contents of the current dirstate"""
1155 """show the contents of the current dirstate"""
1156 timestr = ""
1156 timestr = ""
1157 showdate = not nodates
1157 showdate = not nodates
1158 for file_, ent in sorted(repo.dirstate._map.iteritems()):
1158 for file_, ent in sorted(repo.dirstate._map.iteritems()):
1159 if showdate:
1159 if showdate:
1160 if ent[3] == -1:
1160 if ent[3] == -1:
1161 # Pad or slice to locale representation
1161 # Pad or slice to locale representation
1162 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
1162 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
1163 time.localtime(0)))
1163 time.localtime(0)))
1164 timestr = 'unset'
1164 timestr = 'unset'
1165 timestr = (timestr[:locale_len] +
1165 timestr = (timestr[:locale_len] +
1166 ' ' * (locale_len - len(timestr)))
1166 ' ' * (locale_len - len(timestr)))
1167 else:
1167 else:
1168 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
1168 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
1169 time.localtime(ent[3]))
1169 time.localtime(ent[3]))
1170 if ent[1] & 020000:
1170 if ent[1] & 020000:
1171 mode = 'lnk'
1171 mode = 'lnk'
1172 else:
1172 else:
1173 mode = '%3o' % (ent[1] & 0777)
1173 mode = '%3o' % (ent[1] & 0777)
1174 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
1174 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
1175 for f in repo.dirstate.copies():
1175 for f in repo.dirstate.copies():
1176 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
1176 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
1177
1177
1178 def debugsub(ui, repo, rev=None):
1178 def debugsub(ui, repo, rev=None):
1179 ctx = cmdutil.revsingle(repo, rev, None)
1179 ctx = cmdutil.revsingle(repo, rev, None)
1180 for k, v in sorted(ctx.substate.items()):
1180 for k, v in sorted(ctx.substate.items()):
1181 ui.write('path %s\n' % k)
1181 ui.write('path %s\n' % k)
1182 ui.write(' source %s\n' % v[0])
1182 ui.write(' source %s\n' % v[0])
1183 ui.write(' revision %s\n' % v[1])
1183 ui.write(' revision %s\n' % v[1])
1184
1184
1185 def debugdag(ui, repo, file_=None, *revs, **opts):
1185 def debugdag(ui, repo, file_=None, *revs, **opts):
1186 """format the changelog or an index DAG as a concise textual description
1186 """format the changelog or an index DAG as a concise textual description
1187
1187
1188 If you pass a revlog index, the revlog's DAG is emitted. If you list
1188 If you pass a revlog index, the revlog's DAG is emitted. If you list
1189 revision numbers, they get labelled in the output as rN.
1189 revision numbers, they get labelled in the output as rN.
1190
1190
1191 Otherwise, the changelog DAG of the current repo is emitted.
1191 Otherwise, the changelog DAG of the current repo is emitted.
1192 """
1192 """
1193 spaces = opts.get('spaces')
1193 spaces = opts.get('spaces')
1194 dots = opts.get('dots')
1194 dots = opts.get('dots')
1195 if file_:
1195 if file_:
1196 rlog = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1196 rlog = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1197 revs = set((int(r) for r in revs))
1197 revs = set((int(r) for r in revs))
1198 def events():
1198 def events():
1199 for r in rlog:
1199 for r in rlog:
1200 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1200 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1201 if r in revs:
1201 if r in revs:
1202 yield 'l', (r, "r%i" % r)
1202 yield 'l', (r, "r%i" % r)
1203 elif repo:
1203 elif repo:
1204 cl = repo.changelog
1204 cl = repo.changelog
1205 tags = opts.get('tags')
1205 tags = opts.get('tags')
1206 branches = opts.get('branches')
1206 branches = opts.get('branches')
1207 if tags:
1207 if tags:
1208 labels = {}
1208 labels = {}
1209 for l, n in repo.tags().items():
1209 for l, n in repo.tags().items():
1210 labels.setdefault(cl.rev(n), []).append(l)
1210 labels.setdefault(cl.rev(n), []).append(l)
1211 def events():
1211 def events():
1212 b = "default"
1212 b = "default"
1213 for r in cl:
1213 for r in cl:
1214 if branches:
1214 if branches:
1215 newb = cl.read(cl.node(r))[5]['branch']
1215 newb = cl.read(cl.node(r))[5]['branch']
1216 if newb != b:
1216 if newb != b:
1217 yield 'a', newb
1217 yield 'a', newb
1218 b = newb
1218 b = newb
1219 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1219 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1220 if tags:
1220 if tags:
1221 ls = labels.get(r)
1221 ls = labels.get(r)
1222 if ls:
1222 if ls:
1223 for l in ls:
1223 for l in ls:
1224 yield 'l', (r, l)
1224 yield 'l', (r, l)
1225 else:
1225 else:
1226 raise util.Abort(_('need repo for changelog dag'))
1226 raise util.Abort(_('need repo for changelog dag'))
1227
1227
1228 for line in dagparser.dagtextlines(events(),
1228 for line in dagparser.dagtextlines(events(),
1229 addspaces=spaces,
1229 addspaces=spaces,
1230 wraplabels=True,
1230 wraplabels=True,
1231 wrapannotations=True,
1231 wrapannotations=True,
1232 wrapnonlinear=dots,
1232 wrapnonlinear=dots,
1233 usedots=dots,
1233 usedots=dots,
1234 maxlinewidth=70):
1234 maxlinewidth=70):
1235 ui.write(line)
1235 ui.write(line)
1236 ui.write("\n")
1236 ui.write("\n")
1237
1237
1238 def debugdata(ui, repo, file_, rev):
1238 def debugdata(ui, repo, file_, rev):
1239 """dump the contents of a data file revision"""
1239 """dump the contents of a data file revision"""
1240 r = None
1240 r = None
1241 if repo:
1241 if repo:
1242 filelog = repo.file(file_)
1242 filelog = repo.file(file_)
1243 if len(filelog):
1243 if len(filelog):
1244 r = filelog
1244 r = filelog
1245 if not r:
1245 if not r:
1246 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_[:-2] + ".i")
1246 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_[:-2] + ".i")
1247 try:
1247 try:
1248 ui.write(r.revision(r.lookup(rev)))
1248 ui.write(r.revision(r.lookup(rev)))
1249 except KeyError:
1249 except KeyError:
1250 raise util.Abort(_('invalid revision identifier %s') % rev)
1250 raise util.Abort(_('invalid revision identifier %s') % rev)
1251
1251
1252 def debugdate(ui, date, range=None, **opts):
1252 def debugdate(ui, date, range=None, **opts):
1253 """parse and display a date"""
1253 """parse and display a date"""
1254 if opts["extended"]:
1254 if opts["extended"]:
1255 d = util.parsedate(date, util.extendeddateformats)
1255 d = util.parsedate(date, util.extendeddateformats)
1256 else:
1256 else:
1257 d = util.parsedate(date)
1257 d = util.parsedate(date)
1258 ui.write("internal: %s %s\n" % d)
1258 ui.write("internal: %s %s\n" % d)
1259 ui.write("standard: %s\n" % util.datestr(d))
1259 ui.write("standard: %s\n" % util.datestr(d))
1260 if range:
1260 if range:
1261 m = util.matchdate(range)
1261 m = util.matchdate(range)
1262 ui.write("match: %s\n" % m(d[0]))
1262 ui.write("match: %s\n" % m(d[0]))
1263
1263
1264 def debugindex(ui, repo, file_, **opts):
1264 def debugindex(ui, repo, file_, **opts):
1265 """dump the contents of an index file"""
1265 """dump the contents of an index file"""
1266 r = None
1266 r = None
1267 if repo:
1267 if repo:
1268 filelog = repo.file(file_)
1268 filelog = repo.file(file_)
1269 if len(filelog):
1269 if len(filelog):
1270 r = filelog
1270 r = filelog
1271
1271
1272 format = opts.get('format', 0)
1272 format = opts.get('format', 0)
1273 if format not in (0, 1):
1273 if format not in (0, 1):
1274 raise util.Abort("unknown format %d" % format)
1274 raise util.Abort("unknown format %d" % format)
1275
1275
1276 if not r:
1276 if not r:
1277 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1277 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1278
1278
1279 if format == 0:
1279 if format == 0:
1280 ui.write(" rev offset length base linkrev"
1280 ui.write(" rev offset length base linkrev"
1281 " nodeid p1 p2\n")
1281 " nodeid p1 p2\n")
1282 elif format == 1:
1282 elif format == 1:
1283 ui.write(" rev flag offset length"
1283 ui.write(" rev flag offset length"
1284 " size base link p1 p2 nodeid\n")
1284 " size base link p1 p2 nodeid\n")
1285
1285
1286 for i in r:
1286 for i in r:
1287 node = r.node(i)
1287 node = r.node(i)
1288 if format == 0:
1288 if format == 0:
1289 try:
1289 try:
1290 pp = r.parents(node)
1290 pp = r.parents(node)
1291 except:
1291 except:
1292 pp = [nullid, nullid]
1292 pp = [nullid, nullid]
1293 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1293 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1294 i, r.start(i), r.length(i), r.base(i), r.linkrev(i),
1294 i, r.start(i), r.length(i), r.base(i), r.linkrev(i),
1295 short(node), short(pp[0]), short(pp[1])))
1295 short(node), short(pp[0]), short(pp[1])))
1296 elif format == 1:
1296 elif format == 1:
1297 pr = r.parentrevs(i)
1297 pr = r.parentrevs(i)
1298 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1298 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1299 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1299 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1300 r.base(i), r.linkrev(i), pr[0], pr[1], short(node)))
1300 r.base(i), r.linkrev(i), pr[0], pr[1], short(node)))
1301
1301
1302 def debugindexdot(ui, repo, file_):
1302 def debugindexdot(ui, repo, file_):
1303 """dump an index DAG as a graphviz dot file"""
1303 """dump an index DAG as a graphviz dot file"""
1304 r = None
1304 r = None
1305 if repo:
1305 if repo:
1306 filelog = repo.file(file_)
1306 filelog = repo.file(file_)
1307 if len(filelog):
1307 if len(filelog):
1308 r = filelog
1308 r = filelog
1309 if not r:
1309 if not r:
1310 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1310 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1311 ui.write("digraph G {\n")
1311 ui.write("digraph G {\n")
1312 for i in r:
1312 for i in r:
1313 node = r.node(i)
1313 node = r.node(i)
1314 pp = r.parents(node)
1314 pp = r.parents(node)
1315 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1315 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1316 if pp[1] != nullid:
1316 if pp[1] != nullid:
1317 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1317 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1318 ui.write("}\n")
1318 ui.write("}\n")
1319
1319
1320 def debuginstall(ui):
1320 def debuginstall(ui):
1321 '''test Mercurial installation
1321 '''test Mercurial installation
1322
1322
1323 Returns 0 on success.
1323 Returns 0 on success.
1324 '''
1324 '''
1325
1325
1326 def writetemp(contents):
1326 def writetemp(contents):
1327 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1327 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1328 f = os.fdopen(fd, "wb")
1328 f = os.fdopen(fd, "wb")
1329 f.write(contents)
1329 f.write(contents)
1330 f.close()
1330 f.close()
1331 return name
1331 return name
1332
1332
1333 problems = 0
1333 problems = 0
1334
1334
1335 # encoding
1335 # encoding
1336 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1336 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1337 try:
1337 try:
1338 encoding.fromlocal("test")
1338 encoding.fromlocal("test")
1339 except util.Abort, inst:
1339 except util.Abort, inst:
1340 ui.write(" %s\n" % inst)
1340 ui.write(" %s\n" % inst)
1341 ui.write(_(" (check that your locale is properly set)\n"))
1341 ui.write(_(" (check that your locale is properly set)\n"))
1342 problems += 1
1342 problems += 1
1343
1343
1344 # compiled modules
1344 # compiled modules
1345 ui.status(_("Checking installed modules (%s)...\n")
1345 ui.status(_("Checking installed modules (%s)...\n")
1346 % os.path.dirname(__file__))
1346 % os.path.dirname(__file__))
1347 try:
1347 try:
1348 import bdiff, mpatch, base85, osutil
1348 import bdiff, mpatch, base85, osutil
1349 except Exception, inst:
1349 except Exception, inst:
1350 ui.write(" %s\n" % inst)
1350 ui.write(" %s\n" % inst)
1351 ui.write(_(" One or more extensions could not be found"))
1351 ui.write(_(" One or more extensions could not be found"))
1352 ui.write(_(" (check that you compiled the extensions)\n"))
1352 ui.write(_(" (check that you compiled the extensions)\n"))
1353 problems += 1
1353 problems += 1
1354
1354
1355 # templates
1355 # templates
1356 ui.status(_("Checking templates...\n"))
1356 ui.status(_("Checking templates...\n"))
1357 try:
1357 try:
1358 import templater
1358 import templater
1359 templater.templater(templater.templatepath("map-cmdline.default"))
1359 templater.templater(templater.templatepath("map-cmdline.default"))
1360 except Exception, inst:
1360 except Exception, inst:
1361 ui.write(" %s\n" % inst)
1361 ui.write(" %s\n" % inst)
1362 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1362 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1363 problems += 1
1363 problems += 1
1364
1364
1365 # patch
1365 # patch
1366 ui.status(_("Checking patch...\n"))
1366 ui.status(_("Checking patch...\n"))
1367 patchproblems = 0
1367 patchproblems = 0
1368 a = "1\n2\n3\n4\n"
1368 a = "1\n2\n3\n4\n"
1369 b = "1\n2\n3\ninsert\n4\n"
1369 b = "1\n2\n3\ninsert\n4\n"
1370 fa = writetemp(a)
1370 fa = writetemp(a)
1371 d = mdiff.unidiff(a, None, b, None, os.path.basename(fa),
1371 d = mdiff.unidiff(a, None, b, None, os.path.basename(fa),
1372 os.path.basename(fa))
1372 os.path.basename(fa))
1373 fd = writetemp(d)
1373 fd = writetemp(d)
1374
1374
1375 files = {}
1375 files = {}
1376 try:
1376 try:
1377 patch.patch(fd, ui, cwd=os.path.dirname(fa), files=files)
1377 patch.patch(fd, ui, cwd=os.path.dirname(fa), files=files)
1378 except util.Abort, e:
1378 except util.Abort, e:
1379 ui.write(_(" patch call failed:\n"))
1379 ui.write(_(" patch call failed:\n"))
1380 ui.write(" " + str(e) + "\n")
1380 ui.write(" " + str(e) + "\n")
1381 patchproblems += 1
1381 patchproblems += 1
1382 else:
1382 else:
1383 if list(files) != [os.path.basename(fa)]:
1383 if list(files) != [os.path.basename(fa)]:
1384 ui.write(_(" unexpected patch output!\n"))
1384 ui.write(_(" unexpected patch output!\n"))
1385 patchproblems += 1
1385 patchproblems += 1
1386 a = open(fa).read()
1386 a = open(fa).read()
1387 if a != b:
1387 if a != b:
1388 ui.write(_(" patch test failed!\n"))
1388 ui.write(_(" patch test failed!\n"))
1389 patchproblems += 1
1389 patchproblems += 1
1390
1390
1391 if patchproblems:
1391 if patchproblems:
1392 if ui.config('ui', 'patch'):
1392 if ui.config('ui', 'patch'):
1393 ui.write(_(" (Current patch tool may be incompatible with patch,"
1393 ui.write(_(" (Current patch tool may be incompatible with patch,"
1394 " or misconfigured. Please check your configuration"
1394 " or misconfigured. Please check your configuration"
1395 " file)\n"))
1395 " file)\n"))
1396 else:
1396 else:
1397 ui.write(_(" Internal patcher failure, please report this error"
1397 ui.write(_(" Internal patcher failure, please report this error"
1398 " to http://mercurial.selenic.com/wiki/BugTracker\n"))
1398 " to http://mercurial.selenic.com/wiki/BugTracker\n"))
1399 problems += patchproblems
1399 problems += patchproblems
1400
1400
1401 os.unlink(fa)
1401 os.unlink(fa)
1402 os.unlink(fd)
1402 os.unlink(fd)
1403
1403
1404 # editor
1404 # editor
1405 ui.status(_("Checking commit editor...\n"))
1405 ui.status(_("Checking commit editor...\n"))
1406 editor = ui.geteditor()
1406 editor = ui.geteditor()
1407 cmdpath = util.find_exe(editor) or util.find_exe(editor.split()[0])
1407 cmdpath = util.find_exe(editor) or util.find_exe(editor.split()[0])
1408 if not cmdpath:
1408 if not cmdpath:
1409 if editor == 'vi':
1409 if editor == 'vi':
1410 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1410 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1411 ui.write(_(" (specify a commit editor in your configuration"
1411 ui.write(_(" (specify a commit editor in your configuration"
1412 " file)\n"))
1412 " file)\n"))
1413 else:
1413 else:
1414 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1414 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1415 ui.write(_(" (specify a commit editor in your configuration"
1415 ui.write(_(" (specify a commit editor in your configuration"
1416 " file)\n"))
1416 " file)\n"))
1417 problems += 1
1417 problems += 1
1418
1418
1419 # check username
1419 # check username
1420 ui.status(_("Checking username...\n"))
1420 ui.status(_("Checking username...\n"))
1421 try:
1421 try:
1422 ui.username()
1422 ui.username()
1423 except util.Abort, e:
1423 except util.Abort, e:
1424 ui.write(" %s\n" % e)
1424 ui.write(" %s\n" % e)
1425 ui.write(_(" (specify a username in your configuration file)\n"))
1425 ui.write(_(" (specify a username in your configuration file)\n"))
1426 problems += 1
1426 problems += 1
1427
1427
1428 if not problems:
1428 if not problems:
1429 ui.status(_("No problems detected\n"))
1429 ui.status(_("No problems detected\n"))
1430 else:
1430 else:
1431 ui.write(_("%s problems detected,"
1431 ui.write(_("%s problems detected,"
1432 " please check your install!\n") % problems)
1432 " please check your install!\n") % problems)
1433
1433
1434 return problems
1434 return problems
1435
1435
1436 def debugrename(ui, repo, file1, *pats, **opts):
1436 def debugrename(ui, repo, file1, *pats, **opts):
1437 """dump rename information"""
1437 """dump rename information"""
1438
1438
1439 ctx = cmdutil.revsingle(repo, opts.get('rev'))
1439 ctx = cmdutil.revsingle(repo, opts.get('rev'))
1440 m = cmdutil.match(repo, (file1,) + pats, opts)
1440 m = cmdutil.match(repo, (file1,) + pats, opts)
1441 for abs in ctx.walk(m):
1441 for abs in ctx.walk(m):
1442 fctx = ctx[abs]
1442 fctx = ctx[abs]
1443 o = fctx.filelog().renamed(fctx.filenode())
1443 o = fctx.filelog().renamed(fctx.filenode())
1444 rel = m.rel(abs)
1444 rel = m.rel(abs)
1445 if o:
1445 if o:
1446 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1446 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1447 else:
1447 else:
1448 ui.write(_("%s not renamed\n") % rel)
1448 ui.write(_("%s not renamed\n") % rel)
1449
1449
1450 def debugwalk(ui, repo, *pats, **opts):
1450 def debugwalk(ui, repo, *pats, **opts):
1451 """show how files match on given patterns"""
1451 """show how files match on given patterns"""
1452 m = cmdutil.match(repo, pats, opts)
1452 m = cmdutil.match(repo, pats, opts)
1453 items = list(repo.walk(m))
1453 items = list(repo.walk(m))
1454 if not items:
1454 if not items:
1455 return
1455 return
1456 fmt = 'f %%-%ds %%-%ds %%s' % (
1456 fmt = 'f %%-%ds %%-%ds %%s' % (
1457 max([len(abs) for abs in items]),
1457 max([len(abs) for abs in items]),
1458 max([len(m.rel(abs)) for abs in items]))
1458 max([len(m.rel(abs)) for abs in items]))
1459 for abs in items:
1459 for abs in items:
1460 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
1460 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
1461 ui.write("%s\n" % line.rstrip())
1461 ui.write("%s\n" % line.rstrip())
1462
1462
1463 def diff(ui, repo, *pats, **opts):
1463 def diff(ui, repo, *pats, **opts):
1464 """diff repository (or selected files)
1464 """diff repository (or selected files)
1465
1465
1466 Show differences between revisions for the specified files.
1466 Show differences between revisions for the specified files.
1467
1467
1468 Differences between files are shown using the unified diff format.
1468 Differences between files are shown using the unified diff format.
1469
1469
1470 .. note::
1470 .. note::
1471 diff may generate unexpected results for merges, as it will
1471 diff may generate unexpected results for merges, as it will
1472 default to comparing against the working directory's first
1472 default to comparing against the working directory's first
1473 parent changeset if no revisions are specified.
1473 parent changeset if no revisions are specified.
1474
1474
1475 When two revision arguments are given, then changes are shown
1475 When two revision arguments are given, then changes are shown
1476 between those revisions. If only one revision is specified then
1476 between those revisions. If only one revision is specified then
1477 that revision is compared to the working directory, and, when no
1477 that revision is compared to the working directory, and, when no
1478 revisions are specified, the working directory files are compared
1478 revisions are specified, the working directory files are compared
1479 to its parent.
1479 to its parent.
1480
1480
1481 Alternatively you can specify -c/--change with a revision to see
1481 Alternatively you can specify -c/--change with a revision to see
1482 the changes in that changeset relative to its first parent.
1482 the changes in that changeset relative to its first parent.
1483
1483
1484 Without the -a/--text option, diff will avoid generating diffs of
1484 Without the -a/--text option, diff will avoid generating diffs of
1485 files it detects as binary. With -a, diff will generate a diff
1485 files it detects as binary. With -a, diff will generate a diff
1486 anyway, probably with undesirable results.
1486 anyway, probably with undesirable results.
1487
1487
1488 Use the -g/--git option to generate diffs in the git extended diff
1488 Use the -g/--git option to generate diffs in the git extended diff
1489 format. For more information, read :hg:`help diffs`.
1489 format. For more information, read :hg:`help diffs`.
1490
1490
1491 Returns 0 on success.
1491 Returns 0 on success.
1492 """
1492 """
1493
1493
1494 revs = opts.get('rev')
1494 revs = opts.get('rev')
1495 change = opts.get('change')
1495 change = opts.get('change')
1496 stat = opts.get('stat')
1496 stat = opts.get('stat')
1497 reverse = opts.get('reverse')
1497 reverse = opts.get('reverse')
1498
1498
1499 if revs and change:
1499 if revs and change:
1500 msg = _('cannot specify --rev and --change at the same time')
1500 msg = _('cannot specify --rev and --change at the same time')
1501 raise util.Abort(msg)
1501 raise util.Abort(msg)
1502 elif change:
1502 elif change:
1503 node2 = repo.lookup(change)
1503 node2 = repo.lookup(change)
1504 node1 = repo[node2].parents()[0].node()
1504 node1 = repo[node2].parents()[0].node()
1505 else:
1505 else:
1506 node1, node2 = cmdutil.revpair(repo, revs)
1506 node1, node2 = cmdutil.revpair(repo, revs)
1507
1507
1508 if reverse:
1508 if reverse:
1509 node1, node2 = node2, node1
1509 node1, node2 = node2, node1
1510
1510
1511 diffopts = patch.diffopts(ui, opts)
1511 diffopts = patch.diffopts(ui, opts)
1512 m = cmdutil.match(repo, pats, opts)
1512 m = cmdutil.match(repo, pats, opts)
1513 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
1513 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
1514 listsubrepos=opts.get('subrepos'))
1514 listsubrepos=opts.get('subrepos'))
1515
1515
1516 def export(ui, repo, *changesets, **opts):
1516 def export(ui, repo, *changesets, **opts):
1517 """dump the header and diffs for one or more changesets
1517 """dump the header and diffs for one or more changesets
1518
1518
1519 Print the changeset header and diffs for one or more revisions.
1519 Print the changeset header and diffs for one or more revisions.
1520
1520
1521 The information shown in the changeset header is: author, date,
1521 The information shown in the changeset header is: author, date,
1522 branch name (if non-default), changeset hash, parent(s) and commit
1522 branch name (if non-default), changeset hash, parent(s) and commit
1523 comment.
1523 comment.
1524
1524
1525 .. note::
1525 .. note::
1526 export may generate unexpected diff output for merge
1526 export may generate unexpected diff output for merge
1527 changesets, as it will compare the merge changeset against its
1527 changesets, as it will compare the merge changeset against its
1528 first parent only.
1528 first parent only.
1529
1529
1530 Output may be to a file, in which case the name of the file is
1530 Output may be to a file, in which case the name of the file is
1531 given using a format string. The formatting rules are as follows:
1531 given using a format string. The formatting rules are as follows:
1532
1532
1533 :``%%``: literal "%" character
1533 :``%%``: literal "%" character
1534 :``%H``: changeset hash (40 hexadecimal digits)
1534 :``%H``: changeset hash (40 hexadecimal digits)
1535 :``%N``: number of patches being generated
1535 :``%N``: number of patches being generated
1536 :``%R``: changeset revision number
1536 :``%R``: changeset revision number
1537 :``%b``: basename of the exporting repository
1537 :``%b``: basename of the exporting repository
1538 :``%h``: short-form changeset hash (12 hexadecimal digits)
1538 :``%h``: short-form changeset hash (12 hexadecimal digits)
1539 :``%n``: zero-padded sequence number, starting at 1
1539 :``%n``: zero-padded sequence number, starting at 1
1540 :``%r``: zero-padded changeset revision number
1540 :``%r``: zero-padded changeset revision number
1541
1541
1542 Without the -a/--text option, export will avoid generating diffs
1542 Without the -a/--text option, export will avoid generating diffs
1543 of files it detects as binary. With -a, export will generate a
1543 of files it detects as binary. With -a, export will generate a
1544 diff anyway, probably with undesirable results.
1544 diff anyway, probably with undesirable results.
1545
1545
1546 Use the -g/--git option to generate diffs in the git extended diff
1546 Use the -g/--git option to generate diffs in the git extended diff
1547 format. See :hg:`help diffs` for more information.
1547 format. See :hg:`help diffs` for more information.
1548
1548
1549 With the --switch-parent option, the diff will be against the
1549 With the --switch-parent option, the diff will be against the
1550 second parent. It can be useful to review a merge.
1550 second parent. It can be useful to review a merge.
1551
1551
1552 Returns 0 on success.
1552 Returns 0 on success.
1553 """
1553 """
1554 changesets += tuple(opts.get('rev', []))
1554 changesets += tuple(opts.get('rev', []))
1555 if not changesets:
1555 if not changesets:
1556 raise util.Abort(_("export requires at least one changeset"))
1556 raise util.Abort(_("export requires at least one changeset"))
1557 revs = cmdutil.revrange(repo, changesets)
1557 revs = cmdutil.revrange(repo, changesets)
1558 if len(revs) > 1:
1558 if len(revs) > 1:
1559 ui.note(_('exporting patches:\n'))
1559 ui.note(_('exporting patches:\n'))
1560 else:
1560 else:
1561 ui.note(_('exporting patch:\n'))
1561 ui.note(_('exporting patch:\n'))
1562 cmdutil.export(repo, revs, template=opts.get('output'),
1562 cmdutil.export(repo, revs, template=opts.get('output'),
1563 switch_parent=opts.get('switch_parent'),
1563 switch_parent=opts.get('switch_parent'),
1564 opts=patch.diffopts(ui, opts))
1564 opts=patch.diffopts(ui, opts))
1565
1565
1566 def forget(ui, repo, *pats, **opts):
1566 def forget(ui, repo, *pats, **opts):
1567 """forget the specified files on the next commit
1567 """forget the specified files on the next commit
1568
1568
1569 Mark the specified files so they will no longer be tracked
1569 Mark the specified files so they will no longer be tracked
1570 after the next commit.
1570 after the next commit.
1571
1571
1572 This only removes files from the current branch, not from the
1572 This only removes files from the current branch, not from the
1573 entire project history, and it does not delete them from the
1573 entire project history, and it does not delete them from the
1574 working directory.
1574 working directory.
1575
1575
1576 To undo a forget before the next commit, see :hg:`add`.
1576 To undo a forget before the next commit, see :hg:`add`.
1577
1577
1578 Returns 0 on success.
1578 Returns 0 on success.
1579 """
1579 """
1580
1580
1581 if not pats:
1581 if not pats:
1582 raise util.Abort(_('no files specified'))
1582 raise util.Abort(_('no files specified'))
1583
1583
1584 m = cmdutil.match(repo, pats, opts)
1584 m = cmdutil.match(repo, pats, opts)
1585 s = repo.status(match=m, clean=True)
1585 s = repo.status(match=m, clean=True)
1586 forget = sorted(s[0] + s[1] + s[3] + s[6])
1586 forget = sorted(s[0] + s[1] + s[3] + s[6])
1587 errs = 0
1587 errs = 0
1588
1588
1589 for f in m.files():
1589 for f in m.files():
1590 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
1590 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
1591 ui.warn(_('not removing %s: file is already untracked\n')
1591 ui.warn(_('not removing %s: file is already untracked\n')
1592 % m.rel(f))
1592 % m.rel(f))
1593 errs = 1
1593 errs = 1
1594
1594
1595 for f in forget:
1595 for f in forget:
1596 if ui.verbose or not m.exact(f):
1596 if ui.verbose or not m.exact(f):
1597 ui.status(_('removing %s\n') % m.rel(f))
1597 ui.status(_('removing %s\n') % m.rel(f))
1598
1598
1599 repo[None].remove(forget, unlink=False)
1599 repo[None].remove(forget, unlink=False)
1600 return errs
1600 return errs
1601
1601
1602 def grep(ui, repo, pattern, *pats, **opts):
1602 def grep(ui, repo, pattern, *pats, **opts):
1603 """search for a pattern in specified files and revisions
1603 """search for a pattern in specified files and revisions
1604
1604
1605 Search revisions of files for a regular expression.
1605 Search revisions of files for a regular expression.
1606
1606
1607 This command behaves differently than Unix grep. It only accepts
1607 This command behaves differently than Unix grep. It only accepts
1608 Python/Perl regexps. It searches repository history, not the
1608 Python/Perl regexps. It searches repository history, not the
1609 working directory. It always prints the revision number in which a
1609 working directory. It always prints the revision number in which a
1610 match appears.
1610 match appears.
1611
1611
1612 By default, grep only prints output for the first revision of a
1612 By default, grep only prints output for the first revision of a
1613 file in which it finds a match. To get it to print every revision
1613 file in which it finds a match. To get it to print every revision
1614 that contains a change in match status ("-" for a match that
1614 that contains a change in match status ("-" for a match that
1615 becomes a non-match, or "+" for a non-match that becomes a match),
1615 becomes a non-match, or "+" for a non-match that becomes a match),
1616 use the --all flag.
1616 use the --all flag.
1617
1617
1618 Returns 0 if a match is found, 1 otherwise.
1618 Returns 0 if a match is found, 1 otherwise.
1619 """
1619 """
1620 reflags = 0
1620 reflags = 0
1621 if opts.get('ignore_case'):
1621 if opts.get('ignore_case'):
1622 reflags |= re.I
1622 reflags |= re.I
1623 try:
1623 try:
1624 regexp = re.compile(pattern, reflags)
1624 regexp = re.compile(pattern, reflags)
1625 except re.error, inst:
1625 except re.error, inst:
1626 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
1626 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
1627 return 1
1627 return 1
1628 sep, eol = ':', '\n'
1628 sep, eol = ':', '\n'
1629 if opts.get('print0'):
1629 if opts.get('print0'):
1630 sep = eol = '\0'
1630 sep = eol = '\0'
1631
1631
1632 getfile = util.lrucachefunc(repo.file)
1632 getfile = util.lrucachefunc(repo.file)
1633
1633
1634 def matchlines(body):
1634 def matchlines(body):
1635 begin = 0
1635 begin = 0
1636 linenum = 0
1636 linenum = 0
1637 while True:
1637 while True:
1638 match = regexp.search(body, begin)
1638 match = regexp.search(body, begin)
1639 if not match:
1639 if not match:
1640 break
1640 break
1641 mstart, mend = match.span()
1641 mstart, mend = match.span()
1642 linenum += body.count('\n', begin, mstart) + 1
1642 linenum += body.count('\n', begin, mstart) + 1
1643 lstart = body.rfind('\n', begin, mstart) + 1 or begin
1643 lstart = body.rfind('\n', begin, mstart) + 1 or begin
1644 begin = body.find('\n', mend) + 1 or len(body)
1644 begin = body.find('\n', mend) + 1 or len(body)
1645 lend = begin - 1
1645 lend = begin - 1
1646 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
1646 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
1647
1647
1648 class linestate(object):
1648 class linestate(object):
1649 def __init__(self, line, linenum, colstart, colend):
1649 def __init__(self, line, linenum, colstart, colend):
1650 self.line = line
1650 self.line = line
1651 self.linenum = linenum
1651 self.linenum = linenum
1652 self.colstart = colstart
1652 self.colstart = colstart
1653 self.colend = colend
1653 self.colend = colend
1654
1654
1655 def __hash__(self):
1655 def __hash__(self):
1656 return hash((self.linenum, self.line))
1656 return hash((self.linenum, self.line))
1657
1657
1658 def __eq__(self, other):
1658 def __eq__(self, other):
1659 return self.line == other.line
1659 return self.line == other.line
1660
1660
1661 matches = {}
1661 matches = {}
1662 copies = {}
1662 copies = {}
1663 def grepbody(fn, rev, body):
1663 def grepbody(fn, rev, body):
1664 matches[rev].setdefault(fn, [])
1664 matches[rev].setdefault(fn, [])
1665 m = matches[rev][fn]
1665 m = matches[rev][fn]
1666 for lnum, cstart, cend, line in matchlines(body):
1666 for lnum, cstart, cend, line in matchlines(body):
1667 s = linestate(line, lnum, cstart, cend)
1667 s = linestate(line, lnum, cstart, cend)
1668 m.append(s)
1668 m.append(s)
1669
1669
1670 def difflinestates(a, b):
1670 def difflinestates(a, b):
1671 sm = difflib.SequenceMatcher(None, a, b)
1671 sm = difflib.SequenceMatcher(None, a, b)
1672 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
1672 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
1673 if tag == 'insert':
1673 if tag == 'insert':
1674 for i in xrange(blo, bhi):
1674 for i in xrange(blo, bhi):
1675 yield ('+', b[i])
1675 yield ('+', b[i])
1676 elif tag == 'delete':
1676 elif tag == 'delete':
1677 for i in xrange(alo, ahi):
1677 for i in xrange(alo, ahi):
1678 yield ('-', a[i])
1678 yield ('-', a[i])
1679 elif tag == 'replace':
1679 elif tag == 'replace':
1680 for i in xrange(alo, ahi):
1680 for i in xrange(alo, ahi):
1681 yield ('-', a[i])
1681 yield ('-', a[i])
1682 for i in xrange(blo, bhi):
1682 for i in xrange(blo, bhi):
1683 yield ('+', b[i])
1683 yield ('+', b[i])
1684
1684
1685 def display(fn, ctx, pstates, states):
1685 def display(fn, ctx, pstates, states):
1686 rev = ctx.rev()
1686 rev = ctx.rev()
1687 datefunc = ui.quiet and util.shortdate or util.datestr
1687 datefunc = ui.quiet and util.shortdate or util.datestr
1688 found = False
1688 found = False
1689 filerevmatches = {}
1689 filerevmatches = {}
1690 if opts.get('all'):
1690 if opts.get('all'):
1691 iter = difflinestates(pstates, states)
1691 iter = difflinestates(pstates, states)
1692 else:
1692 else:
1693 iter = [('', l) for l in states]
1693 iter = [('', l) for l in states]
1694 for change, l in iter:
1694 for change, l in iter:
1695 cols = [fn, str(rev)]
1695 cols = [fn, str(rev)]
1696 before, match, after = None, None, None
1696 before, match, after = None, None, None
1697 if opts.get('line_number'):
1697 if opts.get('line_number'):
1698 cols.append(str(l.linenum))
1698 cols.append(str(l.linenum))
1699 if opts.get('all'):
1699 if opts.get('all'):
1700 cols.append(change)
1700 cols.append(change)
1701 if opts.get('user'):
1701 if opts.get('user'):
1702 cols.append(ui.shortuser(ctx.user()))
1702 cols.append(ui.shortuser(ctx.user()))
1703 if opts.get('date'):
1703 if opts.get('date'):
1704 cols.append(datefunc(ctx.date()))
1704 cols.append(datefunc(ctx.date()))
1705 if opts.get('files_with_matches'):
1705 if opts.get('files_with_matches'):
1706 c = (fn, rev)
1706 c = (fn, rev)
1707 if c in filerevmatches:
1707 if c in filerevmatches:
1708 continue
1708 continue
1709 filerevmatches[c] = 1
1709 filerevmatches[c] = 1
1710 else:
1710 else:
1711 before = l.line[:l.colstart]
1711 before = l.line[:l.colstart]
1712 match = l.line[l.colstart:l.colend]
1712 match = l.line[l.colstart:l.colend]
1713 after = l.line[l.colend:]
1713 after = l.line[l.colend:]
1714 ui.write(sep.join(cols))
1714 ui.write(sep.join(cols))
1715 if before is not None:
1715 if before is not None:
1716 ui.write(sep + before)
1716 ui.write(sep + before)
1717 ui.write(match, label='grep.match')
1717 ui.write(match, label='grep.match')
1718 ui.write(after)
1718 ui.write(after)
1719 ui.write(eol)
1719 ui.write(eol)
1720 found = True
1720 found = True
1721 return found
1721 return found
1722
1722
1723 skip = {}
1723 skip = {}
1724 revfiles = {}
1724 revfiles = {}
1725 matchfn = cmdutil.match(repo, pats, opts)
1725 matchfn = cmdutil.match(repo, pats, opts)
1726 found = False
1726 found = False
1727 follow = opts.get('follow')
1727 follow = opts.get('follow')
1728
1728
1729 def prep(ctx, fns):
1729 def prep(ctx, fns):
1730 rev = ctx.rev()
1730 rev = ctx.rev()
1731 pctx = ctx.parents()[0]
1731 pctx = ctx.parents()[0]
1732 parent = pctx.rev()
1732 parent = pctx.rev()
1733 matches.setdefault(rev, {})
1733 matches.setdefault(rev, {})
1734 matches.setdefault(parent, {})
1734 matches.setdefault(parent, {})
1735 files = revfiles.setdefault(rev, [])
1735 files = revfiles.setdefault(rev, [])
1736 for fn in fns:
1736 for fn in fns:
1737 flog = getfile(fn)
1737 flog = getfile(fn)
1738 try:
1738 try:
1739 fnode = ctx.filenode(fn)
1739 fnode = ctx.filenode(fn)
1740 except error.LookupError:
1740 except error.LookupError:
1741 continue
1741 continue
1742
1742
1743 copied = flog.renamed(fnode)
1743 copied = flog.renamed(fnode)
1744 copy = follow and copied and copied[0]
1744 copy = follow and copied and copied[0]
1745 if copy:
1745 if copy:
1746 copies.setdefault(rev, {})[fn] = copy
1746 copies.setdefault(rev, {})[fn] = copy
1747 if fn in skip:
1747 if fn in skip:
1748 if copy:
1748 if copy:
1749 skip[copy] = True
1749 skip[copy] = True
1750 continue
1750 continue
1751 files.append(fn)
1751 files.append(fn)
1752
1752
1753 if fn not in matches[rev]:
1753 if fn not in matches[rev]:
1754 grepbody(fn, rev, flog.read(fnode))
1754 grepbody(fn, rev, flog.read(fnode))
1755
1755
1756 pfn = copy or fn
1756 pfn = copy or fn
1757 if pfn not in matches[parent]:
1757 if pfn not in matches[parent]:
1758 try:
1758 try:
1759 fnode = pctx.filenode(pfn)
1759 fnode = pctx.filenode(pfn)
1760 grepbody(pfn, parent, flog.read(fnode))
1760 grepbody(pfn, parent, flog.read(fnode))
1761 except error.LookupError:
1761 except error.LookupError:
1762 pass
1762 pass
1763
1763
1764 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
1764 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
1765 rev = ctx.rev()
1765 rev = ctx.rev()
1766 parent = ctx.parents()[0].rev()
1766 parent = ctx.parents()[0].rev()
1767 for fn in sorted(revfiles.get(rev, [])):
1767 for fn in sorted(revfiles.get(rev, [])):
1768 states = matches[rev][fn]
1768 states = matches[rev][fn]
1769 copy = copies.get(rev, {}).get(fn)
1769 copy = copies.get(rev, {}).get(fn)
1770 if fn in skip:
1770 if fn in skip:
1771 if copy:
1771 if copy:
1772 skip[copy] = True
1772 skip[copy] = True
1773 continue
1773 continue
1774 pstates = matches.get(parent, {}).get(copy or fn, [])
1774 pstates = matches.get(parent, {}).get(copy or fn, [])
1775 if pstates or states:
1775 if pstates or states:
1776 r = display(fn, ctx, pstates, states)
1776 r = display(fn, ctx, pstates, states)
1777 found = found or r
1777 found = found or r
1778 if r and not opts.get('all'):
1778 if r and not opts.get('all'):
1779 skip[fn] = True
1779 skip[fn] = True
1780 if copy:
1780 if copy:
1781 skip[copy] = True
1781 skip[copy] = True
1782 del matches[rev]
1782 del matches[rev]
1783 del revfiles[rev]
1783 del revfiles[rev]
1784
1784
1785 return not found
1785 return not found
1786
1786
1787 def heads(ui, repo, *branchrevs, **opts):
1787 def heads(ui, repo, *branchrevs, **opts):
1788 """show current repository heads or show branch heads
1788 """show current repository heads or show branch heads
1789
1789
1790 With no arguments, show all repository branch heads.
1790 With no arguments, show all repository branch heads.
1791
1791
1792 Repository "heads" are changesets with no child changesets. They are
1792 Repository "heads" are changesets with no child changesets. They are
1793 where development generally takes place and are the usual targets
1793 where development generally takes place and are the usual targets
1794 for update and merge operations. Branch heads are changesets that have
1794 for update and merge operations. Branch heads are changesets that have
1795 no child changeset on the same branch.
1795 no child changeset on the same branch.
1796
1796
1797 If one or more REVs are given, only branch heads on the branches
1797 If one or more REVs are given, only branch heads on the branches
1798 associated with the specified changesets are shown.
1798 associated with the specified changesets are shown.
1799
1799
1800 If -c/--closed is specified, also show branch heads marked closed
1800 If -c/--closed is specified, also show branch heads marked closed
1801 (see :hg:`commit --close-branch`).
1801 (see :hg:`commit --close-branch`).
1802
1802
1803 If STARTREV is specified, only those heads that are descendants of
1803 If STARTREV is specified, only those heads that are descendants of
1804 STARTREV will be displayed.
1804 STARTREV will be displayed.
1805
1805
1806 If -t/--topo is specified, named branch mechanics will be ignored and only
1806 If -t/--topo is specified, named branch mechanics will be ignored and only
1807 changesets without children will be shown.
1807 changesets without children will be shown.
1808
1808
1809 Returns 0 if matching heads are found, 1 if not.
1809 Returns 0 if matching heads are found, 1 if not.
1810 """
1810 """
1811
1811
1812 start = None
1812 start = None
1813 if 'rev' in opts:
1813 if 'rev' in opts:
1814 start = cmdutil.revsingle(repo, opts['rev'], None).node()
1814 start = cmdutil.revsingle(repo, opts['rev'], None).node()
1815
1815
1816 if opts.get('topo'):
1816 if opts.get('topo'):
1817 heads = [repo[h] for h in repo.heads(start)]
1817 heads = [repo[h] for h in repo.heads(start)]
1818 else:
1818 else:
1819 heads = []
1819 heads = []
1820 for b, ls in repo.branchmap().iteritems():
1820 for b, ls in repo.branchmap().iteritems():
1821 if start is None:
1821 if start is None:
1822 heads += [repo[h] for h in ls]
1822 heads += [repo[h] for h in ls]
1823 continue
1823 continue
1824 startrev = repo.changelog.rev(start)
1824 startrev = repo.changelog.rev(start)
1825 descendants = set(repo.changelog.descendants(startrev))
1825 descendants = set(repo.changelog.descendants(startrev))
1826 descendants.add(startrev)
1826 descendants.add(startrev)
1827 rev = repo.changelog.rev
1827 rev = repo.changelog.rev
1828 heads += [repo[h] for h in ls if rev(h) in descendants]
1828 heads += [repo[h] for h in ls if rev(h) in descendants]
1829
1829
1830 if branchrevs:
1830 if branchrevs:
1831 branches = set(repo[br].branch() for br in branchrevs)
1831 branches = set(repo[br].branch() for br in branchrevs)
1832 heads = [h for h in heads if h.branch() in branches]
1832 heads = [h for h in heads if h.branch() in branches]
1833
1833
1834 if not opts.get('closed'):
1834 if not opts.get('closed'):
1835 heads = [h for h in heads if not h.extra().get('close')]
1835 heads = [h for h in heads if not h.extra().get('close')]
1836
1836
1837 if opts.get('active') and branchrevs:
1837 if opts.get('active') and branchrevs:
1838 dagheads = repo.heads(start)
1838 dagheads = repo.heads(start)
1839 heads = [h for h in heads if h.node() in dagheads]
1839 heads = [h for h in heads if h.node() in dagheads]
1840
1840
1841 if branchrevs:
1841 if branchrevs:
1842 haveheads = set(h.branch() for h in heads)
1842 haveheads = set(h.branch() for h in heads)
1843 if branches - haveheads:
1843 if branches - haveheads:
1844 headless = ', '.join(b for b in branches - haveheads)
1844 headless = ', '.join(b for b in branches - haveheads)
1845 msg = _('no open branch heads found on branches %s')
1845 msg = _('no open branch heads found on branches %s')
1846 if opts.get('rev'):
1846 if opts.get('rev'):
1847 msg += _(' (started at %s)' % opts['rev'])
1847 msg += _(' (started at %s)' % opts['rev'])
1848 ui.warn((msg + '\n') % headless)
1848 ui.warn((msg + '\n') % headless)
1849
1849
1850 if not heads:
1850 if not heads:
1851 return 1
1851 return 1
1852
1852
1853 heads = sorted(heads, key=lambda x: -x.rev())
1853 heads = sorted(heads, key=lambda x: -x.rev())
1854 displayer = cmdutil.show_changeset(ui, repo, opts)
1854 displayer = cmdutil.show_changeset(ui, repo, opts)
1855 for ctx in heads:
1855 for ctx in heads:
1856 displayer.show(ctx)
1856 displayer.show(ctx)
1857 displayer.close()
1857 displayer.close()
1858
1858
1859 def help_(ui, name=None, with_version=False, unknowncmd=False):
1859 def help_(ui, name=None, with_version=False, unknowncmd=False):
1860 """show help for a given topic or a help overview
1860 """show help for a given topic or a help overview
1861
1861
1862 With no arguments, print a list of commands with short help messages.
1862 With no arguments, print a list of commands with short help messages.
1863
1863
1864 Given a topic, extension, or command name, print help for that
1864 Given a topic, extension, or command name, print help for that
1865 topic.
1865 topic.
1866
1866
1867 Returns 0 if successful.
1867 Returns 0 if successful.
1868 """
1868 """
1869 option_lists = []
1869 option_lists = []
1870 textwidth = ui.termwidth() - 2
1870 textwidth = ui.termwidth() - 2
1871
1871
1872 def addglobalopts(aliases):
1872 def addglobalopts(aliases):
1873 if ui.verbose:
1873 if ui.verbose:
1874 option_lists.append((_("global options:"), globalopts))
1874 option_lists.append((_("global options:"), globalopts))
1875 if name == 'shortlist':
1875 if name == 'shortlist':
1876 option_lists.append((_('use "hg help" for the full list '
1876 option_lists.append((_('use "hg help" for the full list '
1877 'of commands'), ()))
1877 'of commands'), ()))
1878 else:
1878 else:
1879 if name == 'shortlist':
1879 if name == 'shortlist':
1880 msg = _('use "hg help" for the full list of commands '
1880 msg = _('use "hg help" for the full list of commands '
1881 'or "hg -v" for details')
1881 'or "hg -v" for details')
1882 elif aliases:
1882 elif aliases:
1883 msg = _('use "hg -v help%s" to show aliases and '
1883 msg = _('use "hg -v help%s" to show builtin aliases and '
1884 'global options') % (name and " " + name or "")
1884 'global options') % (name and " " + name or "")
1885 else:
1885 else:
1886 msg = _('use "hg -v help %s" to show global options') % name
1886 msg = _('use "hg -v help %s" to show global options') % name
1887 option_lists.append((msg, ()))
1887 option_lists.append((msg, ()))
1888
1888
1889 def helpcmd(name):
1889 def helpcmd(name):
1890 if with_version:
1890 if with_version:
1891 version_(ui)
1891 version_(ui)
1892 ui.write('\n')
1892 ui.write('\n')
1893
1893
1894 try:
1894 try:
1895 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
1895 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
1896 except error.AmbiguousCommand, inst:
1896 except error.AmbiguousCommand, inst:
1897 # py3k fix: except vars can't be used outside the scope of the
1897 # py3k fix: except vars can't be used outside the scope of the
1898 # except block, nor can be used inside a lambda. python issue4617
1898 # except block, nor can be used inside a lambda. python issue4617
1899 prefix = inst.args[0]
1899 prefix = inst.args[0]
1900 select = lambda c: c.lstrip('^').startswith(prefix)
1900 select = lambda c: c.lstrip('^').startswith(prefix)
1901 helplist(_('list of commands:\n\n'), select)
1901 helplist(_('list of commands:\n\n'), select)
1902 return
1902 return
1903
1903
1904 # check if it's an invalid alias and display its error if it is
1904 # check if it's an invalid alias and display its error if it is
1905 if getattr(entry[0], 'badalias', False):
1905 if getattr(entry[0], 'badalias', False):
1906 if not unknowncmd:
1906 if not unknowncmd:
1907 entry[0](ui)
1907 entry[0](ui)
1908 return
1908 return
1909
1909
1910 # synopsis
1910 # synopsis
1911 if len(entry) > 2:
1911 if len(entry) > 2:
1912 if entry[2].startswith('hg'):
1912 if entry[2].startswith('hg'):
1913 ui.write("%s\n" % entry[2])
1913 ui.write("%s\n" % entry[2])
1914 else:
1914 else:
1915 ui.write('hg %s %s\n' % (aliases[0], entry[2]))
1915 ui.write('hg %s %s\n' % (aliases[0], entry[2]))
1916 else:
1916 else:
1917 ui.write('hg %s\n' % aliases[0])
1917 ui.write('hg %s\n' % aliases[0])
1918
1918
1919 # aliases
1919 # aliases
1920 if not ui.quiet and len(aliases) > 1:
1920 if not ui.quiet and len(aliases) > 1:
1921 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
1921 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
1922
1922
1923 # description
1923 # description
1924 doc = gettext(entry[0].__doc__)
1924 doc = gettext(entry[0].__doc__)
1925 if not doc:
1925 if not doc:
1926 doc = _("(no help text available)")
1926 doc = _("(no help text available)")
1927 if hasattr(entry[0], 'definition'): # aliased command
1927 if hasattr(entry[0], 'definition'): # aliased command
1928 if entry[0].definition.startswith('!'): # shell alias
1928 if entry[0].definition.startswith('!'): # shell alias
1929 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
1929 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
1930 else:
1930 else:
1931 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
1931 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
1932 if ui.quiet:
1932 if ui.quiet:
1933 doc = doc.splitlines()[0]
1933 doc = doc.splitlines()[0]
1934 keep = ui.verbose and ['verbose'] or []
1934 keep = ui.verbose and ['verbose'] or []
1935 formatted, pruned = minirst.format(doc, textwidth, keep=keep)
1935 formatted, pruned = minirst.format(doc, textwidth, keep=keep)
1936 ui.write("\n%s\n" % formatted)
1936 ui.write("\n%s\n" % formatted)
1937 if pruned:
1937 if pruned:
1938 ui.write(_('\nuse "hg -v help %s" to show verbose help\n') % name)
1938 ui.write(_('\nuse "hg -v help %s" to show verbose help\n') % name)
1939
1939
1940 if not ui.quiet:
1940 if not ui.quiet:
1941 # options
1941 # options
1942 if entry[1]:
1942 if entry[1]:
1943 option_lists.append((_("options:\n"), entry[1]))
1943 option_lists.append((_("options:\n"), entry[1]))
1944
1944
1945 addglobalopts(False)
1945 addglobalopts(False)
1946
1946
1947 def helplist(header, select=None):
1947 def helplist(header, select=None):
1948 h = {}
1948 h = {}
1949 cmds = {}
1949 cmds = {}
1950 for c, e in table.iteritems():
1950 for c, e in table.iteritems():
1951 f = c.split("|", 1)[0]
1951 f = c.split("|", 1)[0]
1952 if select and not select(f):
1952 if select and not select(f):
1953 continue
1953 continue
1954 if (not select and name != 'shortlist' and
1954 if (not select and name != 'shortlist' and
1955 e[0].__module__ != __name__):
1955 e[0].__module__ != __name__):
1956 continue
1956 continue
1957 if name == "shortlist" and not f.startswith("^"):
1957 if name == "shortlist" and not f.startswith("^"):
1958 continue
1958 continue
1959 f = f.lstrip("^")
1959 f = f.lstrip("^")
1960 if not ui.debugflag and f.startswith("debug"):
1960 if not ui.debugflag and f.startswith("debug"):
1961 continue
1961 continue
1962 doc = e[0].__doc__
1962 doc = e[0].__doc__
1963 if doc and 'DEPRECATED' in doc and not ui.verbose:
1963 if doc and 'DEPRECATED' in doc and not ui.verbose:
1964 continue
1964 continue
1965 doc = gettext(doc)
1965 doc = gettext(doc)
1966 if not doc:
1966 if not doc:
1967 doc = _("(no help text available)")
1967 doc = _("(no help text available)")
1968 h[f] = doc.splitlines()[0].rstrip()
1968 h[f] = doc.splitlines()[0].rstrip()
1969 cmds[f] = c.lstrip("^")
1969 cmds[f] = c.lstrip("^")
1970
1970
1971 if not h:
1971 if not h:
1972 ui.status(_('no commands defined\n'))
1972 ui.status(_('no commands defined\n'))
1973 return
1973 return
1974
1974
1975 ui.status(header)
1975 ui.status(header)
1976 fns = sorted(h)
1976 fns = sorted(h)
1977 m = max(map(len, fns))
1977 m = max(map(len, fns))
1978 for f in fns:
1978 for f in fns:
1979 if ui.verbose:
1979 if ui.verbose:
1980 commands = cmds[f].replace("|",", ")
1980 commands = cmds[f].replace("|",", ")
1981 ui.write(" %s:\n %s\n"%(commands, h[f]))
1981 ui.write(" %s:\n %s\n"%(commands, h[f]))
1982 else:
1982 else:
1983 ui.write('%s\n' % (util.wrap(h[f], textwidth,
1983 ui.write('%s\n' % (util.wrap(h[f], textwidth,
1984 initindent=' %-*s ' % (m, f),
1984 initindent=' %-*s ' % (m, f),
1985 hangindent=' ' * (m + 4))))
1985 hangindent=' ' * (m + 4))))
1986
1986
1987 if not ui.quiet:
1987 if not ui.quiet:
1988 addglobalopts(True)
1988 addglobalopts(True)
1989
1989
1990 def helptopic(name):
1990 def helptopic(name):
1991 for names, header, doc in help.helptable:
1991 for names, header, doc in help.helptable:
1992 if name in names:
1992 if name in names:
1993 break
1993 break
1994 else:
1994 else:
1995 raise error.UnknownCommand(name)
1995 raise error.UnknownCommand(name)
1996
1996
1997 # description
1997 # description
1998 if not doc:
1998 if not doc:
1999 doc = _("(no help text available)")
1999 doc = _("(no help text available)")
2000 if hasattr(doc, '__call__'):
2000 if hasattr(doc, '__call__'):
2001 doc = doc()
2001 doc = doc()
2002
2002
2003 ui.write("%s\n\n" % header)
2003 ui.write("%s\n\n" % header)
2004 ui.write("%s\n" % minirst.format(doc, textwidth, indent=4))
2004 ui.write("%s\n" % minirst.format(doc, textwidth, indent=4))
2005
2005
2006 def helpext(name):
2006 def helpext(name):
2007 try:
2007 try:
2008 mod = extensions.find(name)
2008 mod = extensions.find(name)
2009 doc = gettext(mod.__doc__) or _('no help text available')
2009 doc = gettext(mod.__doc__) or _('no help text available')
2010 except KeyError:
2010 except KeyError:
2011 mod = None
2011 mod = None
2012 doc = extensions.disabledext(name)
2012 doc = extensions.disabledext(name)
2013 if not doc:
2013 if not doc:
2014 raise error.UnknownCommand(name)
2014 raise error.UnknownCommand(name)
2015
2015
2016 if '\n' not in doc:
2016 if '\n' not in doc:
2017 head, tail = doc, ""
2017 head, tail = doc, ""
2018 else:
2018 else:
2019 head, tail = doc.split('\n', 1)
2019 head, tail = doc.split('\n', 1)
2020 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
2020 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
2021 if tail:
2021 if tail:
2022 ui.write(minirst.format(tail, textwidth))
2022 ui.write(minirst.format(tail, textwidth))
2023 ui.status('\n\n')
2023 ui.status('\n\n')
2024
2024
2025 if mod:
2025 if mod:
2026 try:
2026 try:
2027 ct = mod.cmdtable
2027 ct = mod.cmdtable
2028 except AttributeError:
2028 except AttributeError:
2029 ct = {}
2029 ct = {}
2030 modcmds = set([c.split('|', 1)[0] for c in ct])
2030 modcmds = set([c.split('|', 1)[0] for c in ct])
2031 helplist(_('list of commands:\n\n'), modcmds.__contains__)
2031 helplist(_('list of commands:\n\n'), modcmds.__contains__)
2032 else:
2032 else:
2033 ui.write(_('use "hg help extensions" for information on enabling '
2033 ui.write(_('use "hg help extensions" for information on enabling '
2034 'extensions\n'))
2034 'extensions\n'))
2035
2035
2036 def helpextcmd(name):
2036 def helpextcmd(name):
2037 cmd, ext, mod = extensions.disabledcmd(ui, name, ui.config('ui', 'strict'))
2037 cmd, ext, mod = extensions.disabledcmd(ui, name, ui.config('ui', 'strict'))
2038 doc = gettext(mod.__doc__).splitlines()[0]
2038 doc = gettext(mod.__doc__).splitlines()[0]
2039
2039
2040 msg = help.listexts(_("'%s' is provided by the following "
2040 msg = help.listexts(_("'%s' is provided by the following "
2041 "extension:") % cmd, {ext: doc}, len(ext),
2041 "extension:") % cmd, {ext: doc}, len(ext),
2042 indent=4)
2042 indent=4)
2043 ui.write(minirst.format(msg, textwidth))
2043 ui.write(minirst.format(msg, textwidth))
2044 ui.write('\n\n')
2044 ui.write('\n\n')
2045 ui.write(_('use "hg help extensions" for information on enabling '
2045 ui.write(_('use "hg help extensions" for information on enabling '
2046 'extensions\n'))
2046 'extensions\n'))
2047
2047
2048 help.addtopichook('revsets', revset.makedoc)
2048 help.addtopichook('revsets', revset.makedoc)
2049
2049
2050 if name and name != 'shortlist':
2050 if name and name != 'shortlist':
2051 i = None
2051 i = None
2052 if unknowncmd:
2052 if unknowncmd:
2053 queries = (helpextcmd,)
2053 queries = (helpextcmd,)
2054 else:
2054 else:
2055 queries = (helptopic, helpcmd, helpext, helpextcmd)
2055 queries = (helptopic, helpcmd, helpext, helpextcmd)
2056 for f in queries:
2056 for f in queries:
2057 try:
2057 try:
2058 f(name)
2058 f(name)
2059 i = None
2059 i = None
2060 break
2060 break
2061 except error.UnknownCommand, inst:
2061 except error.UnknownCommand, inst:
2062 i = inst
2062 i = inst
2063 if i:
2063 if i:
2064 raise i
2064 raise i
2065
2065
2066 else:
2066 else:
2067 # program name
2067 # program name
2068 if ui.verbose or with_version:
2068 if ui.verbose or with_version:
2069 version_(ui)
2069 version_(ui)
2070 else:
2070 else:
2071 ui.status(_("Mercurial Distributed SCM\n"))
2071 ui.status(_("Mercurial Distributed SCM\n"))
2072 ui.status('\n')
2072 ui.status('\n')
2073
2073
2074 # list of commands
2074 # list of commands
2075 if name == "shortlist":
2075 if name == "shortlist":
2076 header = _('basic commands:\n\n')
2076 header = _('basic commands:\n\n')
2077 else:
2077 else:
2078 header = _('list of commands:\n\n')
2078 header = _('list of commands:\n\n')
2079
2079
2080 helplist(header)
2080 helplist(header)
2081 if name != 'shortlist':
2081 if name != 'shortlist':
2082 exts, maxlength = extensions.enabled()
2082 exts, maxlength = extensions.enabled()
2083 text = help.listexts(_('enabled extensions:'), exts, maxlength)
2083 text = help.listexts(_('enabled extensions:'), exts, maxlength)
2084 if text:
2084 if text:
2085 ui.write("\n%s\n" % minirst.format(text, textwidth))
2085 ui.write("\n%s\n" % minirst.format(text, textwidth))
2086
2086
2087 # list all option lists
2087 # list all option lists
2088 opt_output = []
2088 opt_output = []
2089 multioccur = False
2089 multioccur = False
2090 for title, options in option_lists:
2090 for title, options in option_lists:
2091 opt_output.append(("\n%s" % title, None))
2091 opt_output.append(("\n%s" % title, None))
2092 for option in options:
2092 for option in options:
2093 if len(option) == 5:
2093 if len(option) == 5:
2094 shortopt, longopt, default, desc, optlabel = option
2094 shortopt, longopt, default, desc, optlabel = option
2095 else:
2095 else:
2096 shortopt, longopt, default, desc = option
2096 shortopt, longopt, default, desc = option
2097 optlabel = _("VALUE") # default label
2097 optlabel = _("VALUE") # default label
2098
2098
2099 if _("DEPRECATED") in desc and not ui.verbose:
2099 if _("DEPRECATED") in desc and not ui.verbose:
2100 continue
2100 continue
2101 if isinstance(default, list):
2101 if isinstance(default, list):
2102 numqualifier = " %s [+]" % optlabel
2102 numqualifier = " %s [+]" % optlabel
2103 multioccur = True
2103 multioccur = True
2104 elif (default is not None) and not isinstance(default, bool):
2104 elif (default is not None) and not isinstance(default, bool):
2105 numqualifier = " %s" % optlabel
2105 numqualifier = " %s" % optlabel
2106 else:
2106 else:
2107 numqualifier = ""
2107 numqualifier = ""
2108 opt_output.append(("%2s%s" %
2108 opt_output.append(("%2s%s" %
2109 (shortopt and "-%s" % shortopt,
2109 (shortopt and "-%s" % shortopt,
2110 longopt and " --%s%s" %
2110 longopt and " --%s%s" %
2111 (longopt, numqualifier)),
2111 (longopt, numqualifier)),
2112 "%s%s" % (desc,
2112 "%s%s" % (desc,
2113 default
2113 default
2114 and _(" (default: %s)") % default
2114 and _(" (default: %s)") % default
2115 or "")))
2115 or "")))
2116 if multioccur:
2116 if multioccur:
2117 msg = _("\n[+] marked option can be specified multiple times")
2117 msg = _("\n[+] marked option can be specified multiple times")
2118 if ui.verbose and name != 'shortlist':
2118 if ui.verbose and name != 'shortlist':
2119 opt_output.append((msg, None))
2119 opt_output.append((msg, None))
2120 else:
2120 else:
2121 opt_output.insert(-1, (msg, None))
2121 opt_output.insert(-1, (msg, None))
2122
2122
2123 if not name:
2123 if not name:
2124 ui.write(_("\nadditional help topics:\n\n"))
2124 ui.write(_("\nadditional help topics:\n\n"))
2125 topics = []
2125 topics = []
2126 for names, header, doc in help.helptable:
2126 for names, header, doc in help.helptable:
2127 topics.append((sorted(names, key=len, reverse=True)[0], header))
2127 topics.append((sorted(names, key=len, reverse=True)[0], header))
2128 topics_len = max([len(s[0]) for s in topics])
2128 topics_len = max([len(s[0]) for s in topics])
2129 for t, desc in topics:
2129 for t, desc in topics:
2130 ui.write(" %-*s %s\n" % (topics_len, t, desc))
2130 ui.write(" %-*s %s\n" % (topics_len, t, desc))
2131
2131
2132 if opt_output:
2132 if opt_output:
2133 colwidth = encoding.colwidth
2133 colwidth = encoding.colwidth
2134 # normalize: (opt or message, desc or None, width of opt)
2134 # normalize: (opt or message, desc or None, width of opt)
2135 entries = [desc and (opt, desc, colwidth(opt)) or (opt, None, 0)
2135 entries = [desc and (opt, desc, colwidth(opt)) or (opt, None, 0)
2136 for opt, desc in opt_output]
2136 for opt, desc in opt_output]
2137 hanging = max([e[2] for e in entries])
2137 hanging = max([e[2] for e in entries])
2138 for opt, desc, width in entries:
2138 for opt, desc, width in entries:
2139 if desc:
2139 if desc:
2140 initindent = ' %s%s ' % (opt, ' ' * (hanging - width))
2140 initindent = ' %s%s ' % (opt, ' ' * (hanging - width))
2141 hangindent = ' ' * (hanging + 3)
2141 hangindent = ' ' * (hanging + 3)
2142 ui.write('%s\n' % (util.wrap(desc, textwidth,
2142 ui.write('%s\n' % (util.wrap(desc, textwidth,
2143 initindent=initindent,
2143 initindent=initindent,
2144 hangindent=hangindent)))
2144 hangindent=hangindent)))
2145 else:
2145 else:
2146 ui.write("%s\n" % opt)
2146 ui.write("%s\n" % opt)
2147
2147
2148 def identify(ui, repo, source=None,
2148 def identify(ui, repo, source=None,
2149 rev=None, num=None, id=None, branch=None, tags=None):
2149 rev=None, num=None, id=None, branch=None, tags=None):
2150 """identify the working copy or specified revision
2150 """identify the working copy or specified revision
2151
2151
2152 With no revision, print a summary of the current state of the
2152 With no revision, print a summary of the current state of the
2153 repository.
2153 repository.
2154
2154
2155 Specifying a path to a repository root or Mercurial bundle will
2155 Specifying a path to a repository root or Mercurial bundle will
2156 cause lookup to operate on that repository/bundle.
2156 cause lookup to operate on that repository/bundle.
2157
2157
2158 This summary identifies the repository state using one or two
2158 This summary identifies the repository state using one or two
2159 parent hash identifiers, followed by a "+" if there are
2159 parent hash identifiers, followed by a "+" if there are
2160 uncommitted changes in the working directory, a list of tags for
2160 uncommitted changes in the working directory, a list of tags for
2161 this revision and a branch name for non-default branches.
2161 this revision and a branch name for non-default branches.
2162
2162
2163 Returns 0 if successful.
2163 Returns 0 if successful.
2164 """
2164 """
2165
2165
2166 if not repo and not source:
2166 if not repo and not source:
2167 raise util.Abort(_("there is no Mercurial repository here "
2167 raise util.Abort(_("there is no Mercurial repository here "
2168 "(.hg not found)"))
2168 "(.hg not found)"))
2169
2169
2170 hexfunc = ui.debugflag and hex or short
2170 hexfunc = ui.debugflag and hex or short
2171 default = not (num or id or branch or tags)
2171 default = not (num or id or branch or tags)
2172 output = []
2172 output = []
2173
2173
2174 revs = []
2174 revs = []
2175 if source:
2175 if source:
2176 source, branches = hg.parseurl(ui.expandpath(source))
2176 source, branches = hg.parseurl(ui.expandpath(source))
2177 repo = hg.repository(ui, source)
2177 repo = hg.repository(ui, source)
2178 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
2178 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
2179
2179
2180 if not repo.local():
2180 if not repo.local():
2181 if not rev and revs:
2181 if not rev and revs:
2182 rev = revs[0]
2182 rev = revs[0]
2183 if not rev:
2183 if not rev:
2184 rev = "tip"
2184 rev = "tip"
2185 if num or branch or tags:
2185 if num or branch or tags:
2186 raise util.Abort(
2186 raise util.Abort(
2187 "can't query remote revision number, branch, or tags")
2187 "can't query remote revision number, branch, or tags")
2188 output = [hexfunc(repo.lookup(rev))]
2188 output = [hexfunc(repo.lookup(rev))]
2189 elif not rev:
2189 elif not rev:
2190 ctx = repo[None]
2190 ctx = repo[None]
2191 parents = ctx.parents()
2191 parents = ctx.parents()
2192 changed = False
2192 changed = False
2193 if default or id or num:
2193 if default or id or num:
2194 changed = util.any(repo.status())
2194 changed = util.any(repo.status())
2195 if default or id:
2195 if default or id:
2196 output = ["%s%s" % ('+'.join([hexfunc(p.node()) for p in parents]),
2196 output = ["%s%s" % ('+'.join([hexfunc(p.node()) for p in parents]),
2197 (changed) and "+" or "")]
2197 (changed) and "+" or "")]
2198 if num:
2198 if num:
2199 output.append("%s%s" % ('+'.join([str(p.rev()) for p in parents]),
2199 output.append("%s%s" % ('+'.join([str(p.rev()) for p in parents]),
2200 (changed) and "+" or ""))
2200 (changed) and "+" or ""))
2201 else:
2201 else:
2202 ctx = cmdutil.revsingle(repo, rev)
2202 ctx = cmdutil.revsingle(repo, rev)
2203 if default or id:
2203 if default or id:
2204 output = [hexfunc(ctx.node())]
2204 output = [hexfunc(ctx.node())]
2205 if num:
2205 if num:
2206 output.append(str(ctx.rev()))
2206 output.append(str(ctx.rev()))
2207
2207
2208 if repo.local() and default and not ui.quiet:
2208 if repo.local() and default and not ui.quiet:
2209 b = ctx.branch()
2209 b = ctx.branch()
2210 if b != 'default':
2210 if b != 'default':
2211 output.append("(%s)" % b)
2211 output.append("(%s)" % b)
2212
2212
2213 # multiple tags for a single parent separated by '/'
2213 # multiple tags for a single parent separated by '/'
2214 t = "/".join(ctx.tags())
2214 t = "/".join(ctx.tags())
2215 if t:
2215 if t:
2216 output.append(t)
2216 output.append(t)
2217
2217
2218 if branch:
2218 if branch:
2219 output.append(ctx.branch())
2219 output.append(ctx.branch())
2220
2220
2221 if tags:
2221 if tags:
2222 output.extend(ctx.tags())
2222 output.extend(ctx.tags())
2223
2223
2224 ui.write("%s\n" % ' '.join(output))
2224 ui.write("%s\n" % ' '.join(output))
2225
2225
2226 def import_(ui, repo, patch1, *patches, **opts):
2226 def import_(ui, repo, patch1, *patches, **opts):
2227 """import an ordered set of patches
2227 """import an ordered set of patches
2228
2228
2229 Import a list of patches and commit them individually (unless
2229 Import a list of patches and commit them individually (unless
2230 --no-commit is specified).
2230 --no-commit is specified).
2231
2231
2232 If there are outstanding changes in the working directory, import
2232 If there are outstanding changes in the working directory, import
2233 will abort unless given the -f/--force flag.
2233 will abort unless given the -f/--force flag.
2234
2234
2235 You can import a patch straight from a mail message. Even patches
2235 You can import a patch straight from a mail message. Even patches
2236 as attachments work (to use the body part, it must have type
2236 as attachments work (to use the body part, it must have type
2237 text/plain or text/x-patch). From and Subject headers of email
2237 text/plain or text/x-patch). From and Subject headers of email
2238 message are used as default committer and commit message. All
2238 message are used as default committer and commit message. All
2239 text/plain body parts before first diff are added to commit
2239 text/plain body parts before first diff are added to commit
2240 message.
2240 message.
2241
2241
2242 If the imported patch was generated by :hg:`export`, user and
2242 If the imported patch was generated by :hg:`export`, user and
2243 description from patch override values from message headers and
2243 description from patch override values from message headers and
2244 body. Values given on command line with -m/--message and -u/--user
2244 body. Values given on command line with -m/--message and -u/--user
2245 override these.
2245 override these.
2246
2246
2247 If --exact is specified, import will set the working directory to
2247 If --exact is specified, import will set the working directory to
2248 the parent of each patch before applying it, and will abort if the
2248 the parent of each patch before applying it, and will abort if the
2249 resulting changeset has a different ID than the one recorded in
2249 resulting changeset has a different ID than the one recorded in
2250 the patch. This may happen due to character set problems or other
2250 the patch. This may happen due to character set problems or other
2251 deficiencies in the text patch format.
2251 deficiencies in the text patch format.
2252
2252
2253 With -s/--similarity, hg will attempt to discover renames and
2253 With -s/--similarity, hg will attempt to discover renames and
2254 copies in the patch in the same way as 'addremove'.
2254 copies in the patch in the same way as 'addremove'.
2255
2255
2256 To read a patch from standard input, use "-" as the patch name. If
2256 To read a patch from standard input, use "-" as the patch name. If
2257 a URL is specified, the patch will be downloaded from it.
2257 a URL is specified, the patch will be downloaded from it.
2258 See :hg:`help dates` for a list of formats valid for -d/--date.
2258 See :hg:`help dates` for a list of formats valid for -d/--date.
2259
2259
2260 Returns 0 on success.
2260 Returns 0 on success.
2261 """
2261 """
2262 patches = (patch1,) + patches
2262 patches = (patch1,) + patches
2263
2263
2264 date = opts.get('date')
2264 date = opts.get('date')
2265 if date:
2265 if date:
2266 opts['date'] = util.parsedate(date)
2266 opts['date'] = util.parsedate(date)
2267
2267
2268 try:
2268 try:
2269 sim = float(opts.get('similarity') or 0)
2269 sim = float(opts.get('similarity') or 0)
2270 except ValueError:
2270 except ValueError:
2271 raise util.Abort(_('similarity must be a number'))
2271 raise util.Abort(_('similarity must be a number'))
2272 if sim < 0 or sim > 100:
2272 if sim < 0 or sim > 100:
2273 raise util.Abort(_('similarity must be between 0 and 100'))
2273 raise util.Abort(_('similarity must be between 0 and 100'))
2274
2274
2275 if opts.get('exact') or not opts.get('force'):
2275 if opts.get('exact') or not opts.get('force'):
2276 cmdutil.bail_if_changed(repo)
2276 cmdutil.bail_if_changed(repo)
2277
2277
2278 d = opts["base"]
2278 d = opts["base"]
2279 strip = opts["strip"]
2279 strip = opts["strip"]
2280 wlock = lock = None
2280 wlock = lock = None
2281 msgs = []
2281 msgs = []
2282
2282
2283 def tryone(ui, hunk):
2283 def tryone(ui, hunk):
2284 tmpname, message, user, date, branch, nodeid, p1, p2 = \
2284 tmpname, message, user, date, branch, nodeid, p1, p2 = \
2285 patch.extract(ui, hunk)
2285 patch.extract(ui, hunk)
2286
2286
2287 if not tmpname:
2287 if not tmpname:
2288 return None
2288 return None
2289 commitid = _('to working directory')
2289 commitid = _('to working directory')
2290
2290
2291 try:
2291 try:
2292 cmdline_message = cmdutil.logmessage(opts)
2292 cmdline_message = cmdutil.logmessage(opts)
2293 if cmdline_message:
2293 if cmdline_message:
2294 # pickup the cmdline msg
2294 # pickup the cmdline msg
2295 message = cmdline_message
2295 message = cmdline_message
2296 elif message:
2296 elif message:
2297 # pickup the patch msg
2297 # pickup the patch msg
2298 message = message.strip()
2298 message = message.strip()
2299 else:
2299 else:
2300 # launch the editor
2300 # launch the editor
2301 message = None
2301 message = None
2302 ui.debug('message:\n%s\n' % message)
2302 ui.debug('message:\n%s\n' % message)
2303
2303
2304 wp = repo.parents()
2304 wp = repo.parents()
2305 if opts.get('exact'):
2305 if opts.get('exact'):
2306 if not nodeid or not p1:
2306 if not nodeid or not p1:
2307 raise util.Abort(_('not a Mercurial patch'))
2307 raise util.Abort(_('not a Mercurial patch'))
2308 p1 = repo.lookup(p1)
2308 p1 = repo.lookup(p1)
2309 p2 = repo.lookup(p2 or hex(nullid))
2309 p2 = repo.lookup(p2 or hex(nullid))
2310
2310
2311 if p1 != wp[0].node():
2311 if p1 != wp[0].node():
2312 hg.clean(repo, p1)
2312 hg.clean(repo, p1)
2313 repo.dirstate.setparents(p1, p2)
2313 repo.dirstate.setparents(p1, p2)
2314 elif p2:
2314 elif p2:
2315 try:
2315 try:
2316 p1 = repo.lookup(p1)
2316 p1 = repo.lookup(p1)
2317 p2 = repo.lookup(p2)
2317 p2 = repo.lookup(p2)
2318 if p1 == wp[0].node():
2318 if p1 == wp[0].node():
2319 repo.dirstate.setparents(p1, p2)
2319 repo.dirstate.setparents(p1, p2)
2320 except error.RepoError:
2320 except error.RepoError:
2321 pass
2321 pass
2322 if opts.get('exact') or opts.get('import_branch'):
2322 if opts.get('exact') or opts.get('import_branch'):
2323 repo.dirstate.setbranch(branch or 'default')
2323 repo.dirstate.setbranch(branch or 'default')
2324
2324
2325 files = {}
2325 files = {}
2326 try:
2326 try:
2327 patch.patch(tmpname, ui, strip=strip, cwd=repo.root,
2327 patch.patch(tmpname, ui, strip=strip, cwd=repo.root,
2328 files=files, eolmode=None)
2328 files=files, eolmode=None)
2329 finally:
2329 finally:
2330 files = cmdutil.updatedir(ui, repo, files,
2330 files = cmdutil.updatedir(ui, repo, files,
2331 similarity=sim / 100.0)
2331 similarity=sim / 100.0)
2332 if opts.get('no_commit'):
2332 if opts.get('no_commit'):
2333 if message:
2333 if message:
2334 msgs.append(message)
2334 msgs.append(message)
2335 else:
2335 else:
2336 if opts.get('exact'):
2336 if opts.get('exact'):
2337 m = None
2337 m = None
2338 else:
2338 else:
2339 m = cmdutil.matchfiles(repo, files or [])
2339 m = cmdutil.matchfiles(repo, files or [])
2340 n = repo.commit(message, opts.get('user') or user,
2340 n = repo.commit(message, opts.get('user') or user,
2341 opts.get('date') or date, match=m,
2341 opts.get('date') or date, match=m,
2342 editor=cmdutil.commiteditor)
2342 editor=cmdutil.commiteditor)
2343 if opts.get('exact'):
2343 if opts.get('exact'):
2344 if hex(n) != nodeid:
2344 if hex(n) != nodeid:
2345 repo.rollback()
2345 repo.rollback()
2346 raise util.Abort(_('patch is damaged'
2346 raise util.Abort(_('patch is damaged'
2347 ' or loses information'))
2347 ' or loses information'))
2348 # Force a dirstate write so that the next transaction
2348 # Force a dirstate write so that the next transaction
2349 # backups an up-do-date file.
2349 # backups an up-do-date file.
2350 repo.dirstate.write()
2350 repo.dirstate.write()
2351 if n:
2351 if n:
2352 commitid = short(n)
2352 commitid = short(n)
2353
2353
2354 return commitid
2354 return commitid
2355 finally:
2355 finally:
2356 os.unlink(tmpname)
2356 os.unlink(tmpname)
2357
2357
2358 try:
2358 try:
2359 wlock = repo.wlock()
2359 wlock = repo.wlock()
2360 lock = repo.lock()
2360 lock = repo.lock()
2361 lastcommit = None
2361 lastcommit = None
2362 for p in patches:
2362 for p in patches:
2363 pf = os.path.join(d, p)
2363 pf = os.path.join(d, p)
2364
2364
2365 if pf == '-':
2365 if pf == '-':
2366 ui.status(_("applying patch from stdin\n"))
2366 ui.status(_("applying patch from stdin\n"))
2367 pf = sys.stdin
2367 pf = sys.stdin
2368 else:
2368 else:
2369 ui.status(_("applying %s\n") % p)
2369 ui.status(_("applying %s\n") % p)
2370 pf = url.open(ui, pf)
2370 pf = url.open(ui, pf)
2371
2371
2372 haspatch = False
2372 haspatch = False
2373 for hunk in patch.split(pf):
2373 for hunk in patch.split(pf):
2374 commitid = tryone(ui, hunk)
2374 commitid = tryone(ui, hunk)
2375 if commitid:
2375 if commitid:
2376 haspatch = True
2376 haspatch = True
2377 if lastcommit:
2377 if lastcommit:
2378 ui.status(_('applied %s\n') % lastcommit)
2378 ui.status(_('applied %s\n') % lastcommit)
2379 lastcommit = commitid
2379 lastcommit = commitid
2380
2380
2381 if not haspatch:
2381 if not haspatch:
2382 raise util.Abort(_('no diffs found'))
2382 raise util.Abort(_('no diffs found'))
2383
2383
2384 if msgs:
2384 if msgs:
2385 repo.opener('last-message.txt', 'wb').write('\n* * *\n'.join(msgs))
2385 repo.opener('last-message.txt', 'wb').write('\n* * *\n'.join(msgs))
2386 finally:
2386 finally:
2387 release(lock, wlock)
2387 release(lock, wlock)
2388
2388
2389 def incoming(ui, repo, source="default", **opts):
2389 def incoming(ui, repo, source="default", **opts):
2390 """show new changesets found in source
2390 """show new changesets found in source
2391
2391
2392 Show new changesets found in the specified path/URL or the default
2392 Show new changesets found in the specified path/URL or the default
2393 pull location. These are the changesets that would have been pulled
2393 pull location. These are the changesets that would have been pulled
2394 if a pull at the time you issued this command.
2394 if a pull at the time you issued this command.
2395
2395
2396 For remote repository, using --bundle avoids downloading the
2396 For remote repository, using --bundle avoids downloading the
2397 changesets twice if the incoming is followed by a pull.
2397 changesets twice if the incoming is followed by a pull.
2398
2398
2399 See pull for valid source format details.
2399 See pull for valid source format details.
2400
2400
2401 Returns 0 if there are incoming changes, 1 otherwise.
2401 Returns 0 if there are incoming changes, 1 otherwise.
2402 """
2402 """
2403 if opts.get('bundle') and opts.get('subrepos'):
2403 if opts.get('bundle') and opts.get('subrepos'):
2404 raise util.Abort(_('cannot combine --bundle and --subrepos'))
2404 raise util.Abort(_('cannot combine --bundle and --subrepos'))
2405
2405
2406 ret = hg.incoming(ui, repo, source, opts)
2406 ret = hg.incoming(ui, repo, source, opts)
2407 return ret
2407 return ret
2408
2408
2409 def init(ui, dest=".", **opts):
2409 def init(ui, dest=".", **opts):
2410 """create a new repository in the given directory
2410 """create a new repository in the given directory
2411
2411
2412 Initialize a new repository in the given directory. If the given
2412 Initialize a new repository in the given directory. If the given
2413 directory does not exist, it will be created.
2413 directory does not exist, it will be created.
2414
2414
2415 If no directory is given, the current directory is used.
2415 If no directory is given, the current directory is used.
2416
2416
2417 It is possible to specify an ``ssh://`` URL as the destination.
2417 It is possible to specify an ``ssh://`` URL as the destination.
2418 See :hg:`help urls` for more information.
2418 See :hg:`help urls` for more information.
2419
2419
2420 Returns 0 on success.
2420 Returns 0 on success.
2421 """
2421 """
2422 hg.repository(hg.remoteui(ui, opts), ui.expandpath(dest), create=1)
2422 hg.repository(hg.remoteui(ui, opts), ui.expandpath(dest), create=1)
2423
2423
2424 def locate(ui, repo, *pats, **opts):
2424 def locate(ui, repo, *pats, **opts):
2425 """locate files matching specific patterns
2425 """locate files matching specific patterns
2426
2426
2427 Print files under Mercurial control in the working directory whose
2427 Print files under Mercurial control in the working directory whose
2428 names match the given patterns.
2428 names match the given patterns.
2429
2429
2430 By default, this command searches all directories in the working
2430 By default, this command searches all directories in the working
2431 directory. To search just the current directory and its
2431 directory. To search just the current directory and its
2432 subdirectories, use "--include .".
2432 subdirectories, use "--include .".
2433
2433
2434 If no patterns are given to match, this command prints the names
2434 If no patterns are given to match, this command prints the names
2435 of all files under Mercurial control in the working directory.
2435 of all files under Mercurial control in the working directory.
2436
2436
2437 If you want to feed the output of this command into the "xargs"
2437 If you want to feed the output of this command into the "xargs"
2438 command, use the -0 option to both this command and "xargs". This
2438 command, use the -0 option to both this command and "xargs". This
2439 will avoid the problem of "xargs" treating single filenames that
2439 will avoid the problem of "xargs" treating single filenames that
2440 contain whitespace as multiple filenames.
2440 contain whitespace as multiple filenames.
2441
2441
2442 Returns 0 if a match is found, 1 otherwise.
2442 Returns 0 if a match is found, 1 otherwise.
2443 """
2443 """
2444 end = opts.get('print0') and '\0' or '\n'
2444 end = opts.get('print0') and '\0' or '\n'
2445 rev = cmdutil.revsingle(repo, opts.get('rev'), None).node()
2445 rev = cmdutil.revsingle(repo, opts.get('rev'), None).node()
2446
2446
2447 ret = 1
2447 ret = 1
2448 m = cmdutil.match(repo, pats, opts, default='relglob')
2448 m = cmdutil.match(repo, pats, opts, default='relglob')
2449 m.bad = lambda x, y: False
2449 m.bad = lambda x, y: False
2450 for abs in repo[rev].walk(m):
2450 for abs in repo[rev].walk(m):
2451 if not rev and abs not in repo.dirstate:
2451 if not rev and abs not in repo.dirstate:
2452 continue
2452 continue
2453 if opts.get('fullpath'):
2453 if opts.get('fullpath'):
2454 ui.write(repo.wjoin(abs), end)
2454 ui.write(repo.wjoin(abs), end)
2455 else:
2455 else:
2456 ui.write(((pats and m.rel(abs)) or abs), end)
2456 ui.write(((pats and m.rel(abs)) or abs), end)
2457 ret = 0
2457 ret = 0
2458
2458
2459 return ret
2459 return ret
2460
2460
2461 def log(ui, repo, *pats, **opts):
2461 def log(ui, repo, *pats, **opts):
2462 """show revision history of entire repository or files
2462 """show revision history of entire repository or files
2463
2463
2464 Print the revision history of the specified files or the entire
2464 Print the revision history of the specified files or the entire
2465 project.
2465 project.
2466
2466
2467 File history is shown without following rename or copy history of
2467 File history is shown without following rename or copy history of
2468 files. Use -f/--follow with a filename to follow history across
2468 files. Use -f/--follow with a filename to follow history across
2469 renames and copies. --follow without a filename will only show
2469 renames and copies. --follow without a filename will only show
2470 ancestors or descendants of the starting revision. --follow-first
2470 ancestors or descendants of the starting revision. --follow-first
2471 only follows the first parent of merge revisions.
2471 only follows the first parent of merge revisions.
2472
2472
2473 If no revision range is specified, the default is ``tip:0`` unless
2473 If no revision range is specified, the default is ``tip:0`` unless
2474 --follow is set, in which case the working directory parent is
2474 --follow is set, in which case the working directory parent is
2475 used as the starting revision. You can specify a revision set for
2475 used as the starting revision. You can specify a revision set for
2476 log, see :hg:`help revsets` for more information.
2476 log, see :hg:`help revsets` for more information.
2477
2477
2478 See :hg:`help dates` for a list of formats valid for -d/--date.
2478 See :hg:`help dates` for a list of formats valid for -d/--date.
2479
2479
2480 By default this command prints revision number and changeset id,
2480 By default this command prints revision number and changeset id,
2481 tags, non-trivial parents, user, date and time, and a summary for
2481 tags, non-trivial parents, user, date and time, and a summary for
2482 each commit. When the -v/--verbose switch is used, the list of
2482 each commit. When the -v/--verbose switch is used, the list of
2483 changed files and full commit message are shown.
2483 changed files and full commit message are shown.
2484
2484
2485 .. note::
2485 .. note::
2486 log -p/--patch may generate unexpected diff output for merge
2486 log -p/--patch may generate unexpected diff output for merge
2487 changesets, as it will only compare the merge changeset against
2487 changesets, as it will only compare the merge changeset against
2488 its first parent. Also, only files different from BOTH parents
2488 its first parent. Also, only files different from BOTH parents
2489 will appear in files:.
2489 will appear in files:.
2490
2490
2491 Returns 0 on success.
2491 Returns 0 on success.
2492 """
2492 """
2493
2493
2494 matchfn = cmdutil.match(repo, pats, opts)
2494 matchfn = cmdutil.match(repo, pats, opts)
2495 limit = cmdutil.loglimit(opts)
2495 limit = cmdutil.loglimit(opts)
2496 count = 0
2496 count = 0
2497
2497
2498 endrev = None
2498 endrev = None
2499 if opts.get('copies') and opts.get('rev'):
2499 if opts.get('copies') and opts.get('rev'):
2500 endrev = max(cmdutil.revrange(repo, opts.get('rev'))) + 1
2500 endrev = max(cmdutil.revrange(repo, opts.get('rev'))) + 1
2501
2501
2502 df = False
2502 df = False
2503 if opts["date"]:
2503 if opts["date"]:
2504 df = util.matchdate(opts["date"])
2504 df = util.matchdate(opts["date"])
2505
2505
2506 branches = opts.get('branch', []) + opts.get('only_branch', [])
2506 branches = opts.get('branch', []) + opts.get('only_branch', [])
2507 opts['branch'] = [repo.lookupbranch(b) for b in branches]
2507 opts['branch'] = [repo.lookupbranch(b) for b in branches]
2508
2508
2509 displayer = cmdutil.show_changeset(ui, repo, opts, True)
2509 displayer = cmdutil.show_changeset(ui, repo, opts, True)
2510 def prep(ctx, fns):
2510 def prep(ctx, fns):
2511 rev = ctx.rev()
2511 rev = ctx.rev()
2512 parents = [p for p in repo.changelog.parentrevs(rev)
2512 parents = [p for p in repo.changelog.parentrevs(rev)
2513 if p != nullrev]
2513 if p != nullrev]
2514 if opts.get('no_merges') and len(parents) == 2:
2514 if opts.get('no_merges') and len(parents) == 2:
2515 return
2515 return
2516 if opts.get('only_merges') and len(parents) != 2:
2516 if opts.get('only_merges') and len(parents) != 2:
2517 return
2517 return
2518 if opts.get('branch') and ctx.branch() not in opts['branch']:
2518 if opts.get('branch') and ctx.branch() not in opts['branch']:
2519 return
2519 return
2520 if df and not df(ctx.date()[0]):
2520 if df and not df(ctx.date()[0]):
2521 return
2521 return
2522 if opts['user'] and not [k for k in opts['user']
2522 if opts['user'] and not [k for k in opts['user']
2523 if k.lower() in ctx.user().lower()]:
2523 if k.lower() in ctx.user().lower()]:
2524 return
2524 return
2525 if opts.get('keyword'):
2525 if opts.get('keyword'):
2526 for k in [kw.lower() for kw in opts['keyword']]:
2526 for k in [kw.lower() for kw in opts['keyword']]:
2527 if (k in ctx.user().lower() or
2527 if (k in ctx.user().lower() or
2528 k in ctx.description().lower() or
2528 k in ctx.description().lower() or
2529 k in " ".join(ctx.files()).lower()):
2529 k in " ".join(ctx.files()).lower()):
2530 break
2530 break
2531 else:
2531 else:
2532 return
2532 return
2533
2533
2534 copies = None
2534 copies = None
2535 if opts.get('copies') and rev:
2535 if opts.get('copies') and rev:
2536 copies = []
2536 copies = []
2537 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
2537 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
2538 for fn in ctx.files():
2538 for fn in ctx.files():
2539 rename = getrenamed(fn, rev)
2539 rename = getrenamed(fn, rev)
2540 if rename:
2540 if rename:
2541 copies.append((fn, rename[0]))
2541 copies.append((fn, rename[0]))
2542
2542
2543 revmatchfn = None
2543 revmatchfn = None
2544 if opts.get('patch') or opts.get('stat'):
2544 if opts.get('patch') or opts.get('stat'):
2545 if opts.get('follow') or opts.get('follow_first'):
2545 if opts.get('follow') or opts.get('follow_first'):
2546 # note: this might be wrong when following through merges
2546 # note: this might be wrong when following through merges
2547 revmatchfn = cmdutil.match(repo, fns, default='path')
2547 revmatchfn = cmdutil.match(repo, fns, default='path')
2548 else:
2548 else:
2549 revmatchfn = matchfn
2549 revmatchfn = matchfn
2550
2550
2551 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
2551 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
2552
2552
2553 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2553 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2554 if count == limit:
2554 if count == limit:
2555 break
2555 break
2556 if displayer.flush(ctx.rev()):
2556 if displayer.flush(ctx.rev()):
2557 count += 1
2557 count += 1
2558 displayer.close()
2558 displayer.close()
2559
2559
2560 def manifest(ui, repo, node=None, rev=None):
2560 def manifest(ui, repo, node=None, rev=None):
2561 """output the current or given revision of the project manifest
2561 """output the current or given revision of the project manifest
2562
2562
2563 Print a list of version controlled files for the given revision.
2563 Print a list of version controlled files for the given revision.
2564 If no revision is given, the first parent of the working directory
2564 If no revision is given, the first parent of the working directory
2565 is used, or the null revision if no revision is checked out.
2565 is used, or the null revision if no revision is checked out.
2566
2566
2567 With -v, print file permissions, symlink and executable bits.
2567 With -v, print file permissions, symlink and executable bits.
2568 With --debug, print file revision hashes.
2568 With --debug, print file revision hashes.
2569
2569
2570 Returns 0 on success.
2570 Returns 0 on success.
2571 """
2571 """
2572
2572
2573 if rev and node:
2573 if rev and node:
2574 raise util.Abort(_("please specify just one revision"))
2574 raise util.Abort(_("please specify just one revision"))
2575
2575
2576 if not node:
2576 if not node:
2577 node = rev
2577 node = rev
2578
2578
2579 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
2579 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
2580 ctx = cmdutil.revsingle(repo, node)
2580 ctx = cmdutil.revsingle(repo, node)
2581 for f in ctx:
2581 for f in ctx:
2582 if ui.debugflag:
2582 if ui.debugflag:
2583 ui.write("%40s " % hex(ctx.manifest()[f]))
2583 ui.write("%40s " % hex(ctx.manifest()[f]))
2584 if ui.verbose:
2584 if ui.verbose:
2585 ui.write(decor[ctx.flags(f)])
2585 ui.write(decor[ctx.flags(f)])
2586 ui.write("%s\n" % f)
2586 ui.write("%s\n" % f)
2587
2587
2588 def merge(ui, repo, node=None, **opts):
2588 def merge(ui, repo, node=None, **opts):
2589 """merge working directory with another revision
2589 """merge working directory with another revision
2590
2590
2591 The current working directory is updated with all changes made in
2591 The current working directory is updated with all changes made in
2592 the requested revision since the last common predecessor revision.
2592 the requested revision since the last common predecessor revision.
2593
2593
2594 Files that changed between either parent are marked as changed for
2594 Files that changed between either parent are marked as changed for
2595 the next commit and a commit must be performed before any further
2595 the next commit and a commit must be performed before any further
2596 updates to the repository are allowed. The next commit will have
2596 updates to the repository are allowed. The next commit will have
2597 two parents.
2597 two parents.
2598
2598
2599 ``--tool`` can be used to specify the merge tool used for file
2599 ``--tool`` can be used to specify the merge tool used for file
2600 merges. It overrides the HGMERGE environment variable and your
2600 merges. It overrides the HGMERGE environment variable and your
2601 configuration files.
2601 configuration files.
2602
2602
2603 If no revision is specified, the working directory's parent is a
2603 If no revision is specified, the working directory's parent is a
2604 head revision, and the current branch contains exactly one other
2604 head revision, and the current branch contains exactly one other
2605 head, the other head is merged with by default. Otherwise, an
2605 head, the other head is merged with by default. Otherwise, an
2606 explicit revision with which to merge with must be provided.
2606 explicit revision with which to merge with must be provided.
2607
2607
2608 :hg:`resolve` must be used to resolve unresolved files.
2608 :hg:`resolve` must be used to resolve unresolved files.
2609
2609
2610 To undo an uncommitted merge, use :hg:`update --clean .` which
2610 To undo an uncommitted merge, use :hg:`update --clean .` which
2611 will check out a clean copy of the original merge parent, losing
2611 will check out a clean copy of the original merge parent, losing
2612 all changes.
2612 all changes.
2613
2613
2614 Returns 0 on success, 1 if there are unresolved files.
2614 Returns 0 on success, 1 if there are unresolved files.
2615 """
2615 """
2616
2616
2617 if opts.get('rev') and node:
2617 if opts.get('rev') and node:
2618 raise util.Abort(_("please specify just one revision"))
2618 raise util.Abort(_("please specify just one revision"))
2619 if not node:
2619 if not node:
2620 node = opts.get('rev')
2620 node = opts.get('rev')
2621
2621
2622 if not node:
2622 if not node:
2623 branch = repo[None].branch()
2623 branch = repo[None].branch()
2624 bheads = repo.branchheads(branch)
2624 bheads = repo.branchheads(branch)
2625 if len(bheads) > 2:
2625 if len(bheads) > 2:
2626 raise util.Abort(_(
2626 raise util.Abort(_(
2627 'branch \'%s\' has %d heads - '
2627 'branch \'%s\' has %d heads - '
2628 'please merge with an explicit rev\n'
2628 'please merge with an explicit rev\n'
2629 '(run \'hg heads .\' to see heads)')
2629 '(run \'hg heads .\' to see heads)')
2630 % (branch, len(bheads)))
2630 % (branch, len(bheads)))
2631
2631
2632 parent = repo.dirstate.parents()[0]
2632 parent = repo.dirstate.parents()[0]
2633 if len(bheads) == 1:
2633 if len(bheads) == 1:
2634 if len(repo.heads()) > 1:
2634 if len(repo.heads()) > 1:
2635 raise util.Abort(_(
2635 raise util.Abort(_(
2636 'branch \'%s\' has one head - '
2636 'branch \'%s\' has one head - '
2637 'please merge with an explicit rev\n'
2637 'please merge with an explicit rev\n'
2638 '(run \'hg heads\' to see all heads)')
2638 '(run \'hg heads\' to see all heads)')
2639 % branch)
2639 % branch)
2640 msg = _('there is nothing to merge')
2640 msg = _('there is nothing to merge')
2641 if parent != repo.lookup(repo[None].branch()):
2641 if parent != repo.lookup(repo[None].branch()):
2642 msg = _('%s - use "hg update" instead') % msg
2642 msg = _('%s - use "hg update" instead') % msg
2643 raise util.Abort(msg)
2643 raise util.Abort(msg)
2644
2644
2645 if parent not in bheads:
2645 if parent not in bheads:
2646 raise util.Abort(_('working dir not at a head rev - '
2646 raise util.Abort(_('working dir not at a head rev - '
2647 'use "hg update" or merge with an explicit rev'))
2647 'use "hg update" or merge with an explicit rev'))
2648 node = parent == bheads[0] and bheads[-1] or bheads[0]
2648 node = parent == bheads[0] and bheads[-1] or bheads[0]
2649 else:
2649 else:
2650 node = cmdutil.revsingle(repo, node).node()
2650 node = cmdutil.revsingle(repo, node).node()
2651
2651
2652 if opts.get('preview'):
2652 if opts.get('preview'):
2653 # find nodes that are ancestors of p2 but not of p1
2653 # find nodes that are ancestors of p2 but not of p1
2654 p1 = repo.lookup('.')
2654 p1 = repo.lookup('.')
2655 p2 = repo.lookup(node)
2655 p2 = repo.lookup(node)
2656 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
2656 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
2657
2657
2658 displayer = cmdutil.show_changeset(ui, repo, opts)
2658 displayer = cmdutil.show_changeset(ui, repo, opts)
2659 for node in nodes:
2659 for node in nodes:
2660 displayer.show(repo[node])
2660 displayer.show(repo[node])
2661 displayer.close()
2661 displayer.close()
2662 return 0
2662 return 0
2663
2663
2664 try:
2664 try:
2665 # ui.forcemerge is an internal variable, do not document
2665 # ui.forcemerge is an internal variable, do not document
2666 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2666 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2667 return hg.merge(repo, node, force=opts.get('force'))
2667 return hg.merge(repo, node, force=opts.get('force'))
2668 finally:
2668 finally:
2669 ui.setconfig('ui', 'forcemerge', '')
2669 ui.setconfig('ui', 'forcemerge', '')
2670
2670
2671 def outgoing(ui, repo, dest=None, **opts):
2671 def outgoing(ui, repo, dest=None, **opts):
2672 """show changesets not found in the destination
2672 """show changesets not found in the destination
2673
2673
2674 Show changesets not found in the specified destination repository
2674 Show changesets not found in the specified destination repository
2675 or the default push location. These are the changesets that would
2675 or the default push location. These are the changesets that would
2676 be pushed if a push was requested.
2676 be pushed if a push was requested.
2677
2677
2678 See pull for details of valid destination formats.
2678 See pull for details of valid destination formats.
2679
2679
2680 Returns 0 if there are outgoing changes, 1 otherwise.
2680 Returns 0 if there are outgoing changes, 1 otherwise.
2681 """
2681 """
2682 ret = hg.outgoing(ui, repo, dest, opts)
2682 ret = hg.outgoing(ui, repo, dest, opts)
2683 return ret
2683 return ret
2684
2684
2685 def parents(ui, repo, file_=None, **opts):
2685 def parents(ui, repo, file_=None, **opts):
2686 """show the parents of the working directory or revision
2686 """show the parents of the working directory or revision
2687
2687
2688 Print the working directory's parent revisions. If a revision is
2688 Print the working directory's parent revisions. If a revision is
2689 given via -r/--rev, the parent of that revision will be printed.
2689 given via -r/--rev, the parent of that revision will be printed.
2690 If a file argument is given, the revision in which the file was
2690 If a file argument is given, the revision in which the file was
2691 last changed (before the working directory revision or the
2691 last changed (before the working directory revision or the
2692 argument to --rev if given) is printed.
2692 argument to --rev if given) is printed.
2693
2693
2694 Returns 0 on success.
2694 Returns 0 on success.
2695 """
2695 """
2696
2696
2697 ctx = cmdutil.revsingle(repo, opts.get('rev'), None)
2697 ctx = cmdutil.revsingle(repo, opts.get('rev'), None)
2698
2698
2699 if file_:
2699 if file_:
2700 m = cmdutil.match(repo, (file_,), opts)
2700 m = cmdutil.match(repo, (file_,), opts)
2701 if m.anypats() or len(m.files()) != 1:
2701 if m.anypats() or len(m.files()) != 1:
2702 raise util.Abort(_('can only specify an explicit filename'))
2702 raise util.Abort(_('can only specify an explicit filename'))
2703 file_ = m.files()[0]
2703 file_ = m.files()[0]
2704 filenodes = []
2704 filenodes = []
2705 for cp in ctx.parents():
2705 for cp in ctx.parents():
2706 if not cp:
2706 if not cp:
2707 continue
2707 continue
2708 try:
2708 try:
2709 filenodes.append(cp.filenode(file_))
2709 filenodes.append(cp.filenode(file_))
2710 except error.LookupError:
2710 except error.LookupError:
2711 pass
2711 pass
2712 if not filenodes:
2712 if not filenodes:
2713 raise util.Abort(_("'%s' not found in manifest!") % file_)
2713 raise util.Abort(_("'%s' not found in manifest!") % file_)
2714 fl = repo.file(file_)
2714 fl = repo.file(file_)
2715 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
2715 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
2716 else:
2716 else:
2717 p = [cp.node() for cp in ctx.parents()]
2717 p = [cp.node() for cp in ctx.parents()]
2718
2718
2719 displayer = cmdutil.show_changeset(ui, repo, opts)
2719 displayer = cmdutil.show_changeset(ui, repo, opts)
2720 for n in p:
2720 for n in p:
2721 if n != nullid:
2721 if n != nullid:
2722 displayer.show(repo[n])
2722 displayer.show(repo[n])
2723 displayer.close()
2723 displayer.close()
2724
2724
2725 def paths(ui, repo, search=None):
2725 def paths(ui, repo, search=None):
2726 """show aliases for remote repositories
2726 """show aliases for remote repositories
2727
2727
2728 Show definition of symbolic path name NAME. If no name is given,
2728 Show definition of symbolic path name NAME. If no name is given,
2729 show definition of all available names.
2729 show definition of all available names.
2730
2730
2731 Path names are defined in the [paths] section of your
2731 Path names are defined in the [paths] section of your
2732 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
2732 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
2733 repository, ``.hg/hgrc`` is used, too.
2733 repository, ``.hg/hgrc`` is used, too.
2734
2734
2735 The path names ``default`` and ``default-push`` have a special
2735 The path names ``default`` and ``default-push`` have a special
2736 meaning. When performing a push or pull operation, they are used
2736 meaning. When performing a push or pull operation, they are used
2737 as fallbacks if no location is specified on the command-line.
2737 as fallbacks if no location is specified on the command-line.
2738 When ``default-push`` is set, it will be used for push and
2738 When ``default-push`` is set, it will be used for push and
2739 ``default`` will be used for pull; otherwise ``default`` is used
2739 ``default`` will be used for pull; otherwise ``default`` is used
2740 as the fallback for both. When cloning a repository, the clone
2740 as the fallback for both. When cloning a repository, the clone
2741 source is written as ``default`` in ``.hg/hgrc``. Note that
2741 source is written as ``default`` in ``.hg/hgrc``. Note that
2742 ``default`` and ``default-push`` apply to all inbound (e.g.
2742 ``default`` and ``default-push`` apply to all inbound (e.g.
2743 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
2743 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
2744 :hg:`bundle`) operations.
2744 :hg:`bundle`) operations.
2745
2745
2746 See :hg:`help urls` for more information.
2746 See :hg:`help urls` for more information.
2747
2747
2748 Returns 0 on success.
2748 Returns 0 on success.
2749 """
2749 """
2750 if search:
2750 if search:
2751 for name, path in ui.configitems("paths"):
2751 for name, path in ui.configitems("paths"):
2752 if name == search:
2752 if name == search:
2753 ui.write("%s\n" % url.hidepassword(path))
2753 ui.write("%s\n" % url.hidepassword(path))
2754 return
2754 return
2755 ui.warn(_("not found!\n"))
2755 ui.warn(_("not found!\n"))
2756 return 1
2756 return 1
2757 else:
2757 else:
2758 for name, path in ui.configitems("paths"):
2758 for name, path in ui.configitems("paths"):
2759 ui.write("%s = %s\n" % (name, url.hidepassword(path)))
2759 ui.write("%s = %s\n" % (name, url.hidepassword(path)))
2760
2760
2761 def postincoming(ui, repo, modheads, optupdate, checkout):
2761 def postincoming(ui, repo, modheads, optupdate, checkout):
2762 if modheads == 0:
2762 if modheads == 0:
2763 return
2763 return
2764 if optupdate:
2764 if optupdate:
2765 if (modheads <= 1 or len(repo.branchheads()) == 1) or checkout:
2765 if (modheads <= 1 or len(repo.branchheads()) == 1) or checkout:
2766 return hg.update(repo, checkout)
2766 return hg.update(repo, checkout)
2767 else:
2767 else:
2768 ui.status(_("not updating, since new heads added\n"))
2768 ui.status(_("not updating, since new heads added\n"))
2769 if modheads > 1:
2769 if modheads > 1:
2770 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
2770 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
2771 else:
2771 else:
2772 ui.status(_("(run 'hg update' to get a working copy)\n"))
2772 ui.status(_("(run 'hg update' to get a working copy)\n"))
2773
2773
2774 def pull(ui, repo, source="default", **opts):
2774 def pull(ui, repo, source="default", **opts):
2775 """pull changes from the specified source
2775 """pull changes from the specified source
2776
2776
2777 Pull changes from a remote repository to a local one.
2777 Pull changes from a remote repository to a local one.
2778
2778
2779 This finds all changes from the repository at the specified path
2779 This finds all changes from the repository at the specified path
2780 or URL and adds them to a local repository (the current one unless
2780 or URL and adds them to a local repository (the current one unless
2781 -R is specified). By default, this does not update the copy of the
2781 -R is specified). By default, this does not update the copy of the
2782 project in the working directory.
2782 project in the working directory.
2783
2783
2784 Use :hg:`incoming` if you want to see what would have been added
2784 Use :hg:`incoming` if you want to see what would have been added
2785 by a pull at the time you issued this command. If you then decide
2785 by a pull at the time you issued this command. If you then decide
2786 to add those changes to the repository, you should use :hg:`pull
2786 to add those changes to the repository, you should use :hg:`pull
2787 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
2787 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
2788
2788
2789 If SOURCE is omitted, the 'default' path will be used.
2789 If SOURCE is omitted, the 'default' path will be used.
2790 See :hg:`help urls` for more information.
2790 See :hg:`help urls` for more information.
2791
2791
2792 Returns 0 on success, 1 if an update had unresolved files.
2792 Returns 0 on success, 1 if an update had unresolved files.
2793 """
2793 """
2794 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
2794 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
2795 other = hg.repository(hg.remoteui(repo, opts), source)
2795 other = hg.repository(hg.remoteui(repo, opts), source)
2796 ui.status(_('pulling from %s\n') % url.hidepassword(source))
2796 ui.status(_('pulling from %s\n') % url.hidepassword(source))
2797 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
2797 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
2798 if revs:
2798 if revs:
2799 try:
2799 try:
2800 revs = [other.lookup(rev) for rev in revs]
2800 revs = [other.lookup(rev) for rev in revs]
2801 except error.CapabilityError:
2801 except error.CapabilityError:
2802 err = _("other repository doesn't support revision lookup, "
2802 err = _("other repository doesn't support revision lookup, "
2803 "so a rev cannot be specified.")
2803 "so a rev cannot be specified.")
2804 raise util.Abort(err)
2804 raise util.Abort(err)
2805
2805
2806 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
2806 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
2807 if checkout:
2807 if checkout:
2808 checkout = str(repo.changelog.rev(other.lookup(checkout)))
2808 checkout = str(repo.changelog.rev(other.lookup(checkout)))
2809 repo._subtoppath = source
2809 repo._subtoppath = source
2810 try:
2810 try:
2811 return postincoming(ui, repo, modheads, opts.get('update'), checkout)
2811 return postincoming(ui, repo, modheads, opts.get('update'), checkout)
2812 finally:
2812 finally:
2813 del repo._subtoppath
2813 del repo._subtoppath
2814
2814
2815 def push(ui, repo, dest=None, **opts):
2815 def push(ui, repo, dest=None, **opts):
2816 """push changes to the specified destination
2816 """push changes to the specified destination
2817
2817
2818 Push changesets from the local repository to the specified
2818 Push changesets from the local repository to the specified
2819 destination.
2819 destination.
2820
2820
2821 This operation is symmetrical to pull: it is identical to a pull
2821 This operation is symmetrical to pull: it is identical to a pull
2822 in the destination repository from the current one.
2822 in the destination repository from the current one.
2823
2823
2824 By default, push will not allow creation of new heads at the
2824 By default, push will not allow creation of new heads at the
2825 destination, since multiple heads would make it unclear which head
2825 destination, since multiple heads would make it unclear which head
2826 to use. In this situation, it is recommended to pull and merge
2826 to use. In this situation, it is recommended to pull and merge
2827 before pushing.
2827 before pushing.
2828
2828
2829 Use --new-branch if you want to allow push to create a new named
2829 Use --new-branch if you want to allow push to create a new named
2830 branch that is not present at the destination. This allows you to
2830 branch that is not present at the destination. This allows you to
2831 only create a new branch without forcing other changes.
2831 only create a new branch without forcing other changes.
2832
2832
2833 Use -f/--force to override the default behavior and push all
2833 Use -f/--force to override the default behavior and push all
2834 changesets on all branches.
2834 changesets on all branches.
2835
2835
2836 If -r/--rev is used, the specified revision and all its ancestors
2836 If -r/--rev is used, the specified revision and all its ancestors
2837 will be pushed to the remote repository.
2837 will be pushed to the remote repository.
2838
2838
2839 Please see :hg:`help urls` for important details about ``ssh://``
2839 Please see :hg:`help urls` for important details about ``ssh://``
2840 URLs. If DESTINATION is omitted, a default path will be used.
2840 URLs. If DESTINATION is omitted, a default path will be used.
2841
2841
2842 Returns 0 if push was successful, 1 if nothing to push.
2842 Returns 0 if push was successful, 1 if nothing to push.
2843 """
2843 """
2844 dest = ui.expandpath(dest or 'default-push', dest or 'default')
2844 dest = ui.expandpath(dest or 'default-push', dest or 'default')
2845 dest, branches = hg.parseurl(dest, opts.get('branch'))
2845 dest, branches = hg.parseurl(dest, opts.get('branch'))
2846 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
2846 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
2847 other = hg.repository(hg.remoteui(repo, opts), dest)
2847 other = hg.repository(hg.remoteui(repo, opts), dest)
2848 ui.status(_('pushing to %s\n') % url.hidepassword(dest))
2848 ui.status(_('pushing to %s\n') % url.hidepassword(dest))
2849 if revs:
2849 if revs:
2850 revs = [repo.lookup(rev) for rev in revs]
2850 revs = [repo.lookup(rev) for rev in revs]
2851
2851
2852 repo._subtoppath = dest
2852 repo._subtoppath = dest
2853 try:
2853 try:
2854 # push subrepos depth-first for coherent ordering
2854 # push subrepos depth-first for coherent ordering
2855 c = repo['']
2855 c = repo['']
2856 subs = c.substate # only repos that are committed
2856 subs = c.substate # only repos that are committed
2857 for s in sorted(subs):
2857 for s in sorted(subs):
2858 if not c.sub(s).push(opts.get('force')):
2858 if not c.sub(s).push(opts.get('force')):
2859 return False
2859 return False
2860 finally:
2860 finally:
2861 del repo._subtoppath
2861 del repo._subtoppath
2862 r = repo.push(other, opts.get('force'), revs=revs,
2862 r = repo.push(other, opts.get('force'), revs=revs,
2863 newbranch=opts.get('new_branch'))
2863 newbranch=opts.get('new_branch'))
2864 return r == 0
2864 return r == 0
2865
2865
2866 def recover(ui, repo):
2866 def recover(ui, repo):
2867 """roll back an interrupted transaction
2867 """roll back an interrupted transaction
2868
2868
2869 Recover from an interrupted commit or pull.
2869 Recover from an interrupted commit or pull.
2870
2870
2871 This command tries to fix the repository status after an
2871 This command tries to fix the repository status after an
2872 interrupted operation. It should only be necessary when Mercurial
2872 interrupted operation. It should only be necessary when Mercurial
2873 suggests it.
2873 suggests it.
2874
2874
2875 Returns 0 if successful, 1 if nothing to recover or verify fails.
2875 Returns 0 if successful, 1 if nothing to recover or verify fails.
2876 """
2876 """
2877 if repo.recover():
2877 if repo.recover():
2878 return hg.verify(repo)
2878 return hg.verify(repo)
2879 return 1
2879 return 1
2880
2880
2881 def remove(ui, repo, *pats, **opts):
2881 def remove(ui, repo, *pats, **opts):
2882 """remove the specified files on the next commit
2882 """remove the specified files on the next commit
2883
2883
2884 Schedule the indicated files for removal from the repository.
2884 Schedule the indicated files for removal from the repository.
2885
2885
2886 This only removes files from the current branch, not from the
2886 This only removes files from the current branch, not from the
2887 entire project history. -A/--after can be used to remove only
2887 entire project history. -A/--after can be used to remove only
2888 files that have already been deleted, -f/--force can be used to
2888 files that have already been deleted, -f/--force can be used to
2889 force deletion, and -Af can be used to remove files from the next
2889 force deletion, and -Af can be used to remove files from the next
2890 revision without deleting them from the working directory.
2890 revision without deleting them from the working directory.
2891
2891
2892 The following table details the behavior of remove for different
2892 The following table details the behavior of remove for different
2893 file states (columns) and option combinations (rows). The file
2893 file states (columns) and option combinations (rows). The file
2894 states are Added [A], Clean [C], Modified [M] and Missing [!] (as
2894 states are Added [A], Clean [C], Modified [M] and Missing [!] (as
2895 reported by :hg:`status`). The actions are Warn, Remove (from
2895 reported by :hg:`status`). The actions are Warn, Remove (from
2896 branch) and Delete (from disk)::
2896 branch) and Delete (from disk)::
2897
2897
2898 A C M !
2898 A C M !
2899 none W RD W R
2899 none W RD W R
2900 -f R RD RD R
2900 -f R RD RD R
2901 -A W W W R
2901 -A W W W R
2902 -Af R R R R
2902 -Af R R R R
2903
2903
2904 This command schedules the files to be removed at the next commit.
2904 This command schedules the files to be removed at the next commit.
2905 To undo a remove before that, see :hg:`revert`.
2905 To undo a remove before that, see :hg:`revert`.
2906
2906
2907 Returns 0 on success, 1 if any warnings encountered.
2907 Returns 0 on success, 1 if any warnings encountered.
2908 """
2908 """
2909
2909
2910 ret = 0
2910 ret = 0
2911 after, force = opts.get('after'), opts.get('force')
2911 after, force = opts.get('after'), opts.get('force')
2912 if not pats and not after:
2912 if not pats and not after:
2913 raise util.Abort(_('no files specified'))
2913 raise util.Abort(_('no files specified'))
2914
2914
2915 m = cmdutil.match(repo, pats, opts)
2915 m = cmdutil.match(repo, pats, opts)
2916 s = repo.status(match=m, clean=True)
2916 s = repo.status(match=m, clean=True)
2917 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
2917 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
2918
2918
2919 for f in m.files():
2919 for f in m.files():
2920 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
2920 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
2921 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
2921 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
2922 ret = 1
2922 ret = 1
2923
2923
2924 if force:
2924 if force:
2925 remove, forget = modified + deleted + clean, added
2925 remove, forget = modified + deleted + clean, added
2926 elif after:
2926 elif after:
2927 remove, forget = deleted, []
2927 remove, forget = deleted, []
2928 for f in modified + added + clean:
2928 for f in modified + added + clean:
2929 ui.warn(_('not removing %s: file still exists (use -f'
2929 ui.warn(_('not removing %s: file still exists (use -f'
2930 ' to force removal)\n') % m.rel(f))
2930 ' to force removal)\n') % m.rel(f))
2931 ret = 1
2931 ret = 1
2932 else:
2932 else:
2933 remove, forget = deleted + clean, []
2933 remove, forget = deleted + clean, []
2934 for f in modified:
2934 for f in modified:
2935 ui.warn(_('not removing %s: file is modified (use -f'
2935 ui.warn(_('not removing %s: file is modified (use -f'
2936 ' to force removal)\n') % m.rel(f))
2936 ' to force removal)\n') % m.rel(f))
2937 ret = 1
2937 ret = 1
2938 for f in added:
2938 for f in added:
2939 ui.warn(_('not removing %s: file has been marked for add (use -f'
2939 ui.warn(_('not removing %s: file has been marked for add (use -f'
2940 ' to force removal)\n') % m.rel(f))
2940 ' to force removal)\n') % m.rel(f))
2941 ret = 1
2941 ret = 1
2942
2942
2943 for f in sorted(remove + forget):
2943 for f in sorted(remove + forget):
2944 if ui.verbose or not m.exact(f):
2944 if ui.verbose or not m.exact(f):
2945 ui.status(_('removing %s\n') % m.rel(f))
2945 ui.status(_('removing %s\n') % m.rel(f))
2946
2946
2947 repo[None].forget(forget)
2947 repo[None].forget(forget)
2948 repo[None].remove(remove, unlink=not after)
2948 repo[None].remove(remove, unlink=not after)
2949 return ret
2949 return ret
2950
2950
2951 def rename(ui, repo, *pats, **opts):
2951 def rename(ui, repo, *pats, **opts):
2952 """rename files; equivalent of copy + remove
2952 """rename files; equivalent of copy + remove
2953
2953
2954 Mark dest as copies of sources; mark sources for deletion. If dest
2954 Mark dest as copies of sources; mark sources for deletion. If dest
2955 is a directory, copies are put in that directory. If dest is a
2955 is a directory, copies are put in that directory. If dest is a
2956 file, there can only be one source.
2956 file, there can only be one source.
2957
2957
2958 By default, this command copies the contents of files as they
2958 By default, this command copies the contents of files as they
2959 exist in the working directory. If invoked with -A/--after, the
2959 exist in the working directory. If invoked with -A/--after, the
2960 operation is recorded, but no copying is performed.
2960 operation is recorded, but no copying is performed.
2961
2961
2962 This command takes effect at the next commit. To undo a rename
2962 This command takes effect at the next commit. To undo a rename
2963 before that, see :hg:`revert`.
2963 before that, see :hg:`revert`.
2964
2964
2965 Returns 0 on success, 1 if errors are encountered.
2965 Returns 0 on success, 1 if errors are encountered.
2966 """
2966 """
2967 wlock = repo.wlock(False)
2967 wlock = repo.wlock(False)
2968 try:
2968 try:
2969 return cmdutil.copy(ui, repo, pats, opts, rename=True)
2969 return cmdutil.copy(ui, repo, pats, opts, rename=True)
2970 finally:
2970 finally:
2971 wlock.release()
2971 wlock.release()
2972
2972
2973 def resolve(ui, repo, *pats, **opts):
2973 def resolve(ui, repo, *pats, **opts):
2974 """redo merges or set/view the merge status of files
2974 """redo merges or set/view the merge status of files
2975
2975
2976 Merges with unresolved conflicts are often the result of
2976 Merges with unresolved conflicts are often the result of
2977 non-interactive merging using the ``internal:merge`` configuration
2977 non-interactive merging using the ``internal:merge`` configuration
2978 setting, or a command-line merge tool like ``diff3``. The resolve
2978 setting, or a command-line merge tool like ``diff3``. The resolve
2979 command is used to manage the files involved in a merge, after
2979 command is used to manage the files involved in a merge, after
2980 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
2980 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
2981 working directory must have two parents).
2981 working directory must have two parents).
2982
2982
2983 The resolve command can be used in the following ways:
2983 The resolve command can be used in the following ways:
2984
2984
2985 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
2985 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
2986 files, discarding any previous merge attempts. Re-merging is not
2986 files, discarding any previous merge attempts. Re-merging is not
2987 performed for files already marked as resolved. Use ``--all/-a``
2987 performed for files already marked as resolved. Use ``--all/-a``
2988 to selects all unresolved files. ``--tool`` can be used to specify
2988 to selects all unresolved files. ``--tool`` can be used to specify
2989 the merge tool used for the given files. It overrides the HGMERGE
2989 the merge tool used for the given files. It overrides the HGMERGE
2990 environment variable and your configuration files.
2990 environment variable and your configuration files.
2991
2991
2992 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
2992 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
2993 (e.g. after having manually fixed-up the files). The default is
2993 (e.g. after having manually fixed-up the files). The default is
2994 to mark all unresolved files.
2994 to mark all unresolved files.
2995
2995
2996 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
2996 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
2997 default is to mark all resolved files.
2997 default is to mark all resolved files.
2998
2998
2999 - :hg:`resolve -l`: list files which had or still have conflicts.
2999 - :hg:`resolve -l`: list files which had or still have conflicts.
3000 In the printed list, ``U`` = unresolved and ``R`` = resolved.
3000 In the printed list, ``U`` = unresolved and ``R`` = resolved.
3001
3001
3002 Note that Mercurial will not let you commit files with unresolved
3002 Note that Mercurial will not let you commit files with unresolved
3003 merge conflicts. You must use :hg:`resolve -m ...` before you can
3003 merge conflicts. You must use :hg:`resolve -m ...` before you can
3004 commit after a conflicting merge.
3004 commit after a conflicting merge.
3005
3005
3006 Returns 0 on success, 1 if any files fail a resolve attempt.
3006 Returns 0 on success, 1 if any files fail a resolve attempt.
3007 """
3007 """
3008
3008
3009 all, mark, unmark, show, nostatus = \
3009 all, mark, unmark, show, nostatus = \
3010 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
3010 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
3011
3011
3012 if (show and (mark or unmark)) or (mark and unmark):
3012 if (show and (mark or unmark)) or (mark and unmark):
3013 raise util.Abort(_("too many options specified"))
3013 raise util.Abort(_("too many options specified"))
3014 if pats and all:
3014 if pats and all:
3015 raise util.Abort(_("can't specify --all and patterns"))
3015 raise util.Abort(_("can't specify --all and patterns"))
3016 if not (all or pats or show or mark or unmark):
3016 if not (all or pats or show or mark or unmark):
3017 raise util.Abort(_('no files or directories specified; '
3017 raise util.Abort(_('no files or directories specified; '
3018 'use --all to remerge all files'))
3018 'use --all to remerge all files'))
3019
3019
3020 ms = mergemod.mergestate(repo)
3020 ms = mergemod.mergestate(repo)
3021 m = cmdutil.match(repo, pats, opts)
3021 m = cmdutil.match(repo, pats, opts)
3022 ret = 0
3022 ret = 0
3023
3023
3024 for f in ms:
3024 for f in ms:
3025 if m(f):
3025 if m(f):
3026 if show:
3026 if show:
3027 if nostatus:
3027 if nostatus:
3028 ui.write("%s\n" % f)
3028 ui.write("%s\n" % f)
3029 else:
3029 else:
3030 ui.write("%s %s\n" % (ms[f].upper(), f),
3030 ui.write("%s %s\n" % (ms[f].upper(), f),
3031 label='resolve.' +
3031 label='resolve.' +
3032 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
3032 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
3033 elif mark:
3033 elif mark:
3034 ms.mark(f, "r")
3034 ms.mark(f, "r")
3035 elif unmark:
3035 elif unmark:
3036 ms.mark(f, "u")
3036 ms.mark(f, "u")
3037 else:
3037 else:
3038 wctx = repo[None]
3038 wctx = repo[None]
3039 mctx = wctx.parents()[-1]
3039 mctx = wctx.parents()[-1]
3040
3040
3041 # backup pre-resolve (merge uses .orig for its own purposes)
3041 # backup pre-resolve (merge uses .orig for its own purposes)
3042 a = repo.wjoin(f)
3042 a = repo.wjoin(f)
3043 util.copyfile(a, a + ".resolve")
3043 util.copyfile(a, a + ".resolve")
3044
3044
3045 try:
3045 try:
3046 # resolve file
3046 # resolve file
3047 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3047 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3048 if ms.resolve(f, wctx, mctx):
3048 if ms.resolve(f, wctx, mctx):
3049 ret = 1
3049 ret = 1
3050 finally:
3050 finally:
3051 ui.setconfig('ui', 'forcemerge', '')
3051 ui.setconfig('ui', 'forcemerge', '')
3052
3052
3053 # replace filemerge's .orig file with our resolve file
3053 # replace filemerge's .orig file with our resolve file
3054 util.rename(a + ".resolve", a + ".orig")
3054 util.rename(a + ".resolve", a + ".orig")
3055
3055
3056 ms.commit()
3056 ms.commit()
3057 return ret
3057 return ret
3058
3058
3059 def revert(ui, repo, *pats, **opts):
3059 def revert(ui, repo, *pats, **opts):
3060 """restore individual files or directories to an earlier state
3060 """restore individual files or directories to an earlier state
3061
3061
3062 .. note::
3062 .. note::
3063 This command is most likely not what you are looking for.
3063 This command is most likely not what you are looking for.
3064 Revert will partially overwrite content in the working
3064 Revert will partially overwrite content in the working
3065 directory without changing the working directory parents. Use
3065 directory without changing the working directory parents. Use
3066 :hg:`update -r rev` to check out earlier revisions, or
3066 :hg:`update -r rev` to check out earlier revisions, or
3067 :hg:`update --clean .` to undo a merge which has added another
3067 :hg:`update --clean .` to undo a merge which has added another
3068 parent.
3068 parent.
3069
3069
3070 With no revision specified, revert the named files or directories
3070 With no revision specified, revert the named files or directories
3071 to the contents they had in the parent of the working directory.
3071 to the contents they had in the parent of the working directory.
3072 This restores the contents of the affected files to an unmodified
3072 This restores the contents of the affected files to an unmodified
3073 state and unschedules adds, removes, copies, and renames. If the
3073 state and unschedules adds, removes, copies, and renames. If the
3074 working directory has two parents, you must explicitly specify a
3074 working directory has two parents, you must explicitly specify a
3075 revision.
3075 revision.
3076
3076
3077 Using the -r/--rev option, revert the given files or directories
3077 Using the -r/--rev option, revert the given files or directories
3078 to their contents as of a specific revision. This can be helpful
3078 to their contents as of a specific revision. This can be helpful
3079 to "roll back" some or all of an earlier change. See :hg:`help
3079 to "roll back" some or all of an earlier change. See :hg:`help
3080 dates` for a list of formats valid for -d/--date.
3080 dates` for a list of formats valid for -d/--date.
3081
3081
3082 Revert modifies the working directory. It does not commit any
3082 Revert modifies the working directory. It does not commit any
3083 changes, or change the parent of the working directory. If you
3083 changes, or change the parent of the working directory. If you
3084 revert to a revision other than the parent of the working
3084 revert to a revision other than the parent of the working
3085 directory, the reverted files will thus appear modified
3085 directory, the reverted files will thus appear modified
3086 afterwards.
3086 afterwards.
3087
3087
3088 If a file has been deleted, it is restored. If the executable mode
3088 If a file has been deleted, it is restored. If the executable mode
3089 of a file was changed, it is reset.
3089 of a file was changed, it is reset.
3090
3090
3091 If names are given, all files matching the names are reverted.
3091 If names are given, all files matching the names are reverted.
3092 If no arguments are given, no files are reverted.
3092 If no arguments are given, no files are reverted.
3093
3093
3094 Modified files are saved with a .orig suffix before reverting.
3094 Modified files are saved with a .orig suffix before reverting.
3095 To disable these backups, use --no-backup.
3095 To disable these backups, use --no-backup.
3096
3096
3097 Returns 0 on success.
3097 Returns 0 on success.
3098 """
3098 """
3099
3099
3100 if opts.get("date"):
3100 if opts.get("date"):
3101 if opts.get("rev"):
3101 if opts.get("rev"):
3102 raise util.Abort(_("you can't specify a revision and a date"))
3102 raise util.Abort(_("you can't specify a revision and a date"))
3103 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
3103 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
3104
3104
3105 parent, p2 = repo.dirstate.parents()
3105 parent, p2 = repo.dirstate.parents()
3106 if not opts.get('rev') and p2 != nullid:
3106 if not opts.get('rev') and p2 != nullid:
3107 raise util.Abort(_('uncommitted merge - '
3107 raise util.Abort(_('uncommitted merge - '
3108 'use "hg update", see "hg help revert"'))
3108 'use "hg update", see "hg help revert"'))
3109
3109
3110 if not pats and not opts.get('all'):
3110 if not pats and not opts.get('all'):
3111 raise util.Abort(_('no files or directories specified; '
3111 raise util.Abort(_('no files or directories specified; '
3112 'use --all to revert the whole repo'))
3112 'use --all to revert the whole repo'))
3113
3113
3114 ctx = cmdutil.revsingle(repo, opts.get('rev'))
3114 ctx = cmdutil.revsingle(repo, opts.get('rev'))
3115 node = ctx.node()
3115 node = ctx.node()
3116 mf = ctx.manifest()
3116 mf = ctx.manifest()
3117 if node == parent:
3117 if node == parent:
3118 pmf = mf
3118 pmf = mf
3119 else:
3119 else:
3120 pmf = None
3120 pmf = None
3121
3121
3122 # need all matching names in dirstate and manifest of target rev,
3122 # need all matching names in dirstate and manifest of target rev,
3123 # so have to walk both. do not print errors if files exist in one
3123 # so have to walk both. do not print errors if files exist in one
3124 # but not other.
3124 # but not other.
3125
3125
3126 names = {}
3126 names = {}
3127
3127
3128 wlock = repo.wlock()
3128 wlock = repo.wlock()
3129 try:
3129 try:
3130 # walk dirstate.
3130 # walk dirstate.
3131
3131
3132 m = cmdutil.match(repo, pats, opts)
3132 m = cmdutil.match(repo, pats, opts)
3133 m.bad = lambda x, y: False
3133 m.bad = lambda x, y: False
3134 for abs in repo.walk(m):
3134 for abs in repo.walk(m):
3135 names[abs] = m.rel(abs), m.exact(abs)
3135 names[abs] = m.rel(abs), m.exact(abs)
3136
3136
3137 # walk target manifest.
3137 # walk target manifest.
3138
3138
3139 def badfn(path, msg):
3139 def badfn(path, msg):
3140 if path in names:
3140 if path in names:
3141 return
3141 return
3142 path_ = path + '/'
3142 path_ = path + '/'
3143 for f in names:
3143 for f in names:
3144 if f.startswith(path_):
3144 if f.startswith(path_):
3145 return
3145 return
3146 ui.warn("%s: %s\n" % (m.rel(path), msg))
3146 ui.warn("%s: %s\n" % (m.rel(path), msg))
3147
3147
3148 m = cmdutil.match(repo, pats, opts)
3148 m = cmdutil.match(repo, pats, opts)
3149 m.bad = badfn
3149 m.bad = badfn
3150 for abs in repo[node].walk(m):
3150 for abs in repo[node].walk(m):
3151 if abs not in names:
3151 if abs not in names:
3152 names[abs] = m.rel(abs), m.exact(abs)
3152 names[abs] = m.rel(abs), m.exact(abs)
3153
3153
3154 m = cmdutil.matchfiles(repo, names)
3154 m = cmdutil.matchfiles(repo, names)
3155 changes = repo.status(match=m)[:4]
3155 changes = repo.status(match=m)[:4]
3156 modified, added, removed, deleted = map(set, changes)
3156 modified, added, removed, deleted = map(set, changes)
3157
3157
3158 # if f is a rename, also revert the source
3158 # if f is a rename, also revert the source
3159 cwd = repo.getcwd()
3159 cwd = repo.getcwd()
3160 for f in added:
3160 for f in added:
3161 src = repo.dirstate.copied(f)
3161 src = repo.dirstate.copied(f)
3162 if src and src not in names and repo.dirstate[src] == 'r':
3162 if src and src not in names and repo.dirstate[src] == 'r':
3163 removed.add(src)
3163 removed.add(src)
3164 names[src] = (repo.pathto(src, cwd), True)
3164 names[src] = (repo.pathto(src, cwd), True)
3165
3165
3166 def removeforget(abs):
3166 def removeforget(abs):
3167 if repo.dirstate[abs] == 'a':
3167 if repo.dirstate[abs] == 'a':
3168 return _('forgetting %s\n')
3168 return _('forgetting %s\n')
3169 return _('removing %s\n')
3169 return _('removing %s\n')
3170
3170
3171 revert = ([], _('reverting %s\n'))
3171 revert = ([], _('reverting %s\n'))
3172 add = ([], _('adding %s\n'))
3172 add = ([], _('adding %s\n'))
3173 remove = ([], removeforget)
3173 remove = ([], removeforget)
3174 undelete = ([], _('undeleting %s\n'))
3174 undelete = ([], _('undeleting %s\n'))
3175
3175
3176 disptable = (
3176 disptable = (
3177 # dispatch table:
3177 # dispatch table:
3178 # file state
3178 # file state
3179 # action if in target manifest
3179 # action if in target manifest
3180 # action if not in target manifest
3180 # action if not in target manifest
3181 # make backup if in target manifest
3181 # make backup if in target manifest
3182 # make backup if not in target manifest
3182 # make backup if not in target manifest
3183 (modified, revert, remove, True, True),
3183 (modified, revert, remove, True, True),
3184 (added, revert, remove, True, False),
3184 (added, revert, remove, True, False),
3185 (removed, undelete, None, False, False),
3185 (removed, undelete, None, False, False),
3186 (deleted, revert, remove, False, False),
3186 (deleted, revert, remove, False, False),
3187 )
3187 )
3188
3188
3189 for abs, (rel, exact) in sorted(names.items()):
3189 for abs, (rel, exact) in sorted(names.items()):
3190 mfentry = mf.get(abs)
3190 mfentry = mf.get(abs)
3191 target = repo.wjoin(abs)
3191 target = repo.wjoin(abs)
3192 def handle(xlist, dobackup):
3192 def handle(xlist, dobackup):
3193 xlist[0].append(abs)
3193 xlist[0].append(abs)
3194 if (dobackup and not opts.get('no_backup') and
3194 if (dobackup and not opts.get('no_backup') and
3195 os.path.lexists(target)):
3195 os.path.lexists(target)):
3196 bakname = "%s.orig" % rel
3196 bakname = "%s.orig" % rel
3197 ui.note(_('saving current version of %s as %s\n') %
3197 ui.note(_('saving current version of %s as %s\n') %
3198 (rel, bakname))
3198 (rel, bakname))
3199 if not opts.get('dry_run'):
3199 if not opts.get('dry_run'):
3200 util.rename(target, bakname)
3200 util.rename(target, bakname)
3201 if ui.verbose or not exact:
3201 if ui.verbose or not exact:
3202 msg = xlist[1]
3202 msg = xlist[1]
3203 if not isinstance(msg, basestring):
3203 if not isinstance(msg, basestring):
3204 msg = msg(abs)
3204 msg = msg(abs)
3205 ui.status(msg % rel)
3205 ui.status(msg % rel)
3206 for table, hitlist, misslist, backuphit, backupmiss in disptable:
3206 for table, hitlist, misslist, backuphit, backupmiss in disptable:
3207 if abs not in table:
3207 if abs not in table:
3208 continue
3208 continue
3209 # file has changed in dirstate
3209 # file has changed in dirstate
3210 if mfentry:
3210 if mfentry:
3211 handle(hitlist, backuphit)
3211 handle(hitlist, backuphit)
3212 elif misslist is not None:
3212 elif misslist is not None:
3213 handle(misslist, backupmiss)
3213 handle(misslist, backupmiss)
3214 break
3214 break
3215 else:
3215 else:
3216 if abs not in repo.dirstate:
3216 if abs not in repo.dirstate:
3217 if mfentry:
3217 if mfentry:
3218 handle(add, True)
3218 handle(add, True)
3219 elif exact:
3219 elif exact:
3220 ui.warn(_('file not managed: %s\n') % rel)
3220 ui.warn(_('file not managed: %s\n') % rel)
3221 continue
3221 continue
3222 # file has not changed in dirstate
3222 # file has not changed in dirstate
3223 if node == parent:
3223 if node == parent:
3224 if exact:
3224 if exact:
3225 ui.warn(_('no changes needed to %s\n') % rel)
3225 ui.warn(_('no changes needed to %s\n') % rel)
3226 continue
3226 continue
3227 if pmf is None:
3227 if pmf is None:
3228 # only need parent manifest in this unlikely case,
3228 # only need parent manifest in this unlikely case,
3229 # so do not read by default
3229 # so do not read by default
3230 pmf = repo[parent].manifest()
3230 pmf = repo[parent].manifest()
3231 if abs in pmf:
3231 if abs in pmf:
3232 if mfentry:
3232 if mfentry:
3233 # if version of file is same in parent and target
3233 # if version of file is same in parent and target
3234 # manifests, do nothing
3234 # manifests, do nothing
3235 if (pmf[abs] != mfentry or
3235 if (pmf[abs] != mfentry or
3236 pmf.flags(abs) != mf.flags(abs)):
3236 pmf.flags(abs) != mf.flags(abs)):
3237 handle(revert, False)
3237 handle(revert, False)
3238 else:
3238 else:
3239 handle(remove, False)
3239 handle(remove, False)
3240
3240
3241 if not opts.get('dry_run'):
3241 if not opts.get('dry_run'):
3242 def checkout(f):
3242 def checkout(f):
3243 fc = ctx[f]
3243 fc = ctx[f]
3244 repo.wwrite(f, fc.data(), fc.flags())
3244 repo.wwrite(f, fc.data(), fc.flags())
3245
3245
3246 audit_path = util.path_auditor(repo.root)
3246 audit_path = util.path_auditor(repo.root)
3247 for f in remove[0]:
3247 for f in remove[0]:
3248 if repo.dirstate[f] == 'a':
3248 if repo.dirstate[f] == 'a':
3249 repo.dirstate.forget(f)
3249 repo.dirstate.forget(f)
3250 continue
3250 continue
3251 audit_path(f)
3251 audit_path(f)
3252 try:
3252 try:
3253 util.unlink(repo.wjoin(f))
3253 util.unlink(repo.wjoin(f))
3254 except OSError:
3254 except OSError:
3255 pass
3255 pass
3256 repo.dirstate.remove(f)
3256 repo.dirstate.remove(f)
3257
3257
3258 normal = None
3258 normal = None
3259 if node == parent:
3259 if node == parent:
3260 # We're reverting to our parent. If possible, we'd like status
3260 # We're reverting to our parent. If possible, we'd like status
3261 # to report the file as clean. We have to use normallookup for
3261 # to report the file as clean. We have to use normallookup for
3262 # merges to avoid losing information about merged/dirty files.
3262 # merges to avoid losing information about merged/dirty files.
3263 if p2 != nullid:
3263 if p2 != nullid:
3264 normal = repo.dirstate.normallookup
3264 normal = repo.dirstate.normallookup
3265 else:
3265 else:
3266 normal = repo.dirstate.normal
3266 normal = repo.dirstate.normal
3267 for f in revert[0]:
3267 for f in revert[0]:
3268 checkout(f)
3268 checkout(f)
3269 if normal:
3269 if normal:
3270 normal(f)
3270 normal(f)
3271
3271
3272 for f in add[0]:
3272 for f in add[0]:
3273 checkout(f)
3273 checkout(f)
3274 repo.dirstate.add(f)
3274 repo.dirstate.add(f)
3275
3275
3276 normal = repo.dirstate.normallookup
3276 normal = repo.dirstate.normallookup
3277 if node == parent and p2 == nullid:
3277 if node == parent and p2 == nullid:
3278 normal = repo.dirstate.normal
3278 normal = repo.dirstate.normal
3279 for f in undelete[0]:
3279 for f in undelete[0]:
3280 checkout(f)
3280 checkout(f)
3281 normal(f)
3281 normal(f)
3282
3282
3283 finally:
3283 finally:
3284 wlock.release()
3284 wlock.release()
3285
3285
3286 def rollback(ui, repo, **opts):
3286 def rollback(ui, repo, **opts):
3287 """roll back the last transaction (dangerous)
3287 """roll back the last transaction (dangerous)
3288
3288
3289 This command should be used with care. There is only one level of
3289 This command should be used with care. There is only one level of
3290 rollback, and there is no way to undo a rollback. It will also
3290 rollback, and there is no way to undo a rollback. It will also
3291 restore the dirstate at the time of the last transaction, losing
3291 restore the dirstate at the time of the last transaction, losing
3292 any dirstate changes since that time. This command does not alter
3292 any dirstate changes since that time. This command does not alter
3293 the working directory.
3293 the working directory.
3294
3294
3295 Transactions are used to encapsulate the effects of all commands
3295 Transactions are used to encapsulate the effects of all commands
3296 that create new changesets or propagate existing changesets into a
3296 that create new changesets or propagate existing changesets into a
3297 repository. For example, the following commands are transactional,
3297 repository. For example, the following commands are transactional,
3298 and their effects can be rolled back:
3298 and their effects can be rolled back:
3299
3299
3300 - commit
3300 - commit
3301 - import
3301 - import
3302 - pull
3302 - pull
3303 - push (with this repository as the destination)
3303 - push (with this repository as the destination)
3304 - unbundle
3304 - unbundle
3305
3305
3306 This command is not intended for use on public repositories. Once
3306 This command is not intended for use on public repositories. Once
3307 changes are visible for pull by other users, rolling a transaction
3307 changes are visible for pull by other users, rolling a transaction
3308 back locally is ineffective (someone else may already have pulled
3308 back locally is ineffective (someone else may already have pulled
3309 the changes). Furthermore, a race is possible with readers of the
3309 the changes). Furthermore, a race is possible with readers of the
3310 repository; for example an in-progress pull from the repository
3310 repository; for example an in-progress pull from the repository
3311 may fail if a rollback is performed.
3311 may fail if a rollback is performed.
3312
3312
3313 Returns 0 on success, 1 if no rollback data is available.
3313 Returns 0 on success, 1 if no rollback data is available.
3314 """
3314 """
3315 return repo.rollback(opts.get('dry_run'))
3315 return repo.rollback(opts.get('dry_run'))
3316
3316
3317 def root(ui, repo):
3317 def root(ui, repo):
3318 """print the root (top) of the current working directory
3318 """print the root (top) of the current working directory
3319
3319
3320 Print the root directory of the current repository.
3320 Print the root directory of the current repository.
3321
3321
3322 Returns 0 on success.
3322 Returns 0 on success.
3323 """
3323 """
3324 ui.write(repo.root + "\n")
3324 ui.write(repo.root + "\n")
3325
3325
3326 def serve(ui, repo, **opts):
3326 def serve(ui, repo, **opts):
3327 """start stand-alone webserver
3327 """start stand-alone webserver
3328
3328
3329 Start a local HTTP repository browser and pull server. You can use
3329 Start a local HTTP repository browser and pull server. You can use
3330 this for ad-hoc sharing and browsing of repositories. It is
3330 this for ad-hoc sharing and browsing of repositories. It is
3331 recommended to use a real web server to serve a repository for
3331 recommended to use a real web server to serve a repository for
3332 longer periods of time.
3332 longer periods of time.
3333
3333
3334 Please note that the server does not implement access control.
3334 Please note that the server does not implement access control.
3335 This means that, by default, anybody can read from the server and
3335 This means that, by default, anybody can read from the server and
3336 nobody can write to it by default. Set the ``web.allow_push``
3336 nobody can write to it by default. Set the ``web.allow_push``
3337 option to ``*`` to allow everybody to push to the server. You
3337 option to ``*`` to allow everybody to push to the server. You
3338 should use a real web server if you need to authenticate users.
3338 should use a real web server if you need to authenticate users.
3339
3339
3340 By default, the server logs accesses to stdout and errors to
3340 By default, the server logs accesses to stdout and errors to
3341 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
3341 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
3342 files.
3342 files.
3343
3343
3344 To have the server choose a free port number to listen on, specify
3344 To have the server choose a free port number to listen on, specify
3345 a port number of 0; in this case, the server will print the port
3345 a port number of 0; in this case, the server will print the port
3346 number it uses.
3346 number it uses.
3347
3347
3348 Returns 0 on success.
3348 Returns 0 on success.
3349 """
3349 """
3350
3350
3351 if opts["stdio"]:
3351 if opts["stdio"]:
3352 if repo is None:
3352 if repo is None:
3353 raise error.RepoError(_("There is no Mercurial repository here"
3353 raise error.RepoError(_("There is no Mercurial repository here"
3354 " (.hg not found)"))
3354 " (.hg not found)"))
3355 s = sshserver.sshserver(ui, repo)
3355 s = sshserver.sshserver(ui, repo)
3356 s.serve_forever()
3356 s.serve_forever()
3357
3357
3358 # this way we can check if something was given in the command-line
3358 # this way we can check if something was given in the command-line
3359 if opts.get('port'):
3359 if opts.get('port'):
3360 opts['port'] = util.getport(opts.get('port'))
3360 opts['port'] = util.getport(opts.get('port'))
3361
3361
3362 baseui = repo and repo.baseui or ui
3362 baseui = repo and repo.baseui or ui
3363 optlist = ("name templates style address port prefix ipv6"
3363 optlist = ("name templates style address port prefix ipv6"
3364 " accesslog errorlog certificate encoding")
3364 " accesslog errorlog certificate encoding")
3365 for o in optlist.split():
3365 for o in optlist.split():
3366 val = opts.get(o, '')
3366 val = opts.get(o, '')
3367 if val in (None, ''): # should check against default options instead
3367 if val in (None, ''): # should check against default options instead
3368 continue
3368 continue
3369 baseui.setconfig("web", o, val)
3369 baseui.setconfig("web", o, val)
3370 if repo and repo.ui != baseui:
3370 if repo and repo.ui != baseui:
3371 repo.ui.setconfig("web", o, val)
3371 repo.ui.setconfig("web", o, val)
3372
3372
3373 o = opts.get('web_conf') or opts.get('webdir_conf')
3373 o = opts.get('web_conf') or opts.get('webdir_conf')
3374 if not o:
3374 if not o:
3375 if not repo:
3375 if not repo:
3376 raise error.RepoError(_("There is no Mercurial repository"
3376 raise error.RepoError(_("There is no Mercurial repository"
3377 " here (.hg not found)"))
3377 " here (.hg not found)"))
3378 o = repo.root
3378 o = repo.root
3379
3379
3380 app = hgweb.hgweb(o, baseui=ui)
3380 app = hgweb.hgweb(o, baseui=ui)
3381
3381
3382 class service(object):
3382 class service(object):
3383 def init(self):
3383 def init(self):
3384 util.set_signal_handler()
3384 util.set_signal_handler()
3385 self.httpd = hgweb.server.create_server(ui, app)
3385 self.httpd = hgweb.server.create_server(ui, app)
3386
3386
3387 if opts['port'] and not ui.verbose:
3387 if opts['port'] and not ui.verbose:
3388 return
3388 return
3389
3389
3390 if self.httpd.prefix:
3390 if self.httpd.prefix:
3391 prefix = self.httpd.prefix.strip('/') + '/'
3391 prefix = self.httpd.prefix.strip('/') + '/'
3392 else:
3392 else:
3393 prefix = ''
3393 prefix = ''
3394
3394
3395 port = ':%d' % self.httpd.port
3395 port = ':%d' % self.httpd.port
3396 if port == ':80':
3396 if port == ':80':
3397 port = ''
3397 port = ''
3398
3398
3399 bindaddr = self.httpd.addr
3399 bindaddr = self.httpd.addr
3400 if bindaddr == '0.0.0.0':
3400 if bindaddr == '0.0.0.0':
3401 bindaddr = '*'
3401 bindaddr = '*'
3402 elif ':' in bindaddr: # IPv6
3402 elif ':' in bindaddr: # IPv6
3403 bindaddr = '[%s]' % bindaddr
3403 bindaddr = '[%s]' % bindaddr
3404
3404
3405 fqaddr = self.httpd.fqaddr
3405 fqaddr = self.httpd.fqaddr
3406 if ':' in fqaddr:
3406 if ':' in fqaddr:
3407 fqaddr = '[%s]' % fqaddr
3407 fqaddr = '[%s]' % fqaddr
3408 if opts['port']:
3408 if opts['port']:
3409 write = ui.status
3409 write = ui.status
3410 else:
3410 else:
3411 write = ui.write
3411 write = ui.write
3412 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
3412 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
3413 (fqaddr, port, prefix, bindaddr, self.httpd.port))
3413 (fqaddr, port, prefix, bindaddr, self.httpd.port))
3414
3414
3415 def run(self):
3415 def run(self):
3416 self.httpd.serve_forever()
3416 self.httpd.serve_forever()
3417
3417
3418 service = service()
3418 service = service()
3419
3419
3420 cmdutil.service(opts, initfn=service.init, runfn=service.run)
3420 cmdutil.service(opts, initfn=service.init, runfn=service.run)
3421
3421
3422 def status(ui, repo, *pats, **opts):
3422 def status(ui, repo, *pats, **opts):
3423 """show changed files in the working directory
3423 """show changed files in the working directory
3424
3424
3425 Show status of files in the repository. If names are given, only
3425 Show status of files in the repository. If names are given, only
3426 files that match are shown. Files that are clean or ignored or
3426 files that match are shown. Files that are clean or ignored or
3427 the source of a copy/move operation, are not listed unless
3427 the source of a copy/move operation, are not listed unless
3428 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
3428 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
3429 Unless options described with "show only ..." are given, the
3429 Unless options described with "show only ..." are given, the
3430 options -mardu are used.
3430 options -mardu are used.
3431
3431
3432 Option -q/--quiet hides untracked (unknown and ignored) files
3432 Option -q/--quiet hides untracked (unknown and ignored) files
3433 unless explicitly requested with -u/--unknown or -i/--ignored.
3433 unless explicitly requested with -u/--unknown or -i/--ignored.
3434
3434
3435 .. note::
3435 .. note::
3436 status may appear to disagree with diff if permissions have
3436 status may appear to disagree with diff if permissions have
3437 changed or a merge has occurred. The standard diff format does
3437 changed or a merge has occurred. The standard diff format does
3438 not report permission changes and diff only reports changes
3438 not report permission changes and diff only reports changes
3439 relative to one merge parent.
3439 relative to one merge parent.
3440
3440
3441 If one revision is given, it is used as the base revision.
3441 If one revision is given, it is used as the base revision.
3442 If two revisions are given, the differences between them are
3442 If two revisions are given, the differences between them are
3443 shown. The --change option can also be used as a shortcut to list
3443 shown. The --change option can also be used as a shortcut to list
3444 the changed files of a revision from its first parent.
3444 the changed files of a revision from its first parent.
3445
3445
3446 The codes used to show the status of files are::
3446 The codes used to show the status of files are::
3447
3447
3448 M = modified
3448 M = modified
3449 A = added
3449 A = added
3450 R = removed
3450 R = removed
3451 C = clean
3451 C = clean
3452 ! = missing (deleted by non-hg command, but still tracked)
3452 ! = missing (deleted by non-hg command, but still tracked)
3453 ? = not tracked
3453 ? = not tracked
3454 I = ignored
3454 I = ignored
3455 = origin of the previous file listed as A (added)
3455 = origin of the previous file listed as A (added)
3456
3456
3457 Returns 0 on success.
3457 Returns 0 on success.
3458 """
3458 """
3459
3459
3460 revs = opts.get('rev')
3460 revs = opts.get('rev')
3461 change = opts.get('change')
3461 change = opts.get('change')
3462
3462
3463 if revs and change:
3463 if revs and change:
3464 msg = _('cannot specify --rev and --change at the same time')
3464 msg = _('cannot specify --rev and --change at the same time')
3465 raise util.Abort(msg)
3465 raise util.Abort(msg)
3466 elif change:
3466 elif change:
3467 node2 = repo.lookup(change)
3467 node2 = repo.lookup(change)
3468 node1 = repo[node2].parents()[0].node()
3468 node1 = repo[node2].parents()[0].node()
3469 else:
3469 else:
3470 node1, node2 = cmdutil.revpair(repo, revs)
3470 node1, node2 = cmdutil.revpair(repo, revs)
3471
3471
3472 cwd = (pats and repo.getcwd()) or ''
3472 cwd = (pats and repo.getcwd()) or ''
3473 end = opts.get('print0') and '\0' or '\n'
3473 end = opts.get('print0') and '\0' or '\n'
3474 copy = {}
3474 copy = {}
3475 states = 'modified added removed deleted unknown ignored clean'.split()
3475 states = 'modified added removed deleted unknown ignored clean'.split()
3476 show = [k for k in states if opts.get(k)]
3476 show = [k for k in states if opts.get(k)]
3477 if opts.get('all'):
3477 if opts.get('all'):
3478 show += ui.quiet and (states[:4] + ['clean']) or states
3478 show += ui.quiet and (states[:4] + ['clean']) or states
3479 if not show:
3479 if not show:
3480 show = ui.quiet and states[:4] or states[:5]
3480 show = ui.quiet and states[:4] or states[:5]
3481
3481
3482 stat = repo.status(node1, node2, cmdutil.match(repo, pats, opts),
3482 stat = repo.status(node1, node2, cmdutil.match(repo, pats, opts),
3483 'ignored' in show, 'clean' in show, 'unknown' in show,
3483 'ignored' in show, 'clean' in show, 'unknown' in show,
3484 opts.get('subrepos'))
3484 opts.get('subrepos'))
3485 changestates = zip(states, 'MAR!?IC', stat)
3485 changestates = zip(states, 'MAR!?IC', stat)
3486
3486
3487 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
3487 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
3488 ctxn = repo[nullid]
3488 ctxn = repo[nullid]
3489 ctx1 = repo[node1]
3489 ctx1 = repo[node1]
3490 ctx2 = repo[node2]
3490 ctx2 = repo[node2]
3491 added = stat[1]
3491 added = stat[1]
3492 if node2 is None:
3492 if node2 is None:
3493 added = stat[0] + stat[1] # merged?
3493 added = stat[0] + stat[1] # merged?
3494
3494
3495 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
3495 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
3496 if k in added:
3496 if k in added:
3497 copy[k] = v
3497 copy[k] = v
3498 elif v in added:
3498 elif v in added:
3499 copy[v] = k
3499 copy[v] = k
3500
3500
3501 for state, char, files in changestates:
3501 for state, char, files in changestates:
3502 if state in show:
3502 if state in show:
3503 format = "%s %%s%s" % (char, end)
3503 format = "%s %%s%s" % (char, end)
3504 if opts.get('no_status'):
3504 if opts.get('no_status'):
3505 format = "%%s%s" % end
3505 format = "%%s%s" % end
3506
3506
3507 for f in files:
3507 for f in files:
3508 ui.write(format % repo.pathto(f, cwd),
3508 ui.write(format % repo.pathto(f, cwd),
3509 label='status.' + state)
3509 label='status.' + state)
3510 if f in copy:
3510 if f in copy:
3511 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
3511 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
3512 label='status.copied')
3512 label='status.copied')
3513
3513
3514 def summary(ui, repo, **opts):
3514 def summary(ui, repo, **opts):
3515 """summarize working directory state
3515 """summarize working directory state
3516
3516
3517 This generates a brief summary of the working directory state,
3517 This generates a brief summary of the working directory state,
3518 including parents, branch, commit status, and available updates.
3518 including parents, branch, commit status, and available updates.
3519
3519
3520 With the --remote option, this will check the default paths for
3520 With the --remote option, this will check the default paths for
3521 incoming and outgoing changes. This can be time-consuming.
3521 incoming and outgoing changes. This can be time-consuming.
3522
3522
3523 Returns 0 on success.
3523 Returns 0 on success.
3524 """
3524 """
3525
3525
3526 ctx = repo[None]
3526 ctx = repo[None]
3527 parents = ctx.parents()
3527 parents = ctx.parents()
3528 pnode = parents[0].node()
3528 pnode = parents[0].node()
3529
3529
3530 for p in parents:
3530 for p in parents:
3531 # label with log.changeset (instead of log.parent) since this
3531 # label with log.changeset (instead of log.parent) since this
3532 # shows a working directory parent *changeset*:
3532 # shows a working directory parent *changeset*:
3533 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
3533 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
3534 label='log.changeset')
3534 label='log.changeset')
3535 ui.write(' '.join(p.tags()), label='log.tag')
3535 ui.write(' '.join(p.tags()), label='log.tag')
3536 if p.rev() == -1:
3536 if p.rev() == -1:
3537 if not len(repo):
3537 if not len(repo):
3538 ui.write(_(' (empty repository)'))
3538 ui.write(_(' (empty repository)'))
3539 else:
3539 else:
3540 ui.write(_(' (no revision checked out)'))
3540 ui.write(_(' (no revision checked out)'))
3541 ui.write('\n')
3541 ui.write('\n')
3542 if p.description():
3542 if p.description():
3543 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
3543 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
3544 label='log.summary')
3544 label='log.summary')
3545
3545
3546 branch = ctx.branch()
3546 branch = ctx.branch()
3547 bheads = repo.branchheads(branch)
3547 bheads = repo.branchheads(branch)
3548 m = _('branch: %s\n') % branch
3548 m = _('branch: %s\n') % branch
3549 if branch != 'default':
3549 if branch != 'default':
3550 ui.write(m, label='log.branch')
3550 ui.write(m, label='log.branch')
3551 else:
3551 else:
3552 ui.status(m, label='log.branch')
3552 ui.status(m, label='log.branch')
3553
3553
3554 st = list(repo.status(unknown=True))[:6]
3554 st = list(repo.status(unknown=True))[:6]
3555
3555
3556 c = repo.dirstate.copies()
3556 c = repo.dirstate.copies()
3557 copied, renamed = [], []
3557 copied, renamed = [], []
3558 for d, s in c.iteritems():
3558 for d, s in c.iteritems():
3559 if s in st[2]:
3559 if s in st[2]:
3560 st[2].remove(s)
3560 st[2].remove(s)
3561 renamed.append(d)
3561 renamed.append(d)
3562 else:
3562 else:
3563 copied.append(d)
3563 copied.append(d)
3564 if d in st[1]:
3564 if d in st[1]:
3565 st[1].remove(d)
3565 st[1].remove(d)
3566 st.insert(3, renamed)
3566 st.insert(3, renamed)
3567 st.insert(4, copied)
3567 st.insert(4, copied)
3568
3568
3569 ms = mergemod.mergestate(repo)
3569 ms = mergemod.mergestate(repo)
3570 st.append([f for f in ms if ms[f] == 'u'])
3570 st.append([f for f in ms if ms[f] == 'u'])
3571
3571
3572 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
3572 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
3573 st.append(subs)
3573 st.append(subs)
3574
3574
3575 labels = [ui.label(_('%d modified'), 'status.modified'),
3575 labels = [ui.label(_('%d modified'), 'status.modified'),
3576 ui.label(_('%d added'), 'status.added'),
3576 ui.label(_('%d added'), 'status.added'),
3577 ui.label(_('%d removed'), 'status.removed'),
3577 ui.label(_('%d removed'), 'status.removed'),
3578 ui.label(_('%d renamed'), 'status.copied'),
3578 ui.label(_('%d renamed'), 'status.copied'),
3579 ui.label(_('%d copied'), 'status.copied'),
3579 ui.label(_('%d copied'), 'status.copied'),
3580 ui.label(_('%d deleted'), 'status.deleted'),
3580 ui.label(_('%d deleted'), 'status.deleted'),
3581 ui.label(_('%d unknown'), 'status.unknown'),
3581 ui.label(_('%d unknown'), 'status.unknown'),
3582 ui.label(_('%d ignored'), 'status.ignored'),
3582 ui.label(_('%d ignored'), 'status.ignored'),
3583 ui.label(_('%d unresolved'), 'resolve.unresolved'),
3583 ui.label(_('%d unresolved'), 'resolve.unresolved'),
3584 ui.label(_('%d subrepos'), 'status.modified')]
3584 ui.label(_('%d subrepos'), 'status.modified')]
3585 t = []
3585 t = []
3586 for s, l in zip(st, labels):
3586 for s, l in zip(st, labels):
3587 if s:
3587 if s:
3588 t.append(l % len(s))
3588 t.append(l % len(s))
3589
3589
3590 t = ', '.join(t)
3590 t = ', '.join(t)
3591 cleanworkdir = False
3591 cleanworkdir = False
3592
3592
3593 if len(parents) > 1:
3593 if len(parents) > 1:
3594 t += _(' (merge)')
3594 t += _(' (merge)')
3595 elif branch != parents[0].branch():
3595 elif branch != parents[0].branch():
3596 t += _(' (new branch)')
3596 t += _(' (new branch)')
3597 elif (parents[0].extra().get('close') and
3597 elif (parents[0].extra().get('close') and
3598 pnode in repo.branchheads(branch, closed=True)):
3598 pnode in repo.branchheads(branch, closed=True)):
3599 t += _(' (head closed)')
3599 t += _(' (head closed)')
3600 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
3600 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
3601 t += _(' (clean)')
3601 t += _(' (clean)')
3602 cleanworkdir = True
3602 cleanworkdir = True
3603 elif pnode not in bheads:
3603 elif pnode not in bheads:
3604 t += _(' (new branch head)')
3604 t += _(' (new branch head)')
3605
3605
3606 if cleanworkdir:
3606 if cleanworkdir:
3607 ui.status(_('commit: %s\n') % t.strip())
3607 ui.status(_('commit: %s\n') % t.strip())
3608 else:
3608 else:
3609 ui.write(_('commit: %s\n') % t.strip())
3609 ui.write(_('commit: %s\n') % t.strip())
3610
3610
3611 # all ancestors of branch heads - all ancestors of parent = new csets
3611 # all ancestors of branch heads - all ancestors of parent = new csets
3612 new = [0] * len(repo)
3612 new = [0] * len(repo)
3613 cl = repo.changelog
3613 cl = repo.changelog
3614 for a in [cl.rev(n) for n in bheads]:
3614 for a in [cl.rev(n) for n in bheads]:
3615 new[a] = 1
3615 new[a] = 1
3616 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
3616 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
3617 new[a] = 1
3617 new[a] = 1
3618 for a in [p.rev() for p in parents]:
3618 for a in [p.rev() for p in parents]:
3619 if a >= 0:
3619 if a >= 0:
3620 new[a] = 0
3620 new[a] = 0
3621 for a in cl.ancestors(*[p.rev() for p in parents]):
3621 for a in cl.ancestors(*[p.rev() for p in parents]):
3622 new[a] = 0
3622 new[a] = 0
3623 new = sum(new)
3623 new = sum(new)
3624
3624
3625 if new == 0:
3625 if new == 0:
3626 ui.status(_('update: (current)\n'))
3626 ui.status(_('update: (current)\n'))
3627 elif pnode not in bheads:
3627 elif pnode not in bheads:
3628 ui.write(_('update: %d new changesets (update)\n') % new)
3628 ui.write(_('update: %d new changesets (update)\n') % new)
3629 else:
3629 else:
3630 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
3630 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
3631 (new, len(bheads)))
3631 (new, len(bheads)))
3632
3632
3633 if opts.get('remote'):
3633 if opts.get('remote'):
3634 t = []
3634 t = []
3635 source, branches = hg.parseurl(ui.expandpath('default'))
3635 source, branches = hg.parseurl(ui.expandpath('default'))
3636 other = hg.repository(hg.remoteui(repo, {}), source)
3636 other = hg.repository(hg.remoteui(repo, {}), source)
3637 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
3637 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
3638 ui.debug('comparing with %s\n' % url.hidepassword(source))
3638 ui.debug('comparing with %s\n' % url.hidepassword(source))
3639 repo.ui.pushbuffer()
3639 repo.ui.pushbuffer()
3640 common, incoming, rheads = discovery.findcommonincoming(repo, other)
3640 common, incoming, rheads = discovery.findcommonincoming(repo, other)
3641 repo.ui.popbuffer()
3641 repo.ui.popbuffer()
3642 if incoming:
3642 if incoming:
3643 t.append(_('1 or more incoming'))
3643 t.append(_('1 or more incoming'))
3644
3644
3645 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
3645 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
3646 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3646 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3647 other = hg.repository(hg.remoteui(repo, {}), dest)
3647 other = hg.repository(hg.remoteui(repo, {}), dest)
3648 ui.debug('comparing with %s\n' % url.hidepassword(dest))
3648 ui.debug('comparing with %s\n' % url.hidepassword(dest))
3649 repo.ui.pushbuffer()
3649 repo.ui.pushbuffer()
3650 o = discovery.findoutgoing(repo, other)
3650 o = discovery.findoutgoing(repo, other)
3651 repo.ui.popbuffer()
3651 repo.ui.popbuffer()
3652 o = repo.changelog.nodesbetween(o, None)[0]
3652 o = repo.changelog.nodesbetween(o, None)[0]
3653 if o:
3653 if o:
3654 t.append(_('%d outgoing') % len(o))
3654 t.append(_('%d outgoing') % len(o))
3655
3655
3656 if t:
3656 if t:
3657 ui.write(_('remote: %s\n') % (', '.join(t)))
3657 ui.write(_('remote: %s\n') % (', '.join(t)))
3658 else:
3658 else:
3659 ui.status(_('remote: (synced)\n'))
3659 ui.status(_('remote: (synced)\n'))
3660
3660
3661 def tag(ui, repo, name1, *names, **opts):
3661 def tag(ui, repo, name1, *names, **opts):
3662 """add one or more tags for the current or given revision
3662 """add one or more tags for the current or given revision
3663
3663
3664 Name a particular revision using <name>.
3664 Name a particular revision using <name>.
3665
3665
3666 Tags are used to name particular revisions of the repository and are
3666 Tags are used to name particular revisions of the repository and are
3667 very useful to compare different revisions, to go back to significant
3667 very useful to compare different revisions, to go back to significant
3668 earlier versions or to mark branch points as releases, etc. Changing
3668 earlier versions or to mark branch points as releases, etc. Changing
3669 an existing tag is normally disallowed; use -f/--force to override.
3669 an existing tag is normally disallowed; use -f/--force to override.
3670
3670
3671 If no revision is given, the parent of the working directory is
3671 If no revision is given, the parent of the working directory is
3672 used, or tip if no revision is checked out.
3672 used, or tip if no revision is checked out.
3673
3673
3674 To facilitate version control, distribution, and merging of tags,
3674 To facilitate version control, distribution, and merging of tags,
3675 they are stored as a file named ".hgtags" which is managed similarly
3675 they are stored as a file named ".hgtags" which is managed similarly
3676 to other project files and can be hand-edited if necessary. This
3676 to other project files and can be hand-edited if necessary. This
3677 also means that tagging creates a new commit. The file
3677 also means that tagging creates a new commit. The file
3678 ".hg/localtags" is used for local tags (not shared among
3678 ".hg/localtags" is used for local tags (not shared among
3679 repositories).
3679 repositories).
3680
3680
3681 Tag commits are usually made at the head of a branch. If the parent
3681 Tag commits are usually made at the head of a branch. If the parent
3682 of the working directory is not a branch head, :hg:`tag` aborts; use
3682 of the working directory is not a branch head, :hg:`tag` aborts; use
3683 -f/--force to force the tag commit to be based on a non-head
3683 -f/--force to force the tag commit to be based on a non-head
3684 changeset.
3684 changeset.
3685
3685
3686 See :hg:`help dates` for a list of formats valid for -d/--date.
3686 See :hg:`help dates` for a list of formats valid for -d/--date.
3687
3687
3688 Since tag names have priority over branch names during revision
3688 Since tag names have priority over branch names during revision
3689 lookup, using an existing branch name as a tag name is discouraged.
3689 lookup, using an existing branch name as a tag name is discouraged.
3690
3690
3691 Returns 0 on success.
3691 Returns 0 on success.
3692 """
3692 """
3693
3693
3694 rev_ = "."
3694 rev_ = "."
3695 names = [t.strip() for t in (name1,) + names]
3695 names = [t.strip() for t in (name1,) + names]
3696 if len(names) != len(set(names)):
3696 if len(names) != len(set(names)):
3697 raise util.Abort(_('tag names must be unique'))
3697 raise util.Abort(_('tag names must be unique'))
3698 for n in names:
3698 for n in names:
3699 if n in ['tip', '.', 'null']:
3699 if n in ['tip', '.', 'null']:
3700 raise util.Abort(_('the name \'%s\' is reserved') % n)
3700 raise util.Abort(_('the name \'%s\' is reserved') % n)
3701 if not n:
3701 if not n:
3702 raise util.Abort(_('tag names cannot consist entirely of whitespace'))
3702 raise util.Abort(_('tag names cannot consist entirely of whitespace'))
3703 if opts.get('rev') and opts.get('remove'):
3703 if opts.get('rev') and opts.get('remove'):
3704 raise util.Abort(_("--rev and --remove are incompatible"))
3704 raise util.Abort(_("--rev and --remove are incompatible"))
3705 if opts.get('rev'):
3705 if opts.get('rev'):
3706 rev_ = opts['rev']
3706 rev_ = opts['rev']
3707 message = opts.get('message')
3707 message = opts.get('message')
3708 if opts.get('remove'):
3708 if opts.get('remove'):
3709 expectedtype = opts.get('local') and 'local' or 'global'
3709 expectedtype = opts.get('local') and 'local' or 'global'
3710 for n in names:
3710 for n in names:
3711 if not repo.tagtype(n):
3711 if not repo.tagtype(n):
3712 raise util.Abort(_('tag \'%s\' does not exist') % n)
3712 raise util.Abort(_('tag \'%s\' does not exist') % n)
3713 if repo.tagtype(n) != expectedtype:
3713 if repo.tagtype(n) != expectedtype:
3714 if expectedtype == 'global':
3714 if expectedtype == 'global':
3715 raise util.Abort(_('tag \'%s\' is not a global tag') % n)
3715 raise util.Abort(_('tag \'%s\' is not a global tag') % n)
3716 else:
3716 else:
3717 raise util.Abort(_('tag \'%s\' is not a local tag') % n)
3717 raise util.Abort(_('tag \'%s\' is not a local tag') % n)
3718 rev_ = nullid
3718 rev_ = nullid
3719 if not message:
3719 if not message:
3720 # we don't translate commit messages
3720 # we don't translate commit messages
3721 message = 'Removed tag %s' % ', '.join(names)
3721 message = 'Removed tag %s' % ', '.join(names)
3722 elif not opts.get('force'):
3722 elif not opts.get('force'):
3723 for n in names:
3723 for n in names:
3724 if n in repo.tags():
3724 if n in repo.tags():
3725 raise util.Abort(_('tag \'%s\' already exists '
3725 raise util.Abort(_('tag \'%s\' already exists '
3726 '(use -f to force)') % n)
3726 '(use -f to force)') % n)
3727 if not opts.get('local'):
3727 if not opts.get('local'):
3728 p1, p2 = repo.dirstate.parents()
3728 p1, p2 = repo.dirstate.parents()
3729 if p2 != nullid:
3729 if p2 != nullid:
3730 raise util.Abort(_('uncommitted merge'))
3730 raise util.Abort(_('uncommitted merge'))
3731 bheads = repo.branchheads()
3731 bheads = repo.branchheads()
3732 if not opts.get('force') and bheads and p1 not in bheads:
3732 if not opts.get('force') and bheads and p1 not in bheads:
3733 raise util.Abort(_('not at a branch head (use -f to force)'))
3733 raise util.Abort(_('not at a branch head (use -f to force)'))
3734 r = cmdutil.revsingle(repo, rev_).node()
3734 r = cmdutil.revsingle(repo, rev_).node()
3735
3735
3736 if not message:
3736 if not message:
3737 # we don't translate commit messages
3737 # we don't translate commit messages
3738 message = ('Added tag %s for changeset %s' %
3738 message = ('Added tag %s for changeset %s' %
3739 (', '.join(names), short(r)))
3739 (', '.join(names), short(r)))
3740
3740
3741 date = opts.get('date')
3741 date = opts.get('date')
3742 if date:
3742 if date:
3743 date = util.parsedate(date)
3743 date = util.parsedate(date)
3744
3744
3745 if opts.get('edit'):
3745 if opts.get('edit'):
3746 message = ui.edit(message, ui.username())
3746 message = ui.edit(message, ui.username())
3747
3747
3748 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
3748 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
3749
3749
3750 def tags(ui, repo):
3750 def tags(ui, repo):
3751 """list repository tags
3751 """list repository tags
3752
3752
3753 This lists both regular and local tags. When the -v/--verbose
3753 This lists both regular and local tags. When the -v/--verbose
3754 switch is used, a third column "local" is printed for local tags.
3754 switch is used, a third column "local" is printed for local tags.
3755
3755
3756 Returns 0 on success.
3756 Returns 0 on success.
3757 """
3757 """
3758
3758
3759 hexfunc = ui.debugflag and hex or short
3759 hexfunc = ui.debugflag and hex or short
3760 tagtype = ""
3760 tagtype = ""
3761
3761
3762 for t, n in reversed(repo.tagslist()):
3762 for t, n in reversed(repo.tagslist()):
3763 if ui.quiet:
3763 if ui.quiet:
3764 ui.write("%s\n" % t)
3764 ui.write("%s\n" % t)
3765 continue
3765 continue
3766
3766
3767 try:
3767 try:
3768 hn = hexfunc(n)
3768 hn = hexfunc(n)
3769 r = "%5d:%s" % (repo.changelog.rev(n), hn)
3769 r = "%5d:%s" % (repo.changelog.rev(n), hn)
3770 except error.LookupError:
3770 except error.LookupError:
3771 r = " ?:%s" % hn
3771 r = " ?:%s" % hn
3772 else:
3772 else:
3773 spaces = " " * (30 - encoding.colwidth(t))
3773 spaces = " " * (30 - encoding.colwidth(t))
3774 if ui.verbose:
3774 if ui.verbose:
3775 if repo.tagtype(t) == 'local':
3775 if repo.tagtype(t) == 'local':
3776 tagtype = " local"
3776 tagtype = " local"
3777 else:
3777 else:
3778 tagtype = ""
3778 tagtype = ""
3779 ui.write("%s%s %s%s\n" % (t, spaces, r, tagtype))
3779 ui.write("%s%s %s%s\n" % (t, spaces, r, tagtype))
3780
3780
3781 def tip(ui, repo, **opts):
3781 def tip(ui, repo, **opts):
3782 """show the tip revision
3782 """show the tip revision
3783
3783
3784 The tip revision (usually just called the tip) is the changeset
3784 The tip revision (usually just called the tip) is the changeset
3785 most recently added to the repository (and therefore the most
3785 most recently added to the repository (and therefore the most
3786 recently changed head).
3786 recently changed head).
3787
3787
3788 If you have just made a commit, that commit will be the tip. If
3788 If you have just made a commit, that commit will be the tip. If
3789 you have just pulled changes from another repository, the tip of
3789 you have just pulled changes from another repository, the tip of
3790 that repository becomes the current tip. The "tip" tag is special
3790 that repository becomes the current tip. The "tip" tag is special
3791 and cannot be renamed or assigned to a different changeset.
3791 and cannot be renamed or assigned to a different changeset.
3792
3792
3793 Returns 0 on success.
3793 Returns 0 on success.
3794 """
3794 """
3795 displayer = cmdutil.show_changeset(ui, repo, opts)
3795 displayer = cmdutil.show_changeset(ui, repo, opts)
3796 displayer.show(repo[len(repo) - 1])
3796 displayer.show(repo[len(repo) - 1])
3797 displayer.close()
3797 displayer.close()
3798
3798
3799 def unbundle(ui, repo, fname1, *fnames, **opts):
3799 def unbundle(ui, repo, fname1, *fnames, **opts):
3800 """apply one or more changegroup files
3800 """apply one or more changegroup files
3801
3801
3802 Apply one or more compressed changegroup files generated by the
3802 Apply one or more compressed changegroup files generated by the
3803 bundle command.
3803 bundle command.
3804
3804
3805 Returns 0 on success, 1 if an update has unresolved files.
3805 Returns 0 on success, 1 if an update has unresolved files.
3806 """
3806 """
3807 fnames = (fname1,) + fnames
3807 fnames = (fname1,) + fnames
3808
3808
3809 lock = repo.lock()
3809 lock = repo.lock()
3810 try:
3810 try:
3811 for fname in fnames:
3811 for fname in fnames:
3812 f = url.open(ui, fname)
3812 f = url.open(ui, fname)
3813 gen = changegroup.readbundle(f, fname)
3813 gen = changegroup.readbundle(f, fname)
3814 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname,
3814 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname,
3815 lock=lock)
3815 lock=lock)
3816 finally:
3816 finally:
3817 lock.release()
3817 lock.release()
3818
3818
3819 return postincoming(ui, repo, modheads, opts.get('update'), None)
3819 return postincoming(ui, repo, modheads, opts.get('update'), None)
3820
3820
3821 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
3821 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
3822 """update working directory (or switch revisions)
3822 """update working directory (or switch revisions)
3823
3823
3824 Update the repository's working directory to the specified
3824 Update the repository's working directory to the specified
3825 changeset. If no changeset is specified, update to the tip of the
3825 changeset. If no changeset is specified, update to the tip of the
3826 current named branch.
3826 current named branch.
3827
3827
3828 If the changeset is not a descendant of the working directory's
3828 If the changeset is not a descendant of the working directory's
3829 parent, the update is aborted. With the -c/--check option, the
3829 parent, the update is aborted. With the -c/--check option, the
3830 working directory is checked for uncommitted changes; if none are
3830 working directory is checked for uncommitted changes; if none are
3831 found, the working directory is updated to the specified
3831 found, the working directory is updated to the specified
3832 changeset.
3832 changeset.
3833
3833
3834 The following rules apply when the working directory contains
3834 The following rules apply when the working directory contains
3835 uncommitted changes:
3835 uncommitted changes:
3836
3836
3837 1. If neither -c/--check nor -C/--clean is specified, and if
3837 1. If neither -c/--check nor -C/--clean is specified, and if
3838 the requested changeset is an ancestor or descendant of
3838 the requested changeset is an ancestor or descendant of
3839 the working directory's parent, the uncommitted changes
3839 the working directory's parent, the uncommitted changes
3840 are merged into the requested changeset and the merged
3840 are merged into the requested changeset and the merged
3841 result is left uncommitted. If the requested changeset is
3841 result is left uncommitted. If the requested changeset is
3842 not an ancestor or descendant (that is, it is on another
3842 not an ancestor or descendant (that is, it is on another
3843 branch), the update is aborted and the uncommitted changes
3843 branch), the update is aborted and the uncommitted changes
3844 are preserved.
3844 are preserved.
3845
3845
3846 2. With the -c/--check option, the update is aborted and the
3846 2. With the -c/--check option, the update is aborted and the
3847 uncommitted changes are preserved.
3847 uncommitted changes are preserved.
3848
3848
3849 3. With the -C/--clean option, uncommitted changes are discarded and
3849 3. With the -C/--clean option, uncommitted changes are discarded and
3850 the working directory is updated to the requested changeset.
3850 the working directory is updated to the requested changeset.
3851
3851
3852 Use null as the changeset to remove the working directory (like
3852 Use null as the changeset to remove the working directory (like
3853 :hg:`clone -U`).
3853 :hg:`clone -U`).
3854
3854
3855 If you want to update just one file to an older changeset, use
3855 If you want to update just one file to an older changeset, use
3856 :hg:`revert`.
3856 :hg:`revert`.
3857
3857
3858 See :hg:`help dates` for a list of formats valid for -d/--date.
3858 See :hg:`help dates` for a list of formats valid for -d/--date.
3859
3859
3860 Returns 0 on success, 1 if there are unresolved files.
3860 Returns 0 on success, 1 if there are unresolved files.
3861 """
3861 """
3862 if rev and node:
3862 if rev and node:
3863 raise util.Abort(_("please specify just one revision"))
3863 raise util.Abort(_("please specify just one revision"))
3864
3864
3865 if not rev:
3865 if not rev:
3866 rev = node
3866 rev = node
3867
3867
3868 rev = cmdutil.revsingle(repo, rev, rev).rev()
3868 rev = cmdutil.revsingle(repo, rev, rev).rev()
3869
3869
3870 if check and clean:
3870 if check and clean:
3871 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
3871 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
3872
3872
3873 if check:
3873 if check:
3874 # we could use dirty() but we can ignore merge and branch trivia
3874 # we could use dirty() but we can ignore merge and branch trivia
3875 c = repo[None]
3875 c = repo[None]
3876 if c.modified() or c.added() or c.removed():
3876 if c.modified() or c.added() or c.removed():
3877 raise util.Abort(_("uncommitted local changes"))
3877 raise util.Abort(_("uncommitted local changes"))
3878
3878
3879 if date:
3879 if date:
3880 if rev:
3880 if rev:
3881 raise util.Abort(_("you can't specify a revision and a date"))
3881 raise util.Abort(_("you can't specify a revision and a date"))
3882 rev = cmdutil.finddate(ui, repo, date)
3882 rev = cmdutil.finddate(ui, repo, date)
3883
3883
3884 if clean or check:
3884 if clean or check:
3885 return hg.clean(repo, rev)
3885 return hg.clean(repo, rev)
3886 else:
3886 else:
3887 return hg.update(repo, rev)
3887 return hg.update(repo, rev)
3888
3888
3889 def verify(ui, repo):
3889 def verify(ui, repo):
3890 """verify the integrity of the repository
3890 """verify the integrity of the repository
3891
3891
3892 Verify the integrity of the current repository.
3892 Verify the integrity of the current repository.
3893
3893
3894 This will perform an extensive check of the repository's
3894 This will perform an extensive check of the repository's
3895 integrity, validating the hashes and checksums of each entry in
3895 integrity, validating the hashes and checksums of each entry in
3896 the changelog, manifest, and tracked files, as well as the
3896 the changelog, manifest, and tracked files, as well as the
3897 integrity of their crosslinks and indices.
3897 integrity of their crosslinks and indices.
3898
3898
3899 Returns 0 on success, 1 if errors are encountered.
3899 Returns 0 on success, 1 if errors are encountered.
3900 """
3900 """
3901 return hg.verify(repo)
3901 return hg.verify(repo)
3902
3902
3903 def version_(ui):
3903 def version_(ui):
3904 """output version and copyright information"""
3904 """output version and copyright information"""
3905 ui.write(_("Mercurial Distributed SCM (version %s)\n")
3905 ui.write(_("Mercurial Distributed SCM (version %s)\n")
3906 % util.version())
3906 % util.version())
3907 ui.status(_(
3907 ui.status(_(
3908 "(see http://mercurial.selenic.com for more information)\n"
3908 "(see http://mercurial.selenic.com for more information)\n"
3909 "\nCopyright (C) 2005-2010 Matt Mackall and others\n"
3909 "\nCopyright (C) 2005-2010 Matt Mackall and others\n"
3910 "This is free software; see the source for copying conditions. "
3910 "This is free software; see the source for copying conditions. "
3911 "There is NO\nwarranty; "
3911 "There is NO\nwarranty; "
3912 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
3912 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
3913 ))
3913 ))
3914
3914
3915 # Command options and aliases are listed here, alphabetically
3915 # Command options and aliases are listed here, alphabetically
3916
3916
3917 globalopts = [
3917 globalopts = [
3918 ('R', 'repository', '',
3918 ('R', 'repository', '',
3919 _('repository root directory or name of overlay bundle file'),
3919 _('repository root directory or name of overlay bundle file'),
3920 _('REPO')),
3920 _('REPO')),
3921 ('', 'cwd', '',
3921 ('', 'cwd', '',
3922 _('change working directory'), _('DIR')),
3922 _('change working directory'), _('DIR')),
3923 ('y', 'noninteractive', None,
3923 ('y', 'noninteractive', None,
3924 _('do not prompt, assume \'yes\' for any required answers')),
3924 _('do not prompt, assume \'yes\' for any required answers')),
3925 ('q', 'quiet', None, _('suppress output')),
3925 ('q', 'quiet', None, _('suppress output')),
3926 ('v', 'verbose', None, _('enable additional output')),
3926 ('v', 'verbose', None, _('enable additional output')),
3927 ('', 'config', [],
3927 ('', 'config', [],
3928 _('set/override config option (use \'section.name=value\')'),
3928 _('set/override config option (use \'section.name=value\')'),
3929 _('CONFIG')),
3929 _('CONFIG')),
3930 ('', 'debug', None, _('enable debugging output')),
3930 ('', 'debug', None, _('enable debugging output')),
3931 ('', 'debugger', None, _('start debugger')),
3931 ('', 'debugger', None, _('start debugger')),
3932 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
3932 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
3933 _('ENCODE')),
3933 _('ENCODE')),
3934 ('', 'encodingmode', encoding.encodingmode,
3934 ('', 'encodingmode', encoding.encodingmode,
3935 _('set the charset encoding mode'), _('MODE')),
3935 _('set the charset encoding mode'), _('MODE')),
3936 ('', 'traceback', None, _('always print a traceback on exception')),
3936 ('', 'traceback', None, _('always print a traceback on exception')),
3937 ('', 'time', None, _('time how long the command takes')),
3937 ('', 'time', None, _('time how long the command takes')),
3938 ('', 'profile', None, _('print command execution profile')),
3938 ('', 'profile', None, _('print command execution profile')),
3939 ('', 'version', None, _('output version information and exit')),
3939 ('', 'version', None, _('output version information and exit')),
3940 ('h', 'help', None, _('display help and exit')),
3940 ('h', 'help', None, _('display help and exit')),
3941 ]
3941 ]
3942
3942
3943 dryrunopts = [('n', 'dry-run', None,
3943 dryrunopts = [('n', 'dry-run', None,
3944 _('do not perform actions, just print output'))]
3944 _('do not perform actions, just print output'))]
3945
3945
3946 remoteopts = [
3946 remoteopts = [
3947 ('e', 'ssh', '',
3947 ('e', 'ssh', '',
3948 _('specify ssh command to use'), _('CMD')),
3948 _('specify ssh command to use'), _('CMD')),
3949 ('', 'remotecmd', '',
3949 ('', 'remotecmd', '',
3950 _('specify hg command to run on the remote side'), _('CMD')),
3950 _('specify hg command to run on the remote side'), _('CMD')),
3951 ]
3951 ]
3952
3952
3953 walkopts = [
3953 walkopts = [
3954 ('I', 'include', [],
3954 ('I', 'include', [],
3955 _('include names matching the given patterns'), _('PATTERN')),
3955 _('include names matching the given patterns'), _('PATTERN')),
3956 ('X', 'exclude', [],
3956 ('X', 'exclude', [],
3957 _('exclude names matching the given patterns'), _('PATTERN')),
3957 _('exclude names matching the given patterns'), _('PATTERN')),
3958 ]
3958 ]
3959
3959
3960 commitopts = [
3960 commitopts = [
3961 ('m', 'message', '',
3961 ('m', 'message', '',
3962 _('use text as commit message'), _('TEXT')),
3962 _('use text as commit message'), _('TEXT')),
3963 ('l', 'logfile', '',
3963 ('l', 'logfile', '',
3964 _('read commit message from file'), _('FILE')),
3964 _('read commit message from file'), _('FILE')),
3965 ]
3965 ]
3966
3966
3967 commitopts2 = [
3967 commitopts2 = [
3968 ('d', 'date', '',
3968 ('d', 'date', '',
3969 _('record datecode as commit date'), _('DATE')),
3969 _('record datecode as commit date'), _('DATE')),
3970 ('u', 'user', '',
3970 ('u', 'user', '',
3971 _('record the specified user as committer'), _('USER')),
3971 _('record the specified user as committer'), _('USER')),
3972 ]
3972 ]
3973
3973
3974 templateopts = [
3974 templateopts = [
3975 ('', 'style', '',
3975 ('', 'style', '',
3976 _('display using template map file'), _('STYLE')),
3976 _('display using template map file'), _('STYLE')),
3977 ('', 'template', '',
3977 ('', 'template', '',
3978 _('display with template'), _('TEMPLATE')),
3978 _('display with template'), _('TEMPLATE')),
3979 ]
3979 ]
3980
3980
3981 logopts = [
3981 logopts = [
3982 ('p', 'patch', None, _('show patch')),
3982 ('p', 'patch', None, _('show patch')),
3983 ('g', 'git', None, _('use git extended diff format')),
3983 ('g', 'git', None, _('use git extended diff format')),
3984 ('l', 'limit', '',
3984 ('l', 'limit', '',
3985 _('limit number of changes displayed'), _('NUM')),
3985 _('limit number of changes displayed'), _('NUM')),
3986 ('M', 'no-merges', None, _('do not show merges')),
3986 ('M', 'no-merges', None, _('do not show merges')),
3987 ('', 'stat', None, _('output diffstat-style summary of changes')),
3987 ('', 'stat', None, _('output diffstat-style summary of changes')),
3988 ] + templateopts
3988 ] + templateopts
3989
3989
3990 diffopts = [
3990 diffopts = [
3991 ('a', 'text', None, _('treat all files as text')),
3991 ('a', 'text', None, _('treat all files as text')),
3992 ('g', 'git', None, _('use git extended diff format')),
3992 ('g', 'git', None, _('use git extended diff format')),
3993 ('', 'nodates', None, _('omit dates from diff headers'))
3993 ('', 'nodates', None, _('omit dates from diff headers'))
3994 ]
3994 ]
3995
3995
3996 diffopts2 = [
3996 diffopts2 = [
3997 ('p', 'show-function', None, _('show which function each change is in')),
3997 ('p', 'show-function', None, _('show which function each change is in')),
3998 ('', 'reverse', None, _('produce a diff that undoes the changes')),
3998 ('', 'reverse', None, _('produce a diff that undoes the changes')),
3999 ('w', 'ignore-all-space', None,
3999 ('w', 'ignore-all-space', None,
4000 _('ignore white space when comparing lines')),
4000 _('ignore white space when comparing lines')),
4001 ('b', 'ignore-space-change', None,
4001 ('b', 'ignore-space-change', None,
4002 _('ignore changes in the amount of white space')),
4002 _('ignore changes in the amount of white space')),
4003 ('B', 'ignore-blank-lines', None,
4003 ('B', 'ignore-blank-lines', None,
4004 _('ignore changes whose lines are all blank')),
4004 _('ignore changes whose lines are all blank')),
4005 ('U', 'unified', '',
4005 ('U', 'unified', '',
4006 _('number of lines of context to show'), _('NUM')),
4006 _('number of lines of context to show'), _('NUM')),
4007 ('', 'stat', None, _('output diffstat-style summary of changes')),
4007 ('', 'stat', None, _('output diffstat-style summary of changes')),
4008 ]
4008 ]
4009
4009
4010 similarityopts = [
4010 similarityopts = [
4011 ('s', 'similarity', '',
4011 ('s', 'similarity', '',
4012 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
4012 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
4013 ]
4013 ]
4014
4014
4015 subrepoopts = [
4015 subrepoopts = [
4016 ('S', 'subrepos', None,
4016 ('S', 'subrepos', None,
4017 _('recurse into subrepositories'))
4017 _('recurse into subrepositories'))
4018 ]
4018 ]
4019
4019
4020 table = {
4020 table = {
4021 "^add": (add, walkopts + subrepoopts + dryrunopts,
4021 "^add": (add, walkopts + subrepoopts + dryrunopts,
4022 _('[OPTION]... [FILE]...')),
4022 _('[OPTION]... [FILE]...')),
4023 "addremove":
4023 "addremove":
4024 (addremove, similarityopts + walkopts + dryrunopts,
4024 (addremove, similarityopts + walkopts + dryrunopts,
4025 _('[OPTION]... [FILE]...')),
4025 _('[OPTION]... [FILE]...')),
4026 "^annotate|blame":
4026 "^annotate|blame":
4027 (annotate,
4027 (annotate,
4028 [('r', 'rev', '',
4028 [('r', 'rev', '',
4029 _('annotate the specified revision'), _('REV')),
4029 _('annotate the specified revision'), _('REV')),
4030 ('', 'follow', None,
4030 ('', 'follow', None,
4031 _('follow copies/renames and list the filename (DEPRECATED)')),
4031 _('follow copies/renames and list the filename (DEPRECATED)')),
4032 ('', 'no-follow', None, _("don't follow copies and renames")),
4032 ('', 'no-follow', None, _("don't follow copies and renames")),
4033 ('a', 'text', None, _('treat all files as text')),
4033 ('a', 'text', None, _('treat all files as text')),
4034 ('u', 'user', None, _('list the author (long with -v)')),
4034 ('u', 'user', None, _('list the author (long with -v)')),
4035 ('f', 'file', None, _('list the filename')),
4035 ('f', 'file', None, _('list the filename')),
4036 ('d', 'date', None, _('list the date (short with -q)')),
4036 ('d', 'date', None, _('list the date (short with -q)')),
4037 ('n', 'number', None, _('list the revision number (default)')),
4037 ('n', 'number', None, _('list the revision number (default)')),
4038 ('c', 'changeset', None, _('list the changeset')),
4038 ('c', 'changeset', None, _('list the changeset')),
4039 ('l', 'line-number', None,
4039 ('l', 'line-number', None,
4040 _('show line number at the first appearance'))
4040 _('show line number at the first appearance'))
4041 ] + walkopts,
4041 ] + walkopts,
4042 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...')),
4042 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...')),
4043 "archive":
4043 "archive":
4044 (archive,
4044 (archive,
4045 [('', 'no-decode', None, _('do not pass files through decoders')),
4045 [('', 'no-decode', None, _('do not pass files through decoders')),
4046 ('p', 'prefix', '',
4046 ('p', 'prefix', '',
4047 _('directory prefix for files in archive'), _('PREFIX')),
4047 _('directory prefix for files in archive'), _('PREFIX')),
4048 ('r', 'rev', '',
4048 ('r', 'rev', '',
4049 _('revision to distribute'), _('REV')),
4049 _('revision to distribute'), _('REV')),
4050 ('t', 'type', '',
4050 ('t', 'type', '',
4051 _('type of distribution to create'), _('TYPE')),
4051 _('type of distribution to create'), _('TYPE')),
4052 ] + subrepoopts + walkopts,
4052 ] + subrepoopts + walkopts,
4053 _('[OPTION]... DEST')),
4053 _('[OPTION]... DEST')),
4054 "backout":
4054 "backout":
4055 (backout,
4055 (backout,
4056 [('', 'merge', None,
4056 [('', 'merge', None,
4057 _('merge with old dirstate parent after backout')),
4057 _('merge with old dirstate parent after backout')),
4058 ('', 'parent', '',
4058 ('', 'parent', '',
4059 _('parent to choose when backing out merge'), _('REV')),
4059 _('parent to choose when backing out merge'), _('REV')),
4060 ('t', 'tool', '',
4060 ('t', 'tool', '',
4061 _('specify merge tool')),
4061 _('specify merge tool')),
4062 ('r', 'rev', '',
4062 ('r', 'rev', '',
4063 _('revision to backout'), _('REV')),
4063 _('revision to backout'), _('REV')),
4064 ] + walkopts + commitopts + commitopts2,
4064 ] + walkopts + commitopts + commitopts2,
4065 _('[OPTION]... [-r] REV')),
4065 _('[OPTION]... [-r] REV')),
4066 "bisect":
4066 "bisect":
4067 (bisect,
4067 (bisect,
4068 [('r', 'reset', False, _('reset bisect state')),
4068 [('r', 'reset', False, _('reset bisect state')),
4069 ('g', 'good', False, _('mark changeset good')),
4069 ('g', 'good', False, _('mark changeset good')),
4070 ('b', 'bad', False, _('mark changeset bad')),
4070 ('b', 'bad', False, _('mark changeset bad')),
4071 ('s', 'skip', False, _('skip testing changeset')),
4071 ('s', 'skip', False, _('skip testing changeset')),
4072 ('c', 'command', '',
4072 ('c', 'command', '',
4073 _('use command to check changeset state'), _('CMD')),
4073 _('use command to check changeset state'), _('CMD')),
4074 ('U', 'noupdate', False, _('do not update to target'))],
4074 ('U', 'noupdate', False, _('do not update to target'))],
4075 _("[-gbsr] [-U] [-c CMD] [REV]")),
4075 _("[-gbsr] [-U] [-c CMD] [REV]")),
4076 "branch":
4076 "branch":
4077 (branch,
4077 (branch,
4078 [('f', 'force', None,
4078 [('f', 'force', None,
4079 _('set branch name even if it shadows an existing branch')),
4079 _('set branch name even if it shadows an existing branch')),
4080 ('C', 'clean', None, _('reset branch name to parent branch name'))],
4080 ('C', 'clean', None, _('reset branch name to parent branch name'))],
4081 _('[-fC] [NAME]')),
4081 _('[-fC] [NAME]')),
4082 "branches":
4082 "branches":
4083 (branches,
4083 (branches,
4084 [('a', 'active', False,
4084 [('a', 'active', False,
4085 _('show only branches that have unmerged heads')),
4085 _('show only branches that have unmerged heads')),
4086 ('c', 'closed', False,
4086 ('c', 'closed', False,
4087 _('show normal and closed branches'))],
4087 _('show normal and closed branches'))],
4088 _('[-ac]')),
4088 _('[-ac]')),
4089 "bundle":
4089 "bundle":
4090 (bundle,
4090 (bundle,
4091 [('f', 'force', None,
4091 [('f', 'force', None,
4092 _('run even when the destination is unrelated')),
4092 _('run even when the destination is unrelated')),
4093 ('r', 'rev', [],
4093 ('r', 'rev', [],
4094 _('a changeset intended to be added to the destination'),
4094 _('a changeset intended to be added to the destination'),
4095 _('REV')),
4095 _('REV')),
4096 ('b', 'branch', [],
4096 ('b', 'branch', [],
4097 _('a specific branch you would like to bundle'),
4097 _('a specific branch you would like to bundle'),
4098 _('BRANCH')),
4098 _('BRANCH')),
4099 ('', 'base', [],
4099 ('', 'base', [],
4100 _('a base changeset assumed to be available at the destination'),
4100 _('a base changeset assumed to be available at the destination'),
4101 _('REV')),
4101 _('REV')),
4102 ('a', 'all', None, _('bundle all changesets in the repository')),
4102 ('a', 'all', None, _('bundle all changesets in the repository')),
4103 ('t', 'type', 'bzip2',
4103 ('t', 'type', 'bzip2',
4104 _('bundle compression type to use'), _('TYPE')),
4104 _('bundle compression type to use'), _('TYPE')),
4105 ] + remoteopts,
4105 ] + remoteopts,
4106 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]')),
4106 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]')),
4107 "cat":
4107 "cat":
4108 (cat,
4108 (cat,
4109 [('o', 'output', '',
4109 [('o', 'output', '',
4110 _('print output to file with formatted name'), _('FORMAT')),
4110 _('print output to file with formatted name'), _('FORMAT')),
4111 ('r', 'rev', '',
4111 ('r', 'rev', '',
4112 _('print the given revision'), _('REV')),
4112 _('print the given revision'), _('REV')),
4113 ('', 'decode', None, _('apply any matching decode filter')),
4113 ('', 'decode', None, _('apply any matching decode filter')),
4114 ] + walkopts,
4114 ] + walkopts,
4115 _('[OPTION]... FILE...')),
4115 _('[OPTION]... FILE...')),
4116 "^clone":
4116 "^clone":
4117 (clone,
4117 (clone,
4118 [('U', 'noupdate', None,
4118 [('U', 'noupdate', None,
4119 _('the clone will include an empty working copy (only a repository)')),
4119 _('the clone will include an empty working copy (only a repository)')),
4120 ('u', 'updaterev', '',
4120 ('u', 'updaterev', '',
4121 _('revision, tag or branch to check out'), _('REV')),
4121 _('revision, tag or branch to check out'), _('REV')),
4122 ('r', 'rev', [],
4122 ('r', 'rev', [],
4123 _('include the specified changeset'), _('REV')),
4123 _('include the specified changeset'), _('REV')),
4124 ('b', 'branch', [],
4124 ('b', 'branch', [],
4125 _('clone only the specified branch'), _('BRANCH')),
4125 _('clone only the specified branch'), _('BRANCH')),
4126 ('', 'pull', None, _('use pull protocol to copy metadata')),
4126 ('', 'pull', None, _('use pull protocol to copy metadata')),
4127 ('', 'uncompressed', None,
4127 ('', 'uncompressed', None,
4128 _('use uncompressed transfer (fast over LAN)')),
4128 _('use uncompressed transfer (fast over LAN)')),
4129 ] + remoteopts,
4129 ] + remoteopts,
4130 _('[OPTION]... SOURCE [DEST]')),
4130 _('[OPTION]... SOURCE [DEST]')),
4131 "^commit|ci":
4131 "^commit|ci":
4132 (commit,
4132 (commit,
4133 [('A', 'addremove', None,
4133 [('A', 'addremove', None,
4134 _('mark new/missing files as added/removed before committing')),
4134 _('mark new/missing files as added/removed before committing')),
4135 ('', 'close-branch', None,
4135 ('', 'close-branch', None,
4136 _('mark a branch as closed, hiding it from the branch list')),
4136 _('mark a branch as closed, hiding it from the branch list')),
4137 ] + walkopts + commitopts + commitopts2,
4137 ] + walkopts + commitopts + commitopts2,
4138 _('[OPTION]... [FILE]...')),
4138 _('[OPTION]... [FILE]...')),
4139 "copy|cp":
4139 "copy|cp":
4140 (copy,
4140 (copy,
4141 [('A', 'after', None, _('record a copy that has already occurred')),
4141 [('A', 'after', None, _('record a copy that has already occurred')),
4142 ('f', 'force', None,
4142 ('f', 'force', None,
4143 _('forcibly copy over an existing managed file')),
4143 _('forcibly copy over an existing managed file')),
4144 ] + walkopts + dryrunopts,
4144 ] + walkopts + dryrunopts,
4145 _('[OPTION]... [SOURCE]... DEST')),
4145 _('[OPTION]... [SOURCE]... DEST')),
4146 "debugancestor": (debugancestor, [], _('[INDEX] REV1 REV2')),
4146 "debugancestor": (debugancestor, [], _('[INDEX] REV1 REV2')),
4147 "debugbuilddag":
4147 "debugbuilddag":
4148 (debugbuilddag,
4148 (debugbuilddag,
4149 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
4149 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
4150 ('a', 'appended-file', None, _('add single file all revs append to')),
4150 ('a', 'appended-file', None, _('add single file all revs append to')),
4151 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
4151 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
4152 ('n', 'new-file', None, _('add new file at each rev')),
4152 ('n', 'new-file', None, _('add new file at each rev')),
4153 ],
4153 ],
4154 _('[OPTION]... TEXT')),
4154 _('[OPTION]... TEXT')),
4155 "debugcheckstate": (debugcheckstate, [], ''),
4155 "debugcheckstate": (debugcheckstate, [], ''),
4156 "debugcommands": (debugcommands, [], _('[COMMAND]')),
4156 "debugcommands": (debugcommands, [], _('[COMMAND]')),
4157 "debugcomplete":
4157 "debugcomplete":
4158 (debugcomplete,
4158 (debugcomplete,
4159 [('o', 'options', None, _('show the command options'))],
4159 [('o', 'options', None, _('show the command options'))],
4160 _('[-o] CMD')),
4160 _('[-o] CMD')),
4161 "debugdag":
4161 "debugdag":
4162 (debugdag,
4162 (debugdag,
4163 [('t', 'tags', None, _('use tags as labels')),
4163 [('t', 'tags', None, _('use tags as labels')),
4164 ('b', 'branches', None, _('annotate with branch names')),
4164 ('b', 'branches', None, _('annotate with branch names')),
4165 ('', 'dots', None, _('use dots for runs')),
4165 ('', 'dots', None, _('use dots for runs')),
4166 ('s', 'spaces', None, _('separate elements by spaces')),
4166 ('s', 'spaces', None, _('separate elements by spaces')),
4167 ],
4167 ],
4168 _('[OPTION]... [FILE [REV]...]')),
4168 _('[OPTION]... [FILE [REV]...]')),
4169 "debugdate":
4169 "debugdate":
4170 (debugdate,
4170 (debugdate,
4171 [('e', 'extended', None, _('try extended date formats'))],
4171 [('e', 'extended', None, _('try extended date formats'))],
4172 _('[-e] DATE [RANGE]')),
4172 _('[-e] DATE [RANGE]')),
4173 "debugdata": (debugdata, [], _('FILE REV')),
4173 "debugdata": (debugdata, [], _('FILE REV')),
4174 "debugfsinfo": (debugfsinfo, [], _('[PATH]')),
4174 "debugfsinfo": (debugfsinfo, [], _('[PATH]')),
4175 "debugindex": (debugindex,
4175 "debugindex": (debugindex,
4176 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
4176 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
4177 _('FILE')),
4177 _('FILE')),
4178 "debugindexdot": (debugindexdot, [], _('FILE')),
4178 "debugindexdot": (debugindexdot, [], _('FILE')),
4179 "debuginstall": (debuginstall, [], ''),
4179 "debuginstall": (debuginstall, [], ''),
4180 "debugpushkey": (debugpushkey, [], _('REPO NAMESPACE [KEY OLD NEW]')),
4180 "debugpushkey": (debugpushkey, [], _('REPO NAMESPACE [KEY OLD NEW]')),
4181 "debugrebuildstate":
4181 "debugrebuildstate":
4182 (debugrebuildstate,
4182 (debugrebuildstate,
4183 [('r', 'rev', '',
4183 [('r', 'rev', '',
4184 _('revision to rebuild to'), _('REV'))],
4184 _('revision to rebuild to'), _('REV'))],
4185 _('[-r REV] [REV]')),
4185 _('[-r REV] [REV]')),
4186 "debugrename":
4186 "debugrename":
4187 (debugrename,
4187 (debugrename,
4188 [('r', 'rev', '',
4188 [('r', 'rev', '',
4189 _('revision to debug'), _('REV'))],
4189 _('revision to debug'), _('REV'))],
4190 _('[-r REV] FILE')),
4190 _('[-r REV] FILE')),
4191 "debugrevspec":
4191 "debugrevspec":
4192 (debugrevspec, [], ('REVSPEC')),
4192 (debugrevspec, [], ('REVSPEC')),
4193 "debugsetparents":
4193 "debugsetparents":
4194 (debugsetparents, [], _('REV1 [REV2]')),
4194 (debugsetparents, [], _('REV1 [REV2]')),
4195 "debugstate":
4195 "debugstate":
4196 (debugstate,
4196 (debugstate,
4197 [('', 'nodates', None, _('do not display the saved mtime'))],
4197 [('', 'nodates', None, _('do not display the saved mtime'))],
4198 _('[OPTION]...')),
4198 _('[OPTION]...')),
4199 "debugsub":
4199 "debugsub":
4200 (debugsub,
4200 (debugsub,
4201 [('r', 'rev', '',
4201 [('r', 'rev', '',
4202 _('revision to check'), _('REV'))],
4202 _('revision to check'), _('REV'))],
4203 _('[-r REV] [REV]')),
4203 _('[-r REV] [REV]')),
4204 "debugwalk": (debugwalk, walkopts, _('[OPTION]... [FILE]...')),
4204 "debugwalk": (debugwalk, walkopts, _('[OPTION]... [FILE]...')),
4205 "^diff":
4205 "^diff":
4206 (diff,
4206 (diff,
4207 [('r', 'rev', [],
4207 [('r', 'rev', [],
4208 _('revision'), _('REV')),
4208 _('revision'), _('REV')),
4209 ('c', 'change', '',
4209 ('c', 'change', '',
4210 _('change made by revision'), _('REV'))
4210 _('change made by revision'), _('REV'))
4211 ] + diffopts + diffopts2 + walkopts + subrepoopts,
4211 ] + diffopts + diffopts2 + walkopts + subrepoopts,
4212 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...')),
4212 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...')),
4213 "^export":
4213 "^export":
4214 (export,
4214 (export,
4215 [('o', 'output', '',
4215 [('o', 'output', '',
4216 _('print output to file with formatted name'), _('FORMAT')),
4216 _('print output to file with formatted name'), _('FORMAT')),
4217 ('', 'switch-parent', None, _('diff against the second parent')),
4217 ('', 'switch-parent', None, _('diff against the second parent')),
4218 ('r', 'rev', [],
4218 ('r', 'rev', [],
4219 _('revisions to export'), _('REV')),
4219 _('revisions to export'), _('REV')),
4220 ] + diffopts,
4220 ] + diffopts,
4221 _('[OPTION]... [-o OUTFILESPEC] REV...')),
4221 _('[OPTION]... [-o OUTFILESPEC] REV...')),
4222 "^forget":
4222 "^forget":
4223 (forget,
4223 (forget,
4224 [] + walkopts,
4224 [] + walkopts,
4225 _('[OPTION]... FILE...')),
4225 _('[OPTION]... FILE...')),
4226 "grep":
4226 "grep":
4227 (grep,
4227 (grep,
4228 [('0', 'print0', None, _('end fields with NUL')),
4228 [('0', 'print0', None, _('end fields with NUL')),
4229 ('', 'all', None, _('print all revisions that match')),
4229 ('', 'all', None, _('print all revisions that match')),
4230 ('f', 'follow', None,
4230 ('f', 'follow', None,
4231 _('follow changeset history,'
4231 _('follow changeset history,'
4232 ' or file history across copies and renames')),
4232 ' or file history across copies and renames')),
4233 ('i', 'ignore-case', None, _('ignore case when matching')),
4233 ('i', 'ignore-case', None, _('ignore case when matching')),
4234 ('l', 'files-with-matches', None,
4234 ('l', 'files-with-matches', None,
4235 _('print only filenames and revisions that match')),
4235 _('print only filenames and revisions that match')),
4236 ('n', 'line-number', None, _('print matching line numbers')),
4236 ('n', 'line-number', None, _('print matching line numbers')),
4237 ('r', 'rev', [],
4237 ('r', 'rev', [],
4238 _('only search files changed within revision range'), _('REV')),
4238 _('only search files changed within revision range'), _('REV')),
4239 ('u', 'user', None, _('list the author (long with -v)')),
4239 ('u', 'user', None, _('list the author (long with -v)')),
4240 ('d', 'date', None, _('list the date (short with -q)')),
4240 ('d', 'date', None, _('list the date (short with -q)')),
4241 ] + walkopts,
4241 ] + walkopts,
4242 _('[OPTION]... PATTERN [FILE]...')),
4242 _('[OPTION]... PATTERN [FILE]...')),
4243 "heads":
4243 "heads":
4244 (heads,
4244 (heads,
4245 [('r', 'rev', '',
4245 [('r', 'rev', '',
4246 _('show only heads which are descendants of STARTREV'),
4246 _('show only heads which are descendants of STARTREV'),
4247 _('STARTREV')),
4247 _('STARTREV')),
4248 ('t', 'topo', False, _('show topological heads only')),
4248 ('t', 'topo', False, _('show topological heads only')),
4249 ('a', 'active', False,
4249 ('a', 'active', False,
4250 _('show active branchheads only (DEPRECATED)')),
4250 _('show active branchheads only (DEPRECATED)')),
4251 ('c', 'closed', False,
4251 ('c', 'closed', False,
4252 _('show normal and closed branch heads')),
4252 _('show normal and closed branch heads')),
4253 ] + templateopts,
4253 ] + templateopts,
4254 _('[-ac] [-r STARTREV] [REV]...')),
4254 _('[-ac] [-r STARTREV] [REV]...')),
4255 "help": (help_, [], _('[TOPIC]')),
4255 "help": (help_, [], _('[TOPIC]')),
4256 "identify|id":
4256 "identify|id":
4257 (identify,
4257 (identify,
4258 [('r', 'rev', '',
4258 [('r', 'rev', '',
4259 _('identify the specified revision'), _('REV')),
4259 _('identify the specified revision'), _('REV')),
4260 ('n', 'num', None, _('show local revision number')),
4260 ('n', 'num', None, _('show local revision number')),
4261 ('i', 'id', None, _('show global revision id')),
4261 ('i', 'id', None, _('show global revision id')),
4262 ('b', 'branch', None, _('show branch')),
4262 ('b', 'branch', None, _('show branch')),
4263 ('t', 'tags', None, _('show tags'))],
4263 ('t', 'tags', None, _('show tags'))],
4264 _('[-nibt] [-r REV] [SOURCE]')),
4264 _('[-nibt] [-r REV] [SOURCE]')),
4265 "import|patch":
4265 "import|patch":
4266 (import_,
4266 (import_,
4267 [('p', 'strip', 1,
4267 [('p', 'strip', 1,
4268 _('directory strip option for patch. This has the same '
4268 _('directory strip option for patch. This has the same '
4269 'meaning as the corresponding patch option'),
4269 'meaning as the corresponding patch option'),
4270 _('NUM')),
4270 _('NUM')),
4271 ('b', 'base', '',
4271 ('b', 'base', '',
4272 _('base path'), _('PATH')),
4272 _('base path'), _('PATH')),
4273 ('f', 'force', None,
4273 ('f', 'force', None,
4274 _('skip check for outstanding uncommitted changes')),
4274 _('skip check for outstanding uncommitted changes')),
4275 ('', 'no-commit', None,
4275 ('', 'no-commit', None,
4276 _("don't commit, just update the working directory")),
4276 _("don't commit, just update the working directory")),
4277 ('', 'exact', None,
4277 ('', 'exact', None,
4278 _('apply patch to the nodes from which it was generated')),
4278 _('apply patch to the nodes from which it was generated')),
4279 ('', 'import-branch', None,
4279 ('', 'import-branch', None,
4280 _('use any branch information in patch (implied by --exact)'))] +
4280 _('use any branch information in patch (implied by --exact)'))] +
4281 commitopts + commitopts2 + similarityopts,
4281 commitopts + commitopts2 + similarityopts,
4282 _('[OPTION]... PATCH...')),
4282 _('[OPTION]... PATCH...')),
4283 "incoming|in":
4283 "incoming|in":
4284 (incoming,
4284 (incoming,
4285 [('f', 'force', None,
4285 [('f', 'force', None,
4286 _('run even if remote repository is unrelated')),
4286 _('run even if remote repository is unrelated')),
4287 ('n', 'newest-first', None, _('show newest record first')),
4287 ('n', 'newest-first', None, _('show newest record first')),
4288 ('', 'bundle', '',
4288 ('', 'bundle', '',
4289 _('file to store the bundles into'), _('FILE')),
4289 _('file to store the bundles into'), _('FILE')),
4290 ('r', 'rev', [],
4290 ('r', 'rev', [],
4291 _('a remote changeset intended to be added'), _('REV')),
4291 _('a remote changeset intended to be added'), _('REV')),
4292 ('b', 'branch', [],
4292 ('b', 'branch', [],
4293 _('a specific branch you would like to pull'), _('BRANCH')),
4293 _('a specific branch you would like to pull'), _('BRANCH')),
4294 ] + logopts + remoteopts + subrepoopts,
4294 ] + logopts + remoteopts + subrepoopts,
4295 _('[-p] [-n] [-M] [-f] [-r REV]...'
4295 _('[-p] [-n] [-M] [-f] [-r REV]...'
4296 ' [--bundle FILENAME] [SOURCE]')),
4296 ' [--bundle FILENAME] [SOURCE]')),
4297 "^init":
4297 "^init":
4298 (init,
4298 (init,
4299 remoteopts,
4299 remoteopts,
4300 _('[-e CMD] [--remotecmd CMD] [DEST]')),
4300 _('[-e CMD] [--remotecmd CMD] [DEST]')),
4301 "locate":
4301 "locate":
4302 (locate,
4302 (locate,
4303 [('r', 'rev', '',
4303 [('r', 'rev', '',
4304 _('search the repository as it is in REV'), _('REV')),
4304 _('search the repository as it is in REV'), _('REV')),
4305 ('0', 'print0', None,
4305 ('0', 'print0', None,
4306 _('end filenames with NUL, for use with xargs')),
4306 _('end filenames with NUL, for use with xargs')),
4307 ('f', 'fullpath', None,
4307 ('f', 'fullpath', None,
4308 _('print complete paths from the filesystem root')),
4308 _('print complete paths from the filesystem root')),
4309 ] + walkopts,
4309 ] + walkopts,
4310 _('[OPTION]... [PATTERN]...')),
4310 _('[OPTION]... [PATTERN]...')),
4311 "^log|history":
4311 "^log|history":
4312 (log,
4312 (log,
4313 [('f', 'follow', None,
4313 [('f', 'follow', None,
4314 _('follow changeset history,'
4314 _('follow changeset history,'
4315 ' or file history across copies and renames')),
4315 ' or file history across copies and renames')),
4316 ('', 'follow-first', None,
4316 ('', 'follow-first', None,
4317 _('only follow the first parent of merge changesets')),
4317 _('only follow the first parent of merge changesets')),
4318 ('d', 'date', '',
4318 ('d', 'date', '',
4319 _('show revisions matching date spec'), _('DATE')),
4319 _('show revisions matching date spec'), _('DATE')),
4320 ('C', 'copies', None, _('show copied files')),
4320 ('C', 'copies', None, _('show copied files')),
4321 ('k', 'keyword', [],
4321 ('k', 'keyword', [],
4322 _('do case-insensitive search for a given text'), _('TEXT')),
4322 _('do case-insensitive search for a given text'), _('TEXT')),
4323 ('r', 'rev', [],
4323 ('r', 'rev', [],
4324 _('show the specified revision or range'), _('REV')),
4324 _('show the specified revision or range'), _('REV')),
4325 ('', 'removed', None, _('include revisions where files were removed')),
4325 ('', 'removed', None, _('include revisions where files were removed')),
4326 ('m', 'only-merges', None, _('show only merges')),
4326 ('m', 'only-merges', None, _('show only merges')),
4327 ('u', 'user', [],
4327 ('u', 'user', [],
4328 _('revisions committed by user'), _('USER')),
4328 _('revisions committed by user'), _('USER')),
4329 ('', 'only-branch', [],
4329 ('', 'only-branch', [],
4330 _('show only changesets within the given named branch (DEPRECATED)'),
4330 _('show only changesets within the given named branch (DEPRECATED)'),
4331 _('BRANCH')),
4331 _('BRANCH')),
4332 ('b', 'branch', [],
4332 ('b', 'branch', [],
4333 _('show changesets within the given named branch'), _('BRANCH')),
4333 _('show changesets within the given named branch'), _('BRANCH')),
4334 ('P', 'prune', [],
4334 ('P', 'prune', [],
4335 _('do not display revision or any of its ancestors'), _('REV')),
4335 _('do not display revision or any of its ancestors'), _('REV')),
4336 ] + logopts + walkopts,
4336 ] + logopts + walkopts,
4337 _('[OPTION]... [FILE]')),
4337 _('[OPTION]... [FILE]')),
4338 "manifest":
4338 "manifest":
4339 (manifest,
4339 (manifest,
4340 [('r', 'rev', '',
4340 [('r', 'rev', '',
4341 _('revision to display'), _('REV'))],
4341 _('revision to display'), _('REV'))],
4342 _('[-r REV]')),
4342 _('[-r REV]')),
4343 "^merge":
4343 "^merge":
4344 (merge,
4344 (merge,
4345 [('f', 'force', None, _('force a merge with outstanding changes')),
4345 [('f', 'force', None, _('force a merge with outstanding changes')),
4346 ('t', 'tool', '', _('specify merge tool')),
4346 ('t', 'tool', '', _('specify merge tool')),
4347 ('r', 'rev', '',
4347 ('r', 'rev', '',
4348 _('revision to merge'), _('REV')),
4348 _('revision to merge'), _('REV')),
4349 ('P', 'preview', None,
4349 ('P', 'preview', None,
4350 _('review revisions to merge (no merge is performed)'))],
4350 _('review revisions to merge (no merge is performed)'))],
4351 _('[-P] [-f] [[-r] REV]')),
4351 _('[-P] [-f] [[-r] REV]')),
4352 "outgoing|out":
4352 "outgoing|out":
4353 (outgoing,
4353 (outgoing,
4354 [('f', 'force', None,
4354 [('f', 'force', None,
4355 _('run even when the destination is unrelated')),
4355 _('run even when the destination is unrelated')),
4356 ('r', 'rev', [],
4356 ('r', 'rev', [],
4357 _('a changeset intended to be included in the destination'),
4357 _('a changeset intended to be included in the destination'),
4358 _('REV')),
4358 _('REV')),
4359 ('n', 'newest-first', None, _('show newest record first')),
4359 ('n', 'newest-first', None, _('show newest record first')),
4360 ('b', 'branch', [],
4360 ('b', 'branch', [],
4361 _('a specific branch you would like to push'), _('BRANCH')),
4361 _('a specific branch you would like to push'), _('BRANCH')),
4362 ] + logopts + remoteopts + subrepoopts,
4362 ] + logopts + remoteopts + subrepoopts,
4363 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]')),
4363 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]')),
4364 "parents":
4364 "parents":
4365 (parents,
4365 (parents,
4366 [('r', 'rev', '',
4366 [('r', 'rev', '',
4367 _('show parents of the specified revision'), _('REV')),
4367 _('show parents of the specified revision'), _('REV')),
4368 ] + templateopts,
4368 ] + templateopts,
4369 _('[-r REV] [FILE]')),
4369 _('[-r REV] [FILE]')),
4370 "paths": (paths, [], _('[NAME]')),
4370 "paths": (paths, [], _('[NAME]')),
4371 "^pull":
4371 "^pull":
4372 (pull,
4372 (pull,
4373 [('u', 'update', None,
4373 [('u', 'update', None,
4374 _('update to new branch head if changesets were pulled')),
4374 _('update to new branch head if changesets were pulled')),
4375 ('f', 'force', None,
4375 ('f', 'force', None,
4376 _('run even when remote repository is unrelated')),
4376 _('run even when remote repository is unrelated')),
4377 ('r', 'rev', [],
4377 ('r', 'rev', [],
4378 _('a remote changeset intended to be added'), _('REV')),
4378 _('a remote changeset intended to be added'), _('REV')),
4379 ('b', 'branch', [],
4379 ('b', 'branch', [],
4380 _('a specific branch you would like to pull'), _('BRANCH')),
4380 _('a specific branch you would like to pull'), _('BRANCH')),
4381 ] + remoteopts,
4381 ] + remoteopts,
4382 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]')),
4382 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]')),
4383 "^push":
4383 "^push":
4384 (push,
4384 (push,
4385 [('f', 'force', None, _('force push')),
4385 [('f', 'force', None, _('force push')),
4386 ('r', 'rev', [],
4386 ('r', 'rev', [],
4387 _('a changeset intended to be included in the destination'),
4387 _('a changeset intended to be included in the destination'),
4388 _('REV')),
4388 _('REV')),
4389 ('b', 'branch', [],
4389 ('b', 'branch', [],
4390 _('a specific branch you would like to push'), _('BRANCH')),
4390 _('a specific branch you would like to push'), _('BRANCH')),
4391 ('', 'new-branch', False, _('allow pushing a new branch')),
4391 ('', 'new-branch', False, _('allow pushing a new branch')),
4392 ] + remoteopts,
4392 ] + remoteopts,
4393 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]')),
4393 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]')),
4394 "recover": (recover, []),
4394 "recover": (recover, []),
4395 "^remove|rm":
4395 "^remove|rm":
4396 (remove,
4396 (remove,
4397 [('A', 'after', None, _('record delete for missing files')),
4397 [('A', 'after', None, _('record delete for missing files')),
4398 ('f', 'force', None,
4398 ('f', 'force', None,
4399 _('remove (and delete) file even if added or modified')),
4399 _('remove (and delete) file even if added or modified')),
4400 ] + walkopts,
4400 ] + walkopts,
4401 _('[OPTION]... FILE...')),
4401 _('[OPTION]... FILE...')),
4402 "rename|move|mv":
4402 "rename|move|mv":
4403 (rename,
4403 (rename,
4404 [('A', 'after', None, _('record a rename that has already occurred')),
4404 [('A', 'after', None, _('record a rename that has already occurred')),
4405 ('f', 'force', None,
4405 ('f', 'force', None,
4406 _('forcibly copy over an existing managed file')),
4406 _('forcibly copy over an existing managed file')),
4407 ] + walkopts + dryrunopts,
4407 ] + walkopts + dryrunopts,
4408 _('[OPTION]... SOURCE... DEST')),
4408 _('[OPTION]... SOURCE... DEST')),
4409 "resolve":
4409 "resolve":
4410 (resolve,
4410 (resolve,
4411 [('a', 'all', None, _('select all unresolved files')),
4411 [('a', 'all', None, _('select all unresolved files')),
4412 ('l', 'list', None, _('list state of files needing merge')),
4412 ('l', 'list', None, _('list state of files needing merge')),
4413 ('m', 'mark', None, _('mark files as resolved')),
4413 ('m', 'mark', None, _('mark files as resolved')),
4414 ('u', 'unmark', None, _('mark files as unresolved')),
4414 ('u', 'unmark', None, _('mark files as unresolved')),
4415 ('t', 'tool', '', _('specify merge tool')),
4415 ('t', 'tool', '', _('specify merge tool')),
4416 ('n', 'no-status', None, _('hide status prefix'))]
4416 ('n', 'no-status', None, _('hide status prefix'))]
4417 + walkopts,
4417 + walkopts,
4418 _('[OPTION]... [FILE]...')),
4418 _('[OPTION]... [FILE]...')),
4419 "revert":
4419 "revert":
4420 (revert,
4420 (revert,
4421 [('a', 'all', None, _('revert all changes when no arguments given')),
4421 [('a', 'all', None, _('revert all changes when no arguments given')),
4422 ('d', 'date', '',
4422 ('d', 'date', '',
4423 _('tipmost revision matching date'), _('DATE')),
4423 _('tipmost revision matching date'), _('DATE')),
4424 ('r', 'rev', '',
4424 ('r', 'rev', '',
4425 _('revert to the specified revision'), _('REV')),
4425 _('revert to the specified revision'), _('REV')),
4426 ('', 'no-backup', None, _('do not save backup copies of files')),
4426 ('', 'no-backup', None, _('do not save backup copies of files')),
4427 ] + walkopts + dryrunopts,
4427 ] + walkopts + dryrunopts,
4428 _('[OPTION]... [-r REV] [NAME]...')),
4428 _('[OPTION]... [-r REV] [NAME]...')),
4429 "rollback": (rollback, dryrunopts),
4429 "rollback": (rollback, dryrunopts),
4430 "root": (root, []),
4430 "root": (root, []),
4431 "^serve":
4431 "^serve":
4432 (serve,
4432 (serve,
4433 [('A', 'accesslog', '',
4433 [('A', 'accesslog', '',
4434 _('name of access log file to write to'), _('FILE')),
4434 _('name of access log file to write to'), _('FILE')),
4435 ('d', 'daemon', None, _('run server in background')),
4435 ('d', 'daemon', None, _('run server in background')),
4436 ('', 'daemon-pipefds', '',
4436 ('', 'daemon-pipefds', '',
4437 _('used internally by daemon mode'), _('NUM')),
4437 _('used internally by daemon mode'), _('NUM')),
4438 ('E', 'errorlog', '',
4438 ('E', 'errorlog', '',
4439 _('name of error log file to write to'), _('FILE')),
4439 _('name of error log file to write to'), _('FILE')),
4440 # use string type, then we can check if something was passed
4440 # use string type, then we can check if something was passed
4441 ('p', 'port', '',
4441 ('p', 'port', '',
4442 _('port to listen on (default: 8000)'), _('PORT')),
4442 _('port to listen on (default: 8000)'), _('PORT')),
4443 ('a', 'address', '',
4443 ('a', 'address', '',
4444 _('address to listen on (default: all interfaces)'), _('ADDR')),
4444 _('address to listen on (default: all interfaces)'), _('ADDR')),
4445 ('', 'prefix', '',
4445 ('', 'prefix', '',
4446 _('prefix path to serve from (default: server root)'), _('PREFIX')),
4446 _('prefix path to serve from (default: server root)'), _('PREFIX')),
4447 ('n', 'name', '',
4447 ('n', 'name', '',
4448 _('name to show in web pages (default: working directory)'),
4448 _('name to show in web pages (default: working directory)'),
4449 _('NAME')),
4449 _('NAME')),
4450 ('', 'web-conf', '',
4450 ('', 'web-conf', '',
4451 _('name of the hgweb config file (see "hg help hgweb")'),
4451 _('name of the hgweb config file (see "hg help hgweb")'),
4452 _('FILE')),
4452 _('FILE')),
4453 ('', 'webdir-conf', '',
4453 ('', 'webdir-conf', '',
4454 _('name of the hgweb config file (DEPRECATED)'), _('FILE')),
4454 _('name of the hgweb config file (DEPRECATED)'), _('FILE')),
4455 ('', 'pid-file', '',
4455 ('', 'pid-file', '',
4456 _('name of file to write process ID to'), _('FILE')),
4456 _('name of file to write process ID to'), _('FILE')),
4457 ('', 'stdio', None, _('for remote clients')),
4457 ('', 'stdio', None, _('for remote clients')),
4458 ('t', 'templates', '',
4458 ('t', 'templates', '',
4459 _('web templates to use'), _('TEMPLATE')),
4459 _('web templates to use'), _('TEMPLATE')),
4460 ('', 'style', '',
4460 ('', 'style', '',
4461 _('template style to use'), _('STYLE')),
4461 _('template style to use'), _('STYLE')),
4462 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4462 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4463 ('', 'certificate', '',
4463 ('', 'certificate', '',
4464 _('SSL certificate file'), _('FILE'))],
4464 _('SSL certificate file'), _('FILE'))],
4465 _('[OPTION]...')),
4465 _('[OPTION]...')),
4466 "showconfig|debugconfig":
4466 "showconfig|debugconfig":
4467 (showconfig,
4467 (showconfig,
4468 [('u', 'untrusted', None, _('show untrusted configuration options'))],
4468 [('u', 'untrusted', None, _('show untrusted configuration options'))],
4469 _('[-u] [NAME]...')),
4469 _('[-u] [NAME]...')),
4470 "^summary|sum":
4470 "^summary|sum":
4471 (summary,
4471 (summary,
4472 [('', 'remote', None, _('check for push and pull'))], '[--remote]'),
4472 [('', 'remote', None, _('check for push and pull'))], '[--remote]'),
4473 "^status|st":
4473 "^status|st":
4474 (status,
4474 (status,
4475 [('A', 'all', None, _('show status of all files')),
4475 [('A', 'all', None, _('show status of all files')),
4476 ('m', 'modified', None, _('show only modified files')),
4476 ('m', 'modified', None, _('show only modified files')),
4477 ('a', 'added', None, _('show only added files')),
4477 ('a', 'added', None, _('show only added files')),
4478 ('r', 'removed', None, _('show only removed files')),
4478 ('r', 'removed', None, _('show only removed files')),
4479 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4479 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4480 ('c', 'clean', None, _('show only files without changes')),
4480 ('c', 'clean', None, _('show only files without changes')),
4481 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4481 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4482 ('i', 'ignored', None, _('show only ignored files')),
4482 ('i', 'ignored', None, _('show only ignored files')),
4483 ('n', 'no-status', None, _('hide status prefix')),
4483 ('n', 'no-status', None, _('hide status prefix')),
4484 ('C', 'copies', None, _('show source of copied files')),
4484 ('C', 'copies', None, _('show source of copied files')),
4485 ('0', 'print0', None,
4485 ('0', 'print0', None,
4486 _('end filenames with NUL, for use with xargs')),
4486 _('end filenames with NUL, for use with xargs')),
4487 ('', 'rev', [],
4487 ('', 'rev', [],
4488 _('show difference from revision'), _('REV')),
4488 _('show difference from revision'), _('REV')),
4489 ('', 'change', '',
4489 ('', 'change', '',
4490 _('list the changed files of a revision'), _('REV')),
4490 _('list the changed files of a revision'), _('REV')),
4491 ] + walkopts + subrepoopts,
4491 ] + walkopts + subrepoopts,
4492 _('[OPTION]... [FILE]...')),
4492 _('[OPTION]... [FILE]...')),
4493 "tag":
4493 "tag":
4494 (tag,
4494 (tag,
4495 [('f', 'force', None, _('force tag')),
4495 [('f', 'force', None, _('force tag')),
4496 ('l', 'local', None, _('make the tag local')),
4496 ('l', 'local', None, _('make the tag local')),
4497 ('r', 'rev', '',
4497 ('r', 'rev', '',
4498 _('revision to tag'), _('REV')),
4498 _('revision to tag'), _('REV')),
4499 ('', 'remove', None, _('remove a tag')),
4499 ('', 'remove', None, _('remove a tag')),
4500 # -l/--local is already there, commitopts cannot be used
4500 # -l/--local is already there, commitopts cannot be used
4501 ('e', 'edit', None, _('edit commit message')),
4501 ('e', 'edit', None, _('edit commit message')),
4502 ('m', 'message', '',
4502 ('m', 'message', '',
4503 _('use <text> as commit message'), _('TEXT')),
4503 _('use <text> as commit message'), _('TEXT')),
4504 ] + commitopts2,
4504 ] + commitopts2,
4505 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...')),
4505 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...')),
4506 "tags": (tags, [], ''),
4506 "tags": (tags, [], ''),
4507 "tip":
4507 "tip":
4508 (tip,
4508 (tip,
4509 [('p', 'patch', None, _('show patch')),
4509 [('p', 'patch', None, _('show patch')),
4510 ('g', 'git', None, _('use git extended diff format')),
4510 ('g', 'git', None, _('use git extended diff format')),
4511 ] + templateopts,
4511 ] + templateopts,
4512 _('[-p] [-g]')),
4512 _('[-p] [-g]')),
4513 "unbundle":
4513 "unbundle":
4514 (unbundle,
4514 (unbundle,
4515 [('u', 'update', None,
4515 [('u', 'update', None,
4516 _('update to new branch head if changesets were unbundled'))],
4516 _('update to new branch head if changesets were unbundled'))],
4517 _('[-u] FILE...')),
4517 _('[-u] FILE...')),
4518 "^update|up|checkout|co":
4518 "^update|up|checkout|co":
4519 (update,
4519 (update,
4520 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
4520 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
4521 ('c', 'check', None,
4521 ('c', 'check', None,
4522 _('update across branches if no uncommitted changes')),
4522 _('update across branches if no uncommitted changes')),
4523 ('d', 'date', '',
4523 ('d', 'date', '',
4524 _('tipmost revision matching date'), _('DATE')),
4524 _('tipmost revision matching date'), _('DATE')),
4525 ('r', 'rev', '',
4525 ('r', 'rev', '',
4526 _('revision'), _('REV'))],
4526 _('revision'), _('REV'))],
4527 _('[-c] [-C] [-d DATE] [[-r] REV]')),
4527 _('[-c] [-C] [-d DATE] [[-r] REV]')),
4528 "verify": (verify, []),
4528 "verify": (verify, []),
4529 "version": (version_, []),
4529 "version": (version_, []),
4530 }
4530 }
4531
4531
4532 norepo = ("clone init version help debugcommands debugcomplete"
4532 norepo = ("clone init version help debugcommands debugcomplete"
4533 " debugdate debuginstall debugfsinfo debugpushkey")
4533 " debugdate debuginstall debugfsinfo debugpushkey")
4534 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
4534 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
4535 " debugdata debugindex debugindexdot")
4535 " debugdata debugindex debugindexdot")
@@ -1,683 +1,683 b''
1 # dirstate.py - working directory tracking for mercurial
1 # dirstate.py - working directory tracking 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 node import nullid
8 from node import nullid
9 from i18n import _
9 from i18n import _
10 import util, ignore, osutil, parsers, encoding
10 import util, ignore, osutil, parsers, encoding
11 import struct, os, stat, errno
11 import struct, os, stat, errno
12 import cStringIO
12 import cStringIO
13
13
14 _format = ">cllll"
14 _format = ">cllll"
15 propertycache = util.propertycache
15 propertycache = util.propertycache
16
16
17 def _finddirs(path):
17 def _finddirs(path):
18 pos = path.rfind('/')
18 pos = path.rfind('/')
19 while pos != -1:
19 while pos != -1:
20 yield path[:pos]
20 yield path[:pos]
21 pos = path.rfind('/', 0, pos)
21 pos = path.rfind('/', 0, pos)
22
22
23 def _incdirs(dirs, path):
23 def _incdirs(dirs, path):
24 for base in _finddirs(path):
24 for base in _finddirs(path):
25 if base in dirs:
25 if base in dirs:
26 dirs[base] += 1
26 dirs[base] += 1
27 return
27 return
28 dirs[base] = 1
28 dirs[base] = 1
29
29
30 def _decdirs(dirs, path):
30 def _decdirs(dirs, path):
31 for base in _finddirs(path):
31 for base in _finddirs(path):
32 if dirs[base] > 1:
32 if dirs[base] > 1:
33 dirs[base] -= 1
33 dirs[base] -= 1
34 return
34 return
35 del dirs[base]
35 del dirs[base]
36
36
37 class dirstate(object):
37 class dirstate(object):
38
38
39 def __init__(self, opener, ui, root, validate):
39 def __init__(self, opener, ui, root, validate):
40 '''Create a new dirstate object.
40 '''Create a new dirstate object.
41
41
42 opener is an open()-like callable that can be used to open the
42 opener is an open()-like callable that can be used to open the
43 dirstate file; root is the root of the directory tracked by
43 dirstate file; root is the root of the directory tracked by
44 the dirstate.
44 the dirstate.
45 '''
45 '''
46 self._opener = opener
46 self._opener = opener
47 self._validate = validate
47 self._validate = validate
48 self._root = root
48 self._root = root
49 self._rootdir = os.path.join(root, '')
49 self._rootdir = os.path.join(root, '')
50 self._dirty = False
50 self._dirty = False
51 self._dirtypl = False
51 self._dirtypl = False
52 self._ui = ui
52 self._ui = ui
53
53
54 @propertycache
54 @propertycache
55 def _map(self):
55 def _map(self):
56 '''Return the dirstate contents as a map from filename to
56 '''Return the dirstate contents as a map from filename to
57 (state, mode, size, time).'''
57 (state, mode, size, time).'''
58 self._read()
58 self._read()
59 return self._map
59 return self._map
60
60
61 @propertycache
61 @propertycache
62 def _copymap(self):
62 def _copymap(self):
63 self._read()
63 self._read()
64 return self._copymap
64 return self._copymap
65
65
66 @propertycache
66 @propertycache
67 def _foldmap(self):
67 def _foldmap(self):
68 f = {}
68 f = {}
69 for name in self._map:
69 for name in self._map:
70 f[os.path.normcase(name)] = name
70 f[os.path.normcase(name)] = name
71 return f
71 return f
72
72
73 @propertycache
73 @propertycache
74 def _branch(self):
74 def _branch(self):
75 try:
75 try:
76 return self._opener("branch").read().strip() or "default"
76 return self._opener("branch").read().strip() or "default"
77 except IOError:
77 except IOError:
78 return "default"
78 return "default"
79
79
80 @propertycache
80 @propertycache
81 def _pl(self):
81 def _pl(self):
82 try:
82 try:
83 st = self._opener("dirstate").read(40)
83 st = self._opener("dirstate").read(40)
84 l = len(st)
84 l = len(st)
85 if l == 40:
85 if l == 40:
86 return st[:20], st[20:40]
86 return st[:20], st[20:40]
87 elif l > 0 and l < 40:
87 elif l > 0 and l < 40:
88 raise util.Abort(_('working directory state appears damaged!'))
88 raise util.Abort(_('working directory state appears damaged!'))
89 except IOError, err:
89 except IOError, err:
90 if err.errno != errno.ENOENT:
90 if err.errno != errno.ENOENT:
91 raise
91 raise
92 return [nullid, nullid]
92 return [nullid, nullid]
93
93
94 @propertycache
94 @propertycache
95 def _dirs(self):
95 def _dirs(self):
96 dirs = {}
96 dirs = {}
97 for f, s in self._map.iteritems():
97 for f, s in self._map.iteritems():
98 if s[0] != 'r':
98 if s[0] != 'r':
99 _incdirs(dirs, f)
99 _incdirs(dirs, f)
100 return dirs
100 return dirs
101
101
102 @propertycache
102 @propertycache
103 def _ignore(self):
103 def _ignore(self):
104 files = [self._join('.hgignore')]
104 files = [self._join('.hgignore')]
105 for name, path in self._ui.configitems("ui"):
105 for name, path in self._ui.configitems("ui"):
106 if name == 'ignore' or name.startswith('ignore.'):
106 if name == 'ignore' or name.startswith('ignore.'):
107 files.append(util.expandpath(path))
107 files.append(util.expandpath(path))
108 return ignore.ignore(self._root, files, self._ui.warn)
108 return ignore.ignore(self._root, files, self._ui.warn)
109
109
110 @propertycache
110 @propertycache
111 def _slash(self):
111 def _slash(self):
112 return self._ui.configbool('ui', 'slash') and os.sep != '/'
112 return self._ui.configbool('ui', 'slash') and os.sep != '/'
113
113
114 @propertycache
114 @propertycache
115 def _checklink(self):
115 def _checklink(self):
116 return util.checklink(self._root)
116 return util.checklink(self._root)
117
117
118 @propertycache
118 @propertycache
119 def _checkexec(self):
119 def _checkexec(self):
120 return util.checkexec(self._root)
120 return util.checkexec(self._root)
121
121
122 @propertycache
122 @propertycache
123 def _checkcase(self):
123 def _checkcase(self):
124 return not util.checkcase(self._join('.hg'))
124 return not util.checkcase(self._join('.hg'))
125
125
126 def _join(self, f):
126 def _join(self, f):
127 # much faster than os.path.join()
127 # much faster than os.path.join()
128 # it's safe because f is always a relative path
128 # it's safe because f is always a relative path
129 return self._rootdir + f
129 return self._rootdir + f
130
130
131 def flagfunc(self, fallback):
131 def flagfunc(self, fallback):
132 if self._checklink:
132 if self._checklink:
133 if self._checkexec:
133 if self._checkexec:
134 def f(x):
134 def f(x):
135 p = self._join(x)
135 p = self._join(x)
136 if os.path.islink(p):
136 if os.path.islink(p):
137 return 'l'
137 return 'l'
138 if util.is_exec(p):
138 if util.is_exec(p):
139 return 'x'
139 return 'x'
140 return ''
140 return ''
141 return f
141 return f
142 def f(x):
142 def f(x):
143 if os.path.islink(self._join(x)):
143 if os.path.islink(self._join(x)):
144 return 'l'
144 return 'l'
145 if 'x' in fallback(x):
145 if 'x' in fallback(x):
146 return 'x'
146 return 'x'
147 return ''
147 return ''
148 return f
148 return f
149 if self._checkexec:
149 if self._checkexec:
150 def f(x):
150 def f(x):
151 if 'l' in fallback(x):
151 if 'l' in fallback(x):
152 return 'l'
152 return 'l'
153 if util.is_exec(self._join(x)):
153 if util.is_exec(self._join(x)):
154 return 'x'
154 return 'x'
155 return ''
155 return ''
156 return f
156 return f
157 return fallback
157 return fallback
158
158
159 def getcwd(self):
159 def getcwd(self):
160 cwd = os.getcwd()
160 cwd = os.getcwd()
161 if cwd == self._root:
161 if cwd == self._root:
162 return ''
162 return ''
163 # self._root ends with a path separator if self._root is '/' or 'C:\'
163 # self._root ends with a path separator if self._root is '/' or 'C:\'
164 rootsep = self._root
164 rootsep = self._root
165 if not util.endswithsep(rootsep):
165 if not util.endswithsep(rootsep):
166 rootsep += os.sep
166 rootsep += os.sep
167 if cwd.startswith(rootsep):
167 if cwd.startswith(rootsep):
168 return cwd[len(rootsep):]
168 return cwd[len(rootsep):]
169 else:
169 else:
170 # we're outside the repo. return an absolute path.
170 # we're outside the repo. return an absolute path.
171 return cwd
171 return cwd
172
172
173 def pathto(self, f, cwd=None):
173 def pathto(self, f, cwd=None):
174 if cwd is None:
174 if cwd is None:
175 cwd = self.getcwd()
175 cwd = self.getcwd()
176 path = util.pathto(self._root, cwd, f)
176 path = util.pathto(self._root, cwd, f)
177 if self._slash:
177 if self._slash:
178 return util.normpath(path)
178 return util.normpath(path)
179 return path
179 return path
180
180
181 def __getitem__(self, key):
181 def __getitem__(self, key):
182 '''Return the current state of key (a filename) in the dirstate.
182 '''Return the current state of key (a filename) in the dirstate.
183
183
184 States are:
184 States are:
185 n normal
185 n normal
186 m needs merging
186 m needs merging
187 r marked for removal
187 r marked for removal
188 a marked for addition
188 a marked for addition
189 ? not tracked
189 ? not tracked
190 '''
190 '''
191 return self._map.get(key, ("?",))[0]
191 return self._map.get(key, ("?",))[0]
192
192
193 def __contains__(self, key):
193 def __contains__(self, key):
194 return key in self._map
194 return key in self._map
195
195
196 def __iter__(self):
196 def __iter__(self):
197 for x in sorted(self._map):
197 for x in sorted(self._map):
198 yield x
198 yield x
199
199
200 def parents(self):
200 def parents(self):
201 return [self._validate(p) for p in self._pl]
201 return [self._validate(p) for p in self._pl]
202
202
203 def branch(self):
203 def branch(self):
204 return encoding.tolocal(self._branch)
204 return encoding.tolocal(self._branch)
205
205
206 def setparents(self, p1, p2=nullid):
206 def setparents(self, p1, p2=nullid):
207 self._dirty = self._dirtypl = True
207 self._dirty = self._dirtypl = True
208 self._pl = p1, p2
208 self._pl = p1, p2
209
209
210 def setbranch(self, branch):
210 def setbranch(self, branch):
211 if branch in ['tip', '.', 'null']:
211 if branch in ['tip', '.', 'null']:
212 raise util.Abort(_('the name \'%s\' is reserved') % branch)
212 raise util.Abort(_('the name \'%s\' is reserved') % branch)
213 self._branch = encoding.fromlocal(branch)
213 self._branch = encoding.fromlocal(branch)
214 self._opener("branch", "w").write(self._branch + '\n')
214 self._opener("branch", "w").write(self._branch + '\n')
215
215
216 def _read(self):
216 def _read(self):
217 self._map = {}
217 self._map = {}
218 self._copymap = {}
218 self._copymap = {}
219 try:
219 try:
220 st = self._opener("dirstate").read()
220 st = self._opener("dirstate").read()
221 except IOError, err:
221 except IOError, err:
222 if err.errno != errno.ENOENT:
222 if err.errno != errno.ENOENT:
223 raise
223 raise
224 return
224 return
225 if not st:
225 if not st:
226 return
226 return
227
227
228 p = parsers.parse_dirstate(self._map, self._copymap, st)
228 p = parsers.parse_dirstate(self._map, self._copymap, st)
229 if not self._dirtypl:
229 if not self._dirtypl:
230 self._pl = p
230 self._pl = p
231
231
232 def invalidate(self):
232 def invalidate(self):
233 for a in ("_map", "_copymap", "_foldmap", "_branch", "_pl", "_dirs",
233 for a in ("_map", "_copymap", "_foldmap", "_branch", "_pl", "_dirs",
234 "_ignore"):
234 "_ignore"):
235 if a in self.__dict__:
235 if a in self.__dict__:
236 delattr(self, a)
236 delattr(self, a)
237 self._dirty = False
237 self._dirty = False
238
238
239 def copy(self, source, dest):
239 def copy(self, source, dest):
240 """Mark dest as a copy of source. Unmark dest if source is None."""
240 """Mark dest as a copy of source. Unmark dest if source is None."""
241 if source == dest:
241 if source == dest:
242 return
242 return
243 self._dirty = True
243 self._dirty = True
244 if source is not None:
244 if source is not None:
245 self._copymap[dest] = source
245 self._copymap[dest] = source
246 elif dest in self._copymap:
246 elif dest in self._copymap:
247 del self._copymap[dest]
247 del self._copymap[dest]
248
248
249 def copied(self, file):
249 def copied(self, file):
250 return self._copymap.get(file, None)
250 return self._copymap.get(file, None)
251
251
252 def copies(self):
252 def copies(self):
253 return self._copymap
253 return self._copymap
254
254
255 def _droppath(self, f):
255 def _droppath(self, f):
256 if self[f] not in "?r" and "_dirs" in self.__dict__:
256 if self[f] not in "?r" and "_dirs" in self.__dict__:
257 _decdirs(self._dirs, f)
257 _decdirs(self._dirs, f)
258
258
259 def _addpath(self, f, check=False):
259 def _addpath(self, f, check=False):
260 oldstate = self[f]
260 oldstate = self[f]
261 if check or oldstate == "r":
261 if check or oldstate == "r":
262 if '\r' in f or '\n' in f:
262 if '\r' in f or '\n' in f:
263 raise util.Abort(
263 raise util.Abort(
264 _("'\\n' and '\\r' disallowed in filenames: %r") % f)
264 _("'\\n' and '\\r' disallowed in filenames: %r") % f)
265 if f in self._dirs:
265 if f in self._dirs:
266 raise util.Abort(_('directory %r already in dirstate') % f)
266 raise util.Abort(_('directory %r already in dirstate') % f)
267 # shadows
267 # shadows
268 for d in _finddirs(f):
268 for d in _finddirs(f):
269 if d in self._dirs:
269 if d in self._dirs:
270 break
270 break
271 if d in self._map and self[d] != 'r':
271 if d in self._map and self[d] != 'r':
272 raise util.Abort(
272 raise util.Abort(
273 _('file %r in dirstate clashes with %r') % (d, f))
273 _('file %r in dirstate clashes with %r') % (d, f))
274 if oldstate in "?r" and "_dirs" in self.__dict__:
274 if oldstate in "?r" and "_dirs" in self.__dict__:
275 _incdirs(self._dirs, f)
275 _incdirs(self._dirs, f)
276
276
277 def normal(self, f):
277 def normal(self, f):
278 '''Mark a file normal and clean.'''
278 '''Mark a file normal and clean.'''
279 self._dirty = True
279 self._dirty = True
280 self._addpath(f)
280 self._addpath(f)
281 s = os.lstat(self._join(f))
281 s = os.lstat(self._join(f))
282 self._map[f] = ('n', s.st_mode, s.st_size, int(s.st_mtime))
282 self._map[f] = ('n', s.st_mode, s.st_size, int(s.st_mtime))
283 if f in self._copymap:
283 if f in self._copymap:
284 del self._copymap[f]
284 del self._copymap[f]
285
285
286 def normallookup(self, f):
286 def normallookup(self, f):
287 '''Mark a file normal, but possibly dirty.'''
287 '''Mark a file normal, but possibly dirty.'''
288 if self._pl[1] != nullid and f in self._map:
288 if self._pl[1] != nullid and f in self._map:
289 # if there is a merge going on and the file was either
289 # if there is a merge going on and the file was either
290 # in state 'm' (-1) or coming from other parent (-2) before
290 # in state 'm' (-1) or coming from other parent (-2) before
291 # being removed, restore that state.
291 # being removed, restore that state.
292 entry = self._map[f]
292 entry = self._map[f]
293 if entry[0] == 'r' and entry[2] in (-1, -2):
293 if entry[0] == 'r' and entry[2] in (-1, -2):
294 source = self._copymap.get(f)
294 source = self._copymap.get(f)
295 if entry[2] == -1:
295 if entry[2] == -1:
296 self.merge(f)
296 self.merge(f)
297 elif entry[2] == -2:
297 elif entry[2] == -2:
298 self.otherparent(f)
298 self.otherparent(f)
299 if source:
299 if source:
300 self.copy(source, f)
300 self.copy(source, f)
301 return
301 return
302 if entry[0] == 'm' or entry[0] == 'n' and entry[2] == -2:
302 if entry[0] == 'm' or entry[0] == 'n' and entry[2] == -2:
303 return
303 return
304 self._dirty = True
304 self._dirty = True
305 self._addpath(f)
305 self._addpath(f)
306 self._map[f] = ('n', 0, -1, -1)
306 self._map[f] = ('n', 0, -1, -1)
307 if f in self._copymap:
307 if f in self._copymap:
308 del self._copymap[f]
308 del self._copymap[f]
309
309
310 def otherparent(self, f):
310 def otherparent(self, f):
311 '''Mark as coming from the other parent, always dirty.'''
311 '''Mark as coming from the other parent, always dirty.'''
312 if self._pl[1] == nullid:
312 if self._pl[1] == nullid:
313 raise util.Abort(_("setting %r to other parent "
313 raise util.Abort(_("setting %r to other parent "
314 "only allowed in merges") % f)
314 "only allowed in merges") % f)
315 self._dirty = True
315 self._dirty = True
316 self._addpath(f)
316 self._addpath(f)
317 self._map[f] = ('n', 0, -2, -1)
317 self._map[f] = ('n', 0, -2, -1)
318 if f in self._copymap:
318 if f in self._copymap:
319 del self._copymap[f]
319 del self._copymap[f]
320
320
321 def add(self, f):
321 def add(self, f):
322 '''Mark a file added.'''
322 '''Mark a file added.'''
323 self._dirty = True
323 self._dirty = True
324 self._addpath(f, True)
324 self._addpath(f, True)
325 self._map[f] = ('a', 0, -1, -1)
325 self._map[f] = ('a', 0, -1, -1)
326 if f in self._copymap:
326 if f in self._copymap:
327 del self._copymap[f]
327 del self._copymap[f]
328
328
329 def remove(self, f):
329 def remove(self, f):
330 '''Mark a file removed.'''
330 '''Mark a file removed.'''
331 self._dirty = True
331 self._dirty = True
332 self._droppath(f)
332 self._droppath(f)
333 size = 0
333 size = 0
334 if self._pl[1] != nullid and f in self._map:
334 if self._pl[1] != nullid and f in self._map:
335 # backup the previous state
335 # backup the previous state
336 entry = self._map[f]
336 entry = self._map[f]
337 if entry[0] == 'm': # merge
337 if entry[0] == 'm': # merge
338 size = -1
338 size = -1
339 elif entry[0] == 'n' and entry[2] == -2: # other parent
339 elif entry[0] == 'n' and entry[2] == -2: # other parent
340 size = -2
340 size = -2
341 self._map[f] = ('r', 0, size, 0)
341 self._map[f] = ('r', 0, size, 0)
342 if size == 0 and f in self._copymap:
342 if size == 0 and f in self._copymap:
343 del self._copymap[f]
343 del self._copymap[f]
344
344
345 def merge(self, f):
345 def merge(self, f):
346 '''Mark a file merged.'''
346 '''Mark a file merged.'''
347 self._dirty = True
347 self._dirty = True
348 s = os.lstat(self._join(f))
348 s = os.lstat(self._join(f))
349 self._addpath(f)
349 self._addpath(f)
350 self._map[f] = ('m', s.st_mode, s.st_size, int(s.st_mtime))
350 self._map[f] = ('m', s.st_mode, s.st_size, int(s.st_mtime))
351 if f in self._copymap:
351 if f in self._copymap:
352 del self._copymap[f]
352 del self._copymap[f]
353
353
354 def forget(self, f):
354 def forget(self, f):
355 '''Forget a file.'''
355 '''Forget a file.'''
356 self._dirty = True
356 self._dirty = True
357 try:
357 try:
358 self._droppath(f)
358 self._droppath(f)
359 del self._map[f]
359 del self._map[f]
360 except KeyError:
360 except KeyError:
361 self._ui.warn(_("not in dirstate: %s\n") % f)
361 self._ui.warn(_("not in dirstate: %s\n") % f)
362
362
363 def _normalize(self, path, knownpath):
363 def _normalize(self, path, knownpath):
364 norm_path = os.path.normcase(path)
364 norm_path = os.path.normcase(path)
365 fold_path = self._foldmap.get(norm_path, None)
365 fold_path = self._foldmap.get(norm_path, None)
366 if fold_path is None:
366 if fold_path is None:
367 if knownpath or not os.path.lexists(os.path.join(self._root, path)):
367 if knownpath or not os.path.lexists(os.path.join(self._root, path)):
368 fold_path = path
368 fold_path = path
369 else:
369 else:
370 fold_path = self._foldmap.setdefault(norm_path,
370 fold_path = self._foldmap.setdefault(norm_path,
371 util.fspath(path, self._root))
371 util.fspath(path, self._root))
372 return fold_path
372 return fold_path
373
373
374 def clear(self):
374 def clear(self):
375 self._map = {}
375 self._map = {}
376 if "_dirs" in self.__dict__:
376 if "_dirs" in self.__dict__:
377 delattr(self, "_dirs")
377 delattr(self, "_dirs")
378 self._copymap = {}
378 self._copymap = {}
379 self._pl = [nullid, nullid]
379 self._pl = [nullid, nullid]
380 self._dirty = True
380 self._dirty = True
381
381
382 def rebuild(self, parent, files):
382 def rebuild(self, parent, files):
383 self.clear()
383 self.clear()
384 for f in files:
384 for f in files:
385 if 'x' in files.flags(f):
385 if 'x' in files.flags(f):
386 self._map[f] = ('n', 0777, -1, 0)
386 self._map[f] = ('n', 0777, -1, 0)
387 else:
387 else:
388 self._map[f] = ('n', 0666, -1, 0)
388 self._map[f] = ('n', 0666, -1, 0)
389 self._pl = (parent, nullid)
389 self._pl = (parent, nullid)
390 self._dirty = True
390 self._dirty = True
391
391
392 def write(self):
392 def write(self):
393 if not self._dirty:
393 if not self._dirty:
394 return
394 return
395 st = self._opener("dirstate", "w", atomictemp=True)
395 st = self._opener("dirstate", "w", atomictemp=True)
396
396
397 # use the modification time of the newly created temporary file as the
397 # use the modification time of the newly created temporary file as the
398 # filesystem's notion of 'now'
398 # filesystem's notion of 'now'
399 now = int(util.fstat(st).st_mtime)
399 now = int(util.fstat(st).st_mtime)
400
400
401 cs = cStringIO.StringIO()
401 cs = cStringIO.StringIO()
402 copymap = self._copymap
402 copymap = self._copymap
403 pack = struct.pack
403 pack = struct.pack
404 write = cs.write
404 write = cs.write
405 write("".join(self._pl))
405 write("".join(self._pl))
406 for f, e in self._map.iteritems():
406 for f, e in self._map.iteritems():
407 if e[0] == 'n' and e[3] == now:
407 if e[0] == 'n' and e[3] == now:
408 # The file was last modified "simultaneously" with the current
408 # The file was last modified "simultaneously" with the current
409 # write to dirstate (i.e. within the same second for file-
409 # write to dirstate (i.e. within the same second for file-
410 # systems with a granularity of 1 sec). This commonly happens
410 # systems with a granularity of 1 sec). This commonly happens
411 # for at least a couple of files on 'update'.
411 # for at least a couple of files on 'update'.
412 # The user could change the file without changing its size
412 # The user could change the file without changing its size
413 # within the same second. Invalidate the file's stat data in
413 # within the same second. Invalidate the file's stat data in
414 # dirstate, forcing future 'status' calls to compare the
414 # dirstate, forcing future 'status' calls to compare the
415 # contents of the file. This prevents mistakenly treating such
415 # contents of the file. This prevents mistakenly treating such
416 # files as clean.
416 # files as clean.
417 e = (e[0], 0, -1, -1) # mark entry as 'unset'
417 e = (e[0], 0, -1, -1) # mark entry as 'unset'
418 self._map[f] = e
418 self._map[f] = e
419
419
420 if f in copymap:
420 if f in copymap:
421 f = "%s\0%s" % (f, copymap[f])
421 f = "%s\0%s" % (f, copymap[f])
422 e = pack(_format, e[0], e[1], e[2], e[3], len(f))
422 e = pack(_format, e[0], e[1], e[2], e[3], len(f))
423 write(e)
423 write(e)
424 write(f)
424 write(f)
425 st.write(cs.getvalue())
425 st.write(cs.getvalue())
426 st.rename()
426 st.rename()
427 self._dirty = self._dirtypl = False
427 self._dirty = self._dirtypl = False
428
428
429 def _dirignore(self, f):
429 def _dirignore(self, f):
430 if f == '.':
430 if f == '.':
431 return False
431 return False
432 if self._ignore(f):
432 if self._ignore(f):
433 return True
433 return True
434 for p in _finddirs(f):
434 for p in _finddirs(f):
435 if self._ignore(p):
435 if self._ignore(p):
436 return True
436 return True
437 return False
437 return False
438
438
439 def walk(self, match, subrepos, unknown, ignored):
439 def walk(self, match, subrepos, unknown, ignored):
440 '''
440 '''
441 Walk recursively through the directory tree, finding all files
441 Walk recursively through the directory tree, finding all files
442 matched by match.
442 matched by match.
443
443
444 Return a dict mapping filename to stat-like object (either
444 Return a dict mapping filename to stat-like object (either
445 mercurial.osutil.stat instance or return value of os.stat()).
445 mercurial.osutil.stat instance or return value of os.stat()).
446 '''
446 '''
447
447
448 def fwarn(f, msg):
448 def fwarn(f, msg):
449 self._ui.warn('%s: %s\n' % (self.pathto(f), msg))
449 self._ui.warn('%s: %s\n' % (self.pathto(f), msg))
450 return False
450 return False
451
451
452 def badtype(mode):
452 def badtype(mode):
453 kind = _('unknown')
453 kind = _('unknown')
454 if stat.S_ISCHR(mode):
454 if stat.S_ISCHR(mode):
455 kind = _('character device')
455 kind = _('character device')
456 elif stat.S_ISBLK(mode):
456 elif stat.S_ISBLK(mode):
457 kind = _('block device')
457 kind = _('block device')
458 elif stat.S_ISFIFO(mode):
458 elif stat.S_ISFIFO(mode):
459 kind = _('fifo')
459 kind = _('fifo')
460 elif stat.S_ISSOCK(mode):
460 elif stat.S_ISSOCK(mode):
461 kind = _('socket')
461 kind = _('socket')
462 elif stat.S_ISDIR(mode):
462 elif stat.S_ISDIR(mode):
463 kind = _('directory')
463 kind = _('directory')
464 return _('unsupported file type (type is %s)') % kind
464 return _('unsupported file type (type is %s)') % kind
465
465
466 ignore = self._ignore
466 ignore = self._ignore
467 dirignore = self._dirignore
467 dirignore = self._dirignore
468 if ignored:
468 if ignored:
469 ignore = util.never
469 ignore = util.never
470 dirignore = util.never
470 dirignore = util.never
471 elif not unknown:
471 elif not unknown:
472 # if unknown and ignored are False, skip step 2
472 # if unknown and ignored are False, skip step 2
473 ignore = util.always
473 ignore = util.always
474 dirignore = util.always
474 dirignore = util.always
475
475
476 matchfn = match.matchfn
476 matchfn = match.matchfn
477 badfn = match.bad
477 badfn = match.bad
478 dmap = self._map
478 dmap = self._map
479 normpath = util.normpath
479 normpath = util.normpath
480 listdir = osutil.listdir
480 listdir = osutil.listdir
481 lstat = os.lstat
481 lstat = os.lstat
482 getkind = stat.S_IFMT
482 getkind = stat.S_IFMT
483 dirkind = stat.S_IFDIR
483 dirkind = stat.S_IFDIR
484 regkind = stat.S_IFREG
484 regkind = stat.S_IFREG
485 lnkkind = stat.S_IFLNK
485 lnkkind = stat.S_IFLNK
486 join = self._join
486 join = self._join
487 work = []
487 work = []
488 wadd = work.append
488 wadd = work.append
489
489
490 exact = skipstep3 = False
490 exact = skipstep3 = False
491 if matchfn == match.exact: # match.exact
491 if matchfn == match.exact: # match.exact
492 exact = True
492 exact = True
493 dirignore = util.always # skip step 2
493 dirignore = util.always # skip step 2
494 elif match.files() and not match.anypats(): # match.match, no patterns
494 elif match.files() and not match.anypats(): # match.match, no patterns
495 skipstep3 = True
495 skipstep3 = True
496
496
497 if self._checkcase:
497 if self._checkcase:
498 normalize = self._normalize
498 normalize = self._normalize
499 skipstep3 = False
499 skipstep3 = False
500 else:
500 else:
501 normalize = lambda x, y: x
501 normalize = lambda x, y: x
502
502
503 files = sorted(match.files())
503 files = sorted(match.files())
504 subrepos.sort()
504 subrepos.sort()
505 i, j = 0, 0
505 i, j = 0, 0
506 while i < len(files) and j < len(subrepos):
506 while i < len(files) and j < len(subrepos):
507 subpath = subrepos[j] + "/"
507 subpath = subrepos[j] + "/"
508 if not files[i].startswith(subpath):
508 if files[i] < subpath:
509 i += 1
509 i += 1
510 continue
510 continue
511 while files and files[i].startswith(subpath):
511 while files and files[i].startswith(subpath):
512 del files[i]
512 del files[i]
513 j += 1
513 j += 1
514
514
515 if not files or '.' in files:
515 if not files or '.' in files:
516 files = ['']
516 files = ['']
517 results = dict.fromkeys(subrepos)
517 results = dict.fromkeys(subrepos)
518 results['.hg'] = None
518 results['.hg'] = None
519
519
520 # step 1: find all explicit files
520 # step 1: find all explicit files
521 for ff in files:
521 for ff in files:
522 nf = normalize(normpath(ff), False)
522 nf = normalize(normpath(ff), False)
523 if nf in results:
523 if nf in results:
524 continue
524 continue
525
525
526 try:
526 try:
527 st = lstat(join(nf))
527 st = lstat(join(nf))
528 kind = getkind(st.st_mode)
528 kind = getkind(st.st_mode)
529 if kind == dirkind:
529 if kind == dirkind:
530 skipstep3 = False
530 skipstep3 = False
531 if nf in dmap:
531 if nf in dmap:
532 #file deleted on disk but still in dirstate
532 #file deleted on disk but still in dirstate
533 results[nf] = None
533 results[nf] = None
534 match.dir(nf)
534 match.dir(nf)
535 if not dirignore(nf):
535 if not dirignore(nf):
536 wadd(nf)
536 wadd(nf)
537 elif kind == regkind or kind == lnkkind:
537 elif kind == regkind or kind == lnkkind:
538 results[nf] = st
538 results[nf] = st
539 else:
539 else:
540 badfn(ff, badtype(kind))
540 badfn(ff, badtype(kind))
541 if nf in dmap:
541 if nf in dmap:
542 results[nf] = None
542 results[nf] = None
543 except OSError, inst:
543 except OSError, inst:
544 if nf in dmap: # does it exactly match a file?
544 if nf in dmap: # does it exactly match a file?
545 results[nf] = None
545 results[nf] = None
546 else: # does it match a directory?
546 else: # does it match a directory?
547 prefix = nf + "/"
547 prefix = nf + "/"
548 for fn in dmap:
548 for fn in dmap:
549 if fn.startswith(prefix):
549 if fn.startswith(prefix):
550 match.dir(nf)
550 match.dir(nf)
551 skipstep3 = False
551 skipstep3 = False
552 break
552 break
553 else:
553 else:
554 badfn(ff, inst.strerror)
554 badfn(ff, inst.strerror)
555
555
556 # step 2: visit subdirectories
556 # step 2: visit subdirectories
557 while work:
557 while work:
558 nd = work.pop()
558 nd = work.pop()
559 skip = None
559 skip = None
560 if nd == '.':
560 if nd == '.':
561 nd = ''
561 nd = ''
562 else:
562 else:
563 skip = '.hg'
563 skip = '.hg'
564 try:
564 try:
565 entries = listdir(join(nd), stat=True, skip=skip)
565 entries = listdir(join(nd), stat=True, skip=skip)
566 except OSError, inst:
566 except OSError, inst:
567 if inst.errno == errno.EACCES:
567 if inst.errno == errno.EACCES:
568 fwarn(nd, inst.strerror)
568 fwarn(nd, inst.strerror)
569 continue
569 continue
570 raise
570 raise
571 for f, kind, st in entries:
571 for f, kind, st in entries:
572 nf = normalize(nd and (nd + "/" + f) or f, True)
572 nf = normalize(nd and (nd + "/" + f) or f, True)
573 if nf not in results:
573 if nf not in results:
574 if kind == dirkind:
574 if kind == dirkind:
575 if not ignore(nf):
575 if not ignore(nf):
576 match.dir(nf)
576 match.dir(nf)
577 wadd(nf)
577 wadd(nf)
578 if nf in dmap and matchfn(nf):
578 if nf in dmap and matchfn(nf):
579 results[nf] = None
579 results[nf] = None
580 elif kind == regkind or kind == lnkkind:
580 elif kind == regkind or kind == lnkkind:
581 if nf in dmap:
581 if nf in dmap:
582 if matchfn(nf):
582 if matchfn(nf):
583 results[nf] = st
583 results[nf] = st
584 elif matchfn(nf) and not ignore(nf):
584 elif matchfn(nf) and not ignore(nf):
585 results[nf] = st
585 results[nf] = st
586 elif nf in dmap and matchfn(nf):
586 elif nf in dmap and matchfn(nf):
587 results[nf] = None
587 results[nf] = None
588
588
589 # step 3: report unseen items in the dmap hash
589 # step 3: report unseen items in the dmap hash
590 if not skipstep3 and not exact:
590 if not skipstep3 and not exact:
591 visit = sorted([f for f in dmap if f not in results and matchfn(f)])
591 visit = sorted([f for f in dmap if f not in results and matchfn(f)])
592 for nf, st in zip(visit, util.statfiles([join(i) for i in visit])):
592 for nf, st in zip(visit, util.statfiles([join(i) for i in visit])):
593 if not st is None and not getkind(st.st_mode) in (regkind, lnkkind):
593 if not st is None and not getkind(st.st_mode) in (regkind, lnkkind):
594 st = None
594 st = None
595 results[nf] = st
595 results[nf] = st
596 for s in subrepos:
596 for s in subrepos:
597 del results[s]
597 del results[s]
598 del results['.hg']
598 del results['.hg']
599 return results
599 return results
600
600
601 def status(self, match, subrepos, ignored, clean, unknown):
601 def status(self, match, subrepos, ignored, clean, unknown):
602 '''Determine the status of the working copy relative to the
602 '''Determine the status of the working copy relative to the
603 dirstate and return a tuple of lists (unsure, modified, added,
603 dirstate and return a tuple of lists (unsure, modified, added,
604 removed, deleted, unknown, ignored, clean), where:
604 removed, deleted, unknown, ignored, clean), where:
605
605
606 unsure:
606 unsure:
607 files that might have been modified since the dirstate was
607 files that might have been modified since the dirstate was
608 written, but need to be read to be sure (size is the same
608 written, but need to be read to be sure (size is the same
609 but mtime differs)
609 but mtime differs)
610 modified:
610 modified:
611 files that have definitely been modified since the dirstate
611 files that have definitely been modified since the dirstate
612 was written (different size or mode)
612 was written (different size or mode)
613 added:
613 added:
614 files that have been explicitly added with hg add
614 files that have been explicitly added with hg add
615 removed:
615 removed:
616 files that have been explicitly removed with hg remove
616 files that have been explicitly removed with hg remove
617 deleted:
617 deleted:
618 files that have been deleted through other means ("missing")
618 files that have been deleted through other means ("missing")
619 unknown:
619 unknown:
620 files not in the dirstate that are not ignored
620 files not in the dirstate that are not ignored
621 ignored:
621 ignored:
622 files not in the dirstate that are ignored
622 files not in the dirstate that are ignored
623 (by _dirignore())
623 (by _dirignore())
624 clean:
624 clean:
625 files that have definitely not been modified since the
625 files that have definitely not been modified since the
626 dirstate was written
626 dirstate was written
627 '''
627 '''
628 listignored, listclean, listunknown = ignored, clean, unknown
628 listignored, listclean, listunknown = ignored, clean, unknown
629 lookup, modified, added, unknown, ignored = [], [], [], [], []
629 lookup, modified, added, unknown, ignored = [], [], [], [], []
630 removed, deleted, clean = [], [], []
630 removed, deleted, clean = [], [], []
631
631
632 dmap = self._map
632 dmap = self._map
633 ladd = lookup.append # aka "unsure"
633 ladd = lookup.append # aka "unsure"
634 madd = modified.append
634 madd = modified.append
635 aadd = added.append
635 aadd = added.append
636 uadd = unknown.append
636 uadd = unknown.append
637 iadd = ignored.append
637 iadd = ignored.append
638 radd = removed.append
638 radd = removed.append
639 dadd = deleted.append
639 dadd = deleted.append
640 cadd = clean.append
640 cadd = clean.append
641
641
642 lnkkind = stat.S_IFLNK
642 lnkkind = stat.S_IFLNK
643
643
644 for fn, st in self.walk(match, subrepos, listunknown,
644 for fn, st in self.walk(match, subrepos, listunknown,
645 listignored).iteritems():
645 listignored).iteritems():
646 if fn not in dmap:
646 if fn not in dmap:
647 if (listignored or match.exact(fn)) and self._dirignore(fn):
647 if (listignored or match.exact(fn)) and self._dirignore(fn):
648 if listignored:
648 if listignored:
649 iadd(fn)
649 iadd(fn)
650 elif listunknown:
650 elif listunknown:
651 uadd(fn)
651 uadd(fn)
652 continue
652 continue
653
653
654 state, mode, size, time = dmap[fn]
654 state, mode, size, time = dmap[fn]
655
655
656 if not st and state in "nma":
656 if not st and state in "nma":
657 dadd(fn)
657 dadd(fn)
658 elif state == 'n':
658 elif state == 'n':
659 # The "mode & lnkkind != lnkkind or self._checklink"
659 # The "mode & lnkkind != lnkkind or self._checklink"
660 # lines are an expansion of "islink => checklink"
660 # lines are an expansion of "islink => checklink"
661 # where islink means "is this a link?" and checklink
661 # where islink means "is this a link?" and checklink
662 # means "can we check links?".
662 # means "can we check links?".
663 if (size >= 0 and
663 if (size >= 0 and
664 (size != st.st_size
664 (size != st.st_size
665 or ((mode ^ st.st_mode) & 0100 and self._checkexec))
665 or ((mode ^ st.st_mode) & 0100 and self._checkexec))
666 and (mode & lnkkind != lnkkind or self._checklink)
666 and (mode & lnkkind != lnkkind or self._checklink)
667 or size == -2 # other parent
667 or size == -2 # other parent
668 or fn in self._copymap):
668 or fn in self._copymap):
669 madd(fn)
669 madd(fn)
670 elif (time != int(st.st_mtime)
670 elif (time != int(st.st_mtime)
671 and (mode & lnkkind != lnkkind or self._checklink)):
671 and (mode & lnkkind != lnkkind or self._checklink)):
672 ladd(fn)
672 ladd(fn)
673 elif listclean:
673 elif listclean:
674 cadd(fn)
674 cadd(fn)
675 elif state == 'm':
675 elif state == 'm':
676 madd(fn)
676 madd(fn)
677 elif state == 'a':
677 elif state == 'a':
678 aadd(fn)
678 aadd(fn)
679 elif state == 'r':
679 elif state == 'r':
680 radd(fn)
680 radd(fn)
681
681
682 return (lookup, modified, added, removed, deleted, unknown, ignored,
682 return (lookup, modified, added, removed, deleted, unknown, ignored,
683 clean)
683 clean)
@@ -1,554 +1,554 b''
1 # hg.py - repository classes for mercurial
1 # hg.py - repository classes for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
4 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
5 #
5 #
6 # This software may be used and distributed according to the terms of the
6 # This software may be used and distributed according to the terms of the
7 # GNU General Public License version 2 or any later version.
7 # GNU General Public License version 2 or any later version.
8
8
9 from i18n import _
9 from i18n import _
10 from lock import release
10 from lock import release
11 from node import hex, nullid, nullrev, short
11 from node import hex, nullid, nullrev, short
12 import localrepo, bundlerepo, httprepo, sshrepo, statichttprepo
12 import localrepo, bundlerepo, httprepo, sshrepo, statichttprepo
13 import lock, util, extensions, error, encoding, node
13 import lock, util, extensions, error, encoding, node
14 import cmdutil, discovery, url
14 import cmdutil, discovery, url
15 import merge as mergemod
15 import merge as mergemod
16 import verify as verifymod
16 import verify as verifymod
17 import errno, os, shutil
17 import errno, os, shutil
18
18
19 def _local(path):
19 def _local(path):
20 path = util.expandpath(util.drop_scheme('file', path))
20 path = util.expandpath(util.drop_scheme('file', path))
21 return (os.path.isfile(path) and bundlerepo or localrepo)
21 return (os.path.isfile(path) and bundlerepo or localrepo)
22
22
23 def addbranchrevs(lrepo, repo, branches, revs):
23 def addbranchrevs(lrepo, repo, branches, revs):
24 hashbranch, branches = branches
24 hashbranch, branches = branches
25 if not hashbranch and not branches:
25 if not hashbranch and not branches:
26 return revs or None, revs and revs[0] or None
26 return revs or None, revs and revs[0] or None
27 revs = revs and list(revs) or []
27 revs = revs and list(revs) or []
28 if not repo.capable('branchmap'):
28 if not repo.capable('branchmap'):
29 if branches:
29 if branches:
30 raise util.Abort(_("remote branch lookup not supported"))
30 raise util.Abort(_("remote branch lookup not supported"))
31 revs.append(hashbranch)
31 revs.append(hashbranch)
32 return revs, revs[0]
32 return revs, revs[0]
33 branchmap = repo.branchmap()
33 branchmap = repo.branchmap()
34
34
35 def primary(branch):
35 def primary(branch):
36 if branch == '.':
36 if branch == '.':
37 if not lrepo or not lrepo.local():
37 if not lrepo or not lrepo.local():
38 raise util.Abort(_("dirstate branch not accessible"))
38 raise util.Abort(_("dirstate branch not accessible"))
39 branch = lrepo.dirstate.branch()
39 branch = lrepo.dirstate.branch()
40 if branch in branchmap:
40 if branch in branchmap:
41 revs.extend(node.hex(r) for r in reversed(branchmap[branch]))
41 revs.extend(node.hex(r) for r in reversed(branchmap[branch]))
42 return True
42 return True
43 else:
43 else:
44 return False
44 return False
45
45
46 for branch in branches:
46 for branch in branches:
47 if not primary(branch):
47 if not primary(branch):
48 raise error.RepoLookupError(_("unknown branch '%s'") % branch)
48 raise error.RepoLookupError(_("unknown branch '%s'") % branch)
49 if hashbranch:
49 if hashbranch:
50 if not primary(hashbranch):
50 if not primary(hashbranch):
51 revs.append(hashbranch)
51 revs.append(hashbranch)
52 return revs, revs[0]
52 return revs, revs[0]
53
53
54 def parseurl(url, branches=None):
54 def parseurl(url, branches=None):
55 '''parse url#branch, returning (url, (branch, branches))'''
55 '''parse url#branch, returning (url, (branch, branches))'''
56
56
57 if '#' not in url:
57 if '#' not in url:
58 return url, (None, branches or [])
58 return url, (None, branches or [])
59 url, branch = url.split('#', 1)
59 url, branch = url.split('#', 1)
60 return url, (branch, branches or [])
60 return url, (branch, branches or [])
61
61
62 schemes = {
62 schemes = {
63 'bundle': bundlerepo,
63 'bundle': bundlerepo,
64 'file': _local,
64 'file': _local,
65 'http': httprepo,
65 'http': httprepo,
66 'https': httprepo,
66 'https': httprepo,
67 'ssh': sshrepo,
67 'ssh': sshrepo,
68 'static-http': statichttprepo,
68 'static-http': statichttprepo,
69 }
69 }
70
70
71 def _lookup(path):
71 def _lookup(path):
72 scheme = 'file'
72 scheme = 'file'
73 if path:
73 if path:
74 c = path.find(':')
74 c = path.find(':')
75 if c > 0:
75 if c > 0:
76 scheme = path[:c]
76 scheme = path[:c]
77 thing = schemes.get(scheme) or schemes['file']
77 thing = schemes.get(scheme) or schemes['file']
78 try:
78 try:
79 return thing(path)
79 return thing(path)
80 except TypeError:
80 except TypeError:
81 return thing
81 return thing
82
82
83 def islocal(repo):
83 def islocal(repo):
84 '''return true if repo or path is local'''
84 '''return true if repo or path is local'''
85 if isinstance(repo, str):
85 if isinstance(repo, str):
86 try:
86 try:
87 return _lookup(repo).islocal(repo)
87 return _lookup(repo).islocal(repo)
88 except AttributeError:
88 except AttributeError:
89 return False
89 return False
90 return repo.local()
90 return repo.local()
91
91
92 def repository(ui, path='', create=False):
92 def repository(ui, path='', create=False):
93 """return a repository object for the specified path"""
93 """return a repository object for the specified path"""
94 repo = _lookup(path).instance(ui, path, create)
94 repo = _lookup(path).instance(ui, path, create)
95 ui = getattr(repo, "ui", ui)
95 ui = getattr(repo, "ui", ui)
96 for name, module in extensions.extensions():
96 for name, module in extensions.extensions():
97 hook = getattr(module, 'reposetup', None)
97 hook = getattr(module, 'reposetup', None)
98 if hook:
98 if hook:
99 hook(ui, repo)
99 hook(ui, repo)
100 return repo
100 return repo
101
101
102 def defaultdest(source):
102 def defaultdest(source):
103 '''return default destination of clone if none is given'''
103 '''return default destination of clone if none is given'''
104 return os.path.basename(os.path.normpath(source))
104 return os.path.basename(os.path.normpath(source))
105
105
106 def localpath(path):
106 def localpath(path):
107 if path.startswith('file://localhost/'):
107 if path.startswith('file://localhost/'):
108 return path[16:]
108 return path[16:]
109 if path.startswith('file://'):
109 if path.startswith('file://'):
110 return path[7:]
110 return path[7:]
111 if path.startswith('file:'):
111 if path.startswith('file:'):
112 return path[5:]
112 return path[5:]
113 return path
113 return path
114
114
115 def share(ui, source, dest=None, update=True):
115 def share(ui, source, dest=None, update=True):
116 '''create a shared repository'''
116 '''create a shared repository'''
117
117
118 if not islocal(source):
118 if not islocal(source):
119 raise util.Abort(_('can only share local repositories'))
119 raise util.Abort(_('can only share local repositories'))
120
120
121 if not dest:
121 if not dest:
122 dest = defaultdest(source)
122 dest = defaultdest(source)
123 else:
123 else:
124 dest = ui.expandpath(dest)
124 dest = ui.expandpath(dest)
125
125
126 if isinstance(source, str):
126 if isinstance(source, str):
127 origsource = ui.expandpath(source)
127 origsource = ui.expandpath(source)
128 source, branches = parseurl(origsource)
128 source, branches = parseurl(origsource)
129 srcrepo = repository(ui, source)
129 srcrepo = repository(ui, source)
130 rev, checkout = addbranchrevs(srcrepo, srcrepo, branches, None)
130 rev, checkout = addbranchrevs(srcrepo, srcrepo, branches, None)
131 else:
131 else:
132 srcrepo = source
132 srcrepo = source
133 origsource = source = srcrepo.url()
133 origsource = source = srcrepo.url()
134 checkout = None
134 checkout = None
135
135
136 sharedpath = srcrepo.sharedpath # if our source is already sharing
136 sharedpath = srcrepo.sharedpath # if our source is already sharing
137
137
138 root = os.path.realpath(dest)
138 root = os.path.realpath(dest)
139 roothg = os.path.join(root, '.hg')
139 roothg = os.path.join(root, '.hg')
140
140
141 if os.path.exists(roothg):
141 if os.path.exists(roothg):
142 raise util.Abort(_('destination already exists'))
142 raise util.Abort(_('destination already exists'))
143
143
144 if not os.path.isdir(root):
144 if not os.path.isdir(root):
145 os.mkdir(root)
145 os.mkdir(root)
146 os.mkdir(roothg)
146 os.mkdir(roothg)
147
147
148 requirements = ''
148 requirements = ''
149 try:
149 try:
150 requirements = srcrepo.opener('requires').read()
150 requirements = srcrepo.opener('requires').read()
151 except IOError, inst:
151 except IOError, inst:
152 if inst.errno != errno.ENOENT:
152 if inst.errno != errno.ENOENT:
153 raise
153 raise
154
154
155 requirements += 'shared\n'
155 requirements += 'shared\n'
156 file(os.path.join(roothg, 'requires'), 'w').write(requirements)
156 file(os.path.join(roothg, 'requires'), 'w').write(requirements)
157 file(os.path.join(roothg, 'sharedpath'), 'w').write(sharedpath)
157 file(os.path.join(roothg, 'sharedpath'), 'w').write(sharedpath)
158
158
159 default = srcrepo.ui.config('paths', 'default')
159 default = srcrepo.ui.config('paths', 'default')
160 if default:
160 if default:
161 f = file(os.path.join(roothg, 'hgrc'), 'w')
161 f = file(os.path.join(roothg, 'hgrc'), 'w')
162 f.write('[paths]\ndefault = %s\n' % default)
162 f.write('[paths]\ndefault = %s\n' % default)
163 f.close()
163 f.close()
164
164
165 r = repository(ui, root)
165 r = repository(ui, root)
166
166
167 if update:
167 if update:
168 r.ui.status(_("updating working directory\n"))
168 r.ui.status(_("updating working directory\n"))
169 if update is not True:
169 if update is not True:
170 checkout = update
170 checkout = update
171 for test in (checkout, 'default', 'tip'):
171 for test in (checkout, 'default', 'tip'):
172 if test is None:
172 if test is None:
173 continue
173 continue
174 try:
174 try:
175 uprev = r.lookup(test)
175 uprev = r.lookup(test)
176 break
176 break
177 except error.RepoLookupError:
177 except error.RepoLookupError:
178 continue
178 continue
179 _update(r, uprev)
179 _update(r, uprev)
180
180
181 def clone(ui, source, dest=None, pull=False, rev=None, update=True,
181 def clone(ui, source, dest=None, pull=False, rev=None, update=True,
182 stream=False, branch=None):
182 stream=False, branch=None):
183 """Make a copy of an existing repository.
183 """Make a copy of an existing repository.
184
184
185 Create a copy of an existing repository in a new directory. The
185 Create a copy of an existing repository in a new directory. The
186 source and destination are URLs, as passed to the repository
186 source and destination are URLs, as passed to the repository
187 function. Returns a pair of repository objects, the source and
187 function. Returns a pair of repository objects, the source and
188 newly created destination.
188 newly created destination.
189
189
190 The location of the source is added to the new repository's
190 The location of the source is added to the new repository's
191 .hg/hgrc file, as the default to be used for future pulls and
191 .hg/hgrc file, as the default to be used for future pulls and
192 pushes.
192 pushes.
193
193
194 If an exception is raised, the partly cloned/updated destination
194 If an exception is raised, the partly cloned/updated destination
195 repository will be deleted.
195 repository will be deleted.
196
196
197 Arguments:
197 Arguments:
198
198
199 source: repository object or URL
199 source: repository object or URL
200
200
201 dest: URL of destination repository to create (defaults to base
201 dest: URL of destination repository to create (defaults to base
202 name of source repository)
202 name of source repository)
203
203
204 pull: always pull from source repository, even in local case
204 pull: always pull from source repository, even in local case
205
205
206 stream: stream raw data uncompressed from repository (fast over
206 stream: stream raw data uncompressed from repository (fast over
207 LAN, slow over WAN)
207 LAN, slow over WAN)
208
208
209 rev: revision to clone up to (implies pull=True)
209 rev: revision to clone up to (implies pull=True)
210
210
211 update: update working directory after clone completes, if
211 update: update working directory after clone completes, if
212 destination is local repository (True means update to default rev,
212 destination is local repository (True means update to default rev,
213 anything else is treated as a revision)
213 anything else is treated as a revision)
214
214
215 branch: branches to clone
215 branch: branches to clone
216 """
216 """
217
217
218 if isinstance(source, str):
218 if isinstance(source, str):
219 origsource = ui.expandpath(source)
219 origsource = ui.expandpath(source)
220 source, branch = parseurl(origsource, branch)
220 source, branch = parseurl(origsource, branch)
221 src_repo = repository(ui, source)
221 src_repo = repository(ui, source)
222 else:
222 else:
223 src_repo = source
223 src_repo = source
224 branch = (None, branch or [])
224 branch = (None, branch or [])
225 origsource = source = src_repo.url()
225 origsource = source = src_repo.url()
226 rev, checkout = addbranchrevs(src_repo, src_repo, branch, rev)
226 rev, checkout = addbranchrevs(src_repo, src_repo, branch, rev)
227
227
228 if dest is None:
228 if dest is None:
229 dest = defaultdest(source)
229 dest = defaultdest(source)
230 ui.status(_("destination directory: %s\n") % dest)
230 ui.status(_("destination directory: %s\n") % dest)
231 else:
231 else:
232 dest = ui.expandpath(dest)
232 dest = ui.expandpath(dest)
233
233
234 dest = localpath(dest)
234 dest = localpath(dest)
235 source = localpath(source)
235 source = localpath(source)
236
236
237 if os.path.exists(dest):
237 if os.path.exists(dest):
238 if not os.path.isdir(dest):
238 if not os.path.isdir(dest):
239 raise util.Abort(_("destination '%s' already exists") % dest)
239 raise util.Abort(_("destination '%s' already exists") % dest)
240 elif os.listdir(dest):
240 elif os.listdir(dest):
241 raise util.Abort(_("destination '%s' is not empty") % dest)
241 raise util.Abort(_("destination '%s' is not empty") % dest)
242
242
243 class DirCleanup(object):
243 class DirCleanup(object):
244 def __init__(self, dir_):
244 def __init__(self, dir_):
245 self.rmtree = shutil.rmtree
245 self.rmtree = shutil.rmtree
246 self.dir_ = dir_
246 self.dir_ = dir_
247 def close(self):
247 def close(self):
248 self.dir_ = None
248 self.dir_ = None
249 def cleanup(self):
249 def cleanup(self):
250 if self.dir_:
250 if self.dir_:
251 self.rmtree(self.dir_, True)
251 self.rmtree(self.dir_, True)
252
252
253 src_lock = dest_lock = dir_cleanup = None
253 src_lock = dest_lock = dir_cleanup = None
254 try:
254 try:
255 if islocal(dest):
255 if islocal(dest):
256 dir_cleanup = DirCleanup(dest)
256 dir_cleanup = DirCleanup(dest)
257
257
258 abspath = origsource
258 abspath = origsource
259 copy = False
259 copy = False
260 if src_repo.cancopy() and islocal(dest):
260 if src_repo.cancopy() and islocal(dest):
261 abspath = os.path.abspath(util.drop_scheme('file', origsource))
261 abspath = os.path.abspath(util.drop_scheme('file', origsource))
262 copy = not pull and not rev
262 copy = not pull and not rev
263
263
264 if copy:
264 if copy:
265 try:
265 try:
266 # we use a lock here because if we race with commit, we
266 # we use a lock here because if we race with commit, we
267 # can end up with extra data in the cloned revlogs that's
267 # can end up with extra data in the cloned revlogs that's
268 # not pointed to by changesets, thus causing verify to
268 # not pointed to by changesets, thus causing verify to
269 # fail
269 # fail
270 src_lock = src_repo.lock(wait=False)
270 src_lock = src_repo.lock(wait=False)
271 except error.LockError:
271 except error.LockError:
272 copy = False
272 copy = False
273
273
274 if copy:
274 if copy:
275 src_repo.hook('preoutgoing', throw=True, source='clone')
275 src_repo.hook('preoutgoing', throw=True, source='clone')
276 hgdir = os.path.realpath(os.path.join(dest, ".hg"))
276 hgdir = os.path.realpath(os.path.join(dest, ".hg"))
277 if not os.path.exists(dest):
277 if not os.path.exists(dest):
278 os.mkdir(dest)
278 os.mkdir(dest)
279 else:
279 else:
280 # only clean up directories we create ourselves
280 # only clean up directories we create ourselves
281 dir_cleanup.dir_ = hgdir
281 dir_cleanup.dir_ = hgdir
282 try:
282 try:
283 dest_path = hgdir
283 dest_path = hgdir
284 os.mkdir(dest_path)
284 os.mkdir(dest_path)
285 except OSError, inst:
285 except OSError, inst:
286 if inst.errno == errno.EEXIST:
286 if inst.errno == errno.EEXIST:
287 dir_cleanup.close()
287 dir_cleanup.close()
288 raise util.Abort(_("destination '%s' already exists")
288 raise util.Abort(_("destination '%s' already exists")
289 % dest)
289 % dest)
290 raise
290 raise
291
291
292 hardlink = None
292 hardlink = None
293 num = 0
293 num = 0
294 for f in src_repo.store.copylist():
294 for f in src_repo.store.copylist():
295 src = os.path.join(src_repo.sharedpath, f)
295 src = os.path.join(src_repo.sharedpath, f)
296 dst = os.path.join(dest_path, f)
296 dst = os.path.join(dest_path, f)
297 dstbase = os.path.dirname(dst)
297 dstbase = os.path.dirname(dst)
298 if dstbase and not os.path.exists(dstbase):
298 if dstbase and not os.path.exists(dstbase):
299 os.mkdir(dstbase)
299 os.mkdir(dstbase)
300 if os.path.exists(src):
300 if os.path.exists(src):
301 if dst.endswith('data'):
301 if dst.endswith('data'):
302 # lock to avoid premature writing to the target
302 # lock to avoid premature writing to the target
303 dest_lock = lock.lock(os.path.join(dstbase, "lock"))
303 dest_lock = lock.lock(os.path.join(dstbase, "lock"))
304 hardlink, n = util.copyfiles(src, dst, hardlink)
304 hardlink, n = util.copyfiles(src, dst, hardlink)
305 num += n
305 num += n
306 if hardlink:
306 if hardlink:
307 ui.debug("linked %d files\n" % num)
307 ui.debug("linked %d files\n" % num)
308 else:
308 else:
309 ui.debug("copied %d files\n" % num)
309 ui.debug("copied %d files\n" % num)
310
310
311 # we need to re-init the repo after manually copying the data
311 # we need to re-init the repo after manually copying the data
312 # into it
312 # into it
313 dest_repo = repository(ui, dest)
313 dest_repo = repository(ui, dest)
314 src_repo.hook('outgoing', source='clone',
314 src_repo.hook('outgoing', source='clone',
315 node=node.hex(node.nullid))
315 node=node.hex(node.nullid))
316 else:
316 else:
317 try:
317 try:
318 dest_repo = repository(ui, dest, create=True)
318 dest_repo = repository(ui, dest, create=True)
319 except OSError, inst:
319 except OSError, inst:
320 if inst.errno == errno.EEXIST:
320 if inst.errno == errno.EEXIST:
321 dir_cleanup.close()
321 dir_cleanup.close()
322 raise util.Abort(_("destination '%s' already exists")
322 raise util.Abort(_("destination '%s' already exists")
323 % dest)
323 % dest)
324 raise
324 raise
325
325
326 revs = None
326 revs = None
327 if rev:
327 if rev:
328 if 'lookup' not in src_repo.capabilities:
328 if 'lookup' not in src_repo.capabilities:
329 raise util.Abort(_("src repository does not support "
329 raise util.Abort(_("src repository does not support "
330 "revision lookup and so doesn't "
330 "revision lookup and so doesn't "
331 "support clone by revision"))
331 "support clone by revision"))
332 revs = [src_repo.lookup(r) for r in rev]
332 revs = [src_repo.lookup(r) for r in rev]
333 checkout = revs[0]
333 checkout = revs[0]
334 if dest_repo.local():
334 if dest_repo.local():
335 dest_repo.clone(src_repo, heads=revs, stream=stream)
335 dest_repo.clone(src_repo, heads=revs, stream=stream)
336 elif src_repo.local():
336 elif src_repo.local():
337 src_repo.push(dest_repo, revs=revs)
337 src_repo.push(dest_repo, revs=revs)
338 else:
338 else:
339 raise util.Abort(_("clone from remote to remote not supported"))
339 raise util.Abort(_("clone from remote to remote not supported"))
340
340
341 if dir_cleanup:
341 if dir_cleanup:
342 dir_cleanup.close()
342 dir_cleanup.close()
343
343
344 if dest_repo.local():
344 if dest_repo.local():
345 fp = dest_repo.opener("hgrc", "w", text=True)
345 fp = dest_repo.opener("hgrc", "w", text=True)
346 fp.write("[paths]\n")
346 fp.write("[paths]\n")
347 fp.write("default = %s\n" % abspath)
347 fp.write("default = %s\n" % abspath)
348 fp.close()
348 fp.close()
349
349
350 dest_repo.ui.setconfig('paths', 'default', abspath)
350 dest_repo.ui.setconfig('paths', 'default', abspath)
351
351
352 if update:
352 if update:
353 if update is not True:
353 if update is not True:
354 checkout = update
354 checkout = update
355 if src_repo.local():
355 if src_repo.local():
356 checkout = src_repo.lookup(update)
356 checkout = src_repo.lookup(update)
357 for test in (checkout, 'default', 'tip'):
357 for test in (checkout, 'default', 'tip'):
358 if test is None:
358 if test is None:
359 continue
359 continue
360 try:
360 try:
361 uprev = dest_repo.lookup(test)
361 uprev = dest_repo.lookup(test)
362 break
362 break
363 except error.RepoLookupError:
363 except error.RepoLookupError:
364 continue
364 continue
365 bn = dest_repo[uprev].branch()
365 bn = dest_repo[uprev].branch()
366 dest_repo.ui.status(_("updating to branch %s\n") % bn)
366 dest_repo.ui.status(_("updating to branch %s\n") % bn)
367 _update(dest_repo, uprev)
367 _update(dest_repo, uprev)
368
368
369 return src_repo, dest_repo
369 return src_repo, dest_repo
370 finally:
370 finally:
371 release(src_lock, dest_lock)
371 release(src_lock, dest_lock)
372 if dir_cleanup is not None:
372 if dir_cleanup is not None:
373 dir_cleanup.cleanup()
373 dir_cleanup.cleanup()
374
374
375 def _showstats(repo, stats):
375 def _showstats(repo, stats):
376 repo.ui.status(_("%d files updated, %d files merged, "
376 repo.ui.status(_("%d files updated, %d files merged, "
377 "%d files removed, %d files unresolved\n") % stats)
377 "%d files removed, %d files unresolved\n") % stats)
378
378
379 def update(repo, node):
379 def update(repo, node):
380 """update the working directory to node, merging linear changes"""
380 """update the working directory to node, merging linear changes"""
381 stats = mergemod.update(repo, node, False, False, None)
381 stats = mergemod.update(repo, node, False, False, None)
382 _showstats(repo, stats)
382 _showstats(repo, stats)
383 if stats[3]:
383 if stats[3]:
384 repo.ui.status(_("use 'hg resolve' to retry unresolved file merges\n"))
384 repo.ui.status(_("use 'hg resolve' to retry unresolved file merges\n"))
385 return stats[3] > 0
385 return stats[3] > 0
386
386
387 # naming conflict in clone()
387 # naming conflict in clone()
388 _update = update
388 _update = update
389
389
390 def clean(repo, node, show_stats=True):
390 def clean(repo, node, show_stats=True):
391 """forcibly switch the working directory to node, clobbering changes"""
391 """forcibly switch the working directory to node, clobbering changes"""
392 stats = mergemod.update(repo, node, False, True, None)
392 stats = mergemod.update(repo, node, False, True, None)
393 if show_stats:
393 if show_stats:
394 _showstats(repo, stats)
394 _showstats(repo, stats)
395 return stats[3] > 0
395 return stats[3] > 0
396
396
397 def merge(repo, node, force=None, remind=True):
397 def merge(repo, node, force=None, remind=True):
398 """Branch merge with node, resolving changes. Return true if any
398 """Branch merge with node, resolving changes. Return true if any
399 unresolved conflicts."""
399 unresolved conflicts."""
400 stats = mergemod.update(repo, node, True, force, False)
400 stats = mergemod.update(repo, node, True, force, False)
401 _showstats(repo, stats)
401 _showstats(repo, stats)
402 if stats[3]:
402 if stats[3]:
403 repo.ui.status(_("use 'hg resolve' to retry unresolved file merges "
403 repo.ui.status(_("use 'hg resolve' to retry unresolved file merges "
404 "or 'hg update -C .' to abandon\n"))
404 "or 'hg update -C .' to abandon\n"))
405 elif remind:
405 elif remind:
406 repo.ui.status(_("(branch merge, don't forget to commit)\n"))
406 repo.ui.status(_("(branch merge, don't forget to commit)\n"))
407 return stats[3] > 0
407 return stats[3] > 0
408
408
409 def _incoming(displaychlist, subreporecurse, ui, repo, source,
409 def _incoming(displaychlist, subreporecurse, ui, repo, source,
410 opts, buffered=False):
410 opts, buffered=False):
411 """
411 """
412 Helper for incoming / gincoming.
412 Helper for incoming / gincoming.
413 displaychlist gets called with
413 displaychlist gets called with
414 (remoterepo, incomingchangesetlist, displayer) parameters,
414 (remoterepo, incomingchangesetlist, displayer) parameters,
415 and is supposed to contain only code that can't be unified.
415 and is supposed to contain only code that can't be unified.
416 """
416 """
417 source, branches = parseurl(ui.expandpath(source), opts.get('branch'))
417 source, branches = parseurl(ui.expandpath(source), opts.get('branch'))
418 other = repository(remoteui(repo, opts), source)
418 other = repository(remoteui(repo, opts), source)
419 ui.status(_('comparing with %s\n') % url.hidepassword(source))
419 ui.status(_('comparing with %s\n') % url.hidepassword(source))
420 revs, checkout = addbranchrevs(repo, other, branches, opts.get('rev'))
420 revs, checkout = addbranchrevs(repo, other, branches, opts.get('rev'))
421
421
422 if revs:
422 if revs:
423 revs = [other.lookup(rev) for rev in revs]
423 revs = [other.lookup(rev) for rev in revs]
424 other, incoming, bundle = bundlerepo.getremotechanges(ui, repo, other, revs,
424 other, incoming, bundle = bundlerepo.getremotechanges(ui, repo, other, revs,
425 opts["bundle"], opts["force"])
425 opts["bundle"], opts["force"])
426 if incoming is None:
426 if incoming is None:
427 ui.status(_("no changes found\n"))
427 ui.status(_("no changes found\n"))
428 return subreporecurse()
428 return subreporecurse()
429
429
430 try:
430 try:
431 chlist = other.changelog.nodesbetween(incoming, revs)[0]
431 chlist = other.changelog.nodesbetween(incoming, revs)[0]
432 displayer = cmdutil.show_changeset(ui, other, opts, buffered)
432 displayer = cmdutil.show_changeset(ui, other, opts, buffered)
433
433
434 # XXX once graphlog extension makes it into core,
434 # XXX once graphlog extension makes it into core,
435 # should be replaced by a if graph/else
435 # should be replaced by a if graph/else
436 displaychlist(other, chlist, displayer)
436 displaychlist(other, chlist, displayer)
437
437
438 displayer.close()
438 displayer.close()
439 finally:
439 finally:
440 if hasattr(other, 'close'):
440 if hasattr(other, 'close'):
441 other.close()
441 other.close()
442 if bundle:
442 if bundle:
443 os.unlink(bundle)
443 os.unlink(bundle)
444 subreporecurse()
444 subreporecurse()
445 return 0 # exit code is zero since we found incoming changes
445 return 0 # exit code is zero since we found incoming changes
446
446
447 def incoming(ui, repo, source, opts):
447 def incoming(ui, repo, source, opts):
448 def subreporecurse():
448 def subreporecurse():
449 ret = 1
449 ret = 1
450 if opts.get('subrepos'):
450 if opts.get('subrepos'):
451 ctx = repo[None]
451 ctx = repo[None]
452 for subpath in sorted(ctx.substate):
452 for subpath in sorted(ctx.substate):
453 sub = ctx.sub(subpath)
453 sub = ctx.sub(subpath)
454 ret = min(ret, sub.incoming(ui, source, opts))
454 ret = min(ret, sub.incoming(ui, source, opts))
455 return ret
455 return ret
456
456
457 def display(other, chlist, displayer):
457 def display(other, chlist, displayer):
458 limit = cmdutil.loglimit(opts)
458 limit = cmdutil.loglimit(opts)
459 if opts.get('newest_first'):
459 if opts.get('newest_first'):
460 chlist.reverse()
460 chlist.reverse()
461 count = 0
461 count = 0
462 for n in chlist:
462 for n in chlist:
463 if limit is not None and count >= limit:
463 if limit is not None and count >= limit:
464 break
464 break
465 parents = [p for p in other.changelog.parents(n) if p != nullid]
465 parents = [p for p in other.changelog.parents(n) if p != nullid]
466 if opts.get('no_merges') and len(parents) == 2:
466 if opts.get('no_merges') and len(parents) == 2:
467 continue
467 continue
468 count += 1
468 count += 1
469 displayer.show(other[n])
469 displayer.show(other[n])
470 return _incoming(display, subreporecurse, ui, repo, source, opts)
470 return _incoming(display, subreporecurse, ui, repo, source, opts)
471
471
472 def _outgoing(ui, repo, dest, opts):
472 def _outgoing(ui, repo, dest, opts):
473 dest = ui.expandpath(dest or 'default-push', dest or 'default')
473 dest = ui.expandpath(dest or 'default-push', dest or 'default')
474 dest, branches = parseurl(dest, opts.get('branch'))
474 dest, branches = parseurl(dest, opts.get('branch'))
475 revs, checkout = addbranchrevs(repo, repo, branches, opts.get('rev'))
475 revs, checkout = addbranchrevs(repo, repo, branches, opts.get('rev'))
476 if revs:
476 if revs:
477 revs = [repo.lookup(rev) for rev in revs]
477 revs = [repo.lookup(rev) for rev in revs]
478
478
479 other = repository(remoteui(repo, opts), dest)
479 other = repository(remoteui(repo, opts), dest)
480 ui.status(_('comparing with %s\n') % url.hidepassword(dest))
480 ui.status(_('comparing with %s\n') % url.hidepassword(dest))
481 o = discovery.findoutgoing(repo, other, force=opts.get('force'))
481 o = discovery.findoutgoing(repo, other, force=opts.get('force'))
482 if not o:
482 if not o:
483 ui.status(_("no changes found\n"))
483 ui.status(_("no changes found\n"))
484 return None
484 return None
485
485
486 return repo.changelog.nodesbetween(o, revs)[0]
486 return repo.changelog.nodesbetween(o, revs)[0]
487
487
488 def outgoing(ui, repo, dest, opts):
488 def outgoing(ui, repo, dest, opts):
489 def recurse():
489 def recurse():
490 ret = 1
490 ret = 1
491 if opts.get('subrepos'):
491 if opts.get('subrepos'):
492 ctx = repo[None]
492 ctx = repo[None]
493 for subpath in sorted(ctx.substate):
493 for subpath in sorted(ctx.substate):
494 sub = ctx.sub(subpath)
494 sub = ctx.sub(subpath)
495 ret = min(ret, sub.outgoing(ui, dest, opts))
495 ret = min(ret, sub.outgoing(ui, dest, opts))
496 return ret
496 return ret
497
497
498 limit = cmdutil.loglimit(opts)
498 limit = cmdutil.loglimit(opts)
499 o = _outgoing(ui, repo, dest, opts)
499 o = _outgoing(ui, repo, dest, opts)
500 if o is None:
500 if o is None:
501 return recurse()
501 return recurse()
502
502
503 if opts.get('newest_first'):
503 if opts.get('newest_first'):
504 o.reverse()
504 o.reverse()
505 displayer = cmdutil.show_changeset(ui, repo, opts)
505 displayer = cmdutil.show_changeset(ui, repo, opts)
506 count = 0
506 count = 0
507 for n in o:
507 for n in o:
508 if limit is not None and count >= limit:
508 if limit is not None and count >= limit:
509 break
509 break
510 parents = [p for p in repo.changelog.parents(n) if p != nullid]
510 parents = [p for p in repo.changelog.parents(n) if p != nullid]
511 if opts.get('no_merges') and len(parents) == 2:
511 if opts.get('no_merges') and len(parents) == 2:
512 continue
512 continue
513 count += 1
513 count += 1
514 displayer.show(repo[n])
514 displayer.show(repo[n])
515 displayer.close()
515 displayer.close()
516 recurse()
516 recurse()
517 return 0 # exit code is zero since we found outgoing changes
517 return 0 # exit code is zero since we found outgoing changes
518
518
519 def revert(repo, node, choose):
519 def revert(repo, node, choose):
520 """revert changes to revision in node without updating dirstate"""
520 """revert changes to revision in node without updating dirstate"""
521 return mergemod.update(repo, node, False, True, choose)[3] > 0
521 return mergemod.update(repo, node, False, True, choose)[3] > 0
522
522
523 def verify(repo):
523 def verify(repo):
524 """verify the consistency of a repository"""
524 """verify the consistency of a repository"""
525 return verifymod.verify(repo)
525 return verifymod.verify(repo)
526
526
527 def remoteui(src, opts):
527 def remoteui(src, opts):
528 'build a remote ui from ui or repo and opts'
528 'build a remote ui from ui or repo and opts'
529 if hasattr(src, 'baseui'): # looks like a repository
529 if hasattr(src, 'baseui'): # looks like a repository
530 dst = src.baseui.copy() # drop repo-specific config
530 dst = src.baseui.copy() # drop repo-specific config
531 src = src.ui # copy target options from repo
531 src = src.ui # copy target options from repo
532 else: # assume it's a global ui object
532 else: # assume it's a global ui object
533 dst = src.copy() # keep all global options
533 dst = src.copy() # keep all global options
534
534
535 # copy ssh-specific options
535 # copy ssh-specific options
536 for o in 'ssh', 'remotecmd':
536 for o in 'ssh', 'remotecmd':
537 v = opts.get(o) or src.config('ui', o)
537 v = opts.get(o) or src.config('ui', o)
538 if v:
538 if v:
539 dst.setconfig("ui", o, v)
539 dst.setconfig("ui", o, v)
540
540
541 # copy bundle-specific options
541 # copy bundle-specific options
542 r = src.config('bundle', 'mainreporoot')
542 r = src.config('bundle', 'mainreporoot')
543 if r:
543 if r:
544 dst.setconfig('bundle', 'mainreporoot', r)
544 dst.setconfig('bundle', 'mainreporoot', r)
545
545
546 # copy selected local settings to the remote ui
546 # copy selected local settings to the remote ui
547 for sect in ('auth', 'http_proxy'):
547 for sect in ('auth', 'http_proxy'):
548 for key, val in src.configitems(sect):
548 for key, val in src.configitems(sect):
549 dst.setconfig(sect, key, val)
549 dst.setconfig(sect, key, val)
550 v = src.config('web', 'cacerts')
550 v = src.config('web', 'cacerts')
551 if v:
551 if v:
552 dst.setconfig('web', 'cacerts', v)
552 dst.setconfig('web', 'cacerts', util.expandpath(v))
553
553
554 return dst
554 return dst
@@ -1,719 +1,721 b''
1 # url.py - HTTP handling for mercurial
1 # url.py - HTTP handling for mercurial
2 #
2 #
3 # Copyright 2005, 2006, 2007, 2008 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005, 2006, 2007, 2008 Matt Mackall <mpm@selenic.com>
4 # Copyright 2006, 2007 Alexis S. L. Carvalho <alexis@cecm.usp.br>
4 # Copyright 2006, 2007 Alexis S. L. Carvalho <alexis@cecm.usp.br>
5 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
5 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
6 #
6 #
7 # This software may be used and distributed according to the terms of the
7 # This software may be used and distributed according to the terms of the
8 # GNU General Public License version 2 or any later version.
8 # GNU General Public License version 2 or any later version.
9
9
10 import urllib, urllib2, urlparse, httplib, os, re, socket, cStringIO
10 import urllib, urllib2, urlparse, httplib, os, re, socket, cStringIO
11 import __builtin__
11 import __builtin__
12 from i18n import _
12 from i18n import _
13 import keepalive, util
13 import keepalive, util
14
14
15 def _urlunparse(scheme, netloc, path, params, query, fragment, url):
15 def _urlunparse(scheme, netloc, path, params, query, fragment, url):
16 '''Handle cases where urlunparse(urlparse(x://)) doesn't preserve the "//"'''
16 '''Handle cases where urlunparse(urlparse(x://)) doesn't preserve the "//"'''
17 result = urlparse.urlunparse((scheme, netloc, path, params, query, fragment))
17 result = urlparse.urlunparse((scheme, netloc, path, params, query, fragment))
18 if (scheme and
18 if (scheme and
19 result.startswith(scheme + ':') and
19 result.startswith(scheme + ':') and
20 not result.startswith(scheme + '://') and
20 not result.startswith(scheme + '://') and
21 url.startswith(scheme + '://')
21 url.startswith(scheme + '://')
22 ):
22 ):
23 result = scheme + '://' + result[len(scheme + ':'):]
23 result = scheme + '://' + result[len(scheme + ':'):]
24 return result
24 return result
25
25
26 def hidepassword(url):
26 def hidepassword(url):
27 '''hide user credential in a url string'''
27 '''hide user credential in a url string'''
28 scheme, netloc, path, params, query, fragment = urlparse.urlparse(url)
28 scheme, netloc, path, params, query, fragment = urlparse.urlparse(url)
29 netloc = re.sub('([^:]*):([^@]*)@(.*)', r'\1:***@\3', netloc)
29 netloc = re.sub('([^:]*):([^@]*)@(.*)', r'\1:***@\3', netloc)
30 return _urlunparse(scheme, netloc, path, params, query, fragment, url)
30 return _urlunparse(scheme, netloc, path, params, query, fragment, url)
31
31
32 def removeauth(url):
32 def removeauth(url):
33 '''remove all authentication information from a url string'''
33 '''remove all authentication information from a url string'''
34 scheme, netloc, path, params, query, fragment = urlparse.urlparse(url)
34 scheme, netloc, path, params, query, fragment = urlparse.urlparse(url)
35 netloc = netloc[netloc.find('@')+1:]
35 netloc = netloc[netloc.find('@')+1:]
36 return _urlunparse(scheme, netloc, path, params, query, fragment, url)
36 return _urlunparse(scheme, netloc, path, params, query, fragment, url)
37
37
38 def netlocsplit(netloc):
38 def netlocsplit(netloc):
39 '''split [user[:passwd]@]host[:port] into 4-tuple.'''
39 '''split [user[:passwd]@]host[:port] into 4-tuple.'''
40
40
41 a = netloc.find('@')
41 a = netloc.find('@')
42 if a == -1:
42 if a == -1:
43 user, passwd = None, None
43 user, passwd = None, None
44 else:
44 else:
45 userpass, netloc = netloc[:a], netloc[a + 1:]
45 userpass, netloc = netloc[:a], netloc[a + 1:]
46 c = userpass.find(':')
46 c = userpass.find(':')
47 if c == -1:
47 if c == -1:
48 user, passwd = urllib.unquote(userpass), None
48 user, passwd = urllib.unquote(userpass), None
49 else:
49 else:
50 user = urllib.unquote(userpass[:c])
50 user = urllib.unquote(userpass[:c])
51 passwd = urllib.unquote(userpass[c + 1:])
51 passwd = urllib.unquote(userpass[c + 1:])
52 c = netloc.find(':')
52 c = netloc.find(':')
53 if c == -1:
53 if c == -1:
54 host, port = netloc, None
54 host, port = netloc, None
55 else:
55 else:
56 host, port = netloc[:c], netloc[c + 1:]
56 host, port = netloc[:c], netloc[c + 1:]
57 return host, port, user, passwd
57 return host, port, user, passwd
58
58
59 def netlocunsplit(host, port, user=None, passwd=None):
59 def netlocunsplit(host, port, user=None, passwd=None):
60 '''turn host, port, user, passwd into [user[:passwd]@]host[:port].'''
60 '''turn host, port, user, passwd into [user[:passwd]@]host[:port].'''
61 if port:
61 if port:
62 hostport = host + ':' + port
62 hostport = host + ':' + port
63 else:
63 else:
64 hostport = host
64 hostport = host
65 if user:
65 if user:
66 quote = lambda s: urllib.quote(s, safe='')
66 quote = lambda s: urllib.quote(s, safe='')
67 if passwd:
67 if passwd:
68 userpass = quote(user) + ':' + quote(passwd)
68 userpass = quote(user) + ':' + quote(passwd)
69 else:
69 else:
70 userpass = quote(user)
70 userpass = quote(user)
71 return userpass + '@' + hostport
71 return userpass + '@' + hostport
72 return hostport
72 return hostport
73
73
74 _safe = ('abcdefghijklmnopqrstuvwxyz'
74 _safe = ('abcdefghijklmnopqrstuvwxyz'
75 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
75 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
76 '0123456789' '_.-/')
76 '0123456789' '_.-/')
77 _safeset = None
77 _safeset = None
78 _hex = None
78 _hex = None
79 def quotepath(path):
79 def quotepath(path):
80 '''quote the path part of a URL
80 '''quote the path part of a URL
81
81
82 This is similar to urllib.quote, but it also tries to avoid
82 This is similar to urllib.quote, but it also tries to avoid
83 quoting things twice (inspired by wget):
83 quoting things twice (inspired by wget):
84
84
85 >>> quotepath('abc def')
85 >>> quotepath('abc def')
86 'abc%20def'
86 'abc%20def'
87 >>> quotepath('abc%20def')
87 >>> quotepath('abc%20def')
88 'abc%20def'
88 'abc%20def'
89 >>> quotepath('abc%20 def')
89 >>> quotepath('abc%20 def')
90 'abc%20%20def'
90 'abc%20%20def'
91 >>> quotepath('abc def%20')
91 >>> quotepath('abc def%20')
92 'abc%20def%20'
92 'abc%20def%20'
93 >>> quotepath('abc def%2')
93 >>> quotepath('abc def%2')
94 'abc%20def%252'
94 'abc%20def%252'
95 >>> quotepath('abc def%')
95 >>> quotepath('abc def%')
96 'abc%20def%25'
96 'abc%20def%25'
97 '''
97 '''
98 global _safeset, _hex
98 global _safeset, _hex
99 if _safeset is None:
99 if _safeset is None:
100 _safeset = set(_safe)
100 _safeset = set(_safe)
101 _hex = set('abcdefABCDEF0123456789')
101 _hex = set('abcdefABCDEF0123456789')
102 l = list(path)
102 l = list(path)
103 for i in xrange(len(l)):
103 for i in xrange(len(l)):
104 c = l[i]
104 c = l[i]
105 if (c == '%' and i + 2 < len(l) and
105 if (c == '%' and i + 2 < len(l) and
106 l[i + 1] in _hex and l[i + 2] in _hex):
106 l[i + 1] in _hex and l[i + 2] in _hex):
107 pass
107 pass
108 elif c not in _safeset:
108 elif c not in _safeset:
109 l[i] = '%%%02X' % ord(c)
109 l[i] = '%%%02X' % ord(c)
110 return ''.join(l)
110 return ''.join(l)
111
111
112 class passwordmgr(urllib2.HTTPPasswordMgrWithDefaultRealm):
112 class passwordmgr(urllib2.HTTPPasswordMgrWithDefaultRealm):
113 def __init__(self, ui):
113 def __init__(self, ui):
114 urllib2.HTTPPasswordMgrWithDefaultRealm.__init__(self)
114 urllib2.HTTPPasswordMgrWithDefaultRealm.__init__(self)
115 self.ui = ui
115 self.ui = ui
116
116
117 def find_user_password(self, realm, authuri):
117 def find_user_password(self, realm, authuri):
118 authinfo = urllib2.HTTPPasswordMgrWithDefaultRealm.find_user_password(
118 authinfo = urllib2.HTTPPasswordMgrWithDefaultRealm.find_user_password(
119 self, realm, authuri)
119 self, realm, authuri)
120 user, passwd = authinfo
120 user, passwd = authinfo
121 if user and passwd:
121 if user and passwd:
122 self._writedebug(user, passwd)
122 self._writedebug(user, passwd)
123 return (user, passwd)
123 return (user, passwd)
124
124
125 if not user:
125 if not user:
126 auth = self.readauthtoken(authuri)
126 auth = self.readauthtoken(authuri)
127 if auth:
127 if auth:
128 user, passwd = auth.get('username'), auth.get('password')
128 user, passwd = auth.get('username'), auth.get('password')
129 if not user or not passwd:
129 if not user or not passwd:
130 if not self.ui.interactive():
130 if not self.ui.interactive():
131 raise util.Abort(_('http authorization required'))
131 raise util.Abort(_('http authorization required'))
132
132
133 self.ui.write(_("http authorization required\n"))
133 self.ui.write(_("http authorization required\n"))
134 self.ui.write(_("realm: %s\n") % realm)
134 self.ui.write(_("realm: %s\n") % realm)
135 if user:
135 if user:
136 self.ui.write(_("user: %s\n") % user)
136 self.ui.write(_("user: %s\n") % user)
137 else:
137 else:
138 user = self.ui.prompt(_("user:"), default=None)
138 user = self.ui.prompt(_("user:"), default=None)
139
139
140 if not passwd:
140 if not passwd:
141 passwd = self.ui.getpass()
141 passwd = self.ui.getpass()
142
142
143 self.add_password(realm, authuri, user, passwd)
143 self.add_password(realm, authuri, user, passwd)
144 self._writedebug(user, passwd)
144 self._writedebug(user, passwd)
145 return (user, passwd)
145 return (user, passwd)
146
146
147 def _writedebug(self, user, passwd):
147 def _writedebug(self, user, passwd):
148 msg = _('http auth: user %s, password %s\n')
148 msg = _('http auth: user %s, password %s\n')
149 self.ui.debug(msg % (user, passwd and '*' * len(passwd) or 'not set'))
149 self.ui.debug(msg % (user, passwd and '*' * len(passwd) or 'not set'))
150
150
151 def readauthtoken(self, uri):
151 def readauthtoken(self, uri):
152 # Read configuration
152 # Read configuration
153 config = dict()
153 config = dict()
154 for key, val in self.ui.configitems('auth'):
154 for key, val in self.ui.configitems('auth'):
155 if '.' not in key:
155 if '.' not in key:
156 self.ui.warn(_("ignoring invalid [auth] key '%s'\n") % key)
156 self.ui.warn(_("ignoring invalid [auth] key '%s'\n") % key)
157 continue
157 continue
158 group, setting = key.split('.', 1)
158 group, setting = key.split('.', 1)
159 gdict = config.setdefault(group, dict())
159 gdict = config.setdefault(group, dict())
160 if setting in ('username', 'cert', 'key'):
160 if setting in ('username', 'cert', 'key'):
161 val = util.expandpath(val)
161 val = util.expandpath(val)
162 gdict[setting] = val
162 gdict[setting] = val
163
163
164 # Find the best match
164 # Find the best match
165 scheme, hostpath = uri.split('://', 1)
165 scheme, hostpath = uri.split('://', 1)
166 bestlen = 0
166 bestlen = 0
167 bestauth = None
167 bestauth = None
168 for auth in config.itervalues():
168 for auth in config.itervalues():
169 prefix = auth.get('prefix')
169 prefix = auth.get('prefix')
170 if not prefix:
170 if not prefix:
171 continue
171 continue
172 p = prefix.split('://', 1)
172 p = prefix.split('://', 1)
173 if len(p) > 1:
173 if len(p) > 1:
174 schemes, prefix = [p[0]], p[1]
174 schemes, prefix = [p[0]], p[1]
175 else:
175 else:
176 schemes = (auth.get('schemes') or 'https').split()
176 schemes = (auth.get('schemes') or 'https').split()
177 if (prefix == '*' or hostpath.startswith(prefix)) and \
177 if (prefix == '*' or hostpath.startswith(prefix)) and \
178 len(prefix) > bestlen and scheme in schemes:
178 len(prefix) > bestlen and scheme in schemes:
179 bestlen = len(prefix)
179 bestlen = len(prefix)
180 bestauth = auth
180 bestauth = auth
181 return bestauth
181 return bestauth
182
182
183 class proxyhandler(urllib2.ProxyHandler):
183 class proxyhandler(urllib2.ProxyHandler):
184 def __init__(self, ui):
184 def __init__(self, ui):
185 proxyurl = ui.config("http_proxy", "host") or os.getenv('http_proxy')
185 proxyurl = ui.config("http_proxy", "host") or os.getenv('http_proxy')
186 # XXX proxyauthinfo = None
186 # XXX proxyauthinfo = None
187
187
188 if proxyurl:
188 if proxyurl:
189 # proxy can be proper url or host[:port]
189 # proxy can be proper url or host[:port]
190 if not (proxyurl.startswith('http:') or
190 if not (proxyurl.startswith('http:') or
191 proxyurl.startswith('https:')):
191 proxyurl.startswith('https:')):
192 proxyurl = 'http://' + proxyurl + '/'
192 proxyurl = 'http://' + proxyurl + '/'
193 snpqf = urlparse.urlsplit(proxyurl)
193 snpqf = urlparse.urlsplit(proxyurl)
194 proxyscheme, proxynetloc, proxypath, proxyquery, proxyfrag = snpqf
194 proxyscheme, proxynetloc, proxypath, proxyquery, proxyfrag = snpqf
195 hpup = netlocsplit(proxynetloc)
195 hpup = netlocsplit(proxynetloc)
196
196
197 proxyhost, proxyport, proxyuser, proxypasswd = hpup
197 proxyhost, proxyport, proxyuser, proxypasswd = hpup
198 if not proxyuser:
198 if not proxyuser:
199 proxyuser = ui.config("http_proxy", "user")
199 proxyuser = ui.config("http_proxy", "user")
200 proxypasswd = ui.config("http_proxy", "passwd")
200 proxypasswd = ui.config("http_proxy", "passwd")
201
201
202 # see if we should use a proxy for this url
202 # see if we should use a proxy for this url
203 no_list = ["localhost", "127.0.0.1"]
203 no_list = ["localhost", "127.0.0.1"]
204 no_list.extend([p.lower() for
204 no_list.extend([p.lower() for
205 p in ui.configlist("http_proxy", "no")])
205 p in ui.configlist("http_proxy", "no")])
206 no_list.extend([p.strip().lower() for
206 no_list.extend([p.strip().lower() for
207 p in os.getenv("no_proxy", '').split(',')
207 p in os.getenv("no_proxy", '').split(',')
208 if p.strip()])
208 if p.strip()])
209 # "http_proxy.always" config is for running tests on localhost
209 # "http_proxy.always" config is for running tests on localhost
210 if ui.configbool("http_proxy", "always"):
210 if ui.configbool("http_proxy", "always"):
211 self.no_list = []
211 self.no_list = []
212 else:
212 else:
213 self.no_list = no_list
213 self.no_list = no_list
214
214
215 proxyurl = urlparse.urlunsplit((
215 proxyurl = urlparse.urlunsplit((
216 proxyscheme, netlocunsplit(proxyhost, proxyport,
216 proxyscheme, netlocunsplit(proxyhost, proxyport,
217 proxyuser, proxypasswd or ''),
217 proxyuser, proxypasswd or ''),
218 proxypath, proxyquery, proxyfrag))
218 proxypath, proxyquery, proxyfrag))
219 proxies = {'http': proxyurl, 'https': proxyurl}
219 proxies = {'http': proxyurl, 'https': proxyurl}
220 ui.debug('proxying through http://%s:%s\n' %
220 ui.debug('proxying through http://%s:%s\n' %
221 (proxyhost, proxyport))
221 (proxyhost, proxyport))
222 else:
222 else:
223 proxies = {}
223 proxies = {}
224
224
225 # urllib2 takes proxy values from the environment and those
225 # urllib2 takes proxy values from the environment and those
226 # will take precedence if found, so drop them
226 # will take precedence if found, so drop them
227 for env in ["HTTP_PROXY", "http_proxy", "no_proxy"]:
227 for env in ["HTTP_PROXY", "http_proxy", "no_proxy"]:
228 try:
228 try:
229 if env in os.environ:
229 if env in os.environ:
230 del os.environ[env]
230 del os.environ[env]
231 except OSError:
231 except OSError:
232 pass
232 pass
233
233
234 urllib2.ProxyHandler.__init__(self, proxies)
234 urllib2.ProxyHandler.__init__(self, proxies)
235 self.ui = ui
235 self.ui = ui
236
236
237 def proxy_open(self, req, proxy, type_):
237 def proxy_open(self, req, proxy, type_):
238 host = req.get_host().split(':')[0]
238 host = req.get_host().split(':')[0]
239 if host in self.no_list:
239 if host in self.no_list:
240 return None
240 return None
241
241
242 # work around a bug in Python < 2.4.2
242 # work around a bug in Python < 2.4.2
243 # (it leaves a "\n" at the end of Proxy-authorization headers)
243 # (it leaves a "\n" at the end of Proxy-authorization headers)
244 baseclass = req.__class__
244 baseclass = req.__class__
245 class _request(baseclass):
245 class _request(baseclass):
246 def add_header(self, key, val):
246 def add_header(self, key, val):
247 if key.lower() == 'proxy-authorization':
247 if key.lower() == 'proxy-authorization':
248 val = val.strip()
248 val = val.strip()
249 return baseclass.add_header(self, key, val)
249 return baseclass.add_header(self, key, val)
250 req.__class__ = _request
250 req.__class__ = _request
251
251
252 return urllib2.ProxyHandler.proxy_open(self, req, proxy, type_)
252 return urllib2.ProxyHandler.proxy_open(self, req, proxy, type_)
253
253
254 class httpsendfile(object):
254 class httpsendfile(object):
255 """This is a wrapper around the objects returned by python's "open".
255 """This is a wrapper around the objects returned by python's "open".
256
256
257 Its purpose is to send file-like objects via HTTP and, to do so, it
257 Its purpose is to send file-like objects via HTTP and, to do so, it
258 defines a __len__ attribute to feed the Content-Length header.
258 defines a __len__ attribute to feed the Content-Length header.
259 """
259 """
260
260
261 def __init__(self, ui, *args, **kwargs):
261 def __init__(self, ui, *args, **kwargs):
262 # We can't just "self._data = open(*args, **kwargs)" here because there
262 # We can't just "self._data = open(*args, **kwargs)" here because there
263 # is an "open" function defined in this module that shadows the global
263 # is an "open" function defined in this module that shadows the global
264 # one
264 # one
265 self.ui = ui
265 self.ui = ui
266 self._data = __builtin__.open(*args, **kwargs)
266 self._data = __builtin__.open(*args, **kwargs)
267 self.seek = self._data.seek
267 self.seek = self._data.seek
268 self.close = self._data.close
268 self.close = self._data.close
269 self.write = self._data.write
269 self.write = self._data.write
270 self._len = os.fstat(self._data.fileno()).st_size
270 self._len = os.fstat(self._data.fileno()).st_size
271 self._pos = 0
271 self._pos = 0
272 self._total = len(self) / 1024 * 2
272 self._total = len(self) / 1024 * 2
273
273
274 def read(self, *args, **kwargs):
274 def read(self, *args, **kwargs):
275 try:
275 try:
276 ret = self._data.read(*args, **kwargs)
276 ret = self._data.read(*args, **kwargs)
277 except EOFError:
277 except EOFError:
278 self.ui.progress(_('sending'), None)
278 self.ui.progress(_('sending'), None)
279 self._pos += len(ret)
279 self._pos += len(ret)
280 # We pass double the max for total because we currently have
280 # We pass double the max for total because we currently have
281 # to send the bundle twice in the case of a server that
281 # to send the bundle twice in the case of a server that
282 # requires authentication. Since we can't know until we try
282 # requires authentication. Since we can't know until we try
283 # once whether authentication will be required, just lie to
283 # once whether authentication will be required, just lie to
284 # the user and maybe the push succeeds suddenly at 50%.
284 # the user and maybe the push succeeds suddenly at 50%.
285 self.ui.progress(_('sending'), self._pos / 1024,
285 self.ui.progress(_('sending'), self._pos / 1024,
286 unit=_('kb'), total=self._total)
286 unit=_('kb'), total=self._total)
287 return ret
287 return ret
288
288
289 def __len__(self):
289 def __len__(self):
290 return self._len
290 return self._len
291
291
292 def _gen_sendfile(connection):
292 def _gen_sendfile(connection):
293 def _sendfile(self, data):
293 def _sendfile(self, data):
294 # send a file
294 # send a file
295 if isinstance(data, httpsendfile):
295 if isinstance(data, httpsendfile):
296 # if auth required, some data sent twice, so rewind here
296 # if auth required, some data sent twice, so rewind here
297 data.seek(0)
297 data.seek(0)
298 for chunk in util.filechunkiter(data):
298 for chunk in util.filechunkiter(data):
299 connection.send(self, chunk)
299 connection.send(self, chunk)
300 else:
300 else:
301 connection.send(self, data)
301 connection.send(self, data)
302 return _sendfile
302 return _sendfile
303
303
304 has_https = hasattr(urllib2, 'HTTPSHandler')
304 has_https = hasattr(urllib2, 'HTTPSHandler')
305 if has_https:
305 if has_https:
306 try:
306 try:
307 # avoid using deprecated/broken FakeSocket in python 2.6
307 # avoid using deprecated/broken FakeSocket in python 2.6
308 import ssl
308 import ssl
309 _ssl_wrap_socket = ssl.wrap_socket
309 _ssl_wrap_socket = ssl.wrap_socket
310 CERT_REQUIRED = ssl.CERT_REQUIRED
310 CERT_REQUIRED = ssl.CERT_REQUIRED
311 except ImportError:
311 except ImportError:
312 CERT_REQUIRED = 2
312 CERT_REQUIRED = 2
313
313
314 def _ssl_wrap_socket(sock, key_file, cert_file,
314 def _ssl_wrap_socket(sock, key_file, cert_file,
315 cert_reqs=CERT_REQUIRED, ca_certs=None):
315 cert_reqs=CERT_REQUIRED, ca_certs=None):
316 if ca_certs:
316 if ca_certs:
317 raise util.Abort(_(
317 raise util.Abort(_(
318 'certificate checking requires Python 2.6'))
318 'certificate checking requires Python 2.6'))
319
319
320 ssl = socket.ssl(sock, key_file, cert_file)
320 ssl = socket.ssl(sock, key_file, cert_file)
321 return httplib.FakeSocket(sock, ssl)
321 return httplib.FakeSocket(sock, ssl)
322
322
323 try:
323 try:
324 _create_connection = socket.create_connection
324 _create_connection = socket.create_connection
325 except AttributeError:
325 except AttributeError:
326 _GLOBAL_DEFAULT_TIMEOUT = object()
326 _GLOBAL_DEFAULT_TIMEOUT = object()
327
327
328 def _create_connection(address, timeout=_GLOBAL_DEFAULT_TIMEOUT,
328 def _create_connection(address, timeout=_GLOBAL_DEFAULT_TIMEOUT,
329 source_address=None):
329 source_address=None):
330 # lifted from Python 2.6
330 # lifted from Python 2.6
331
331
332 msg = "getaddrinfo returns an empty list"
332 msg = "getaddrinfo returns an empty list"
333 host, port = address
333 host, port = address
334 for res in socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM):
334 for res in socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM):
335 af, socktype, proto, canonname, sa = res
335 af, socktype, proto, canonname, sa = res
336 sock = None
336 sock = None
337 try:
337 try:
338 sock = socket.socket(af, socktype, proto)
338 sock = socket.socket(af, socktype, proto)
339 if timeout is not _GLOBAL_DEFAULT_TIMEOUT:
339 if timeout is not _GLOBAL_DEFAULT_TIMEOUT:
340 sock.settimeout(timeout)
340 sock.settimeout(timeout)
341 if source_address:
341 if source_address:
342 sock.bind(source_address)
342 sock.bind(source_address)
343 sock.connect(sa)
343 sock.connect(sa)
344 return sock
344 return sock
345
345
346 except socket.error, msg:
346 except socket.error, msg:
347 if sock is not None:
347 if sock is not None:
348 sock.close()
348 sock.close()
349
349
350 raise socket.error, msg
350 raise socket.error, msg
351
351
352 class httpconnection(keepalive.HTTPConnection):
352 class httpconnection(keepalive.HTTPConnection):
353 # must be able to send big bundle as stream.
353 # must be able to send big bundle as stream.
354 send = _gen_sendfile(keepalive.HTTPConnection)
354 send = _gen_sendfile(keepalive.HTTPConnection)
355
355
356 def connect(self):
356 def connect(self):
357 if has_https and self.realhostport: # use CONNECT proxy
357 if has_https and self.realhostport: # use CONNECT proxy
358 self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
358 self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
359 self.sock.connect((self.host, self.port))
359 self.sock.connect((self.host, self.port))
360 if _generic_proxytunnel(self):
360 if _generic_proxytunnel(self):
361 # we do not support client x509 certificates
361 # we do not support client x509 certificates
362 self.sock = _ssl_wrap_socket(self.sock, None, None)
362 self.sock = _ssl_wrap_socket(self.sock, None, None)
363 else:
363 else:
364 keepalive.HTTPConnection.connect(self)
364 keepalive.HTTPConnection.connect(self)
365
365
366 def getresponse(self):
366 def getresponse(self):
367 proxyres = getattr(self, 'proxyres', None)
367 proxyres = getattr(self, 'proxyres', None)
368 if proxyres:
368 if proxyres:
369 if proxyres.will_close:
369 if proxyres.will_close:
370 self.close()
370 self.close()
371 self.proxyres = None
371 self.proxyres = None
372 return proxyres
372 return proxyres
373 return keepalive.HTTPConnection.getresponse(self)
373 return keepalive.HTTPConnection.getresponse(self)
374
374
375 # general transaction handler to support different ways to handle
375 # general transaction handler to support different ways to handle
376 # HTTPS proxying before and after Python 2.6.3.
376 # HTTPS proxying before and after Python 2.6.3.
377 def _generic_start_transaction(handler, h, req):
377 def _generic_start_transaction(handler, h, req):
378 if hasattr(req, '_tunnel_host') and req._tunnel_host:
378 if hasattr(req, '_tunnel_host') and req._tunnel_host:
379 tunnel_host = req._tunnel_host
379 tunnel_host = req._tunnel_host
380 if tunnel_host[:7] not in ['http://', 'https:/']:
380 if tunnel_host[:7] not in ['http://', 'https:/']:
381 tunnel_host = 'https://' + tunnel_host
381 tunnel_host = 'https://' + tunnel_host
382 new_tunnel = True
382 new_tunnel = True
383 else:
383 else:
384 tunnel_host = req.get_selector()
384 tunnel_host = req.get_selector()
385 new_tunnel = False
385 new_tunnel = False
386
386
387 if new_tunnel or tunnel_host == req.get_full_url(): # has proxy
387 if new_tunnel or tunnel_host == req.get_full_url(): # has proxy
388 urlparts = urlparse.urlparse(tunnel_host)
388 urlparts = urlparse.urlparse(tunnel_host)
389 if new_tunnel or urlparts[0] == 'https': # only use CONNECT for HTTPS
389 if new_tunnel or urlparts[0] == 'https': # only use CONNECT for HTTPS
390 realhostport = urlparts[1]
390 realhostport = urlparts[1]
391 if realhostport[-1] == ']' or ':' not in realhostport:
391 if realhostport[-1] == ']' or ':' not in realhostport:
392 realhostport += ':443'
392 realhostport += ':443'
393
393
394 h.realhostport = realhostport
394 h.realhostport = realhostport
395 h.headers = req.headers.copy()
395 h.headers = req.headers.copy()
396 h.headers.update(handler.parent.addheaders)
396 h.headers.update(handler.parent.addheaders)
397 return
397 return
398
398
399 h.realhostport = None
399 h.realhostport = None
400 h.headers = None
400 h.headers = None
401
401
402 def _generic_proxytunnel(self):
402 def _generic_proxytunnel(self):
403 proxyheaders = dict(
403 proxyheaders = dict(
404 [(x, self.headers[x]) for x in self.headers
404 [(x, self.headers[x]) for x in self.headers
405 if x.lower().startswith('proxy-')])
405 if x.lower().startswith('proxy-')])
406 self._set_hostport(self.host, self.port)
406 self._set_hostport(self.host, self.port)
407 self.send('CONNECT %s HTTP/1.0\r\n' % self.realhostport)
407 self.send('CONNECT %s HTTP/1.0\r\n' % self.realhostport)
408 for header in proxyheaders.iteritems():
408 for header in proxyheaders.iteritems():
409 self.send('%s: %s\r\n' % header)
409 self.send('%s: %s\r\n' % header)
410 self.send('\r\n')
410 self.send('\r\n')
411
411
412 # majority of the following code is duplicated from
412 # majority of the following code is duplicated from
413 # httplib.HTTPConnection as there are no adequate places to
413 # httplib.HTTPConnection as there are no adequate places to
414 # override functions to provide the needed functionality
414 # override functions to provide the needed functionality
415 res = self.response_class(self.sock,
415 res = self.response_class(self.sock,
416 strict=self.strict,
416 strict=self.strict,
417 method=self._method)
417 method=self._method)
418
418
419 while True:
419 while True:
420 version, status, reason = res._read_status()
420 version, status, reason = res._read_status()
421 if status != httplib.CONTINUE:
421 if status != httplib.CONTINUE:
422 break
422 break
423 while True:
423 while True:
424 skip = res.fp.readline().strip()
424 skip = res.fp.readline().strip()
425 if not skip:
425 if not skip:
426 break
426 break
427 res.status = status
427 res.status = status
428 res.reason = reason.strip()
428 res.reason = reason.strip()
429
429
430 if res.status == 200:
430 if res.status == 200:
431 while True:
431 while True:
432 line = res.fp.readline()
432 line = res.fp.readline()
433 if line == '\r\n':
433 if line == '\r\n':
434 break
434 break
435 return True
435 return True
436
436
437 if version == 'HTTP/1.0':
437 if version == 'HTTP/1.0':
438 res.version = 10
438 res.version = 10
439 elif version.startswith('HTTP/1.'):
439 elif version.startswith('HTTP/1.'):
440 res.version = 11
440 res.version = 11
441 elif version == 'HTTP/0.9':
441 elif version == 'HTTP/0.9':
442 res.version = 9
442 res.version = 9
443 else:
443 else:
444 raise httplib.UnknownProtocol(version)
444 raise httplib.UnknownProtocol(version)
445
445
446 if res.version == 9:
446 if res.version == 9:
447 res.length = None
447 res.length = None
448 res.chunked = 0
448 res.chunked = 0
449 res.will_close = 1
449 res.will_close = 1
450 res.msg = httplib.HTTPMessage(cStringIO.StringIO())
450 res.msg = httplib.HTTPMessage(cStringIO.StringIO())
451 return False
451 return False
452
452
453 res.msg = httplib.HTTPMessage(res.fp)
453 res.msg = httplib.HTTPMessage(res.fp)
454 res.msg.fp = None
454 res.msg.fp = None
455
455
456 # are we using the chunked-style of transfer encoding?
456 # are we using the chunked-style of transfer encoding?
457 trenc = res.msg.getheader('transfer-encoding')
457 trenc = res.msg.getheader('transfer-encoding')
458 if trenc and trenc.lower() == "chunked":
458 if trenc and trenc.lower() == "chunked":
459 res.chunked = 1
459 res.chunked = 1
460 res.chunk_left = None
460 res.chunk_left = None
461 else:
461 else:
462 res.chunked = 0
462 res.chunked = 0
463
463
464 # will the connection close at the end of the response?
464 # will the connection close at the end of the response?
465 res.will_close = res._check_close()
465 res.will_close = res._check_close()
466
466
467 # do we have a Content-Length?
467 # do we have a Content-Length?
468 # NOTE: RFC 2616, S4.4, #3 says we ignore this if tr_enc is "chunked"
468 # NOTE: RFC 2616, S4.4, #3 says we ignore this if tr_enc is "chunked"
469 length = res.msg.getheader('content-length')
469 length = res.msg.getheader('content-length')
470 if length and not res.chunked:
470 if length and not res.chunked:
471 try:
471 try:
472 res.length = int(length)
472 res.length = int(length)
473 except ValueError:
473 except ValueError:
474 res.length = None
474 res.length = None
475 else:
475 else:
476 if res.length < 0: # ignore nonsensical negative lengths
476 if res.length < 0: # ignore nonsensical negative lengths
477 res.length = None
477 res.length = None
478 else:
478 else:
479 res.length = None
479 res.length = None
480
480
481 # does the body have a fixed length? (of zero)
481 # does the body have a fixed length? (of zero)
482 if (status == httplib.NO_CONTENT or status == httplib.NOT_MODIFIED or
482 if (status == httplib.NO_CONTENT or status == httplib.NOT_MODIFIED or
483 100 <= status < 200 or # 1xx codes
483 100 <= status < 200 or # 1xx codes
484 res._method == 'HEAD'):
484 res._method == 'HEAD'):
485 res.length = 0
485 res.length = 0
486
486
487 # if the connection remains open, and we aren't using chunked, and
487 # if the connection remains open, and we aren't using chunked, and
488 # a content-length was not provided, then assume that the connection
488 # a content-length was not provided, then assume that the connection
489 # WILL close.
489 # WILL close.
490 if (not res.will_close and
490 if (not res.will_close and
491 not res.chunked and
491 not res.chunked and
492 res.length is None):
492 res.length is None):
493 res.will_close = 1
493 res.will_close = 1
494
494
495 self.proxyres = res
495 self.proxyres = res
496
496
497 return False
497 return False
498
498
499 class httphandler(keepalive.HTTPHandler):
499 class httphandler(keepalive.HTTPHandler):
500 def http_open(self, req):
500 def http_open(self, req):
501 return self.do_open(httpconnection, req)
501 return self.do_open(httpconnection, req)
502
502
503 def _start_transaction(self, h, req):
503 def _start_transaction(self, h, req):
504 _generic_start_transaction(self, h, req)
504 _generic_start_transaction(self, h, req)
505 return keepalive.HTTPHandler._start_transaction(self, h, req)
505 return keepalive.HTTPHandler._start_transaction(self, h, req)
506
506
507 def _verifycert(cert, hostname):
507 def _verifycert(cert, hostname):
508 '''Verify that cert (in socket.getpeercert() format) matches hostname.
508 '''Verify that cert (in socket.getpeercert() format) matches hostname.
509 CRLs and subjectAltName are not handled.
509 CRLs and subjectAltName are not handled.
510
510
511 Returns error message if any problems are found and None on success.
511 Returns error message if any problems are found and None on success.
512 '''
512 '''
513 if not cert:
513 if not cert:
514 return _('no certificate received')
514 return _('no certificate received')
515 dnsname = hostname.lower()
515 dnsname = hostname.lower()
516 for s in cert.get('subject', []):
516 for s in cert.get('subject', []):
517 key, value = s[0]
517 key, value = s[0]
518 if key == 'commonName':
518 if key == 'commonName':
519 certname = value.lower()
519 certname = value.lower()
520 if (certname == dnsname or
520 if (certname == dnsname or
521 '.' in dnsname and certname == '*.' + dnsname.split('.', 1)[1]):
521 '.' in dnsname and certname == '*.' + dnsname.split('.', 1)[1]):
522 return None
522 return None
523 return _('certificate is for %s') % certname
523 return _('certificate is for %s') % certname
524 return _('no commonName found in certificate')
524 return _('no commonName found in certificate')
525
525
526 if has_https:
526 if has_https:
527 class BetterHTTPS(httplib.HTTPSConnection):
527 class BetterHTTPS(httplib.HTTPSConnection):
528 send = keepalive.safesend
528 send = keepalive.safesend
529
529
530 def connect(self):
530 def connect(self):
531 if hasattr(self, 'ui'):
531 if hasattr(self, 'ui'):
532 cacerts = self.ui.config('web', 'cacerts')
532 cacerts = self.ui.config('web', 'cacerts')
533 if cacerts:
534 cacerts = util.expandpath(cacerts)
533 else:
535 else:
534 cacerts = None
536 cacerts = None
535
537
536 if cacerts:
538 if cacerts:
537 sock = _create_connection((self.host, self.port))
539 sock = _create_connection((self.host, self.port))
538 self.sock = _ssl_wrap_socket(sock, self.key_file,
540 self.sock = _ssl_wrap_socket(sock, self.key_file,
539 self.cert_file, cert_reqs=CERT_REQUIRED,
541 self.cert_file, cert_reqs=CERT_REQUIRED,
540 ca_certs=cacerts)
542 ca_certs=cacerts)
541 msg = _verifycert(self.sock.getpeercert(), self.host)
543 msg = _verifycert(self.sock.getpeercert(), self.host)
542 if msg:
544 if msg:
543 raise util.Abort(_('%s certificate error: %s') %
545 raise util.Abort(_('%s certificate error: %s') %
544 (self.host, msg))
546 (self.host, msg))
545 self.ui.debug('%s certificate successfully verified\n' %
547 self.ui.debug('%s certificate successfully verified\n' %
546 self.host)
548 self.host)
547 else:
549 else:
548 self.ui.warn(_("warning: %s certificate not verified "
550 self.ui.warn(_("warning: %s certificate not verified "
549 "(check web.cacerts config setting)\n") %
551 "(check web.cacerts config setting)\n") %
550 self.host)
552 self.host)
551 httplib.HTTPSConnection.connect(self)
553 httplib.HTTPSConnection.connect(self)
552
554
553 class httpsconnection(BetterHTTPS):
555 class httpsconnection(BetterHTTPS):
554 response_class = keepalive.HTTPResponse
556 response_class = keepalive.HTTPResponse
555 # must be able to send big bundle as stream.
557 # must be able to send big bundle as stream.
556 send = _gen_sendfile(BetterHTTPS)
558 send = _gen_sendfile(BetterHTTPS)
557 getresponse = keepalive.wrapgetresponse(httplib.HTTPSConnection)
559 getresponse = keepalive.wrapgetresponse(httplib.HTTPSConnection)
558
560
559 def connect(self):
561 def connect(self):
560 if self.realhostport: # use CONNECT proxy
562 if self.realhostport: # use CONNECT proxy
561 self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
563 self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
562 self.sock.connect((self.host, self.port))
564 self.sock.connect((self.host, self.port))
563 if _generic_proxytunnel(self):
565 if _generic_proxytunnel(self):
564 self.sock = _ssl_wrap_socket(self.sock, self.key_file,
566 self.sock = _ssl_wrap_socket(self.sock, self.key_file,
565 self.cert_file)
567 self.cert_file)
566 else:
568 else:
567 BetterHTTPS.connect(self)
569 BetterHTTPS.connect(self)
568
570
569 class httpshandler(keepalive.KeepAliveHandler, urllib2.HTTPSHandler):
571 class httpshandler(keepalive.KeepAliveHandler, urllib2.HTTPSHandler):
570 def __init__(self, ui):
572 def __init__(self, ui):
571 keepalive.KeepAliveHandler.__init__(self)
573 keepalive.KeepAliveHandler.__init__(self)
572 urllib2.HTTPSHandler.__init__(self)
574 urllib2.HTTPSHandler.__init__(self)
573 self.ui = ui
575 self.ui = ui
574 self.pwmgr = passwordmgr(self.ui)
576 self.pwmgr = passwordmgr(self.ui)
575
577
576 def _start_transaction(self, h, req):
578 def _start_transaction(self, h, req):
577 _generic_start_transaction(self, h, req)
579 _generic_start_transaction(self, h, req)
578 return keepalive.KeepAliveHandler._start_transaction(self, h, req)
580 return keepalive.KeepAliveHandler._start_transaction(self, h, req)
579
581
580 def https_open(self, req):
582 def https_open(self, req):
581 self.auth = self.pwmgr.readauthtoken(req.get_full_url())
583 self.auth = self.pwmgr.readauthtoken(req.get_full_url())
582 return self.do_open(self._makeconnection, req)
584 return self.do_open(self._makeconnection, req)
583
585
584 def _makeconnection(self, host, port=None, *args, **kwargs):
586 def _makeconnection(self, host, port=None, *args, **kwargs):
585 keyfile = None
587 keyfile = None
586 certfile = None
588 certfile = None
587
589
588 if len(args) >= 1: # key_file
590 if len(args) >= 1: # key_file
589 keyfile = args[0]
591 keyfile = args[0]
590 if len(args) >= 2: # cert_file
592 if len(args) >= 2: # cert_file
591 certfile = args[1]
593 certfile = args[1]
592 args = args[2:]
594 args = args[2:]
593
595
594 # if the user has specified different key/cert files in
596 # if the user has specified different key/cert files in
595 # hgrc, we prefer these
597 # hgrc, we prefer these
596 if self.auth and 'key' in self.auth and 'cert' in self.auth:
598 if self.auth and 'key' in self.auth and 'cert' in self.auth:
597 keyfile = self.auth['key']
599 keyfile = self.auth['key']
598 certfile = self.auth['cert']
600 certfile = self.auth['cert']
599
601
600 conn = httpsconnection(host, port, keyfile, certfile, *args, **kwargs)
602 conn = httpsconnection(host, port, keyfile, certfile, *args, **kwargs)
601 conn.ui = self.ui
603 conn.ui = self.ui
602 return conn
604 return conn
603
605
604 class httpdigestauthhandler(urllib2.HTTPDigestAuthHandler):
606 class httpdigestauthhandler(urllib2.HTTPDigestAuthHandler):
605 def __init__(self, *args, **kwargs):
607 def __init__(self, *args, **kwargs):
606 urllib2.HTTPDigestAuthHandler.__init__(self, *args, **kwargs)
608 urllib2.HTTPDigestAuthHandler.__init__(self, *args, **kwargs)
607 self.retried_req = None
609 self.retried_req = None
608
610
609 def reset_retry_count(self):
611 def reset_retry_count(self):
610 # Python 2.6.5 will call this on 401 or 407 errors and thus loop
612 # Python 2.6.5 will call this on 401 or 407 errors and thus loop
611 # forever. We disable reset_retry_count completely and reset in
613 # forever. We disable reset_retry_count completely and reset in
612 # http_error_auth_reqed instead.
614 # http_error_auth_reqed instead.
613 pass
615 pass
614
616
615 def http_error_auth_reqed(self, auth_header, host, req, headers):
617 def http_error_auth_reqed(self, auth_header, host, req, headers):
616 # Reset the retry counter once for each request.
618 # Reset the retry counter once for each request.
617 if req is not self.retried_req:
619 if req is not self.retried_req:
618 self.retried_req = req
620 self.retried_req = req
619 self.retried = 0
621 self.retried = 0
620 # In python < 2.5 AbstractDigestAuthHandler raises a ValueError if
622 # In python < 2.5 AbstractDigestAuthHandler raises a ValueError if
621 # it doesn't know about the auth type requested. This can happen if
623 # it doesn't know about the auth type requested. This can happen if
622 # somebody is using BasicAuth and types a bad password.
624 # somebody is using BasicAuth and types a bad password.
623 try:
625 try:
624 return urllib2.HTTPDigestAuthHandler.http_error_auth_reqed(
626 return urllib2.HTTPDigestAuthHandler.http_error_auth_reqed(
625 self, auth_header, host, req, headers)
627 self, auth_header, host, req, headers)
626 except ValueError, inst:
628 except ValueError, inst:
627 arg = inst.args[0]
629 arg = inst.args[0]
628 if arg.startswith("AbstractDigestAuthHandler doesn't know "):
630 if arg.startswith("AbstractDigestAuthHandler doesn't know "):
629 return
631 return
630 raise
632 raise
631
633
632 class httpbasicauthhandler(urllib2.HTTPBasicAuthHandler):
634 class httpbasicauthhandler(urllib2.HTTPBasicAuthHandler):
633 def __init__(self, *args, **kwargs):
635 def __init__(self, *args, **kwargs):
634 urllib2.HTTPBasicAuthHandler.__init__(self, *args, **kwargs)
636 urllib2.HTTPBasicAuthHandler.__init__(self, *args, **kwargs)
635 self.retried_req = None
637 self.retried_req = None
636
638
637 def reset_retry_count(self):
639 def reset_retry_count(self):
638 # Python 2.6.5 will call this on 401 or 407 errors and thus loop
640 # Python 2.6.5 will call this on 401 or 407 errors and thus loop
639 # forever. We disable reset_retry_count completely and reset in
641 # forever. We disable reset_retry_count completely and reset in
640 # http_error_auth_reqed instead.
642 # http_error_auth_reqed instead.
641 pass
643 pass
642
644
643 def http_error_auth_reqed(self, auth_header, host, req, headers):
645 def http_error_auth_reqed(self, auth_header, host, req, headers):
644 # Reset the retry counter once for each request.
646 # Reset the retry counter once for each request.
645 if req is not self.retried_req:
647 if req is not self.retried_req:
646 self.retried_req = req
648 self.retried_req = req
647 self.retried = 0
649 self.retried = 0
648 return urllib2.HTTPBasicAuthHandler.http_error_auth_reqed(
650 return urllib2.HTTPBasicAuthHandler.http_error_auth_reqed(
649 self, auth_header, host, req, headers)
651 self, auth_header, host, req, headers)
650
652
651 def getauthinfo(path):
653 def getauthinfo(path):
652 scheme, netloc, urlpath, query, frag = urlparse.urlsplit(path)
654 scheme, netloc, urlpath, query, frag = urlparse.urlsplit(path)
653 if not urlpath:
655 if not urlpath:
654 urlpath = '/'
656 urlpath = '/'
655 if scheme != 'file':
657 if scheme != 'file':
656 # XXX: why are we quoting the path again with some smart
658 # XXX: why are we quoting the path again with some smart
657 # heuristic here? Anyway, it cannot be done with file://
659 # heuristic here? Anyway, it cannot be done with file://
658 # urls since path encoding is os/fs dependent (see
660 # urls since path encoding is os/fs dependent (see
659 # urllib.pathname2url() for details).
661 # urllib.pathname2url() for details).
660 urlpath = quotepath(urlpath)
662 urlpath = quotepath(urlpath)
661 host, port, user, passwd = netlocsplit(netloc)
663 host, port, user, passwd = netlocsplit(netloc)
662
664
663 # urllib cannot handle URLs with embedded user or passwd
665 # urllib cannot handle URLs with embedded user or passwd
664 url = urlparse.urlunsplit((scheme, netlocunsplit(host, port),
666 url = urlparse.urlunsplit((scheme, netlocunsplit(host, port),
665 urlpath, query, frag))
667 urlpath, query, frag))
666 if user:
668 if user:
667 netloc = host
669 netloc = host
668 if port:
670 if port:
669 netloc += ':' + port
671 netloc += ':' + port
670 # Python < 2.4.3 uses only the netloc to search for a password
672 # Python < 2.4.3 uses only the netloc to search for a password
671 authinfo = (None, (url, netloc), user, passwd or '')
673 authinfo = (None, (url, netloc), user, passwd or '')
672 else:
674 else:
673 authinfo = None
675 authinfo = None
674 return url, authinfo
676 return url, authinfo
675
677
676 handlerfuncs = []
678 handlerfuncs = []
677
679
678 def opener(ui, authinfo=None):
680 def opener(ui, authinfo=None):
679 '''
681 '''
680 construct an opener suitable for urllib2
682 construct an opener suitable for urllib2
681 authinfo will be added to the password manager
683 authinfo will be added to the password manager
682 '''
684 '''
683 handlers = [httphandler()]
685 handlers = [httphandler()]
684 if has_https:
686 if has_https:
685 handlers.append(httpshandler(ui))
687 handlers.append(httpshandler(ui))
686
688
687 handlers.append(proxyhandler(ui))
689 handlers.append(proxyhandler(ui))
688
690
689 passmgr = passwordmgr(ui)
691 passmgr = passwordmgr(ui)
690 if authinfo is not None:
692 if authinfo is not None:
691 passmgr.add_password(*authinfo)
693 passmgr.add_password(*authinfo)
692 user, passwd = authinfo[2:4]
694 user, passwd = authinfo[2:4]
693 ui.debug('http auth: user %s, password %s\n' %
695 ui.debug('http auth: user %s, password %s\n' %
694 (user, passwd and '*' * len(passwd) or 'not set'))
696 (user, passwd and '*' * len(passwd) or 'not set'))
695
697
696 handlers.extend((httpbasicauthhandler(passmgr),
698 handlers.extend((httpbasicauthhandler(passmgr),
697 httpdigestauthhandler(passmgr)))
699 httpdigestauthhandler(passmgr)))
698 handlers.extend([h(ui, passmgr) for h in handlerfuncs])
700 handlers.extend([h(ui, passmgr) for h in handlerfuncs])
699 opener = urllib2.build_opener(*handlers)
701 opener = urllib2.build_opener(*handlers)
700
702
701 # 1.0 here is the _protocol_ version
703 # 1.0 here is the _protocol_ version
702 opener.addheaders = [('User-agent', 'mercurial/proto-1.0')]
704 opener.addheaders = [('User-agent', 'mercurial/proto-1.0')]
703 opener.addheaders.append(('Accept', 'application/mercurial-0.1'))
705 opener.addheaders.append(('Accept', 'application/mercurial-0.1'))
704 return opener
706 return opener
705
707
706 scheme_re = re.compile(r'^([a-zA-Z0-9+-.]+)://')
708 scheme_re = re.compile(r'^([a-zA-Z0-9+-.]+)://')
707
709
708 def open(ui, url, data=None):
710 def open(ui, url, data=None):
709 scheme = None
711 scheme = None
710 m = scheme_re.search(url)
712 m = scheme_re.search(url)
711 if m:
713 if m:
712 scheme = m.group(1).lower()
714 scheme = m.group(1).lower()
713 if not scheme:
715 if not scheme:
714 path = util.normpath(os.path.abspath(url))
716 path = util.normpath(os.path.abspath(url))
715 url = 'file://' + urllib.pathname2url(path)
717 url = 'file://' + urllib.pathname2url(path)
716 authinfo = None
718 authinfo = None
717 else:
719 else:
718 url, authinfo = getauthinfo(url)
720 url, authinfo = getauthinfo(url)
719 return opener(ui, authinfo).open(url, data)
721 return opener(ui, authinfo).open(url, data)
@@ -1,429 +1,429 b''
1 $ "$TESTDIR/hghave" no-outer-repo || exit 80
1 $ "$TESTDIR/hghave" no-outer-repo || exit 80
2
2
3 $ hg init a
3 $ hg init a
4 $ cd a
4 $ cd a
5 $ echo a > a
5 $ echo a > a
6 $ hg ci -A -d'1 0' -m a
6 $ hg ci -A -d'1 0' -m a
7 adding a
7 adding a
8
8
9 $ cd ..
9 $ cd ..
10
10
11 $ hg init b
11 $ hg init b
12 $ cd b
12 $ cd b
13 $ echo b > b
13 $ echo b > b
14 $ hg ci -A -d'1 0' -m b
14 $ hg ci -A -d'1 0' -m b
15 adding b
15 adding b
16
16
17 $ cd ..
17 $ cd ..
18
18
19 $ hg clone a c
19 $ hg clone a c
20 updating to branch default
20 updating to branch default
21 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
21 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
22 $ cd c
22 $ cd c
23 $ cat >> .hg/hgrc <<EOF
23 $ cat >> .hg/hgrc <<EOF
24 > [paths]
24 > [paths]
25 > relative = ../a
25 > relative = ../a
26 > EOF
26 > EOF
27 $ hg pull -f ../b
27 $ hg pull -f ../b
28 pulling from ../b
28 pulling from ../b
29 searching for changes
29 searching for changes
30 warning: repository is unrelated
30 warning: repository is unrelated
31 adding changesets
31 adding changesets
32 adding manifests
32 adding manifests
33 adding file changes
33 adding file changes
34 added 1 changesets with 1 changes to 1 files (+1 heads)
34 added 1 changesets with 1 changes to 1 files (+1 heads)
35 (run 'hg heads' to see heads, 'hg merge' to merge)
35 (run 'hg heads' to see heads, 'hg merge' to merge)
36 $ hg merge
36 $ hg merge
37 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
37 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
38 (branch merge, don't forget to commit)
38 (branch merge, don't forget to commit)
39
39
40 $ cd ..
40 $ cd ..
41
41
42 Testing -R/--repository:
42 Testing -R/--repository:
43
43
44 $ hg -R a tip
44 $ hg -R a tip
45 changeset: 0:8580ff50825a
45 changeset: 0:8580ff50825a
46 tag: tip
46 tag: tip
47 user: test
47 user: test
48 date: Thu Jan 01 00:00:01 1970 +0000
48 date: Thu Jan 01 00:00:01 1970 +0000
49 summary: a
49 summary: a
50
50
51 $ hg --repository b tip
51 $ hg --repository b tip
52 changeset: 0:b6c483daf290
52 changeset: 0:b6c483daf290
53 tag: tip
53 tag: tip
54 user: test
54 user: test
55 date: Thu Jan 01 00:00:01 1970 +0000
55 date: Thu Jan 01 00:00:01 1970 +0000
56 summary: b
56 summary: b
57
57
58
58
59 -R with a URL:
59 -R with a URL:
60
60
61 $ hg -R file:a identify
61 $ hg -R file:a identify
62 8580ff50825a tip
62 8580ff50825a tip
63 $ hg -R file://localhost/`pwd`/a/ identify
63 $ hg -R file://localhost/`pwd`/a/ identify
64 8580ff50825a tip
64 8580ff50825a tip
65
65
66 -R with path aliases:
66 -R with path aliases:
67
67
68 $ cd c
68 $ cd c
69 $ hg -R default identify
69 $ hg -R default identify
70 8580ff50825a tip
70 8580ff50825a tip
71 $ hg -R relative identify
71 $ hg -R relative identify
72 8580ff50825a tip
72 8580ff50825a tip
73 $ echo '[paths]' >> $HGRCPATH
73 $ echo '[paths]' >> $HGRCPATH
74 $ echo 'relativetohome = a' >> $HGRCPATH
74 $ echo 'relativetohome = a' >> $HGRCPATH
75 $ HOME=`pwd`/../ hg -R relativetohome identify
75 $ HOME=`pwd`/../ hg -R relativetohome identify
76 8580ff50825a tip
76 8580ff50825a tip
77 $ cd ..
77 $ cd ..
78
78
79 Implicit -R:
79 Implicit -R:
80
80
81 $ hg ann a/a
81 $ hg ann a/a
82 0: a
82 0: a
83 $ hg ann a/a a/a
83 $ hg ann a/a a/a
84 0: a
84 0: a
85 $ hg ann a/a b/b
85 $ hg ann a/a b/b
86 abort: There is no Mercurial repository here (.hg not found)!
86 abort: There is no Mercurial repository here (.hg not found)!
87 [255]
87 [255]
88 $ hg -R b ann a/a
88 $ hg -R b ann a/a
89 abort: a/a not under root
89 abort: a/a not under root
90 [255]
90 [255]
91 $ hg log
91 $ hg log
92 abort: There is no Mercurial repository here (.hg not found)!
92 abort: There is no Mercurial repository here (.hg not found)!
93 [255]
93 [255]
94
94
95 Abbreviation of long option:
95 Abbreviation of long option:
96
96
97 $ hg --repo c tip
97 $ hg --repo c tip
98 changeset: 1:b6c483daf290
98 changeset: 1:b6c483daf290
99 tag: tip
99 tag: tip
100 parent: -1:000000000000
100 parent: -1:000000000000
101 user: test
101 user: test
102 date: Thu Jan 01 00:00:01 1970 +0000
102 date: Thu Jan 01 00:00:01 1970 +0000
103 summary: b
103 summary: b
104
104
105
105
106 earlygetopt with duplicate options (36d23de02da1):
106 earlygetopt with duplicate options (36d23de02da1):
107
107
108 $ hg --cwd a --cwd b --cwd c tip
108 $ hg --cwd a --cwd b --cwd c tip
109 changeset: 1:b6c483daf290
109 changeset: 1:b6c483daf290
110 tag: tip
110 tag: tip
111 parent: -1:000000000000
111 parent: -1:000000000000
112 user: test
112 user: test
113 date: Thu Jan 01 00:00:01 1970 +0000
113 date: Thu Jan 01 00:00:01 1970 +0000
114 summary: b
114 summary: b
115
115
116 $ hg --repo c --repository b -R a tip
116 $ hg --repo c --repository b -R a tip
117 changeset: 0:8580ff50825a
117 changeset: 0:8580ff50825a
118 tag: tip
118 tag: tip
119 user: test
119 user: test
120 date: Thu Jan 01 00:00:01 1970 +0000
120 date: Thu Jan 01 00:00:01 1970 +0000
121 summary: a
121 summary: a
122
122
123
123
124 earlygetopt short option without following space:
124 earlygetopt short option without following space:
125
125
126 $ hg -q -Rb tip
126 $ hg -q -Rb tip
127 0:b6c483daf290
127 0:b6c483daf290
128
128
129 earlygetopt with illegal abbreviations:
129 earlygetopt with illegal abbreviations:
130
130
131 $ hg --confi "foo.bar=baz"
131 $ hg --confi "foo.bar=baz"
132 abort: option --config may not be abbreviated!
132 abort: option --config may not be abbreviated!
133 [255]
133 [255]
134 $ hg --cw a tip
134 $ hg --cw a tip
135 abort: option --cwd may not be abbreviated!
135 abort: option --cwd may not be abbreviated!
136 [255]
136 [255]
137 $ hg --rep a tip
137 $ hg --rep a tip
138 abort: Option -R has to be separated from other options (e.g. not -qR) and --repository may only be abbreviated as --repo!
138 abort: Option -R has to be separated from other options (e.g. not -qR) and --repository may only be abbreviated as --repo!
139 [255]
139 [255]
140 $ hg --repositor a tip
140 $ hg --repositor a tip
141 abort: Option -R has to be separated from other options (e.g. not -qR) and --repository may only be abbreviated as --repo!
141 abort: Option -R has to be separated from other options (e.g. not -qR) and --repository may only be abbreviated as --repo!
142 [255]
142 [255]
143 $ hg -qR a tip
143 $ hg -qR a tip
144 abort: Option -R has to be separated from other options (e.g. not -qR) and --repository may only be abbreviated as --repo!
144 abort: Option -R has to be separated from other options (e.g. not -qR) and --repository may only be abbreviated as --repo!
145 [255]
145 [255]
146 $ hg -qRa tip
146 $ hg -qRa tip
147 abort: Option -R has to be separated from other options (e.g. not -qR) and --repository may only be abbreviated as --repo!
147 abort: Option -R has to be separated from other options (e.g. not -qR) and --repository may only be abbreviated as --repo!
148 [255]
148 [255]
149
149
150 Testing --cwd:
150 Testing --cwd:
151
151
152 $ hg --cwd a parents
152 $ hg --cwd a parents
153 changeset: 0:8580ff50825a
153 changeset: 0:8580ff50825a
154 tag: tip
154 tag: tip
155 user: test
155 user: test
156 date: Thu Jan 01 00:00:01 1970 +0000
156 date: Thu Jan 01 00:00:01 1970 +0000
157 summary: a
157 summary: a
158
158
159
159
160 Testing -y/--noninteractive - just be sure it is parsed:
160 Testing -y/--noninteractive - just be sure it is parsed:
161
161
162 $ hg --cwd a tip -q --noninteractive
162 $ hg --cwd a tip -q --noninteractive
163 0:8580ff50825a
163 0:8580ff50825a
164 $ hg --cwd a tip -q -y
164 $ hg --cwd a tip -q -y
165 0:8580ff50825a
165 0:8580ff50825a
166
166
167 Testing -q/--quiet:
167 Testing -q/--quiet:
168
168
169 $ hg -R a -q tip
169 $ hg -R a -q tip
170 0:8580ff50825a
170 0:8580ff50825a
171 $ hg -R b -q tip
171 $ hg -R b -q tip
172 0:b6c483daf290
172 0:b6c483daf290
173 $ hg -R c --quiet parents
173 $ hg -R c --quiet parents
174 0:8580ff50825a
174 0:8580ff50825a
175 1:b6c483daf290
175 1:b6c483daf290
176
176
177 Testing -v/--verbose:
177 Testing -v/--verbose:
178
178
179 $ hg --cwd c head -v
179 $ hg --cwd c head -v
180 changeset: 1:b6c483daf290
180 changeset: 1:b6c483daf290
181 tag: tip
181 tag: tip
182 parent: -1:000000000000
182 parent: -1:000000000000
183 user: test
183 user: test
184 date: Thu Jan 01 00:00:01 1970 +0000
184 date: Thu Jan 01 00:00:01 1970 +0000
185 files: b
185 files: b
186 description:
186 description:
187 b
187 b
188
188
189
189
190 changeset: 0:8580ff50825a
190 changeset: 0:8580ff50825a
191 user: test
191 user: test
192 date: Thu Jan 01 00:00:01 1970 +0000
192 date: Thu Jan 01 00:00:01 1970 +0000
193 files: a
193 files: a
194 description:
194 description:
195 a
195 a
196
196
197
197
198 $ hg --cwd b tip --verbose
198 $ hg --cwd b tip --verbose
199 changeset: 0:b6c483daf290
199 changeset: 0:b6c483daf290
200 tag: tip
200 tag: tip
201 user: test
201 user: test
202 date: Thu Jan 01 00:00:01 1970 +0000
202 date: Thu Jan 01 00:00:01 1970 +0000
203 files: b
203 files: b
204 description:
204 description:
205 b
205 b
206
206
207
207
208
208
209 Testing --config:
209 Testing --config:
210
210
211 $ hg --cwd c --config paths.quuxfoo=bar paths | grep quuxfoo > /dev/null && echo quuxfoo
211 $ hg --cwd c --config paths.quuxfoo=bar paths | grep quuxfoo > /dev/null && echo quuxfoo
212 quuxfoo
212 quuxfoo
213 $ hg --cwd c --config '' tip -q
213 $ hg --cwd c --config '' tip -q
214 abort: malformed --config option: '' (use --config section.name=value)
214 abort: malformed --config option: '' (use --config section.name=value)
215 [255]
215 [255]
216 $ hg --cwd c --config a.b tip -q
216 $ hg --cwd c --config a.b tip -q
217 abort: malformed --config option: 'a.b' (use --config section.name=value)
217 abort: malformed --config option: 'a.b' (use --config section.name=value)
218 [255]
218 [255]
219 $ hg --cwd c --config a tip -q
219 $ hg --cwd c --config a tip -q
220 abort: malformed --config option: 'a' (use --config section.name=value)
220 abort: malformed --config option: 'a' (use --config section.name=value)
221 [255]
221 [255]
222 $ hg --cwd c --config a.= tip -q
222 $ hg --cwd c --config a.= tip -q
223 abort: malformed --config option: 'a.=' (use --config section.name=value)
223 abort: malformed --config option: 'a.=' (use --config section.name=value)
224 [255]
224 [255]
225 $ hg --cwd c --config .b= tip -q
225 $ hg --cwd c --config .b= tip -q
226 abort: malformed --config option: '.b=' (use --config section.name=value)
226 abort: malformed --config option: '.b=' (use --config section.name=value)
227 [255]
227 [255]
228
228
229 Testing --debug:
229 Testing --debug:
230
230
231 $ hg --cwd c log --debug
231 $ hg --cwd c log --debug
232 changeset: 1:b6c483daf2907ce5825c0bb50f5716226281cc1a
232 changeset: 1:b6c483daf2907ce5825c0bb50f5716226281cc1a
233 tag: tip
233 tag: tip
234 parent: -1:0000000000000000000000000000000000000000
234 parent: -1:0000000000000000000000000000000000000000
235 parent: -1:0000000000000000000000000000000000000000
235 parent: -1:0000000000000000000000000000000000000000
236 manifest: 1:23226e7a252cacdc2d99e4fbdc3653441056de49
236 manifest: 1:23226e7a252cacdc2d99e4fbdc3653441056de49
237 user: test
237 user: test
238 date: Thu Jan 01 00:00:01 1970 +0000
238 date: Thu Jan 01 00:00:01 1970 +0000
239 files+: b
239 files+: b
240 extra: branch=default
240 extra: branch=default
241 description:
241 description:
242 b
242 b
243
243
244
244
245 changeset: 0:8580ff50825a50c8f716709acdf8de0deddcd6ab
245 changeset: 0:8580ff50825a50c8f716709acdf8de0deddcd6ab
246 parent: -1:0000000000000000000000000000000000000000
246 parent: -1:0000000000000000000000000000000000000000
247 parent: -1:0000000000000000000000000000000000000000
247 parent: -1:0000000000000000000000000000000000000000
248 manifest: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0
248 manifest: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0
249 user: test
249 user: test
250 date: Thu Jan 01 00:00:01 1970 +0000
250 date: Thu Jan 01 00:00:01 1970 +0000
251 files+: a
251 files+: a
252 extra: branch=default
252 extra: branch=default
253 description:
253 description:
254 a
254 a
255
255
256
256
257
257
258 Testing --traceback:
258 Testing --traceback:
259
259
260 $ hg --cwd c --config x --traceback id 2>&1 | grep -i 'traceback'
260 $ hg --cwd c --config x --traceback id 2>&1 | grep -i 'traceback'
261 Traceback (most recent call last):
261 Traceback (most recent call last):
262
262
263 Testing --time:
263 Testing --time:
264
264
265 $ hg --cwd a --time id
265 $ hg --cwd a --time id
266 8580ff50825a tip
266 8580ff50825a tip
267 Time: real * (glob)
267 Time: real * (glob)
268
268
269 Testing --version:
269 Testing --version:
270
270
271 $ hg --version -q
271 $ hg --version -q
272 Mercurial Distributed SCM * (glob)
272 Mercurial Distributed SCM * (glob)
273
273
274 Testing -h/--help:
274 Testing -h/--help:
275
275
276 $ hg -h
276 $ hg -h
277 Mercurial Distributed SCM
277 Mercurial Distributed SCM
278
278
279 list of commands:
279 list of commands:
280
280
281 add add the specified files on the next commit
281 add add the specified files on the next commit
282 addremove add all new files, delete all missing files
282 addremove add all new files, delete all missing files
283 annotate show changeset information by line for each file
283 annotate show changeset information by line for each file
284 archive create an unversioned archive of a repository revision
284 archive create an unversioned archive of a repository revision
285 backout reverse effect of earlier changeset
285 backout reverse effect of earlier changeset
286 bisect subdivision search of changesets
286 bisect subdivision search of changesets
287 branch set or show the current branch name
287 branch set or show the current branch name
288 branches list repository named branches
288 branches list repository named branches
289 bundle create a changegroup file
289 bundle create a changegroup file
290 cat output the current or given revision of files
290 cat output the current or given revision of files
291 clone make a copy of an existing repository
291 clone make a copy of an existing repository
292 commit commit the specified files or all outstanding changes
292 commit commit the specified files or all outstanding changes
293 copy mark files as copied for the next commit
293 copy mark files as copied for the next commit
294 diff diff repository (or selected files)
294 diff diff repository (or selected files)
295 export dump the header and diffs for one or more changesets
295 export dump the header and diffs for one or more changesets
296 forget forget the specified files on the next commit
296 forget forget the specified files on the next commit
297 grep search for a pattern in specified files and revisions
297 grep search for a pattern in specified files and revisions
298 heads show current repository heads or show branch heads
298 heads show current repository heads or show branch heads
299 help show help for a given topic or a help overview
299 help show help for a given topic or a help overview
300 identify identify the working copy or specified revision
300 identify identify the working copy or specified revision
301 import import an ordered set of patches
301 import import an ordered set of patches
302 incoming show new changesets found in source
302 incoming show new changesets found in source
303 init create a new repository in the given directory
303 init create a new repository in the given directory
304 locate locate files matching specific patterns
304 locate locate files matching specific patterns
305 log show revision history of entire repository or files
305 log show revision history of entire repository or files
306 manifest output the current or given revision of the project manifest
306 manifest output the current or given revision of the project manifest
307 merge merge working directory with another revision
307 merge merge working directory with another revision
308 outgoing show changesets not found in the destination
308 outgoing show changesets not found in the destination
309 parents show the parents of the working directory or revision
309 parents show the parents of the working directory or revision
310 paths show aliases for remote repositories
310 paths show aliases for remote repositories
311 pull pull changes from the specified source
311 pull pull changes from the specified source
312 push push changes to the specified destination
312 push push changes to the specified destination
313 recover roll back an interrupted transaction
313 recover roll back an interrupted transaction
314 remove remove the specified files on the next commit
314 remove remove the specified files on the next commit
315 rename rename files; equivalent of copy + remove
315 rename rename files; equivalent of copy + remove
316 resolve redo merges or set/view the merge status of files
316 resolve redo merges or set/view the merge status of files
317 revert restore individual files or directories to an earlier state
317 revert restore individual files or directories to an earlier state
318 rollback roll back the last transaction (dangerous)
318 rollback roll back the last transaction (dangerous)
319 root print the root (top) of the current working directory
319 root print the root (top) of the current working directory
320 serve start stand-alone webserver
320 serve start stand-alone webserver
321 showconfig show combined config settings from all hgrc files
321 showconfig show combined config settings from all hgrc files
322 status show changed files in the working directory
322 status show changed files in the working directory
323 summary summarize working directory state
323 summary summarize working directory state
324 tag add one or more tags for the current or given revision
324 tag add one or more tags for the current or given revision
325 tags list repository tags
325 tags list repository tags
326 tip show the tip revision
326 tip show the tip revision
327 unbundle apply one or more changegroup files
327 unbundle apply one or more changegroup files
328 update update working directory (or switch revisions)
328 update update working directory (or switch revisions)
329 verify verify the integrity of the repository
329 verify verify the integrity of the repository
330 version output version and copyright information
330 version output version and copyright information
331
331
332 additional help topics:
332 additional help topics:
333
333
334 config Configuration Files
334 config Configuration Files
335 dates Date Formats
335 dates Date Formats
336 patterns File Name Patterns
336 patterns File Name Patterns
337 environment Environment Variables
337 environment Environment Variables
338 revisions Specifying Single Revisions
338 revisions Specifying Single Revisions
339 multirevs Specifying Multiple Revisions
339 multirevs Specifying Multiple Revisions
340 revsets Specifying Revision Sets
340 revsets Specifying Revision Sets
341 diffs Diff Formats
341 diffs Diff Formats
342 merge-tools Merge Tools
342 merge-tools Merge Tools
343 templating Template Usage
343 templating Template Usage
344 urls URL Paths
344 urls URL Paths
345 extensions Using additional features
345 extensions Using additional features
346 subrepos Subrepositories
346 subrepos Subrepositories
347 hgweb Configuring hgweb
347 hgweb Configuring hgweb
348 glossary Glossary
348 glossary Glossary
349
349
350 use "hg -v help" to show aliases and global options
350 use "hg -v help" to show builtin aliases and global options
351
351
352 $ hg --help
352 $ hg --help
353 Mercurial Distributed SCM
353 Mercurial Distributed SCM
354
354
355 list of commands:
355 list of commands:
356
356
357 add add the specified files on the next commit
357 add add the specified files on the next commit
358 addremove add all new files, delete all missing files
358 addremove add all new files, delete all missing files
359 annotate show changeset information by line for each file
359 annotate show changeset information by line for each file
360 archive create an unversioned archive of a repository revision
360 archive create an unversioned archive of a repository revision
361 backout reverse effect of earlier changeset
361 backout reverse effect of earlier changeset
362 bisect subdivision search of changesets
362 bisect subdivision search of changesets
363 branch set or show the current branch name
363 branch set or show the current branch name
364 branches list repository named branches
364 branches list repository named branches
365 bundle create a changegroup file
365 bundle create a changegroup file
366 cat output the current or given revision of files
366 cat output the current or given revision of files
367 clone make a copy of an existing repository
367 clone make a copy of an existing repository
368 commit commit the specified files or all outstanding changes
368 commit commit the specified files or all outstanding changes
369 copy mark files as copied for the next commit
369 copy mark files as copied for the next commit
370 diff diff repository (or selected files)
370 diff diff repository (or selected files)
371 export dump the header and diffs for one or more changesets
371 export dump the header and diffs for one or more changesets
372 forget forget the specified files on the next commit
372 forget forget the specified files on the next commit
373 grep search for a pattern in specified files and revisions
373 grep search for a pattern in specified files and revisions
374 heads show current repository heads or show branch heads
374 heads show current repository heads or show branch heads
375 help show help for a given topic or a help overview
375 help show help for a given topic or a help overview
376 identify identify the working copy or specified revision
376 identify identify the working copy or specified revision
377 import import an ordered set of patches
377 import import an ordered set of patches
378 incoming show new changesets found in source
378 incoming show new changesets found in source
379 init create a new repository in the given directory
379 init create a new repository in the given directory
380 locate locate files matching specific patterns
380 locate locate files matching specific patterns
381 log show revision history of entire repository or files
381 log show revision history of entire repository or files
382 manifest output the current or given revision of the project manifest
382 manifest output the current or given revision of the project manifest
383 merge merge working directory with another revision
383 merge merge working directory with another revision
384 outgoing show changesets not found in the destination
384 outgoing show changesets not found in the destination
385 parents show the parents of the working directory or revision
385 parents show the parents of the working directory or revision
386 paths show aliases for remote repositories
386 paths show aliases for remote repositories
387 pull pull changes from the specified source
387 pull pull changes from the specified source
388 push push changes to the specified destination
388 push push changes to the specified destination
389 recover roll back an interrupted transaction
389 recover roll back an interrupted transaction
390 remove remove the specified files on the next commit
390 remove remove the specified files on the next commit
391 rename rename files; equivalent of copy + remove
391 rename rename files; equivalent of copy + remove
392 resolve redo merges or set/view the merge status of files
392 resolve redo merges or set/view the merge status of files
393 revert restore individual files or directories to an earlier state
393 revert restore individual files or directories to an earlier state
394 rollback roll back the last transaction (dangerous)
394 rollback roll back the last transaction (dangerous)
395 root print the root (top) of the current working directory
395 root print the root (top) of the current working directory
396 serve start stand-alone webserver
396 serve start stand-alone webserver
397 showconfig show combined config settings from all hgrc files
397 showconfig show combined config settings from all hgrc files
398 status show changed files in the working directory
398 status show changed files in the working directory
399 summary summarize working directory state
399 summary summarize working directory state
400 tag add one or more tags for the current or given revision
400 tag add one or more tags for the current or given revision
401 tags list repository tags
401 tags list repository tags
402 tip show the tip revision
402 tip show the tip revision
403 unbundle apply one or more changegroup files
403 unbundle apply one or more changegroup files
404 update update working directory (or switch revisions)
404 update update working directory (or switch revisions)
405 verify verify the integrity of the repository
405 verify verify the integrity of the repository
406 version output version and copyright information
406 version output version and copyright information
407
407
408 additional help topics:
408 additional help topics:
409
409
410 config Configuration Files
410 config Configuration Files
411 dates Date Formats
411 dates Date Formats
412 patterns File Name Patterns
412 patterns File Name Patterns
413 environment Environment Variables
413 environment Environment Variables
414 revisions Specifying Single Revisions
414 revisions Specifying Single Revisions
415 multirevs Specifying Multiple Revisions
415 multirevs Specifying Multiple Revisions
416 revsets Specifying Revision Sets
416 revsets Specifying Revision Sets
417 diffs Diff Formats
417 diffs Diff Formats
418 merge-tools Merge Tools
418 merge-tools Merge Tools
419 templating Template Usage
419 templating Template Usage
420 urls URL Paths
420 urls URL Paths
421 extensions Using additional features
421 extensions Using additional features
422 subrepos Subrepositories
422 subrepos Subrepositories
423 hgweb Configuring hgweb
423 hgweb Configuring hgweb
424 glossary Glossary
424 glossary Glossary
425
425
426 use "hg -v help" to show aliases and global options
426 use "hg -v help" to show builtin aliases and global options
427
427
428 Not tested: --debugger
428 Not tested: --debugger
429
429
@@ -1,790 +1,790 b''
1 Short help:
1 Short help:
2
2
3 $ hg
3 $ hg
4 Mercurial Distributed SCM
4 Mercurial Distributed SCM
5
5
6 basic commands:
6 basic commands:
7
7
8 add add the specified files on the next commit
8 add add the specified files on the next commit
9 annotate show changeset information by line for each file
9 annotate show changeset information by line for each file
10 clone make a copy of an existing repository
10 clone make a copy of an existing repository
11 commit commit the specified files or all outstanding changes
11 commit commit the specified files or all outstanding changes
12 diff diff repository (or selected files)
12 diff diff repository (or selected files)
13 export dump the header and diffs for one or more changesets
13 export dump the header and diffs for one or more changesets
14 forget forget the specified files on the next commit
14 forget forget the specified files on the next commit
15 init create a new repository in the given directory
15 init create a new repository in the given directory
16 log show revision history of entire repository or files
16 log show revision history of entire repository or files
17 merge merge working directory with another revision
17 merge merge working directory with another revision
18 pull pull changes from the specified source
18 pull pull changes from the specified source
19 push push changes to the specified destination
19 push push changes to the specified destination
20 remove remove the specified files on the next commit
20 remove remove the specified files on the next commit
21 serve start stand-alone webserver
21 serve start stand-alone webserver
22 status show changed files in the working directory
22 status show changed files in the working directory
23 summary summarize working directory state
23 summary summarize working directory state
24 update update working directory (or switch revisions)
24 update update working directory (or switch revisions)
25
25
26 use "hg help" for the full list of commands or "hg -v" for details
26 use "hg help" for the full list of commands or "hg -v" for details
27
27
28 $ hg -q
28 $ hg -q
29 add add the specified files on the next commit
29 add add the specified files on the next commit
30 annotate show changeset information by line for each file
30 annotate show changeset information by line for each file
31 clone make a copy of an existing repository
31 clone make a copy of an existing repository
32 commit commit the specified files or all outstanding changes
32 commit commit the specified files or all outstanding changes
33 diff diff repository (or selected files)
33 diff diff repository (or selected files)
34 export dump the header and diffs for one or more changesets
34 export dump the header and diffs for one or more changesets
35 forget forget the specified files on the next commit
35 forget forget the specified files on the next commit
36 init create a new repository in the given directory
36 init create a new repository in the given directory
37 log show revision history of entire repository or files
37 log show revision history of entire repository or files
38 merge merge working directory with another revision
38 merge merge working directory with another revision
39 pull pull changes from the specified source
39 pull pull changes from the specified source
40 push push changes to the specified destination
40 push push changes to the specified destination
41 remove remove the specified files on the next commit
41 remove remove the specified files on the next commit
42 serve start stand-alone webserver
42 serve start stand-alone webserver
43 status show changed files in the working directory
43 status show changed files in the working directory
44 summary summarize working directory state
44 summary summarize working directory state
45 update update working directory (or switch revisions)
45 update update working directory (or switch revisions)
46
46
47 $ hg help
47 $ hg help
48 Mercurial Distributed SCM
48 Mercurial Distributed SCM
49
49
50 list of commands:
50 list of commands:
51
51
52 add add the specified files on the next commit
52 add add the specified files on the next commit
53 addremove add all new files, delete all missing files
53 addremove add all new files, delete all missing files
54 annotate show changeset information by line for each file
54 annotate show changeset information by line for each file
55 archive create an unversioned archive of a repository revision
55 archive create an unversioned archive of a repository revision
56 backout reverse effect of earlier changeset
56 backout reverse effect of earlier changeset
57 bisect subdivision search of changesets
57 bisect subdivision search of changesets
58 branch set or show the current branch name
58 branch set or show the current branch name
59 branches list repository named branches
59 branches list repository named branches
60 bundle create a changegroup file
60 bundle create a changegroup file
61 cat output the current or given revision of files
61 cat output the current or given revision of files
62 clone make a copy of an existing repository
62 clone make a copy of an existing repository
63 commit commit the specified files or all outstanding changes
63 commit commit the specified files or all outstanding changes
64 copy mark files as copied for the next commit
64 copy mark files as copied for the next commit
65 diff diff repository (or selected files)
65 diff diff repository (or selected files)
66 export dump the header and diffs for one or more changesets
66 export dump the header and diffs for one or more changesets
67 forget forget the specified files on the next commit
67 forget forget the specified files on the next commit
68 grep search for a pattern in specified files and revisions
68 grep search for a pattern in specified files and revisions
69 heads show current repository heads or show branch heads
69 heads show current repository heads or show branch heads
70 help show help for a given topic or a help overview
70 help show help for a given topic or a help overview
71 identify identify the working copy or specified revision
71 identify identify the working copy or specified revision
72 import import an ordered set of patches
72 import import an ordered set of patches
73 incoming show new changesets found in source
73 incoming show new changesets found in source
74 init create a new repository in the given directory
74 init create a new repository in the given directory
75 locate locate files matching specific patterns
75 locate locate files matching specific patterns
76 log show revision history of entire repository or files
76 log show revision history of entire repository or files
77 manifest output the current or given revision of the project manifest
77 manifest output the current or given revision of the project manifest
78 merge merge working directory with another revision
78 merge merge working directory with another revision
79 outgoing show changesets not found in the destination
79 outgoing show changesets not found in the destination
80 parents show the parents of the working directory or revision
80 parents show the parents of the working directory or revision
81 paths show aliases for remote repositories
81 paths show aliases for remote repositories
82 pull pull changes from the specified source
82 pull pull changes from the specified source
83 push push changes to the specified destination
83 push push changes to the specified destination
84 recover roll back an interrupted transaction
84 recover roll back an interrupted transaction
85 remove remove the specified files on the next commit
85 remove remove the specified files on the next commit
86 rename rename files; equivalent of copy + remove
86 rename rename files; equivalent of copy + remove
87 resolve redo merges or set/view the merge status of files
87 resolve redo merges or set/view the merge status of files
88 revert restore individual files or directories to an earlier state
88 revert restore individual files or directories to an earlier state
89 rollback roll back the last transaction (dangerous)
89 rollback roll back the last transaction (dangerous)
90 root print the root (top) of the current working directory
90 root print the root (top) of the current working directory
91 serve start stand-alone webserver
91 serve start stand-alone webserver
92 showconfig show combined config settings from all hgrc files
92 showconfig show combined config settings from all hgrc files
93 status show changed files in the working directory
93 status show changed files in the working directory
94 summary summarize working directory state
94 summary summarize working directory state
95 tag add one or more tags for the current or given revision
95 tag add one or more tags for the current or given revision
96 tags list repository tags
96 tags list repository tags
97 tip show the tip revision
97 tip show the tip revision
98 unbundle apply one or more changegroup files
98 unbundle apply one or more changegroup files
99 update update working directory (or switch revisions)
99 update update working directory (or switch revisions)
100 verify verify the integrity of the repository
100 verify verify the integrity of the repository
101 version output version and copyright information
101 version output version and copyright information
102
102
103 additional help topics:
103 additional help topics:
104
104
105 config Configuration Files
105 config Configuration Files
106 dates Date Formats
106 dates Date Formats
107 patterns File Name Patterns
107 patterns File Name Patterns
108 environment Environment Variables
108 environment Environment Variables
109 revisions Specifying Single Revisions
109 revisions Specifying Single Revisions
110 multirevs Specifying Multiple Revisions
110 multirevs Specifying Multiple Revisions
111 revsets Specifying Revision Sets
111 revsets Specifying Revision Sets
112 diffs Diff Formats
112 diffs Diff Formats
113 merge-tools Merge Tools
113 merge-tools Merge Tools
114 templating Template Usage
114 templating Template Usage
115 urls URL Paths
115 urls URL Paths
116 extensions Using additional features
116 extensions Using additional features
117 subrepos Subrepositories
117 subrepos Subrepositories
118 hgweb Configuring hgweb
118 hgweb Configuring hgweb
119 glossary Glossary
119 glossary Glossary
120
120
121 use "hg -v help" to show aliases and global options
121 use "hg -v help" to show builtin aliases and global options
122
122
123 $ hg -q help
123 $ hg -q help
124 add add the specified files on the next commit
124 add add the specified files on the next commit
125 addremove add all new files, delete all missing files
125 addremove add all new files, delete all missing files
126 annotate show changeset information by line for each file
126 annotate show changeset information by line for each file
127 archive create an unversioned archive of a repository revision
127 archive create an unversioned archive of a repository revision
128 backout reverse effect of earlier changeset
128 backout reverse effect of earlier changeset
129 bisect subdivision search of changesets
129 bisect subdivision search of changesets
130 branch set or show the current branch name
130 branch set or show the current branch name
131 branches list repository named branches
131 branches list repository named branches
132 bundle create a changegroup file
132 bundle create a changegroup file
133 cat output the current or given revision of files
133 cat output the current or given revision of files
134 clone make a copy of an existing repository
134 clone make a copy of an existing repository
135 commit commit the specified files or all outstanding changes
135 commit commit the specified files or all outstanding changes
136 copy mark files as copied for the next commit
136 copy mark files as copied for the next commit
137 diff diff repository (or selected files)
137 diff diff repository (or selected files)
138 export dump the header and diffs for one or more changesets
138 export dump the header and diffs for one or more changesets
139 forget forget the specified files on the next commit
139 forget forget the specified files on the next commit
140 grep search for a pattern in specified files and revisions
140 grep search for a pattern in specified files and revisions
141 heads show current repository heads or show branch heads
141 heads show current repository heads or show branch heads
142 help show help for a given topic or a help overview
142 help show help for a given topic or a help overview
143 identify identify the working copy or specified revision
143 identify identify the working copy or specified revision
144 import import an ordered set of patches
144 import import an ordered set of patches
145 incoming show new changesets found in source
145 incoming show new changesets found in source
146 init create a new repository in the given directory
146 init create a new repository in the given directory
147 locate locate files matching specific patterns
147 locate locate files matching specific patterns
148 log show revision history of entire repository or files
148 log show revision history of entire repository or files
149 manifest output the current or given revision of the project manifest
149 manifest output the current or given revision of the project manifest
150 merge merge working directory with another revision
150 merge merge working directory with another revision
151 outgoing show changesets not found in the destination
151 outgoing show changesets not found in the destination
152 parents show the parents of the working directory or revision
152 parents show the parents of the working directory or revision
153 paths show aliases for remote repositories
153 paths show aliases for remote repositories
154 pull pull changes from the specified source
154 pull pull changes from the specified source
155 push push changes to the specified destination
155 push push changes to the specified destination
156 recover roll back an interrupted transaction
156 recover roll back an interrupted transaction
157 remove remove the specified files on the next commit
157 remove remove the specified files on the next commit
158 rename rename files; equivalent of copy + remove
158 rename rename files; equivalent of copy + remove
159 resolve redo merges or set/view the merge status of files
159 resolve redo merges or set/view the merge status of files
160 revert restore individual files or directories to an earlier state
160 revert restore individual files or directories to an earlier state
161 rollback roll back the last transaction (dangerous)
161 rollback roll back the last transaction (dangerous)
162 root print the root (top) of the current working directory
162 root print the root (top) of the current working directory
163 serve start stand-alone webserver
163 serve start stand-alone webserver
164 showconfig show combined config settings from all hgrc files
164 showconfig show combined config settings from all hgrc files
165 status show changed files in the working directory
165 status show changed files in the working directory
166 summary summarize working directory state
166 summary summarize working directory state
167 tag add one or more tags for the current or given revision
167 tag add one or more tags for the current or given revision
168 tags list repository tags
168 tags list repository tags
169 tip show the tip revision
169 tip show the tip revision
170 unbundle apply one or more changegroup files
170 unbundle apply one or more changegroup files
171 update update working directory (or switch revisions)
171 update update working directory (or switch revisions)
172 verify verify the integrity of the repository
172 verify verify the integrity of the repository
173 version output version and copyright information
173 version output version and copyright information
174
174
175 additional help topics:
175 additional help topics:
176
176
177 config Configuration Files
177 config Configuration Files
178 dates Date Formats
178 dates Date Formats
179 patterns File Name Patterns
179 patterns File Name Patterns
180 environment Environment Variables
180 environment Environment Variables
181 revisions Specifying Single Revisions
181 revisions Specifying Single Revisions
182 multirevs Specifying Multiple Revisions
182 multirevs Specifying Multiple Revisions
183 revsets Specifying Revision Sets
183 revsets Specifying Revision Sets
184 diffs Diff Formats
184 diffs Diff Formats
185 merge-tools Merge Tools
185 merge-tools Merge Tools
186 templating Template Usage
186 templating Template Usage
187 urls URL Paths
187 urls URL Paths
188 extensions Using additional features
188 extensions Using additional features
189 subrepos Subrepositories
189 subrepos Subrepositories
190 hgweb Configuring hgweb
190 hgweb Configuring hgweb
191 glossary Glossary
191 glossary Glossary
192
192
193 Test short command list with verbose option
193 Test short command list with verbose option
194
194
195 $ hg -v help shortlist
195 $ hg -v help shortlist
196 Mercurial Distributed SCM (version *) (glob)
196 Mercurial Distributed SCM (version *) (glob)
197 (see http://mercurial.selenic.com for more information)
197 (see http://mercurial.selenic.com for more information)
198
198
199 Copyright (C) 2005-2010 Matt Mackall and others
199 Copyright (C) 2005-2010 Matt Mackall and others
200 This is free software; see the source for copying conditions. There is NO
200 This is free software; see the source for copying conditions. There is NO
201 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
201 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
202
202
203 basic commands:
203 basic commands:
204
204
205 add:
205 add:
206 add the specified files on the next commit
206 add the specified files on the next commit
207 annotate, blame:
207 annotate, blame:
208 show changeset information by line for each file
208 show changeset information by line for each file
209 clone:
209 clone:
210 make a copy of an existing repository
210 make a copy of an existing repository
211 commit, ci:
211 commit, ci:
212 commit the specified files or all outstanding changes
212 commit the specified files or all outstanding changes
213 diff:
213 diff:
214 diff repository (or selected files)
214 diff repository (or selected files)
215 export:
215 export:
216 dump the header and diffs for one or more changesets
216 dump the header and diffs for one or more changesets
217 forget:
217 forget:
218 forget the specified files on the next commit
218 forget the specified files on the next commit
219 init:
219 init:
220 create a new repository in the given directory
220 create a new repository in the given directory
221 log, history:
221 log, history:
222 show revision history of entire repository or files
222 show revision history of entire repository or files
223 merge:
223 merge:
224 merge working directory with another revision
224 merge working directory with another revision
225 pull:
225 pull:
226 pull changes from the specified source
226 pull changes from the specified source
227 push:
227 push:
228 push changes to the specified destination
228 push changes to the specified destination
229 remove, rm:
229 remove, rm:
230 remove the specified files on the next commit
230 remove the specified files on the next commit
231 serve:
231 serve:
232 start stand-alone webserver
232 start stand-alone webserver
233 status, st:
233 status, st:
234 show changed files in the working directory
234 show changed files in the working directory
235 summary, sum:
235 summary, sum:
236 summarize working directory state
236 summarize working directory state
237 update, up, checkout, co:
237 update, up, checkout, co:
238 update working directory (or switch revisions)
238 update working directory (or switch revisions)
239
239
240 global options:
240 global options:
241 -R --repository REPO repository root directory or name of overlay bundle
241 -R --repository REPO repository root directory or name of overlay bundle
242 file
242 file
243 --cwd DIR change working directory
243 --cwd DIR change working directory
244 -y --noninteractive do not prompt, assume 'yes' for any required answers
244 -y --noninteractive do not prompt, assume 'yes' for any required answers
245 -q --quiet suppress output
245 -q --quiet suppress output
246 -v --verbose enable additional output
246 -v --verbose enable additional output
247 --config CONFIG [+] set/override config option (use 'section.name=value')
247 --config CONFIG [+] set/override config option (use 'section.name=value')
248 --debug enable debugging output
248 --debug enable debugging output
249 --debugger start debugger
249 --debugger start debugger
250 --encoding ENCODE set the charset encoding (default: ascii)
250 --encoding ENCODE set the charset encoding (default: ascii)
251 --encodingmode MODE set the charset encoding mode (default: strict)
251 --encodingmode MODE set the charset encoding mode (default: strict)
252 --traceback always print a traceback on exception
252 --traceback always print a traceback on exception
253 --time time how long the command takes
253 --time time how long the command takes
254 --profile print command execution profile
254 --profile print command execution profile
255 --version output version information and exit
255 --version output version information and exit
256 -h --help display help and exit
256 -h --help display help and exit
257
257
258 [+] marked option can be specified multiple times
258 [+] marked option can be specified multiple times
259
259
260 use "hg help" for the full list of commands
260 use "hg help" for the full list of commands
261
261
262 $ hg add -h
262 $ hg add -h
263 hg add [OPTION]... [FILE]...
263 hg add [OPTION]... [FILE]...
264
264
265 add the specified files on the next commit
265 add the specified files on the next commit
266
266
267 Schedule files to be version controlled and added to the repository.
267 Schedule files to be version controlled and added to the repository.
268
268
269 The files will be added to the repository at the next commit. To undo an
269 The files will be added to the repository at the next commit. To undo an
270 add before that, see "hg forget".
270 add before that, see "hg forget".
271
271
272 If no names are given, add all files to the repository.
272 If no names are given, add all files to the repository.
273
273
274 Returns 0 if all files are successfully added.
274 Returns 0 if all files are successfully added.
275
275
276 use "hg -v help add" to show verbose help
276 use "hg -v help add" to show verbose help
277
277
278 options:
278 options:
279
279
280 -I --include PATTERN [+] include names matching the given patterns
280 -I --include PATTERN [+] include names matching the given patterns
281 -X --exclude PATTERN [+] exclude names matching the given patterns
281 -X --exclude PATTERN [+] exclude names matching the given patterns
282 -S --subrepos recurse into subrepositories
282 -S --subrepos recurse into subrepositories
283 -n --dry-run do not perform actions, just print output
283 -n --dry-run do not perform actions, just print output
284
284
285 [+] marked option can be specified multiple times
285 [+] marked option can be specified multiple times
286
286
287 use "hg -v help add" to show global options
287 use "hg -v help add" to show global options
288
288
289 Verbose help for add
289 Verbose help for add
290
290
291 $ hg add -hv
291 $ hg add -hv
292 hg add [OPTION]... [FILE]...
292 hg add [OPTION]... [FILE]...
293
293
294 add the specified files on the next commit
294 add the specified files on the next commit
295
295
296 Schedule files to be version controlled and added to the repository.
296 Schedule files to be version controlled and added to the repository.
297
297
298 The files will be added to the repository at the next commit. To undo an
298 The files will be added to the repository at the next commit. To undo an
299 add before that, see "hg forget".
299 add before that, see "hg forget".
300
300
301 If no names are given, add all files to the repository.
301 If no names are given, add all files to the repository.
302
302
303 An example showing how new (unknown) files are added automatically by "hg
303 An example showing how new (unknown) files are added automatically by "hg
304 add":
304 add":
305
305
306 $ ls
306 $ ls
307 foo.c
307 foo.c
308 $ hg status
308 $ hg status
309 ? foo.c
309 ? foo.c
310 $ hg add
310 $ hg add
311 adding foo.c
311 adding foo.c
312 $ hg status
312 $ hg status
313 A foo.c
313 A foo.c
314
314
315 Returns 0 if all files are successfully added.
315 Returns 0 if all files are successfully added.
316
316
317 options:
317 options:
318
318
319 -I --include PATTERN [+] include names matching the given patterns
319 -I --include PATTERN [+] include names matching the given patterns
320 -X --exclude PATTERN [+] exclude names matching the given patterns
320 -X --exclude PATTERN [+] exclude names matching the given patterns
321 -S --subrepos recurse into subrepositories
321 -S --subrepos recurse into subrepositories
322 -n --dry-run do not perform actions, just print output
322 -n --dry-run do not perform actions, just print output
323
323
324 global options:
324 global options:
325 -R --repository REPO repository root directory or name of overlay bundle
325 -R --repository REPO repository root directory or name of overlay bundle
326 file
326 file
327 --cwd DIR change working directory
327 --cwd DIR change working directory
328 -y --noninteractive do not prompt, assume 'yes' for any required
328 -y --noninteractive do not prompt, assume 'yes' for any required
329 answers
329 answers
330 -q --quiet suppress output
330 -q --quiet suppress output
331 -v --verbose enable additional output
331 -v --verbose enable additional output
332 --config CONFIG [+] set/override config option (use
332 --config CONFIG [+] set/override config option (use
333 'section.name=value')
333 'section.name=value')
334 --debug enable debugging output
334 --debug enable debugging output
335 --debugger start debugger
335 --debugger start debugger
336 --encoding ENCODE set the charset encoding (default: ascii)
336 --encoding ENCODE set the charset encoding (default: ascii)
337 --encodingmode MODE set the charset encoding mode (default: strict)
337 --encodingmode MODE set the charset encoding mode (default: strict)
338 --traceback always print a traceback on exception
338 --traceback always print a traceback on exception
339 --time time how long the command takes
339 --time time how long the command takes
340 --profile print command execution profile
340 --profile print command execution profile
341 --version output version information and exit
341 --version output version information and exit
342 -h --help display help and exit
342 -h --help display help and exit
343
343
344 [+] marked option can be specified multiple times
344 [+] marked option can be specified multiple times
345
345
346 Test help option with version option
346 Test help option with version option
347
347
348 $ hg add -h --version
348 $ hg add -h --version
349 Mercurial Distributed SCM (version *) (glob)
349 Mercurial Distributed SCM (version *) (glob)
350 (see http://mercurial.selenic.com for more information)
350 (see http://mercurial.selenic.com for more information)
351
351
352 Copyright (C) 2005-2010 Matt Mackall and others
352 Copyright (C) 2005-2010 Matt Mackall and others
353 This is free software; see the source for copying conditions. There is NO
353 This is free software; see the source for copying conditions. There is NO
354 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
354 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
355
355
356 hg add [OPTION]... [FILE]...
356 hg add [OPTION]... [FILE]...
357
357
358 add the specified files on the next commit
358 add the specified files on the next commit
359
359
360 Schedule files to be version controlled and added to the repository.
360 Schedule files to be version controlled and added to the repository.
361
361
362 The files will be added to the repository at the next commit. To undo an
362 The files will be added to the repository at the next commit. To undo an
363 add before that, see "hg forget".
363 add before that, see "hg forget".
364
364
365 If no names are given, add all files to the repository.
365 If no names are given, add all files to the repository.
366
366
367 Returns 0 if all files are successfully added.
367 Returns 0 if all files are successfully added.
368
368
369 use "hg -v help add" to show verbose help
369 use "hg -v help add" to show verbose help
370
370
371 options:
371 options:
372
372
373 -I --include PATTERN [+] include names matching the given patterns
373 -I --include PATTERN [+] include names matching the given patterns
374 -X --exclude PATTERN [+] exclude names matching the given patterns
374 -X --exclude PATTERN [+] exclude names matching the given patterns
375 -S --subrepos recurse into subrepositories
375 -S --subrepos recurse into subrepositories
376 -n --dry-run do not perform actions, just print output
376 -n --dry-run do not perform actions, just print output
377
377
378 [+] marked option can be specified multiple times
378 [+] marked option can be specified multiple times
379
379
380 use "hg -v help add" to show global options
380 use "hg -v help add" to show global options
381
381
382 $ hg add --skjdfks
382 $ hg add --skjdfks
383 hg add: option --skjdfks not recognized
383 hg add: option --skjdfks not recognized
384 hg add [OPTION]... [FILE]...
384 hg add [OPTION]... [FILE]...
385
385
386 add the specified files on the next commit
386 add the specified files on the next commit
387
387
388 Schedule files to be version controlled and added to the repository.
388 Schedule files to be version controlled and added to the repository.
389
389
390 The files will be added to the repository at the next commit. To undo an
390 The files will be added to the repository at the next commit. To undo an
391 add before that, see "hg forget".
391 add before that, see "hg forget".
392
392
393 If no names are given, add all files to the repository.
393 If no names are given, add all files to the repository.
394
394
395 Returns 0 if all files are successfully added.
395 Returns 0 if all files are successfully added.
396
396
397 use "hg -v help add" to show verbose help
397 use "hg -v help add" to show verbose help
398
398
399 options:
399 options:
400
400
401 -I --include PATTERN [+] include names matching the given patterns
401 -I --include PATTERN [+] include names matching the given patterns
402 -X --exclude PATTERN [+] exclude names matching the given patterns
402 -X --exclude PATTERN [+] exclude names matching the given patterns
403 -S --subrepos recurse into subrepositories
403 -S --subrepos recurse into subrepositories
404 -n --dry-run do not perform actions, just print output
404 -n --dry-run do not perform actions, just print output
405
405
406 [+] marked option can be specified multiple times
406 [+] marked option can be specified multiple times
407
407
408 use "hg -v help add" to show global options
408 use "hg -v help add" to show global options
409 [255]
409 [255]
410
410
411 Test ambiguous command help
411 Test ambiguous command help
412
412
413 $ hg help ad
413 $ hg help ad
414 list of commands:
414 list of commands:
415
415
416 add add the specified files on the next commit
416 add add the specified files on the next commit
417 addremove add all new files, delete all missing files
417 addremove add all new files, delete all missing files
418
418
419 use "hg -v help ad" to show aliases and global options
419 use "hg -v help ad" to show builtin aliases and global options
420
420
421 Test command without options
421 Test command without options
422
422
423 $ hg help verify
423 $ hg help verify
424 hg verify
424 hg verify
425
425
426 verify the integrity of the repository
426 verify the integrity of the repository
427
427
428 Verify the integrity of the current repository.
428 Verify the integrity of the current repository.
429
429
430 This will perform an extensive check of the repository's integrity,
430 This will perform an extensive check of the repository's integrity,
431 validating the hashes and checksums of each entry in the changelog,
431 validating the hashes and checksums of each entry in the changelog,
432 manifest, and tracked files, as well as the integrity of their crosslinks
432 manifest, and tracked files, as well as the integrity of their crosslinks
433 and indices.
433 and indices.
434
434
435 Returns 0 on success, 1 if errors are encountered.
435 Returns 0 on success, 1 if errors are encountered.
436
436
437 use "hg -v help verify" to show global options
437 use "hg -v help verify" to show global options
438
438
439 $ hg help diff
439 $ hg help diff
440 hg diff [OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...
440 hg diff [OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...
441
441
442 diff repository (or selected files)
442 diff repository (or selected files)
443
443
444 Show differences between revisions for the specified files.
444 Show differences between revisions for the specified files.
445
445
446 Differences between files are shown using the unified diff format.
446 Differences between files are shown using the unified diff format.
447
447
448 Note:
448 Note:
449 diff may generate unexpected results for merges, as it will default to
449 diff may generate unexpected results for merges, as it will default to
450 comparing against the working directory's first parent changeset if no
450 comparing against the working directory's first parent changeset if no
451 revisions are specified.
451 revisions are specified.
452
452
453 When two revision arguments are given, then changes are shown between
453 When two revision arguments are given, then changes are shown between
454 those revisions. If only one revision is specified then that revision is
454 those revisions. If only one revision is specified then that revision is
455 compared to the working directory, and, when no revisions are specified,
455 compared to the working directory, and, when no revisions are specified,
456 the working directory files are compared to its parent.
456 the working directory files are compared to its parent.
457
457
458 Alternatively you can specify -c/--change with a revision to see the
458 Alternatively you can specify -c/--change with a revision to see the
459 changes in that changeset relative to its first parent.
459 changes in that changeset relative to its first parent.
460
460
461 Without the -a/--text option, diff will avoid generating diffs of files it
461 Without the -a/--text option, diff will avoid generating diffs of files it
462 detects as binary. With -a, diff will generate a diff anyway, probably
462 detects as binary. With -a, diff will generate a diff anyway, probably
463 with undesirable results.
463 with undesirable results.
464
464
465 Use the -g/--git option to generate diffs in the git extended diff format.
465 Use the -g/--git option to generate diffs in the git extended diff format.
466 For more information, read "hg help diffs".
466 For more information, read "hg help diffs".
467
467
468 Returns 0 on success.
468 Returns 0 on success.
469
469
470 options:
470 options:
471
471
472 -r --rev REV [+] revision
472 -r --rev REV [+] revision
473 -c --change REV change made by revision
473 -c --change REV change made by revision
474 -a --text treat all files as text
474 -a --text treat all files as text
475 -g --git use git extended diff format
475 -g --git use git extended diff format
476 --nodates omit dates from diff headers
476 --nodates omit dates from diff headers
477 -p --show-function show which function each change is in
477 -p --show-function show which function each change is in
478 --reverse produce a diff that undoes the changes
478 --reverse produce a diff that undoes the changes
479 -w --ignore-all-space ignore white space when comparing lines
479 -w --ignore-all-space ignore white space when comparing lines
480 -b --ignore-space-change ignore changes in the amount of white space
480 -b --ignore-space-change ignore changes in the amount of white space
481 -B --ignore-blank-lines ignore changes whose lines are all blank
481 -B --ignore-blank-lines ignore changes whose lines are all blank
482 -U --unified NUM number of lines of context to show
482 -U --unified NUM number of lines of context to show
483 --stat output diffstat-style summary of changes
483 --stat output diffstat-style summary of changes
484 -I --include PATTERN [+] include names matching the given patterns
484 -I --include PATTERN [+] include names matching the given patterns
485 -X --exclude PATTERN [+] exclude names matching the given patterns
485 -X --exclude PATTERN [+] exclude names matching the given patterns
486 -S --subrepos recurse into subrepositories
486 -S --subrepos recurse into subrepositories
487
487
488 [+] marked option can be specified multiple times
488 [+] marked option can be specified multiple times
489
489
490 use "hg -v help diff" to show global options
490 use "hg -v help diff" to show global options
491
491
492 $ hg help status
492 $ hg help status
493 hg status [OPTION]... [FILE]...
493 hg status [OPTION]... [FILE]...
494
494
495 aliases: st
495 aliases: st
496
496
497 show changed files in the working directory
497 show changed files in the working directory
498
498
499 Show status of files in the repository. If names are given, only files
499 Show status of files in the repository. If names are given, only files
500 that match are shown. Files that are clean or ignored or the source of a
500 that match are shown. Files that are clean or ignored or the source of a
501 copy/move operation, are not listed unless -c/--clean, -i/--ignored,
501 copy/move operation, are not listed unless -c/--clean, -i/--ignored,
502 -C/--copies or -A/--all are given. Unless options described with "show
502 -C/--copies or -A/--all are given. Unless options described with "show
503 only ..." are given, the options -mardu are used.
503 only ..." are given, the options -mardu are used.
504
504
505 Option -q/--quiet hides untracked (unknown and ignored) files unless
505 Option -q/--quiet hides untracked (unknown and ignored) files unless
506 explicitly requested with -u/--unknown or -i/--ignored.
506 explicitly requested with -u/--unknown or -i/--ignored.
507
507
508 Note:
508 Note:
509 status may appear to disagree with diff if permissions have changed or
509 status may appear to disagree with diff if permissions have changed or
510 a merge has occurred. The standard diff format does not report
510 a merge has occurred. The standard diff format does not report
511 permission changes and diff only reports changes relative to one merge
511 permission changes and diff only reports changes relative to one merge
512 parent.
512 parent.
513
513
514 If one revision is given, it is used as the base revision. If two
514 If one revision is given, it is used as the base revision. If two
515 revisions are given, the differences between them are shown. The --change
515 revisions are given, the differences between them are shown. The --change
516 option can also be used as a shortcut to list the changed files of a
516 option can also be used as a shortcut to list the changed files of a
517 revision from its first parent.
517 revision from its first parent.
518
518
519 The codes used to show the status of files are:
519 The codes used to show the status of files are:
520
520
521 M = modified
521 M = modified
522 A = added
522 A = added
523 R = removed
523 R = removed
524 C = clean
524 C = clean
525 ! = missing (deleted by non-hg command, but still tracked)
525 ! = missing (deleted by non-hg command, but still tracked)
526 ? = not tracked
526 ? = not tracked
527 I = ignored
527 I = ignored
528 = origin of the previous file listed as A (added)
528 = origin of the previous file listed as A (added)
529
529
530 Returns 0 on success.
530 Returns 0 on success.
531
531
532 options:
532 options:
533
533
534 -A --all show status of all files
534 -A --all show status of all files
535 -m --modified show only modified files
535 -m --modified show only modified files
536 -a --added show only added files
536 -a --added show only added files
537 -r --removed show only removed files
537 -r --removed show only removed files
538 -d --deleted show only deleted (but tracked) files
538 -d --deleted show only deleted (but tracked) files
539 -c --clean show only files without changes
539 -c --clean show only files without changes
540 -u --unknown show only unknown (not tracked) files
540 -u --unknown show only unknown (not tracked) files
541 -i --ignored show only ignored files
541 -i --ignored show only ignored files
542 -n --no-status hide status prefix
542 -n --no-status hide status prefix
543 -C --copies show source of copied files
543 -C --copies show source of copied files
544 -0 --print0 end filenames with NUL, for use with xargs
544 -0 --print0 end filenames with NUL, for use with xargs
545 --rev REV [+] show difference from revision
545 --rev REV [+] show difference from revision
546 --change REV list the changed files of a revision
546 --change REV list the changed files of a revision
547 -I --include PATTERN [+] include names matching the given patterns
547 -I --include PATTERN [+] include names matching the given patterns
548 -X --exclude PATTERN [+] exclude names matching the given patterns
548 -X --exclude PATTERN [+] exclude names matching the given patterns
549 -S --subrepos recurse into subrepositories
549 -S --subrepos recurse into subrepositories
550
550
551 [+] marked option can be specified multiple times
551 [+] marked option can be specified multiple times
552
552
553 use "hg -v help status" to show global options
553 use "hg -v help status" to show global options
554
554
555 $ hg -q help status
555 $ hg -q help status
556 hg status [OPTION]... [FILE]...
556 hg status [OPTION]... [FILE]...
557
557
558 show changed files in the working directory
558 show changed files in the working directory
559
559
560 $ hg help foo
560 $ hg help foo
561 hg: unknown command 'foo'
561 hg: unknown command 'foo'
562 Mercurial Distributed SCM
562 Mercurial Distributed SCM
563
563
564 basic commands:
564 basic commands:
565
565
566 add add the specified files on the next commit
566 add add the specified files on the next commit
567 annotate show changeset information by line for each file
567 annotate show changeset information by line for each file
568 clone make a copy of an existing repository
568 clone make a copy of an existing repository
569 commit commit the specified files or all outstanding changes
569 commit commit the specified files or all outstanding changes
570 diff diff repository (or selected files)
570 diff diff repository (or selected files)
571 export dump the header and diffs for one or more changesets
571 export dump the header and diffs for one or more changesets
572 forget forget the specified files on the next commit
572 forget forget the specified files on the next commit
573 init create a new repository in the given directory
573 init create a new repository in the given directory
574 log show revision history of entire repository or files
574 log show revision history of entire repository or files
575 merge merge working directory with another revision
575 merge merge working directory with another revision
576 pull pull changes from the specified source
576 pull pull changes from the specified source
577 push push changes to the specified destination
577 push push changes to the specified destination
578 remove remove the specified files on the next commit
578 remove remove the specified files on the next commit
579 serve start stand-alone webserver
579 serve start stand-alone webserver
580 status show changed files in the working directory
580 status show changed files in the working directory
581 summary summarize working directory state
581 summary summarize working directory state
582 update update working directory (or switch revisions)
582 update update working directory (or switch revisions)
583
583
584 use "hg help" for the full list of commands or "hg -v" for details
584 use "hg help" for the full list of commands or "hg -v" for details
585 [255]
585 [255]
586
586
587 $ hg skjdfks
587 $ hg skjdfks
588 hg: unknown command 'skjdfks'
588 hg: unknown command 'skjdfks'
589 Mercurial Distributed SCM
589 Mercurial Distributed SCM
590
590
591 basic commands:
591 basic commands:
592
592
593 add add the specified files on the next commit
593 add add the specified files on the next commit
594 annotate show changeset information by line for each file
594 annotate show changeset information by line for each file
595 clone make a copy of an existing repository
595 clone make a copy of an existing repository
596 commit commit the specified files or all outstanding changes
596 commit commit the specified files or all outstanding changes
597 diff diff repository (or selected files)
597 diff diff repository (or selected files)
598 export dump the header and diffs for one or more changesets
598 export dump the header and diffs for one or more changesets
599 forget forget the specified files on the next commit
599 forget forget the specified files on the next commit
600 init create a new repository in the given directory
600 init create a new repository in the given directory
601 log show revision history of entire repository or files
601 log show revision history of entire repository or files
602 merge merge working directory with another revision
602 merge merge working directory with another revision
603 pull pull changes from the specified source
603 pull pull changes from the specified source
604 push push changes to the specified destination
604 push push changes to the specified destination
605 remove remove the specified files on the next commit
605 remove remove the specified files on the next commit
606 serve start stand-alone webserver
606 serve start stand-alone webserver
607 status show changed files in the working directory
607 status show changed files in the working directory
608 summary summarize working directory state
608 summary summarize working directory state
609 update update working directory (or switch revisions)
609 update update working directory (or switch revisions)
610
610
611 use "hg help" for the full list of commands or "hg -v" for details
611 use "hg help" for the full list of commands or "hg -v" for details
612 [255]
612 [255]
613
613
614 $ cat > helpext.py <<EOF
614 $ cat > helpext.py <<EOF
615 > import os
615 > import os
616 > from mercurial import commands
616 > from mercurial import commands
617 >
617 >
618 > def nohelp(ui, *args, **kwargs):
618 > def nohelp(ui, *args, **kwargs):
619 > pass
619 > pass
620 >
620 >
621 > cmdtable = {
621 > cmdtable = {
622 > "nohelp": (nohelp, [], "hg nohelp"),
622 > "nohelp": (nohelp, [], "hg nohelp"),
623 > }
623 > }
624 >
624 >
625 > commands.norepo += ' nohelp'
625 > commands.norepo += ' nohelp'
626 > EOF
626 > EOF
627 $ echo '[extensions]' >> $HGRCPATH
627 $ echo '[extensions]' >> $HGRCPATH
628 $ echo "helpext = `pwd`/helpext.py" >> $HGRCPATH
628 $ echo "helpext = `pwd`/helpext.py" >> $HGRCPATH
629
629
630 Test command with no help text
630 Test command with no help text
631
631
632 $ hg help nohelp
632 $ hg help nohelp
633 hg nohelp
633 hg nohelp
634
634
635 (no help text available)
635 (no help text available)
636
636
637 use "hg -v help nohelp" to show global options
637 use "hg -v help nohelp" to show global options
638
638
639 Test that default list of commands omits extension commands
639 Test that default list of commands omits extension commands
640
640
641 $ hg help
641 $ hg help
642 Mercurial Distributed SCM
642 Mercurial Distributed SCM
643
643
644 list of commands:
644 list of commands:
645
645
646 add add the specified files on the next commit
646 add add the specified files on the next commit
647 addremove add all new files, delete all missing files
647 addremove add all new files, delete all missing files
648 annotate show changeset information by line for each file
648 annotate show changeset information by line for each file
649 archive create an unversioned archive of a repository revision
649 archive create an unversioned archive of a repository revision
650 backout reverse effect of earlier changeset
650 backout reverse effect of earlier changeset
651 bisect subdivision search of changesets
651 bisect subdivision search of changesets
652 branch set or show the current branch name
652 branch set or show the current branch name
653 branches list repository named branches
653 branches list repository named branches
654 bundle create a changegroup file
654 bundle create a changegroup file
655 cat output the current or given revision of files
655 cat output the current or given revision of files
656 clone make a copy of an existing repository
656 clone make a copy of an existing repository
657 commit commit the specified files or all outstanding changes
657 commit commit the specified files or all outstanding changes
658 copy mark files as copied for the next commit
658 copy mark files as copied for the next commit
659 diff diff repository (or selected files)
659 diff diff repository (or selected files)
660 export dump the header and diffs for one or more changesets
660 export dump the header and diffs for one or more changesets
661 forget forget the specified files on the next commit
661 forget forget the specified files on the next commit
662 grep search for a pattern in specified files and revisions
662 grep search for a pattern in specified files and revisions
663 heads show current repository heads or show branch heads
663 heads show current repository heads or show branch heads
664 help show help for a given topic or a help overview
664 help show help for a given topic or a help overview
665 identify identify the working copy or specified revision
665 identify identify the working copy or specified revision
666 import import an ordered set of patches
666 import import an ordered set of patches
667 incoming show new changesets found in source
667 incoming show new changesets found in source
668 init create a new repository in the given directory
668 init create a new repository in the given directory
669 locate locate files matching specific patterns
669 locate locate files matching specific patterns
670 log show revision history of entire repository or files
670 log show revision history of entire repository or files
671 manifest output the current or given revision of the project manifest
671 manifest output the current or given revision of the project manifest
672 merge merge working directory with another revision
672 merge merge working directory with another revision
673 outgoing show changesets not found in the destination
673 outgoing show changesets not found in the destination
674 parents show the parents of the working directory or revision
674 parents show the parents of the working directory or revision
675 paths show aliases for remote repositories
675 paths show aliases for remote repositories
676 pull pull changes from the specified source
676 pull pull changes from the specified source
677 push push changes to the specified destination
677 push push changes to the specified destination
678 recover roll back an interrupted transaction
678 recover roll back an interrupted transaction
679 remove remove the specified files on the next commit
679 remove remove the specified files on the next commit
680 rename rename files; equivalent of copy + remove
680 rename rename files; equivalent of copy + remove
681 resolve redo merges or set/view the merge status of files
681 resolve redo merges or set/view the merge status of files
682 revert restore individual files or directories to an earlier state
682 revert restore individual files or directories to an earlier state
683 rollback roll back the last transaction (dangerous)
683 rollback roll back the last transaction (dangerous)
684 root print the root (top) of the current working directory
684 root print the root (top) of the current working directory
685 serve start stand-alone webserver
685 serve start stand-alone webserver
686 showconfig show combined config settings from all hgrc files
686 showconfig show combined config settings from all hgrc files
687 status show changed files in the working directory
687 status show changed files in the working directory
688 summary summarize working directory state
688 summary summarize working directory state
689 tag add one or more tags for the current or given revision
689 tag add one or more tags for the current or given revision
690 tags list repository tags
690 tags list repository tags
691 tip show the tip revision
691 tip show the tip revision
692 unbundle apply one or more changegroup files
692 unbundle apply one or more changegroup files
693 update update working directory (or switch revisions)
693 update update working directory (or switch revisions)
694 verify verify the integrity of the repository
694 verify verify the integrity of the repository
695 version output version and copyright information
695 version output version and copyright information
696
696
697 enabled extensions:
697 enabled extensions:
698
698
699 helpext (no help text available)
699 helpext (no help text available)
700
700
701 additional help topics:
701 additional help topics:
702
702
703 config Configuration Files
703 config Configuration Files
704 dates Date Formats
704 dates Date Formats
705 patterns File Name Patterns
705 patterns File Name Patterns
706 environment Environment Variables
706 environment Environment Variables
707 revisions Specifying Single Revisions
707 revisions Specifying Single Revisions
708 multirevs Specifying Multiple Revisions
708 multirevs Specifying Multiple Revisions
709 revsets Specifying Revision Sets
709 revsets Specifying Revision Sets
710 diffs Diff Formats
710 diffs Diff Formats
711 merge-tools Merge Tools
711 merge-tools Merge Tools
712 templating Template Usage
712 templating Template Usage
713 urls URL Paths
713 urls URL Paths
714 extensions Using additional features
714 extensions Using additional features
715 subrepos Subrepositories
715 subrepos Subrepositories
716 hgweb Configuring hgweb
716 hgweb Configuring hgweb
717 glossary Glossary
717 glossary Glossary
718
718
719 use "hg -v help" to show aliases and global options
719 use "hg -v help" to show builtin aliases and global options
720
720
721 Test list of commands with command with no help text
721 Test list of commands with command with no help text
722
722
723 $ hg help helpext
723 $ hg help helpext
724 helpext extension - no help text available
724 helpext extension - no help text available
725
725
726 list of commands:
726 list of commands:
727
727
728 nohelp (no help text available)
728 nohelp (no help text available)
729
729
730 use "hg -v help helpext" to show aliases and global options
730 use "hg -v help helpext" to show builtin aliases and global options
731
731
732 Test a help topic
732 Test a help topic
733
733
734 $ hg help revs
734 $ hg help revs
735 Specifying Single Revisions
735 Specifying Single Revisions
736
736
737 Mercurial supports several ways to specify individual revisions.
737 Mercurial supports several ways to specify individual revisions.
738
738
739 A plain integer is treated as a revision number. Negative integers are
739 A plain integer is treated as a revision number. Negative integers are
740 treated as sequential offsets from the tip, with -1 denoting the tip, -2
740 treated as sequential offsets from the tip, with -1 denoting the tip, -2
741 denoting the revision prior to the tip, and so forth.
741 denoting the revision prior to the tip, and so forth.
742
742
743 A 40-digit hexadecimal string is treated as a unique revision identifier.
743 A 40-digit hexadecimal string is treated as a unique revision identifier.
744
744
745 A hexadecimal string less than 40 characters long is treated as a unique
745 A hexadecimal string less than 40 characters long is treated as a unique
746 revision identifier and is referred to as a short-form identifier. A
746 revision identifier and is referred to as a short-form identifier. A
747 short-form identifier is only valid if it is the prefix of exactly one
747 short-form identifier is only valid if it is the prefix of exactly one
748 full-length identifier.
748 full-length identifier.
749
749
750 Any other string is treated as a tag or branch name. A tag name is a
750 Any other string is treated as a tag or branch name. A tag name is a
751 symbolic name associated with a revision identifier. A branch name denotes
751 symbolic name associated with a revision identifier. A branch name denotes
752 the tipmost revision of that branch. Tag and branch names must not contain
752 the tipmost revision of that branch. Tag and branch names must not contain
753 the ":" character.
753 the ":" character.
754
754
755 The reserved name "tip" is a special tag that always identifies the most
755 The reserved name "tip" is a special tag that always identifies the most
756 recent revision.
756 recent revision.
757
757
758 The reserved name "null" indicates the null revision. This is the revision
758 The reserved name "null" indicates the null revision. This is the revision
759 of an empty repository, and the parent of revision 0.
759 of an empty repository, and the parent of revision 0.
760
760
761 The reserved name "." indicates the working directory parent. If no
761 The reserved name "." indicates the working directory parent. If no
762 working directory is checked out, it is equivalent to null. If an
762 working directory is checked out, it is equivalent to null. If an
763 uncommitted merge is in progress, "." is the revision of the first parent.
763 uncommitted merge is in progress, "." is the revision of the first parent.
764
764
765 Test help hooks
765 Test help hooks
766
766
767 $ cat > helphook1.py <<EOF
767 $ cat > helphook1.py <<EOF
768 > from mercurial import help
768 > from mercurial import help
769 >
769 >
770 > def rewrite(topic, doc):
770 > def rewrite(topic, doc):
771 > return doc + '\nhelphook1\n'
771 > return doc + '\nhelphook1\n'
772 >
772 >
773 > def extsetup(ui):
773 > def extsetup(ui):
774 > help.addtopichook('revsets', rewrite)
774 > help.addtopichook('revsets', rewrite)
775 > EOF
775 > EOF
776 $ cat > helphook2.py <<EOF
776 $ cat > helphook2.py <<EOF
777 > from mercurial import help
777 > from mercurial import help
778 >
778 >
779 > def rewrite(topic, doc):
779 > def rewrite(topic, doc):
780 > return doc + '\nhelphook2\n'
780 > return doc + '\nhelphook2\n'
781 >
781 >
782 > def extsetup(ui):
782 > def extsetup(ui):
783 > help.addtopichook('revsets', rewrite)
783 > help.addtopichook('revsets', rewrite)
784 > EOF
784 > EOF
785 $ echo '[extensions]' >> $HGRCPATH
785 $ echo '[extensions]' >> $HGRCPATH
786 $ echo "helphook1 = `pwd`/helphook1.py" >> $HGRCPATH
786 $ echo "helphook1 = `pwd`/helphook1.py" >> $HGRCPATH
787 $ echo "helphook2 = `pwd`/helphook2.py" >> $HGRCPATH
787 $ echo "helphook2 = `pwd`/helphook2.py" >> $HGRCPATH
788 $ hg help revsets | grep helphook
788 $ hg help revsets | grep helphook
789 helphook1
789 helphook1
790 helphook2
790 helphook2
@@ -1,189 +1,190 b''
1 Proper https client requires the built-in ssl from Python 2.6.
1 Proper https client requires the built-in ssl from Python 2.6.
2
2
3 $ "$TESTDIR/hghave" ssl || exit 80
3 $ "$TESTDIR/hghave" ssl || exit 80
4
4
5 Certificates created with:
5 Certificates created with:
6 printf '.\n.\n.\n.\n.\nlocalhost\nhg@localhost\n' | \
6 printf '.\n.\n.\n.\n.\nlocalhost\nhg@localhost\n' | \
7 openssl req -newkey rsa:512 -keyout priv.pem -nodes -x509 -days 9000 -out pub.pem
7 openssl req -newkey rsa:512 -keyout priv.pem -nodes -x509 -days 9000 -out pub.pem
8 Can be dumped with:
8 Can be dumped with:
9 openssl x509 -in pub.pem -text
9 openssl x509 -in pub.pem -text
10
10
11 $ cat << EOT > priv.pem
11 $ cat << EOT > priv.pem
12 > -----BEGIN PRIVATE KEY-----
12 > -----BEGIN PRIVATE KEY-----
13 > MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEApjCWeYGrIa/Vo7LH
13 > MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEApjCWeYGrIa/Vo7LH
14 > aRF8ou0tbgHKE33Use/whCnKEUm34rDaXQd4lxxX6aDWg06n9tiVStAKTgQAHJY8
14 > aRF8ou0tbgHKE33Use/whCnKEUm34rDaXQd4lxxX6aDWg06n9tiVStAKTgQAHJY8
15 > j/xgSwIDAQABAkBxHC6+Qlf0VJXGlb6NL16yEVVTQxqDS6hA9zqu6TZjrr0YMfzc
15 > j/xgSwIDAQABAkBxHC6+Qlf0VJXGlb6NL16yEVVTQxqDS6hA9zqu6TZjrr0YMfzc
16 > EGNIiZGt7HCBL0zO+cPDg/LeCZc6HQhf0KrhAiEAzlJq4hWWzvguWFIJWSoBeBUG
16 > EGNIiZGt7HCBL0zO+cPDg/LeCZc6HQhf0KrhAiEAzlJq4hWWzvguWFIJWSoBeBUG
17 > MF1ACazQO7PYE8M0qfECIQDONHHP0SKZzz/ZwBZcAveC5K61f/v9hONFwbeYulzR
17 > MF1ACazQO7PYE8M0qfECIQDONHHP0SKZzz/ZwBZcAveC5K61f/v9hONFwbeYulzR
18 > +wIgc9SvbtgB/5Yzpp//4ZAEnR7oh5SClCvyB+KSx52K3nECICbhQphhoXmI10wy
18 > +wIgc9SvbtgB/5Yzpp//4ZAEnR7oh5SClCvyB+KSx52K3nECICbhQphhoXmI10wy
19 > aMTellaq0bpNMHFDziqH9RsqAHhjAiEAgYGxfzkftt5IUUn/iFK89aaIpyrpuaAh
19 > aMTellaq0bpNMHFDziqH9RsqAHhjAiEAgYGxfzkftt5IUUn/iFK89aaIpyrpuaAh
20 > HY8gUVkVRVs=
20 > HY8gUVkVRVs=
21 > -----END PRIVATE KEY-----
21 > -----END PRIVATE KEY-----
22 > EOT
22 > EOT
23
23
24 $ cat << EOT > pub.pem
24 $ cat << EOT > pub.pem
25 > -----BEGIN CERTIFICATE-----
25 > -----BEGIN CERTIFICATE-----
26 > MIIBqzCCAVWgAwIBAgIJANAXFFyWjGnRMA0GCSqGSIb3DQEBBQUAMDExEjAQBgNV
26 > MIIBqzCCAVWgAwIBAgIJANAXFFyWjGnRMA0GCSqGSIb3DQEBBQUAMDExEjAQBgNV
27 > BAMMCWxvY2FsaG9zdDEbMBkGCSqGSIb3DQEJARYMaGdAbG9jYWxob3N0MB4XDTEw
27 > BAMMCWxvY2FsaG9zdDEbMBkGCSqGSIb3DQEJARYMaGdAbG9jYWxob3N0MB4XDTEw
28 > MTAxNDIwMzAxNFoXDTM1MDYwNTIwMzAxNFowMTESMBAGA1UEAwwJbG9jYWxob3N0
28 > MTAxNDIwMzAxNFoXDTM1MDYwNTIwMzAxNFowMTESMBAGA1UEAwwJbG9jYWxob3N0
29 > MRswGQYJKoZIhvcNAQkBFgxoZ0Bsb2NhbGhvc3QwXDANBgkqhkiG9w0BAQEFAANL
29 > MRswGQYJKoZIhvcNAQkBFgxoZ0Bsb2NhbGhvc3QwXDANBgkqhkiG9w0BAQEFAANL
30 > ADBIAkEApjCWeYGrIa/Vo7LHaRF8ou0tbgHKE33Use/whCnKEUm34rDaXQd4lxxX
30 > ADBIAkEApjCWeYGrIa/Vo7LHaRF8ou0tbgHKE33Use/whCnKEUm34rDaXQd4lxxX
31 > 6aDWg06n9tiVStAKTgQAHJY8j/xgSwIDAQABo1AwTjAdBgNVHQ4EFgQUE6sA+amm
31 > 6aDWg06n9tiVStAKTgQAHJY8j/xgSwIDAQABo1AwTjAdBgNVHQ4EFgQUE6sA+amm
32 > r24dGX0kpjxOgO45hzQwHwYDVR0jBBgwFoAUE6sA+ammr24dGX0kpjxOgO45hzQw
32 > r24dGX0kpjxOgO45hzQwHwYDVR0jBBgwFoAUE6sA+ammr24dGX0kpjxOgO45hzQw
33 > DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAANBAFArvQFiAZJgQczRsbYlG1xl
33 > DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAANBAFArvQFiAZJgQczRsbYlG1xl
34 > t+truk37w5B3m3Ick1ntRcQrqs+hf0CO1q6Squ144geYaQ8CDirSR92fICELI1c=
34 > t+truk37w5B3m3Ick1ntRcQrqs+hf0CO1q6Squ144geYaQ8CDirSR92fICELI1c=
35 > -----END CERTIFICATE-----
35 > -----END CERTIFICATE-----
36 > EOT
36 > EOT
37 $ cat priv.pem pub.pem >> server.pem
37 $ cat priv.pem pub.pem >> server.pem
38 $ PRIV=`pwd`/server.pem
38 $ PRIV=`pwd`/server.pem
39
39
40 $ cat << EOT > pub-other.pem
40 $ cat << EOT > pub-other.pem
41 > -----BEGIN CERTIFICATE-----
41 > -----BEGIN CERTIFICATE-----
42 > MIIBqzCCAVWgAwIBAgIJALwZS731c/ORMA0GCSqGSIb3DQEBBQUAMDExEjAQBgNV
42 > MIIBqzCCAVWgAwIBAgIJALwZS731c/ORMA0GCSqGSIb3DQEBBQUAMDExEjAQBgNV
43 > BAMMCWxvY2FsaG9zdDEbMBkGCSqGSIb3DQEJARYMaGdAbG9jYWxob3N0MB4XDTEw
43 > BAMMCWxvY2FsaG9zdDEbMBkGCSqGSIb3DQEJARYMaGdAbG9jYWxob3N0MB4XDTEw
44 > MTAxNDIwNDUxNloXDTM1MDYwNTIwNDUxNlowMTESMBAGA1UEAwwJbG9jYWxob3N0
44 > MTAxNDIwNDUxNloXDTM1MDYwNTIwNDUxNlowMTESMBAGA1UEAwwJbG9jYWxob3N0
45 > MRswGQYJKoZIhvcNAQkBFgxoZ0Bsb2NhbGhvc3QwXDANBgkqhkiG9w0BAQEFAANL
45 > MRswGQYJKoZIhvcNAQkBFgxoZ0Bsb2NhbGhvc3QwXDANBgkqhkiG9w0BAQEFAANL
46 > ADBIAkEAsxsapLbHrqqUKuQBxdpK4G3m2LjtyrTSdpzzzFlecxd5yhNP6AyWrufo
46 > ADBIAkEAsxsapLbHrqqUKuQBxdpK4G3m2LjtyrTSdpzzzFlecxd5yhNP6AyWrufo
47 > K4VMGo2xlu9xOo88nDSUNSKPuD09MwIDAQABo1AwTjAdBgNVHQ4EFgQUoIB1iMhN
47 > K4VMGo2xlu9xOo88nDSUNSKPuD09MwIDAQABo1AwTjAdBgNVHQ4EFgQUoIB1iMhN
48 > y868rpQ2qk9dHnU6ebswHwYDVR0jBBgwFoAUoIB1iMhNy868rpQ2qk9dHnU6ebsw
48 > y868rpQ2qk9dHnU6ebswHwYDVR0jBBgwFoAUoIB1iMhNy868rpQ2qk9dHnU6ebsw
49 > DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAANBAJ544f125CsE7J2t55PdFaF6
49 > DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAANBAJ544f125CsE7J2t55PdFaF6
50 > bBlNBb91FCywBgSjhBjf+GG3TNPwrPdc3yqeq+hzJiuInqbOBv9abmMyq8Wsoig=
50 > bBlNBb91FCywBgSjhBjf+GG3TNPwrPdc3yqeq+hzJiuInqbOBv9abmMyq8Wsoig=
51 > -----END CERTIFICATE-----
51 > -----END CERTIFICATE-----
52 > EOT
52 > EOT
53
53
54 pub.pem patched with other notBefore / notAfter:
54 pub.pem patched with other notBefore / notAfter:
55
55
56 $ cat << EOT > pub-not-yet.pem
56 $ cat << EOT > pub-not-yet.pem
57 > -----BEGIN CERTIFICATE-----
57 > -----BEGIN CERTIFICATE-----
58 > MIIBqzCCAVWgAwIBAgIJANAXFFyWjGnRMA0GCSqGSIb3DQEBBQUAMDExEjAQBgNVBAMMCWxvY2Fs
58 > MIIBqzCCAVWgAwIBAgIJANAXFFyWjGnRMA0GCSqGSIb3DQEBBQUAMDExEjAQBgNVBAMMCWxvY2Fs
59 > aG9zdDEbMBkGCSqGSIb3DQEJARYMaGdAbG9jYWxob3N0MB4XDTM1MDYwNTIwMzAxNFoXDTM1MDYw
59 > aG9zdDEbMBkGCSqGSIb3DQEJARYMaGdAbG9jYWxob3N0MB4XDTM1MDYwNTIwMzAxNFoXDTM1MDYw
60 > NTIwMzAxNFowMTESMBAGA1UEAwwJbG9jYWxob3N0MRswGQYJKoZIhvcNAQkBFgxoZ0Bsb2NhbGhv
60 > NTIwMzAxNFowMTESMBAGA1UEAwwJbG9jYWxob3N0MRswGQYJKoZIhvcNAQkBFgxoZ0Bsb2NhbGhv
61 > c3QwXDANBgkqhkiG9w0BAQEFAANLADBIAkEApjCWeYGrIa/Vo7LHaRF8ou0tbgHKE33Use/whCnK
61 > c3QwXDANBgkqhkiG9w0BAQEFAANLADBIAkEApjCWeYGrIa/Vo7LHaRF8ou0tbgHKE33Use/whCnK
62 > EUm34rDaXQd4lxxX6aDWg06n9tiVStAKTgQAHJY8j/xgSwIDAQABo1AwTjAdBgNVHQ4EFgQUE6sA
62 > EUm34rDaXQd4lxxX6aDWg06n9tiVStAKTgQAHJY8j/xgSwIDAQABo1AwTjAdBgNVHQ4EFgQUE6sA
63 > +ammr24dGX0kpjxOgO45hzQwHwYDVR0jBBgwFoAUE6sA+ammr24dGX0kpjxOgO45hzQwDAYDVR0T
63 > +ammr24dGX0kpjxOgO45hzQwHwYDVR0jBBgwFoAUE6sA+ammr24dGX0kpjxOgO45hzQwDAYDVR0T
64 > BAUwAwEB/zANBgkqhkiG9w0BAQUFAANBAJXV41gWnkgC7jcpPpFRSUSZaxyzrXmD1CIqQf0WgVDb
64 > BAUwAwEB/zANBgkqhkiG9w0BAQUFAANBAJXV41gWnkgC7jcpPpFRSUSZaxyzrXmD1CIqQf0WgVDb
65 > /12E0vR2DuZitgzUYtBaofM81aTtc0a2/YsrmqePGm0=
65 > /12E0vR2DuZitgzUYtBaofM81aTtc0a2/YsrmqePGm0=
66 > -----END CERTIFICATE-----
66 > -----END CERTIFICATE-----
67 > EOT
67 > EOT
68 $ cat priv.pem pub-not-yet.pem > server-not-yet.pem
68 $ cat priv.pem pub-not-yet.pem > server-not-yet.pem
69
69
70 $ cat << EOT > pub-expired.pem
70 $ cat << EOT > pub-expired.pem
71 > -----BEGIN CERTIFICATE-----
71 > -----BEGIN CERTIFICATE-----
72 > MIIBqzCCAVWgAwIBAgIJANAXFFyWjGnRMA0GCSqGSIb3DQEBBQUAMDExEjAQBgNVBAMMCWxvY2Fs
72 > MIIBqzCCAVWgAwIBAgIJANAXFFyWjGnRMA0GCSqGSIb3DQEBBQUAMDExEjAQBgNVBAMMCWxvY2Fs
73 > aG9zdDEbMBkGCSqGSIb3DQEJARYMaGdAbG9jYWxob3N0MB4XDTEwMTAxNDIwMzAxNFoXDTEwMTAx
73 > aG9zdDEbMBkGCSqGSIb3DQEJARYMaGdAbG9jYWxob3N0MB4XDTEwMTAxNDIwMzAxNFoXDTEwMTAx
74 > NDIwMzAxNFowMTESMBAGA1UEAwwJbG9jYWxob3N0MRswGQYJKoZIhvcNAQkBFgxoZ0Bsb2NhbGhv
74 > NDIwMzAxNFowMTESMBAGA1UEAwwJbG9jYWxob3N0MRswGQYJKoZIhvcNAQkBFgxoZ0Bsb2NhbGhv
75 > c3QwXDANBgkqhkiG9w0BAQEFAANLADBIAkEApjCWeYGrIa/Vo7LHaRF8ou0tbgHKE33Use/whCnK
75 > c3QwXDANBgkqhkiG9w0BAQEFAANLADBIAkEApjCWeYGrIa/Vo7LHaRF8ou0tbgHKE33Use/whCnK
76 > EUm34rDaXQd4lxxX6aDWg06n9tiVStAKTgQAHJY8j/xgSwIDAQABo1AwTjAdBgNVHQ4EFgQUE6sA
76 > EUm34rDaXQd4lxxX6aDWg06n9tiVStAKTgQAHJY8j/xgSwIDAQABo1AwTjAdBgNVHQ4EFgQUE6sA
77 > +ammr24dGX0kpjxOgO45hzQwHwYDVR0jBBgwFoAUE6sA+ammr24dGX0kpjxOgO45hzQwDAYDVR0T
77 > +ammr24dGX0kpjxOgO45hzQwHwYDVR0jBBgwFoAUE6sA+ammr24dGX0kpjxOgO45hzQwDAYDVR0T
78 > BAUwAwEB/zANBgkqhkiG9w0BAQUFAANBAJfk57DTRf2nUbYaMSlVAARxMNbFGOjQhAUtY400GhKt
78 > BAUwAwEB/zANBgkqhkiG9w0BAQUFAANBAJfk57DTRf2nUbYaMSlVAARxMNbFGOjQhAUtY400GhKt
79 > 2uiKCNGKXVXD3AHWe13yHc5KttzbHQStE5Nm/DlWBWQ=
79 > 2uiKCNGKXVXD3AHWe13yHc5KttzbHQStE5Nm/DlWBWQ=
80 > -----END CERTIFICATE-----
80 > -----END CERTIFICATE-----
81 > EOT
81 > EOT
82 $ cat priv.pem pub-expired.pem > server-expired.pem
82 $ cat priv.pem pub-expired.pem > server-expired.pem
83
83
84 $ hg init test
84 $ hg init test
85 $ cd test
85 $ cd test
86 $ echo foo>foo
86 $ echo foo>foo
87 $ mkdir foo.d foo.d/bAr.hg.d foo.d/baR.d.hg
87 $ mkdir foo.d foo.d/bAr.hg.d foo.d/baR.d.hg
88 $ echo foo>foo.d/foo
88 $ echo foo>foo.d/foo
89 $ echo bar>foo.d/bAr.hg.d/BaR
89 $ echo bar>foo.d/bAr.hg.d/BaR
90 $ echo bar>foo.d/baR.d.hg/bAR
90 $ echo bar>foo.d/baR.d.hg/bAR
91 $ hg commit -A -m 1
91 $ hg commit -A -m 1
92 adding foo
92 adding foo
93 adding foo.d/bAr.hg.d/BaR
93 adding foo.d/bAr.hg.d/BaR
94 adding foo.d/baR.d.hg/bAR
94 adding foo.d/baR.d.hg/bAR
95 adding foo.d/foo
95 adding foo.d/foo
96 $ hg serve -p $HGPORT -d --pid-file=../hg0.pid --certificate=$PRIV
96 $ hg serve -p $HGPORT -d --pid-file=../hg0.pid --certificate=$PRIV
97 $ cat ../hg0.pid >> $DAEMON_PIDS
97 $ cat ../hg0.pid >> $DAEMON_PIDS
98
98
99 Test server address cannot be reused
99 Test server address cannot be reused
100
100
101 $ hg serve -p $HGPORT --certificate=$PRIV 2>&1
101 $ hg serve -p $HGPORT --certificate=$PRIV 2>&1
102 abort: cannot start server at ':$HGPORT': Address already in use
102 abort: cannot start server at ':$HGPORT': Address already in use
103 [255]
103 [255]
104 $ cd ..
104 $ cd ..
105
105
106 clone via pull
106 clone via pull
107
107
108 $ hg clone https://localhost:$HGPORT/ copy-pull
108 $ hg clone https://localhost:$HGPORT/ copy-pull
109 warning: localhost certificate not verified (check web.cacerts config setting)
109 warning: localhost certificate not verified (check web.cacerts config setting)
110 requesting all changes
110 requesting all changes
111 adding changesets
111 adding changesets
112 adding manifests
112 adding manifests
113 adding file changes
113 adding file changes
114 added 1 changesets with 4 changes to 4 files
114 added 1 changesets with 4 changes to 4 files
115 updating to branch default
115 updating to branch default
116 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
116 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
117 $ hg verify -R copy-pull
117 $ hg verify -R copy-pull
118 checking changesets
118 checking changesets
119 checking manifests
119 checking manifests
120 crosschecking files in changesets and manifests
120 crosschecking files in changesets and manifests
121 checking files
121 checking files
122 4 files, 1 changesets, 4 total revisions
122 4 files, 1 changesets, 4 total revisions
123 $ cd test
123 $ cd test
124 $ echo bar > bar
124 $ echo bar > bar
125 $ hg commit -A -d '1 0' -m 2
125 $ hg commit -A -d '1 0' -m 2
126 adding bar
126 adding bar
127 $ cd ..
127 $ cd ..
128
128
129 pull without cacert
129 pull without cacert
130
130
131 $ cd copy-pull
131 $ cd copy-pull
132 $ echo '[hooks]' >> .hg/hgrc
132 $ echo '[hooks]' >> .hg/hgrc
133 $ echo "changegroup = python '$TESTDIR'/printenv.py changegroup" >> .hg/hgrc
133 $ echo "changegroup = python '$TESTDIR'/printenv.py changegroup" >> .hg/hgrc
134 $ hg pull
134 $ hg pull
135 warning: localhost certificate not verified (check web.cacerts config setting)
135 warning: localhost certificate not verified (check web.cacerts config setting)
136 changegroup hook: HG_NODE=5fed3813f7f5e1824344fdc9cf8f63bb662c292d HG_SOURCE=pull HG_URL=https://localhost:$HGPORT/
136 changegroup hook: HG_NODE=5fed3813f7f5e1824344fdc9cf8f63bb662c292d HG_SOURCE=pull HG_URL=https://localhost:$HGPORT/
137 pulling from https://localhost:$HGPORT/
137 pulling from https://localhost:$HGPORT/
138 searching for changes
138 searching for changes
139 adding changesets
139 adding changesets
140 adding manifests
140 adding manifests
141 adding file changes
141 adding file changes
142 added 1 changesets with 1 changes to 1 files
142 added 1 changesets with 1 changes to 1 files
143 (run 'hg update' to get a working copy)
143 (run 'hg update' to get a working copy)
144 $ cd ..
144 $ cd ..
145
145
146 cacert configured in local repo
146 cacert configured in local repo
147
147
148 $ cp copy-pull/.hg/hgrc copy-pull/.hg/hgrc.bu
148 $ cp copy-pull/.hg/hgrc copy-pull/.hg/hgrc.bu
149 $ echo "[web]" >> copy-pull/.hg/hgrc
149 $ echo "[web]" >> copy-pull/.hg/hgrc
150 $ echo "cacerts=`pwd`/pub.pem" >> copy-pull/.hg/hgrc
150 $ echo "cacerts=`pwd`/pub.pem" >> copy-pull/.hg/hgrc
151 $ hg -R copy-pull pull --traceback
151 $ hg -R copy-pull pull --traceback
152 pulling from https://localhost:$HGPORT/
152 pulling from https://localhost:$HGPORT/
153 searching for changes
153 searching for changes
154 no changes found
154 no changes found
155 $ mv copy-pull/.hg/hgrc.bu copy-pull/.hg/hgrc
155 $ mv copy-pull/.hg/hgrc.bu copy-pull/.hg/hgrc
156
156
157 cacert configured globally
157 cacert configured globally, also testing expansion of environment
158 variables in the filename
158
159
159 $ echo "[web]" >> $HGRCPATH
160 $ echo "[web]" >> $HGRCPATH
160 $ echo "cacerts=`pwd`/pub.pem" >> $HGRCPATH
161 $ echo 'cacerts=$P/pub.pem' >> $HGRCPATH
161 $ hg -R copy-pull pull
162 $ P=`pwd` hg -R copy-pull pull
162 pulling from https://localhost:$HGPORT/
163 pulling from https://localhost:$HGPORT/
163 searching for changes
164 searching for changes
164 no changes found
165 no changes found
165
166
166 cacert mismatch
167 cacert mismatch
167
168
168 $ hg -R copy-pull pull --config web.cacerts=pub.pem https://127.0.0.1:$HGPORT/
169 $ hg -R copy-pull pull --config web.cacerts=pub.pem https://127.0.0.1:$HGPORT/
169 abort: 127.0.0.1 certificate error: certificate is for localhost
170 abort: 127.0.0.1 certificate error: certificate is for localhost
170 [255]
171 [255]
171 $ hg -R copy-pull pull --config web.cacerts=pub-other.pem
172 $ hg -R copy-pull pull --config web.cacerts=pub-other.pem
172 abort: error: *:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed (glob)
173 abort: error: *:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed (glob)
173 [255]
174 [255]
174
175
175 Test server cert which isn't valid yet
176 Test server cert which isn't valid yet
176
177
177 $ hg -R test serve -p $HGPORT1 -d --pid-file=hg1.pid --certificate=server-not-yet.pem
178 $ hg -R test serve -p $HGPORT1 -d --pid-file=hg1.pid --certificate=server-not-yet.pem
178 $ cat hg1.pid >> $DAEMON_PIDS
179 $ cat hg1.pid >> $DAEMON_PIDS
179 $ hg -R copy-pull pull --config web.cacerts=pub-not-yet.pem https://localhost:$HGPORT1/
180 $ hg -R copy-pull pull --config web.cacerts=pub-not-yet.pem https://localhost:$HGPORT1/
180 abort: error: *:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed (glob)
181 abort: error: *:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed (glob)
181 [255]
182 [255]
182
183
183 Test server cert which no longer is valid
184 Test server cert which no longer is valid
184
185
185 $ hg -R test serve -p $HGPORT2 -d --pid-file=hg2.pid --certificate=server-expired.pem
186 $ hg -R test serve -p $HGPORT2 -d --pid-file=hg2.pid --certificate=server-expired.pem
186 $ cat hg2.pid >> $DAEMON_PIDS
187 $ cat hg2.pid >> $DAEMON_PIDS
187 $ hg -R copy-pull pull --config web.cacerts=pub-expired.pem https://localhost:$HGPORT2/
188 $ hg -R copy-pull pull --config web.cacerts=pub-expired.pem https://localhost:$HGPORT2/
188 abort: error: *:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed (glob)
189 abort: error: *:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed (glob)
189 [255]
190 [255]
@@ -1,1368 +1,1368 b''
1 $ checkundo()
1 $ checkundo()
2 > {
2 > {
3 > if [ -f .hg/store/undo ]; then
3 > if [ -f .hg/store/undo ]; then
4 > echo ".hg/store/undo still exists after $1"
4 > echo ".hg/store/undo still exists after $1"
5 > fi
5 > fi
6 > }
6 > }
7
7
8 $ echo "[extensions]" >> $HGRCPATH
8 $ echo "[extensions]" >> $HGRCPATH
9 $ echo "mq=" >> $HGRCPATH
9 $ echo "mq=" >> $HGRCPATH
10
10
11 $ echo "[mq]" >> $HGRCPATH
11 $ echo "[mq]" >> $HGRCPATH
12 $ echo "plain=true" >> $HGRCPATH
12 $ echo "plain=true" >> $HGRCPATH
13
13
14
14
15 help
15 help
16
16
17 $ hg help mq
17 $ hg help mq
18 mq extension - manage a stack of patches
18 mq extension - manage a stack of patches
19
19
20 This extension lets you work with a stack of patches in a Mercurial
20 This extension lets you work with a stack of patches in a Mercurial
21 repository. It manages two stacks of patches - all known patches, and applied
21 repository. It manages two stacks of patches - all known patches, and applied
22 patches (subset of known patches).
22 patches (subset of known patches).
23
23
24 Known patches are represented as patch files in the .hg/patches directory.
24 Known patches are represented as patch files in the .hg/patches directory.
25 Applied patches are both patch files and changesets.
25 Applied patches are both patch files and changesets.
26
26
27 Common tasks (use "hg help command" for more details):
27 Common tasks (use "hg help command" for more details):
28
28
29 create new patch qnew
29 create new patch qnew
30 import existing patch qimport
30 import existing patch qimport
31
31
32 print patch series qseries
32 print patch series qseries
33 print applied patches qapplied
33 print applied patches qapplied
34
34
35 add known patch to applied stack qpush
35 add known patch to applied stack qpush
36 remove patch from applied stack qpop
36 remove patch from applied stack qpop
37 refresh contents of top applied patch qrefresh
37 refresh contents of top applied patch qrefresh
38
38
39 By default, mq will automatically use git patches when required to avoid
39 By default, mq will automatically use git patches when required to avoid
40 losing file mode changes, copy records, binary files or empty files creations
40 losing file mode changes, copy records, binary files or empty files creations
41 or deletions. This behaviour can be configured with:
41 or deletions. This behaviour can be configured with:
42
42
43 [mq]
43 [mq]
44 git = auto/keep/yes/no
44 git = auto/keep/yes/no
45
45
46 If set to 'keep', mq will obey the [diff] section configuration while
46 If set to 'keep', mq will obey the [diff] section configuration while
47 preserving existing git patches upon qrefresh. If set to 'yes' or 'no', mq
47 preserving existing git patches upon qrefresh. If set to 'yes' or 'no', mq
48 will override the [diff] section and always generate git or regular patches,
48 will override the [diff] section and always generate git or regular patches,
49 possibly losing data in the second case.
49 possibly losing data in the second case.
50
50
51 You will by default be managing a patch queue named "patches". You can create
51 You will by default be managing a patch queue named "patches". You can create
52 other, independent patch queues with the "hg qqueue" command.
52 other, independent patch queues with the "hg qqueue" command.
53
53
54 list of commands:
54 list of commands:
55
55
56 qapplied print the patches already applied
56 qapplied print the patches already applied
57 qclone clone main and patch repository at same time
57 qclone clone main and patch repository at same time
58 qdelete remove patches from queue
58 qdelete remove patches from queue
59 qdiff diff of the current patch and subsequent modifications
59 qdiff diff of the current patch and subsequent modifications
60 qfinish move applied patches into repository history
60 qfinish move applied patches into repository history
61 qfold fold the named patches into the current patch
61 qfold fold the named patches into the current patch
62 qgoto push or pop patches until named patch is at top of stack
62 qgoto push or pop patches until named patch is at top of stack
63 qguard set or print guards for a patch
63 qguard set or print guards for a patch
64 qheader print the header of the topmost or specified patch
64 qheader print the header of the topmost or specified patch
65 qimport import a patch
65 qimport import a patch
66 qnew create a new patch
66 qnew create a new patch
67 qnext print the name of the next patch
67 qnext print the name of the next patch
68 qpop pop the current patch off the stack
68 qpop pop the current patch off the stack
69 qprev print the name of the previous patch
69 qprev print the name of the previous patch
70 qpush push the next patch onto the stack
70 qpush push the next patch onto the stack
71 qqueue manage multiple patch queues
71 qqueue manage multiple patch queues
72 qrefresh update the current patch
72 qrefresh update the current patch
73 qrename rename a patch
73 qrename rename a patch
74 qselect set or print guarded patches to push
74 qselect set or print guarded patches to push
75 qseries print the entire series file
75 qseries print the entire series file
76 qtop print the name of the current patch
76 qtop print the name of the current patch
77 qunapplied print the patches not yet applied
77 qunapplied print the patches not yet applied
78 strip strip changesets and all their descendants from the repository
78 strip strip changesets and all their descendants from the repository
79
79
80 use "hg -v help mq" to show aliases and global options
80 use "hg -v help mq" to show builtin aliases and global options
81
81
82 $ hg init a
82 $ hg init a
83 $ cd a
83 $ cd a
84 $ echo a > a
84 $ echo a > a
85 $ hg ci -Ama
85 $ hg ci -Ama
86 adding a
86 adding a
87
87
88 $ hg clone . ../k
88 $ hg clone . ../k
89 updating to branch default
89 updating to branch default
90 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
90 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
91
91
92 $ mkdir b
92 $ mkdir b
93 $ echo z > b/z
93 $ echo z > b/z
94 $ hg ci -Ama
94 $ hg ci -Ama
95 adding b/z
95 adding b/z
96
96
97
97
98 qinit
98 qinit
99
99
100 $ hg qinit
100 $ hg qinit
101
101
102 $ cd ..
102 $ cd ..
103 $ hg init b
103 $ hg init b
104
104
105
105
106 -R qinit
106 -R qinit
107
107
108 $ hg -R b qinit
108 $ hg -R b qinit
109
109
110 $ hg init c
110 $ hg init c
111
111
112
112
113 qinit -c
113 qinit -c
114
114
115 $ hg --cwd c qinit -c
115 $ hg --cwd c qinit -c
116 $ hg -R c/.hg/patches st
116 $ hg -R c/.hg/patches st
117 A .hgignore
117 A .hgignore
118 A series
118 A series
119
119
120
120
121 qinit; qinit -c
121 qinit; qinit -c
122
122
123 $ hg init d
123 $ hg init d
124 $ cd d
124 $ cd d
125 $ hg qinit
125 $ hg qinit
126 $ hg qinit -c
126 $ hg qinit -c
127
127
128 qinit -c should create both files if they don't exist
128 qinit -c should create both files if they don't exist
129
129
130 $ cat .hg/patches/.hgignore
130 $ cat .hg/patches/.hgignore
131 ^\.hg
131 ^\.hg
132 ^\.mq
132 ^\.mq
133 syntax: glob
133 syntax: glob
134 status
134 status
135 guards
135 guards
136 $ cat .hg/patches/series
136 $ cat .hg/patches/series
137 $ hg qinit -c
137 $ hg qinit -c
138 abort: repository $TESTTMP/d/.hg/patches already exists!
138 abort: repository $TESTTMP/d/.hg/patches already exists!
139 [255]
139 [255]
140 $ cd ..
140 $ cd ..
141
141
142 $ echo '% qinit; <stuff>; qinit -c'
142 $ echo '% qinit; <stuff>; qinit -c'
143 % qinit; <stuff>; qinit -c
143 % qinit; <stuff>; qinit -c
144 $ hg init e
144 $ hg init e
145 $ cd e
145 $ cd e
146 $ hg qnew A
146 $ hg qnew A
147 $ checkundo qnew
147 $ checkundo qnew
148 $ echo foo > foo
148 $ echo foo > foo
149 $ hg add foo
149 $ hg add foo
150 $ hg qrefresh
150 $ hg qrefresh
151 $ hg qnew B
151 $ hg qnew B
152 $ echo >> foo
152 $ echo >> foo
153 $ hg qrefresh
153 $ hg qrefresh
154 $ echo status >> .hg/patches/.hgignore
154 $ echo status >> .hg/patches/.hgignore
155 $ echo bleh >> .hg/patches/.hgignore
155 $ echo bleh >> .hg/patches/.hgignore
156 $ hg qinit -c
156 $ hg qinit -c
157 adding .hg/patches/A
157 adding .hg/patches/A
158 adding .hg/patches/B
158 adding .hg/patches/B
159 $ hg -R .hg/patches status
159 $ hg -R .hg/patches status
160 A .hgignore
160 A .hgignore
161 A A
161 A A
162 A B
162 A B
163 A series
163 A series
164
164
165 qinit -c shouldn't touch these files if they already exist
165 qinit -c shouldn't touch these files if they already exist
166
166
167 $ cat .hg/patches/.hgignore
167 $ cat .hg/patches/.hgignore
168 status
168 status
169 bleh
169 bleh
170 $ cat .hg/patches/series
170 $ cat .hg/patches/series
171 A
171 A
172 B
172 B
173
173
174 add an untracked file
174 add an untracked file
175
175
176 $ echo >> .hg/patches/flaf
176 $ echo >> .hg/patches/flaf
177
177
178 status --mq with color (issue2096)
178 status --mq with color (issue2096)
179
179
180 $ hg status --mq --config extensions.color= --color=always
180 $ hg status --mq --config extensions.color= --color=always
181 \x1b[0;32;1mA .hgignore\x1b[0m (esc)
181 \x1b[0;32;1mA .hgignore\x1b[0m (esc)
182 \x1b[0;32;1mA A\x1b[0m (esc)
182 \x1b[0;32;1mA A\x1b[0m (esc)
183 \x1b[0;32;1mA B\x1b[0m (esc)
183 \x1b[0;32;1mA B\x1b[0m (esc)
184 \x1b[0;32;1mA series\x1b[0m (esc)
184 \x1b[0;32;1mA series\x1b[0m (esc)
185 \x1b[0;35;1;4m? flaf\x1b[0m (esc)
185 \x1b[0;35;1;4m? flaf\x1b[0m (esc)
186
186
187 try the --mq option on a command provided by an extension
187 try the --mq option on a command provided by an extension
188
188
189 $ hg purge --mq --verbose --config extensions.purge=
189 $ hg purge --mq --verbose --config extensions.purge=
190 Removing file flaf
190 Removing file flaf
191
191
192 $ cd ..
192 $ cd ..
193
193
194 init --mq without repo
194 init --mq without repo
195
195
196 $ mkdir f
196 $ mkdir f
197 $ cd f
197 $ cd f
198 $ hg init --mq
198 $ hg init --mq
199 abort: there is no Mercurial repository here (.hg not found)
199 abort: there is no Mercurial repository here (.hg not found)
200 [255]
200 [255]
201 $ cd ..
201 $ cd ..
202
202
203 init --mq with repo path
203 init --mq with repo path
204
204
205 $ hg init g
205 $ hg init g
206 $ hg init --mq g
206 $ hg init --mq g
207 $ test -d g/.hg/patches/.hg
207 $ test -d g/.hg/patches/.hg
208
208
209 init --mq with nonexistent directory
209 init --mq with nonexistent directory
210
210
211 $ hg init --mq nonexistentdir
211 $ hg init --mq nonexistentdir
212 abort: repository nonexistentdir not found!
212 abort: repository nonexistentdir not found!
213 [255]
213 [255]
214
214
215
215
216 init --mq with bundle (non "local")
216 init --mq with bundle (non "local")
217
217
218 $ hg -R a bundle --all a.bundle >/dev/null
218 $ hg -R a bundle --all a.bundle >/dev/null
219 $ hg init --mq a.bundle
219 $ hg init --mq a.bundle
220 abort: only a local queue repository may be initialized
220 abort: only a local queue repository may be initialized
221 [255]
221 [255]
222
222
223 $ cd a
223 $ cd a
224
224
225 $ hg qnew -m 'foo bar' test.patch
225 $ hg qnew -m 'foo bar' test.patch
226
226
227 $ echo '# comment' > .hg/patches/series.tmp
227 $ echo '# comment' > .hg/patches/series.tmp
228 $ echo >> .hg/patches/series.tmp # empty line
228 $ echo >> .hg/patches/series.tmp # empty line
229 $ cat .hg/patches/series >> .hg/patches/series.tmp
229 $ cat .hg/patches/series >> .hg/patches/series.tmp
230 $ mv .hg/patches/series.tmp .hg/patches/series
230 $ mv .hg/patches/series.tmp .hg/patches/series
231
231
232
232
233 qrefresh
233 qrefresh
234
234
235 $ echo a >> a
235 $ echo a >> a
236 $ hg qrefresh
236 $ hg qrefresh
237 $ cat .hg/patches/test.patch
237 $ cat .hg/patches/test.patch
238 foo bar
238 foo bar
239
239
240 diff -r [a-f0-9]* a (re)
240 diff -r [a-f0-9]* a (re)
241 --- a/a\t(?P<date>.*) (re)
241 --- a/a\t(?P<date>.*) (re)
242 \+\+\+ b/a\t(?P<date2>.*) (re)
242 \+\+\+ b/a\t(?P<date2>.*) (re)
243 @@ -1,1 +1,2 @@
243 @@ -1,1 +1,2 @@
244 a
244 a
245 +a
245 +a
246
246
247 empty qrefresh
247 empty qrefresh
248
248
249 $ hg qrefresh -X a
249 $ hg qrefresh -X a
250
250
251 revision:
251 revision:
252
252
253 $ hg diff -r -2 -r -1
253 $ hg diff -r -2 -r -1
254
254
255 patch:
255 patch:
256
256
257 $ cat .hg/patches/test.patch
257 $ cat .hg/patches/test.patch
258 foo bar
258 foo bar
259
259
260
260
261 working dir diff:
261 working dir diff:
262
262
263 $ hg diff --nodates -q
263 $ hg diff --nodates -q
264 --- a/a
264 --- a/a
265 +++ b/a
265 +++ b/a
266 @@ -1,1 +1,2 @@
266 @@ -1,1 +1,2 @@
267 a
267 a
268 +a
268 +a
269
269
270 restore things
270 restore things
271
271
272 $ hg qrefresh
272 $ hg qrefresh
273 $ checkundo qrefresh
273 $ checkundo qrefresh
274
274
275
275
276 qpop
276 qpop
277
277
278 $ hg qpop
278 $ hg qpop
279 popping test.patch
279 popping test.patch
280 patch queue now empty
280 patch queue now empty
281 $ checkundo qpop
281 $ checkundo qpop
282
282
283
283
284 qpush with dump of tag cache
284 qpush with dump of tag cache
285 Dump the tag cache to ensure that it has exactly one head after qpush.
285 Dump the tag cache to ensure that it has exactly one head after qpush.
286
286
287 $ rm -f .hg/tags.cache
287 $ rm -f .hg/tags.cache
288 $ hg tags > /dev/null
288 $ hg tags > /dev/null
289
289
290 .hg/tags.cache (pre qpush):
290 .hg/tags.cache (pre qpush):
291
291
292 $ cat .hg/tags.cache
292 $ cat .hg/tags.cache
293 1 [\da-f]{40} (re)
293 1 [\da-f]{40} (re)
294
294
295 $ hg qpush
295 $ hg qpush
296 applying test.patch
296 applying test.patch
297 now at: test.patch
297 now at: test.patch
298 $ hg tags > /dev/null
298 $ hg tags > /dev/null
299
299
300 .hg/tags.cache (post qpush):
300 .hg/tags.cache (post qpush):
301
301
302 $ cat .hg/tags.cache
302 $ cat .hg/tags.cache
303 2 [\da-f]{40} (re)
303 2 [\da-f]{40} (re)
304
304
305 $ checkundo qpush
305 $ checkundo qpush
306 $ cd ..
306 $ cd ..
307
307
308
308
309 pop/push outside repo
309 pop/push outside repo
310 $ hg -R a qpop
310 $ hg -R a qpop
311 popping test.patch
311 popping test.patch
312 patch queue now empty
312 patch queue now empty
313 $ hg -R a qpush
313 $ hg -R a qpush
314 applying test.patch
314 applying test.patch
315 now at: test.patch
315 now at: test.patch
316
316
317 $ cd a
317 $ cd a
318 $ hg qnew test2.patch
318 $ hg qnew test2.patch
319
319
320 qrefresh in subdir
320 qrefresh in subdir
321
321
322 $ cd b
322 $ cd b
323 $ echo a > a
323 $ echo a > a
324 $ hg add a
324 $ hg add a
325 $ hg qrefresh
325 $ hg qrefresh
326
326
327 pop/push -a in subdir
327 pop/push -a in subdir
328
328
329 $ hg qpop -a
329 $ hg qpop -a
330 popping test2.patch
330 popping test2.patch
331 popping test.patch
331 popping test.patch
332 patch queue now empty
332 patch queue now empty
333 $ hg --traceback qpush -a
333 $ hg --traceback qpush -a
334 applying test.patch
334 applying test.patch
335 applying test2.patch
335 applying test2.patch
336 now at: test2.patch
336 now at: test2.patch
337
337
338
338
339 setting columns & formatted tests truncating (issue1912)
339 setting columns & formatted tests truncating (issue1912)
340
340
341 $ COLUMNS=4 hg qseries --config ui.formatted=true
341 $ COLUMNS=4 hg qseries --config ui.formatted=true
342 test.patch
342 test.patch
343 test2.patch
343 test2.patch
344 $ COLUMNS=20 hg qseries --config ui.formatted=true -vs
344 $ COLUMNS=20 hg qseries --config ui.formatted=true -vs
345 0 A test.patch: f...
345 0 A test.patch: f...
346 1 A test2.patch:
346 1 A test2.patch:
347 $ hg qpop
347 $ hg qpop
348 popping test2.patch
348 popping test2.patch
349 now at: test.patch
349 now at: test.patch
350 $ hg qseries -vs
350 $ hg qseries -vs
351 0 A test.patch: foo bar
351 0 A test.patch: foo bar
352 1 U test2.patch:
352 1 U test2.patch:
353 $ hg sum | grep mq
353 $ hg sum | grep mq
354 mq: 1 applied, 1 unapplied
354 mq: 1 applied, 1 unapplied
355 $ hg qpush
355 $ hg qpush
356 applying test2.patch
356 applying test2.patch
357 now at: test2.patch
357 now at: test2.patch
358 $ hg sum | grep mq
358 $ hg sum | grep mq
359 mq: 2 applied
359 mq: 2 applied
360 $ hg qapplied
360 $ hg qapplied
361 test.patch
361 test.patch
362 test2.patch
362 test2.patch
363 $ hg qtop
363 $ hg qtop
364 test2.patch
364 test2.patch
365
365
366
366
367 prev
367 prev
368
368
369 $ hg qapp -1
369 $ hg qapp -1
370 test.patch
370 test.patch
371
371
372 next
372 next
373
373
374 $ hg qunapp -1
374 $ hg qunapp -1
375 all patches applied
375 all patches applied
376 [1]
376 [1]
377
377
378 $ hg qpop
378 $ hg qpop
379 popping test2.patch
379 popping test2.patch
380 now at: test.patch
380 now at: test.patch
381
381
382 commit should fail
382 commit should fail
383
383
384 $ hg commit
384 $ hg commit
385 abort: cannot commit over an applied mq patch
385 abort: cannot commit over an applied mq patch
386 [255]
386 [255]
387
387
388 push should fail
388 push should fail
389
389
390 $ hg push ../../k
390 $ hg push ../../k
391 pushing to ../../k
391 pushing to ../../k
392 abort: source has mq patches applied
392 abort: source has mq patches applied
393 [255]
393 [255]
394
394
395
395
396 import should fail
396 import should fail
397
397
398 $ hg st .
398 $ hg st .
399 $ echo foo >> ../a
399 $ echo foo >> ../a
400 $ hg diff > ../../import.diff
400 $ hg diff > ../../import.diff
401 $ hg revert --no-backup ../a
401 $ hg revert --no-backup ../a
402 $ hg import ../../import.diff
402 $ hg import ../../import.diff
403 abort: cannot import over an applied patch
403 abort: cannot import over an applied patch
404 [255]
404 [255]
405 $ hg st
405 $ hg st
406
406
407 import --no-commit should succeed
407 import --no-commit should succeed
408
408
409 $ hg import --no-commit ../../import.diff
409 $ hg import --no-commit ../../import.diff
410 applying ../../import.diff
410 applying ../../import.diff
411 $ hg st
411 $ hg st
412 M a
412 M a
413 $ hg revert --no-backup ../a
413 $ hg revert --no-backup ../a
414
414
415
415
416 qunapplied
416 qunapplied
417
417
418 $ hg qunapplied
418 $ hg qunapplied
419 test2.patch
419 test2.patch
420
420
421
421
422 qpush/qpop with index
422 qpush/qpop with index
423
423
424 $ hg qnew test1b.patch
424 $ hg qnew test1b.patch
425 $ echo 1b > 1b
425 $ echo 1b > 1b
426 $ hg add 1b
426 $ hg add 1b
427 $ hg qrefresh
427 $ hg qrefresh
428 $ hg qpush 2
428 $ hg qpush 2
429 applying test2.patch
429 applying test2.patch
430 now at: test2.patch
430 now at: test2.patch
431 $ hg qpop 0
431 $ hg qpop 0
432 popping test2.patch
432 popping test2.patch
433 popping test1b.patch
433 popping test1b.patch
434 now at: test.patch
434 now at: test.patch
435 $ hg qpush test.patch+1
435 $ hg qpush test.patch+1
436 applying test1b.patch
436 applying test1b.patch
437 now at: test1b.patch
437 now at: test1b.patch
438 $ hg qpush test.patch+2
438 $ hg qpush test.patch+2
439 applying test2.patch
439 applying test2.patch
440 now at: test2.patch
440 now at: test2.patch
441 $ hg qpop test2.patch-1
441 $ hg qpop test2.patch-1
442 popping test2.patch
442 popping test2.patch
443 now at: test1b.patch
443 now at: test1b.patch
444 $ hg qpop test2.patch-2
444 $ hg qpop test2.patch-2
445 popping test1b.patch
445 popping test1b.patch
446 now at: test.patch
446 now at: test.patch
447 $ hg qpush test1b.patch+1
447 $ hg qpush test1b.patch+1
448 applying test1b.patch
448 applying test1b.patch
449 applying test2.patch
449 applying test2.patch
450 now at: test2.patch
450 now at: test2.patch
451
451
452
452
453 qpush --move
453 qpush --move
454
454
455 $ hg qpop -a
455 $ hg qpop -a
456 popping test2.patch
456 popping test2.patch
457 popping test1b.patch
457 popping test1b.patch
458 popping test.patch
458 popping test.patch
459 patch queue now empty
459 patch queue now empty
460 $ hg qguard test1b.patch -- -negguard
460 $ hg qguard test1b.patch -- -negguard
461 $ hg qguard test2.patch -- +posguard
461 $ hg qguard test2.patch -- +posguard
462 $ hg qpush --move test2.patch # can't move guarded patch
462 $ hg qpush --move test2.patch # can't move guarded patch
463 cannot push 'test2.patch' - guarded by ['+posguard']
463 cannot push 'test2.patch' - guarded by ['+posguard']
464 [1]
464 [1]
465 $ hg qselect posguard
465 $ hg qselect posguard
466 number of unguarded, unapplied patches has changed from 2 to 3
466 number of unguarded, unapplied patches has changed from 2 to 3
467 $ hg qpush --move test2.patch # move to front
467 $ hg qpush --move test2.patch # move to front
468 applying test2.patch
468 applying test2.patch
469 now at: test2.patch
469 now at: test2.patch
470 $ hg qpush --move test1b.patch # negative guard unselected
470 $ hg qpush --move test1b.patch # negative guard unselected
471 applying test1b.patch
471 applying test1b.patch
472 now at: test1b.patch
472 now at: test1b.patch
473 $ hg qpush --move test.patch # noop move
473 $ hg qpush --move test.patch # noop move
474 applying test.patch
474 applying test.patch
475 now at: test.patch
475 now at: test.patch
476 $ hg qseries -v
476 $ hg qseries -v
477 0 A test2.patch
477 0 A test2.patch
478 1 A test1b.patch
478 1 A test1b.patch
479 2 A test.patch
479 2 A test.patch
480 $ hg qpop -a
480 $ hg qpop -a
481 popping test.patch
481 popping test.patch
482 popping test1b.patch
482 popping test1b.patch
483 popping test2.patch
483 popping test2.patch
484 patch queue now empty
484 patch queue now empty
485
485
486 cleaning up
486 cleaning up
487
487
488 $ hg qselect --none
488 $ hg qselect --none
489 guards deactivated
489 guards deactivated
490 number of unguarded, unapplied patches has changed from 3 to 2
490 number of unguarded, unapplied patches has changed from 3 to 2
491 $ hg qguard --none test1b.patch
491 $ hg qguard --none test1b.patch
492 $ hg qguard --none test2.patch
492 $ hg qguard --none test2.patch
493 $ hg qpush --move test.patch
493 $ hg qpush --move test.patch
494 applying test.patch
494 applying test.patch
495 now at: test.patch
495 now at: test.patch
496 $ hg qpush --move test1b.patch
496 $ hg qpush --move test1b.patch
497 applying test1b.patch
497 applying test1b.patch
498 now at: test1b.patch
498 now at: test1b.patch
499 $ hg qpush --move bogus # nonexistent patch
499 $ hg qpush --move bogus # nonexistent patch
500 abort: patch bogus not in series
500 abort: patch bogus not in series
501 [255]
501 [255]
502 $ hg qpush --move # no patch
502 $ hg qpush --move # no patch
503 abort: please specify the patch to move
503 abort: please specify the patch to move
504 [255]
504 [255]
505 $ hg qpush --move test.patch # already applied
505 $ hg qpush --move test.patch # already applied
506 abort: cannot push to a previous patch: test.patch
506 abort: cannot push to a previous patch: test.patch
507 [255]
507 [255]
508 $ hg qpush
508 $ hg qpush
509 applying test2.patch
509 applying test2.patch
510 now at: test2.patch
510 now at: test2.patch
511
511
512
512
513 series after move
513 series after move
514
514
515 $ cat `hg root`/.hg/patches/series
515 $ cat `hg root`/.hg/patches/series
516 test.patch
516 test.patch
517 test1b.patch
517 test1b.patch
518 test2.patch
518 test2.patch
519 # comment
519 # comment
520
520
521
521
522
522
523 pop, qapplied, qunapplied
523 pop, qapplied, qunapplied
524
524
525 $ hg qseries -v
525 $ hg qseries -v
526 0 A test.patch
526 0 A test.patch
527 1 A test1b.patch
527 1 A test1b.patch
528 2 A test2.patch
528 2 A test2.patch
529
529
530 qapplied -1 test.patch
530 qapplied -1 test.patch
531
531
532 $ hg qapplied -1 test.patch
532 $ hg qapplied -1 test.patch
533 only one patch applied
533 only one patch applied
534 [1]
534 [1]
535
535
536 qapplied -1 test1b.patch
536 qapplied -1 test1b.patch
537
537
538 $ hg qapplied -1 test1b.patch
538 $ hg qapplied -1 test1b.patch
539 test.patch
539 test.patch
540
540
541 qapplied -1 test2.patch
541 qapplied -1 test2.patch
542
542
543 $ hg qapplied -1 test2.patch
543 $ hg qapplied -1 test2.patch
544 test1b.patch
544 test1b.patch
545
545
546 qapplied -1
546 qapplied -1
547
547
548 $ hg qapplied -1
548 $ hg qapplied -1
549 test1b.patch
549 test1b.patch
550
550
551 qapplied
551 qapplied
552
552
553 $ hg qapplied
553 $ hg qapplied
554 test.patch
554 test.patch
555 test1b.patch
555 test1b.patch
556 test2.patch
556 test2.patch
557
557
558 qapplied test1b.patch
558 qapplied test1b.patch
559
559
560 $ hg qapplied test1b.patch
560 $ hg qapplied test1b.patch
561 test.patch
561 test.patch
562 test1b.patch
562 test1b.patch
563
563
564 qunapplied -1
564 qunapplied -1
565
565
566 $ hg qunapplied -1
566 $ hg qunapplied -1
567 all patches applied
567 all patches applied
568 [1]
568 [1]
569
569
570 qunapplied
570 qunapplied
571
571
572 $ hg qunapplied
572 $ hg qunapplied
573
573
574 popping
574 popping
575
575
576 $ hg qpop
576 $ hg qpop
577 popping test2.patch
577 popping test2.patch
578 now at: test1b.patch
578 now at: test1b.patch
579
579
580 qunapplied -1
580 qunapplied -1
581
581
582 $ hg qunapplied -1
582 $ hg qunapplied -1
583 test2.patch
583 test2.patch
584
584
585 qunapplied
585 qunapplied
586
586
587 $ hg qunapplied
587 $ hg qunapplied
588 test2.patch
588 test2.patch
589
589
590 qunapplied test2.patch
590 qunapplied test2.patch
591
591
592 $ hg qunapplied test2.patch
592 $ hg qunapplied test2.patch
593
593
594 qunapplied -1 test2.patch
594 qunapplied -1 test2.patch
595
595
596 $ hg qunapplied -1 test2.patch
596 $ hg qunapplied -1 test2.patch
597 all patches applied
597 all patches applied
598 [1]
598 [1]
599
599
600 popping -a
600 popping -a
601
601
602 $ hg qpop -a
602 $ hg qpop -a
603 popping test1b.patch
603 popping test1b.patch
604 popping test.patch
604 popping test.patch
605 patch queue now empty
605 patch queue now empty
606
606
607 qapplied
607 qapplied
608
608
609 $ hg qapplied
609 $ hg qapplied
610
610
611 qapplied -1
611 qapplied -1
612
612
613 $ hg qapplied -1
613 $ hg qapplied -1
614 no patches applied
614 no patches applied
615 [1]
615 [1]
616 $ hg qpush
616 $ hg qpush
617 applying test.patch
617 applying test.patch
618 now at: test.patch
618 now at: test.patch
619
619
620
620
621 push should succeed
621 push should succeed
622
622
623 $ hg qpop -a
623 $ hg qpop -a
624 popping test.patch
624 popping test.patch
625 patch queue now empty
625 patch queue now empty
626 $ hg push ../../k
626 $ hg push ../../k
627 pushing to ../../k
627 pushing to ../../k
628 searching for changes
628 searching for changes
629 adding changesets
629 adding changesets
630 adding manifests
630 adding manifests
631 adding file changes
631 adding file changes
632 added 1 changesets with 1 changes to 1 files
632 added 1 changesets with 1 changes to 1 files
633
633
634
634
635 we want to start with some patches applied
635 we want to start with some patches applied
636
636
637 $ hg qpush -a
637 $ hg qpush -a
638 applying test.patch
638 applying test.patch
639 applying test1b.patch
639 applying test1b.patch
640 applying test2.patch
640 applying test2.patch
641 now at: test2.patch
641 now at: test2.patch
642
642
643 % pops all patches and succeeds
643 % pops all patches and succeeds
644
644
645 $ hg qpop -a
645 $ hg qpop -a
646 popping test2.patch
646 popping test2.patch
647 popping test1b.patch
647 popping test1b.patch
648 popping test.patch
648 popping test.patch
649 patch queue now empty
649 patch queue now empty
650
650
651 % does nothing and succeeds
651 % does nothing and succeeds
652
652
653 $ hg qpop -a
653 $ hg qpop -a
654 no patches applied
654 no patches applied
655
655
656 % fails - nothing else to pop
656 % fails - nothing else to pop
657
657
658 $ hg qpop
658 $ hg qpop
659 no patches applied
659 no patches applied
660 [1]
660 [1]
661
661
662 % pushes a patch and succeeds
662 % pushes a patch and succeeds
663
663
664 $ hg qpush
664 $ hg qpush
665 applying test.patch
665 applying test.patch
666 now at: test.patch
666 now at: test.patch
667
667
668 % pops a patch and succeeds
668 % pops a patch and succeeds
669
669
670 $ hg qpop
670 $ hg qpop
671 popping test.patch
671 popping test.patch
672 patch queue now empty
672 patch queue now empty
673
673
674 % pushes up to test1b.patch and succeeds
674 % pushes up to test1b.patch and succeeds
675
675
676 $ hg qpush test1b.patch
676 $ hg qpush test1b.patch
677 applying test.patch
677 applying test.patch
678 applying test1b.patch
678 applying test1b.patch
679 now at: test1b.patch
679 now at: test1b.patch
680
680
681 % does nothing and succeeds
681 % does nothing and succeeds
682
682
683 $ hg qpush test1b.patch
683 $ hg qpush test1b.patch
684 qpush: test1b.patch is already at the top
684 qpush: test1b.patch is already at the top
685
685
686 % does nothing and succeeds
686 % does nothing and succeeds
687
687
688 $ hg qpop test1b.patch
688 $ hg qpop test1b.patch
689 qpop: test1b.patch is already at the top
689 qpop: test1b.patch is already at the top
690
690
691 % fails - can't push to this patch
691 % fails - can't push to this patch
692
692
693 $ hg qpush test.patch
693 $ hg qpush test.patch
694 abort: cannot push to a previous patch: test.patch
694 abort: cannot push to a previous patch: test.patch
695 [255]
695 [255]
696
696
697 % fails - can't pop to this patch
697 % fails - can't pop to this patch
698
698
699 $ hg qpop test2.patch
699 $ hg qpop test2.patch
700 abort: patch test2.patch is not applied
700 abort: patch test2.patch is not applied
701 [255]
701 [255]
702
702
703 % pops up to test.patch and succeeds
703 % pops up to test.patch and succeeds
704
704
705 $ hg qpop test.patch
705 $ hg qpop test.patch
706 popping test1b.patch
706 popping test1b.patch
707 now at: test.patch
707 now at: test.patch
708
708
709 % pushes all patches and succeeds
709 % pushes all patches and succeeds
710
710
711 $ hg qpush -a
711 $ hg qpush -a
712 applying test1b.patch
712 applying test1b.patch
713 applying test2.patch
713 applying test2.patch
714 now at: test2.patch
714 now at: test2.patch
715
715
716 % does nothing and succeeds
716 % does nothing and succeeds
717
717
718 $ hg qpush -a
718 $ hg qpush -a
719 all patches are currently applied
719 all patches are currently applied
720
720
721 % fails - nothing else to push
721 % fails - nothing else to push
722
722
723 $ hg qpush
723 $ hg qpush
724 patch series already fully applied
724 patch series already fully applied
725 [1]
725 [1]
726
726
727 % does nothing and succeeds
727 % does nothing and succeeds
728
728
729 $ hg qpush test2.patch
729 $ hg qpush test2.patch
730 qpush: test2.patch is already at the top
730 qpush: test2.patch is already at the top
731
731
732 strip
732 strip
733
733
734 $ cd ../../b
734 $ cd ../../b
735 $ echo x>x
735 $ echo x>x
736 $ hg ci -Ama
736 $ hg ci -Ama
737 adding x
737 adding x
738 $ hg strip tip
738 $ hg strip tip
739 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
739 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
740 saved backup bundle to $TESTTMP/b/.hg/strip-backup/*-backup.hg (glob)
740 saved backup bundle to $TESTTMP/b/.hg/strip-backup/*-backup.hg (glob)
741 $ hg unbundle .hg/strip-backup/*
741 $ hg unbundle .hg/strip-backup/*
742 adding changesets
742 adding changesets
743 adding manifests
743 adding manifests
744 adding file changes
744 adding file changes
745 added 1 changesets with 1 changes to 1 files
745 added 1 changesets with 1 changes to 1 files
746 (run 'hg update' to get a working copy)
746 (run 'hg update' to get a working copy)
747
747
748
748
749 strip with local changes, should complain
749 strip with local changes, should complain
750
750
751 $ hg up
751 $ hg up
752 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
752 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
753 $ echo y>y
753 $ echo y>y
754 $ hg add y
754 $ hg add y
755 $ hg strip tip
755 $ hg strip tip
756 abort: local changes found
756 abort: local changes found
757 [255]
757 [255]
758
758
759 --force strip with local changes
759 --force strip with local changes
760
760
761 $ hg strip -f tip
761 $ hg strip -f tip
762 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
762 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
763 saved backup bundle to $TESTTMP/b/.hg/strip-backup/*-backup.hg (glob)
763 saved backup bundle to $TESTTMP/b/.hg/strip-backup/*-backup.hg (glob)
764
764
765
765
766 cd b; hg qrefresh
766 cd b; hg qrefresh
767
767
768 $ hg init refresh
768 $ hg init refresh
769 $ cd refresh
769 $ cd refresh
770 $ echo a > a
770 $ echo a > a
771 $ hg ci -Ama
771 $ hg ci -Ama
772 adding a
772 adding a
773 $ hg qnew -mfoo foo
773 $ hg qnew -mfoo foo
774 $ echo a >> a
774 $ echo a >> a
775 $ hg qrefresh
775 $ hg qrefresh
776 $ mkdir b
776 $ mkdir b
777 $ cd b
777 $ cd b
778 $ echo f > f
778 $ echo f > f
779 $ hg add f
779 $ hg add f
780 $ hg qrefresh
780 $ hg qrefresh
781 $ cat ../.hg/patches/foo
781 $ cat ../.hg/patches/foo
782 foo
782 foo
783
783
784 diff -r cb9a9f314b8b a
784 diff -r cb9a9f314b8b a
785 --- a/a\t(?P<date>.*) (re)
785 --- a/a\t(?P<date>.*) (re)
786 \+\+\+ b/a\t(?P<date>.*) (re)
786 \+\+\+ b/a\t(?P<date>.*) (re)
787 @@ -1,1 +1,2 @@
787 @@ -1,1 +1,2 @@
788 a
788 a
789 +a
789 +a
790 diff -r cb9a9f314b8b b/f
790 diff -r cb9a9f314b8b b/f
791 --- /dev/null\t(?P<date>.*) (re)
791 --- /dev/null\t(?P<date>.*) (re)
792 \+\+\+ b/b/f\t(?P<date>.*) (re)
792 \+\+\+ b/b/f\t(?P<date>.*) (re)
793 @@ -0,0 +1,1 @@
793 @@ -0,0 +1,1 @@
794 +f
794 +f
795
795
796 hg qrefresh .
796 hg qrefresh .
797
797
798 $ hg qrefresh .
798 $ hg qrefresh .
799 $ cat ../.hg/patches/foo
799 $ cat ../.hg/patches/foo
800 foo
800 foo
801
801
802 diff -r cb9a9f314b8b b/f
802 diff -r cb9a9f314b8b b/f
803 --- /dev/null\t(?P<date>.*) (re)
803 --- /dev/null\t(?P<date>.*) (re)
804 \+\+\+ b/b/f\t(?P<date>.*) (re)
804 \+\+\+ b/b/f\t(?P<date>.*) (re)
805 @@ -0,0 +1,1 @@
805 @@ -0,0 +1,1 @@
806 +f
806 +f
807 $ hg status
807 $ hg status
808 M a
808 M a
809
809
810
810
811 qpush failure
811 qpush failure
812
812
813 $ cd ..
813 $ cd ..
814 $ hg qrefresh
814 $ hg qrefresh
815 $ hg qnew -mbar bar
815 $ hg qnew -mbar bar
816 $ echo foo > foo
816 $ echo foo > foo
817 $ echo bar > bar
817 $ echo bar > bar
818 $ hg add foo bar
818 $ hg add foo bar
819 $ hg qrefresh
819 $ hg qrefresh
820 $ hg qpop -a
820 $ hg qpop -a
821 popping bar
821 popping bar
822 popping foo
822 popping foo
823 patch queue now empty
823 patch queue now empty
824 $ echo bar > foo
824 $ echo bar > foo
825 $ hg qpush -a
825 $ hg qpush -a
826 applying foo
826 applying foo
827 applying bar
827 applying bar
828 file foo already exists
828 file foo already exists
829 1 out of 1 hunks FAILED -- saving rejects to file foo.rej
829 1 out of 1 hunks FAILED -- saving rejects to file foo.rej
830 patch failed, unable to continue (try -v)
830 patch failed, unable to continue (try -v)
831 patch failed, rejects left in working dir
831 patch failed, rejects left in working dir
832 errors during apply, please fix and refresh bar
832 errors during apply, please fix and refresh bar
833 [2]
833 [2]
834 $ hg st
834 $ hg st
835 ? foo
835 ? foo
836 ? foo.rej
836 ? foo.rej
837
837
838
838
839 mq tags
839 mq tags
840
840
841 $ hg log --template '{rev} {tags}\n' -r qparent:qtip
841 $ hg log --template '{rev} {tags}\n' -r qparent:qtip
842 0 qparent
842 0 qparent
843 1 foo qbase
843 1 foo qbase
844 2 bar qtip tip
844 2 bar qtip tip
845
845
846
846
847 bad node in status
847 bad node in status
848
848
849 $ hg qpop
849 $ hg qpop
850 popping bar
850 popping bar
851 now at: foo
851 now at: foo
852 $ hg strip -qn tip
852 $ hg strip -qn tip
853 $ hg tip
853 $ hg tip
854 changeset: 0:cb9a9f314b8b
854 changeset: 0:cb9a9f314b8b
855 tag: tip
855 tag: tip
856 user: test
856 user: test
857 date: Thu Jan 01 00:00:00 1970 +0000
857 date: Thu Jan 01 00:00:00 1970 +0000
858 summary: a
858 summary: a
859
859
860 $ hg branches
860 $ hg branches
861 default 0:cb9a9f314b8b
861 default 0:cb9a9f314b8b
862 $ hg qpop
862 $ hg qpop
863 no patches applied
863 no patches applied
864 [1]
864 [1]
865
865
866 $ cat >>$HGRCPATH <<EOF
866 $ cat >>$HGRCPATH <<EOF
867 > [diff]
867 > [diff]
868 > git = True
868 > git = True
869 > EOF
869 > EOF
870 $ cd ..
870 $ cd ..
871 $ hg init git
871 $ hg init git
872 $ cd git
872 $ cd git
873 $ hg qinit
873 $ hg qinit
874
874
875 $ hg qnew -m'new file' new
875 $ hg qnew -m'new file' new
876 $ echo foo > new
876 $ echo foo > new
877 $ chmod +x new
877 $ chmod +x new
878 $ hg add new
878 $ hg add new
879 $ hg qrefresh
879 $ hg qrefresh
880 $ cat .hg/patches/new
880 $ cat .hg/patches/new
881 new file
881 new file
882
882
883 diff --git a/new b/new
883 diff --git a/new b/new
884 new file mode 100755
884 new file mode 100755
885 --- /dev/null
885 --- /dev/null
886 +++ b/new
886 +++ b/new
887 @@ -0,0 +1,1 @@
887 @@ -0,0 +1,1 @@
888 +foo
888 +foo
889
889
890 $ hg qnew -m'copy file' copy
890 $ hg qnew -m'copy file' copy
891 $ hg cp new copy
891 $ hg cp new copy
892 $ hg qrefresh
892 $ hg qrefresh
893 $ cat .hg/patches/copy
893 $ cat .hg/patches/copy
894 copy file
894 copy file
895
895
896 diff --git a/new b/copy
896 diff --git a/new b/copy
897 copy from new
897 copy from new
898 copy to copy
898 copy to copy
899
899
900 $ hg qpop
900 $ hg qpop
901 popping copy
901 popping copy
902 now at: new
902 now at: new
903 $ hg qpush
903 $ hg qpush
904 applying copy
904 applying copy
905 now at: copy
905 now at: copy
906 $ hg qdiff
906 $ hg qdiff
907 diff --git a/new b/copy
907 diff --git a/new b/copy
908 copy from new
908 copy from new
909 copy to copy
909 copy to copy
910 $ cat >>$HGRCPATH <<EOF
910 $ cat >>$HGRCPATH <<EOF
911 > [diff]
911 > [diff]
912 > git = False
912 > git = False
913 > EOF
913 > EOF
914 $ hg qdiff --git
914 $ hg qdiff --git
915 diff --git a/new b/copy
915 diff --git a/new b/copy
916 copy from new
916 copy from new
917 copy to copy
917 copy to copy
918 $ cd ..
918 $ cd ..
919
919
920
920
921 test file addition in slow path
921 test file addition in slow path
922
922
923 $ hg init slow
923 $ hg init slow
924 $ cd slow
924 $ cd slow
925 $ hg qinit
925 $ hg qinit
926 $ echo foo > foo
926 $ echo foo > foo
927 $ hg add foo
927 $ hg add foo
928 $ hg ci -m 'add foo'
928 $ hg ci -m 'add foo'
929 $ hg qnew bar
929 $ hg qnew bar
930 $ echo bar > bar
930 $ echo bar > bar
931 $ hg add bar
931 $ hg add bar
932 $ hg mv foo baz
932 $ hg mv foo baz
933 $ hg qrefresh --git
933 $ hg qrefresh --git
934 $ hg up -C 0
934 $ hg up -C 0
935 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
935 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
936 $ echo >> foo
936 $ echo >> foo
937 $ hg ci -m 'change foo'
937 $ hg ci -m 'change foo'
938 created new head
938 created new head
939 $ hg up -C 1
939 $ hg up -C 1
940 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
940 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
941 $ hg qrefresh --git
941 $ hg qrefresh --git
942 $ cat .hg/patches/bar
942 $ cat .hg/patches/bar
943 diff --git a/bar b/bar
943 diff --git a/bar b/bar
944 new file mode 100644
944 new file mode 100644
945 --- /dev/null
945 --- /dev/null
946 +++ b/bar
946 +++ b/bar
947 @@ -0,0 +1,1 @@
947 @@ -0,0 +1,1 @@
948 +bar
948 +bar
949 diff --git a/foo b/baz
949 diff --git a/foo b/baz
950 rename from foo
950 rename from foo
951 rename to baz
951 rename to baz
952 $ hg log -v --template '{rev} {file_copies}\n' -r .
952 $ hg log -v --template '{rev} {file_copies}\n' -r .
953 2 baz (foo)
953 2 baz (foo)
954 $ hg qrefresh --git
954 $ hg qrefresh --git
955 $ cat .hg/patches/bar
955 $ cat .hg/patches/bar
956 diff --git a/bar b/bar
956 diff --git a/bar b/bar
957 new file mode 100644
957 new file mode 100644
958 --- /dev/null
958 --- /dev/null
959 +++ b/bar
959 +++ b/bar
960 @@ -0,0 +1,1 @@
960 @@ -0,0 +1,1 @@
961 +bar
961 +bar
962 diff --git a/foo b/baz
962 diff --git a/foo b/baz
963 rename from foo
963 rename from foo
964 rename to baz
964 rename to baz
965 $ hg log -v --template '{rev} {file_copies}\n' -r .
965 $ hg log -v --template '{rev} {file_copies}\n' -r .
966 2 baz (foo)
966 2 baz (foo)
967 $ hg qrefresh
967 $ hg qrefresh
968 $ grep 'diff --git' .hg/patches/bar
968 $ grep 'diff --git' .hg/patches/bar
969 diff --git a/bar b/bar
969 diff --git a/bar b/bar
970 diff --git a/foo b/baz
970 diff --git a/foo b/baz
971
971
972
972
973 test file move chains in the slow path
973 test file move chains in the slow path
974
974
975 $ hg up -C 1
975 $ hg up -C 1
976 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
976 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
977 $ echo >> foo
977 $ echo >> foo
978 $ hg ci -m 'change foo again'
978 $ hg ci -m 'change foo again'
979 $ hg up -C 2
979 $ hg up -C 2
980 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
980 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
981 $ hg mv bar quux
981 $ hg mv bar quux
982 $ hg mv baz bleh
982 $ hg mv baz bleh
983 $ hg qrefresh --git
983 $ hg qrefresh --git
984 $ cat .hg/patches/bar
984 $ cat .hg/patches/bar
985 diff --git a/foo b/bleh
985 diff --git a/foo b/bleh
986 rename from foo
986 rename from foo
987 rename to bleh
987 rename to bleh
988 diff --git a/quux b/quux
988 diff --git a/quux b/quux
989 new file mode 100644
989 new file mode 100644
990 --- /dev/null
990 --- /dev/null
991 +++ b/quux
991 +++ b/quux
992 @@ -0,0 +1,1 @@
992 @@ -0,0 +1,1 @@
993 +bar
993 +bar
994 $ hg log -v --template '{rev} {file_copies}\n' -r .
994 $ hg log -v --template '{rev} {file_copies}\n' -r .
995 3 bleh (foo)
995 3 bleh (foo)
996 $ hg mv quux fred
996 $ hg mv quux fred
997 $ hg mv bleh barney
997 $ hg mv bleh barney
998 $ hg qrefresh --git
998 $ hg qrefresh --git
999 $ cat .hg/patches/bar
999 $ cat .hg/patches/bar
1000 diff --git a/foo b/barney
1000 diff --git a/foo b/barney
1001 rename from foo
1001 rename from foo
1002 rename to barney
1002 rename to barney
1003 diff --git a/fred b/fred
1003 diff --git a/fred b/fred
1004 new file mode 100644
1004 new file mode 100644
1005 --- /dev/null
1005 --- /dev/null
1006 +++ b/fred
1006 +++ b/fred
1007 @@ -0,0 +1,1 @@
1007 @@ -0,0 +1,1 @@
1008 +bar
1008 +bar
1009 $ hg log -v --template '{rev} {file_copies}\n' -r .
1009 $ hg log -v --template '{rev} {file_copies}\n' -r .
1010 3 barney (foo)
1010 3 barney (foo)
1011
1011
1012
1012
1013 refresh omitting an added file
1013 refresh omitting an added file
1014
1014
1015 $ hg qnew baz
1015 $ hg qnew baz
1016 $ echo newfile > newfile
1016 $ echo newfile > newfile
1017 $ hg add newfile
1017 $ hg add newfile
1018 $ hg qrefresh
1018 $ hg qrefresh
1019 $ hg st -A newfile
1019 $ hg st -A newfile
1020 C newfile
1020 C newfile
1021 $ hg qrefresh -X newfile
1021 $ hg qrefresh -X newfile
1022 $ hg st -A newfile
1022 $ hg st -A newfile
1023 A newfile
1023 A newfile
1024 $ hg revert newfile
1024 $ hg revert newfile
1025 $ rm newfile
1025 $ rm newfile
1026 $ hg qpop
1026 $ hg qpop
1027 popping baz
1027 popping baz
1028 now at: bar
1028 now at: bar
1029 $ hg qdel baz
1029 $ hg qdel baz
1030
1030
1031
1031
1032 create a git patch
1032 create a git patch
1033
1033
1034 $ echo a > alexander
1034 $ echo a > alexander
1035 $ hg add alexander
1035 $ hg add alexander
1036 $ hg qnew -f --git addalexander
1036 $ hg qnew -f --git addalexander
1037 $ grep diff .hg/patches/addalexander
1037 $ grep diff .hg/patches/addalexander
1038 diff --git a/alexander b/alexander
1038 diff --git a/alexander b/alexander
1039
1039
1040
1040
1041 create a git binary patch
1041 create a git binary patch
1042
1042
1043 $ cat > writebin.py <<EOF
1043 $ cat > writebin.py <<EOF
1044 > import sys
1044 > import sys
1045 > path = sys.argv[1]
1045 > path = sys.argv[1]
1046 > open(path, 'wb').write('BIN\x00ARY')
1046 > open(path, 'wb').write('BIN\x00ARY')
1047 > EOF
1047 > EOF
1048 $ python writebin.py bucephalus
1048 $ python writebin.py bucephalus
1049
1049
1050 $ python "$TESTDIR/md5sum.py" bucephalus
1050 $ python "$TESTDIR/md5sum.py" bucephalus
1051 8ba2a2f3e77b55d03051ff9c24ad65e7 bucephalus
1051 8ba2a2f3e77b55d03051ff9c24ad65e7 bucephalus
1052 $ hg add bucephalus
1052 $ hg add bucephalus
1053 $ hg qnew -f --git addbucephalus
1053 $ hg qnew -f --git addbucephalus
1054 $ grep diff .hg/patches/addbucephalus
1054 $ grep diff .hg/patches/addbucephalus
1055 diff --git a/bucephalus b/bucephalus
1055 diff --git a/bucephalus b/bucephalus
1056
1056
1057
1057
1058 check binary patches can be popped and pushed
1058 check binary patches can be popped and pushed
1059
1059
1060 $ hg qpop
1060 $ hg qpop
1061 popping addbucephalus
1061 popping addbucephalus
1062 now at: addalexander
1062 now at: addalexander
1063 $ test -f bucephalus && echo % bucephalus should not be there
1063 $ test -f bucephalus && echo % bucephalus should not be there
1064 [1]
1064 [1]
1065 $ hg qpush
1065 $ hg qpush
1066 applying addbucephalus
1066 applying addbucephalus
1067 now at: addbucephalus
1067 now at: addbucephalus
1068 $ test -f bucephalus
1068 $ test -f bucephalus
1069 $ python "$TESTDIR/md5sum.py" bucephalus
1069 $ python "$TESTDIR/md5sum.py" bucephalus
1070 8ba2a2f3e77b55d03051ff9c24ad65e7 bucephalus
1070 8ba2a2f3e77b55d03051ff9c24ad65e7 bucephalus
1071
1071
1072
1072
1073
1073
1074 strip again
1074 strip again
1075
1075
1076 $ cd ..
1076 $ cd ..
1077 $ hg init strip
1077 $ hg init strip
1078 $ cd strip
1078 $ cd strip
1079 $ touch foo
1079 $ touch foo
1080 $ hg add foo
1080 $ hg add foo
1081 $ hg ci -m 'add foo'
1081 $ hg ci -m 'add foo'
1082 $ echo >> foo
1082 $ echo >> foo
1083 $ hg ci -m 'change foo 1'
1083 $ hg ci -m 'change foo 1'
1084 $ hg up -C 0
1084 $ hg up -C 0
1085 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1085 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1086 $ echo 1 >> foo
1086 $ echo 1 >> foo
1087 $ hg ci -m 'change foo 2'
1087 $ hg ci -m 'change foo 2'
1088 created new head
1088 created new head
1089 $ HGMERGE=true hg merge
1089 $ HGMERGE=true hg merge
1090 merging foo
1090 merging foo
1091 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1091 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1092 (branch merge, don't forget to commit)
1092 (branch merge, don't forget to commit)
1093 $ hg ci -m merge
1093 $ hg ci -m merge
1094 $ hg log
1094 $ hg log
1095 changeset: 3:99615015637b
1095 changeset: 3:99615015637b
1096 tag: tip
1096 tag: tip
1097 parent: 2:20cbbe65cff7
1097 parent: 2:20cbbe65cff7
1098 parent: 1:d2871fc282d4
1098 parent: 1:d2871fc282d4
1099 user: test
1099 user: test
1100 date: Thu Jan 01 00:00:00 1970 +0000
1100 date: Thu Jan 01 00:00:00 1970 +0000
1101 summary: merge
1101 summary: merge
1102
1102
1103 changeset: 2:20cbbe65cff7
1103 changeset: 2:20cbbe65cff7
1104 parent: 0:53245c60e682
1104 parent: 0:53245c60e682
1105 user: test
1105 user: test
1106 date: Thu Jan 01 00:00:00 1970 +0000
1106 date: Thu Jan 01 00:00:00 1970 +0000
1107 summary: change foo 2
1107 summary: change foo 2
1108
1108
1109 changeset: 1:d2871fc282d4
1109 changeset: 1:d2871fc282d4
1110 user: test
1110 user: test
1111 date: Thu Jan 01 00:00:00 1970 +0000
1111 date: Thu Jan 01 00:00:00 1970 +0000
1112 summary: change foo 1
1112 summary: change foo 1
1113
1113
1114 changeset: 0:53245c60e682
1114 changeset: 0:53245c60e682
1115 user: test
1115 user: test
1116 date: Thu Jan 01 00:00:00 1970 +0000
1116 date: Thu Jan 01 00:00:00 1970 +0000
1117 summary: add foo
1117 summary: add foo
1118
1118
1119 $ hg strip 1
1119 $ hg strip 1
1120 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1120 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1121 saved backup bundle to $TESTTMP/b/strip/.hg/strip-backup/*-backup.hg (glob)
1121 saved backup bundle to $TESTTMP/b/strip/.hg/strip-backup/*-backup.hg (glob)
1122 $ checkundo strip
1122 $ checkundo strip
1123 $ hg log
1123 $ hg log
1124 changeset: 1:20cbbe65cff7
1124 changeset: 1:20cbbe65cff7
1125 tag: tip
1125 tag: tip
1126 user: test
1126 user: test
1127 date: Thu Jan 01 00:00:00 1970 +0000
1127 date: Thu Jan 01 00:00:00 1970 +0000
1128 summary: change foo 2
1128 summary: change foo 2
1129
1129
1130 changeset: 0:53245c60e682
1130 changeset: 0:53245c60e682
1131 user: test
1131 user: test
1132 date: Thu Jan 01 00:00:00 1970 +0000
1132 date: Thu Jan 01 00:00:00 1970 +0000
1133 summary: add foo
1133 summary: add foo
1134
1134
1135 $ cd ..
1135 $ cd ..
1136
1136
1137
1137
1138 qclone
1138 qclone
1139
1139
1140 $ qlog()
1140 $ qlog()
1141 > {
1141 > {
1142 > echo 'main repo:'
1142 > echo 'main repo:'
1143 > hg log --template ' rev {rev}: {desc}\n'
1143 > hg log --template ' rev {rev}: {desc}\n'
1144 > echo 'patch repo:'
1144 > echo 'patch repo:'
1145 > hg -R .hg/patches log --template ' rev {rev}: {desc}\n'
1145 > hg -R .hg/patches log --template ' rev {rev}: {desc}\n'
1146 > }
1146 > }
1147 $ hg init qclonesource
1147 $ hg init qclonesource
1148 $ cd qclonesource
1148 $ cd qclonesource
1149 $ echo foo > foo
1149 $ echo foo > foo
1150 $ hg add foo
1150 $ hg add foo
1151 $ hg ci -m 'add foo'
1151 $ hg ci -m 'add foo'
1152 $ hg qinit
1152 $ hg qinit
1153 $ hg qnew patch1
1153 $ hg qnew patch1
1154 $ echo bar >> foo
1154 $ echo bar >> foo
1155 $ hg qrefresh -m 'change foo'
1155 $ hg qrefresh -m 'change foo'
1156 $ cd ..
1156 $ cd ..
1157
1157
1158
1158
1159 repo with unversioned patch dir
1159 repo with unversioned patch dir
1160
1160
1161 $ hg qclone qclonesource failure
1161 $ hg qclone qclonesource failure
1162 abort: versioned patch repository not found (see init --mq)
1162 abort: versioned patch repository not found (see init --mq)
1163 [255]
1163 [255]
1164
1164
1165 $ cd qclonesource
1165 $ cd qclonesource
1166 $ hg qinit -c
1166 $ hg qinit -c
1167 adding .hg/patches/patch1
1167 adding .hg/patches/patch1
1168 $ hg qci -m checkpoint
1168 $ hg qci -m checkpoint
1169 $ qlog
1169 $ qlog
1170 main repo:
1170 main repo:
1171 rev 1: change foo
1171 rev 1: change foo
1172 rev 0: add foo
1172 rev 0: add foo
1173 patch repo:
1173 patch repo:
1174 rev 0: checkpoint
1174 rev 0: checkpoint
1175 $ cd ..
1175 $ cd ..
1176
1176
1177
1177
1178 repo with patches applied
1178 repo with patches applied
1179
1179
1180 $ hg qclone qclonesource qclonedest
1180 $ hg qclone qclonesource qclonedest
1181 updating to branch default
1181 updating to branch default
1182 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
1182 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
1183 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1183 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1184 $ cd qclonedest
1184 $ cd qclonedest
1185 $ qlog
1185 $ qlog
1186 main repo:
1186 main repo:
1187 rev 0: add foo
1187 rev 0: add foo
1188 patch repo:
1188 patch repo:
1189 rev 0: checkpoint
1189 rev 0: checkpoint
1190 $ cd ..
1190 $ cd ..
1191
1191
1192
1192
1193 repo with patches unapplied
1193 repo with patches unapplied
1194
1194
1195 $ cd qclonesource
1195 $ cd qclonesource
1196 $ hg qpop -a
1196 $ hg qpop -a
1197 popping patch1
1197 popping patch1
1198 patch queue now empty
1198 patch queue now empty
1199 $ qlog
1199 $ qlog
1200 main repo:
1200 main repo:
1201 rev 0: add foo
1201 rev 0: add foo
1202 patch repo:
1202 patch repo:
1203 rev 0: checkpoint
1203 rev 0: checkpoint
1204 $ cd ..
1204 $ cd ..
1205 $ hg qclone qclonesource qclonedest2
1205 $ hg qclone qclonesource qclonedest2
1206 updating to branch default
1206 updating to branch default
1207 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
1207 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
1208 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1208 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1209 $ cd qclonedest2
1209 $ cd qclonedest2
1210 $ qlog
1210 $ qlog
1211 main repo:
1211 main repo:
1212 rev 0: add foo
1212 rev 0: add foo
1213 patch repo:
1213 patch repo:
1214 rev 0: checkpoint
1214 rev 0: checkpoint
1215 $ cd ..
1215 $ cd ..
1216
1216
1217
1217
1218 Issue1033: test applying on an empty file
1218 Issue1033: test applying on an empty file
1219
1219
1220 $ hg init empty
1220 $ hg init empty
1221 $ cd empty
1221 $ cd empty
1222 $ touch a
1222 $ touch a
1223 $ hg ci -Am addempty
1223 $ hg ci -Am addempty
1224 adding a
1224 adding a
1225 $ echo a > a
1225 $ echo a > a
1226 $ hg qnew -f -e changea
1226 $ hg qnew -f -e changea
1227 $ hg qpop
1227 $ hg qpop
1228 popping changea
1228 popping changea
1229 patch queue now empty
1229 patch queue now empty
1230 $ hg qpush
1230 $ hg qpush
1231 applying changea
1231 applying changea
1232 now at: changea
1232 now at: changea
1233 $ cd ..
1233 $ cd ..
1234
1234
1235
1235
1236 test qpush with --force, issue1087
1236 test qpush with --force, issue1087
1237
1237
1238 $ hg init forcepush
1238 $ hg init forcepush
1239 $ cd forcepush
1239 $ cd forcepush
1240 $ echo hello > hello.txt
1240 $ echo hello > hello.txt
1241 $ echo bye > bye.txt
1241 $ echo bye > bye.txt
1242 $ hg ci -Ama
1242 $ hg ci -Ama
1243 adding bye.txt
1243 adding bye.txt
1244 adding hello.txt
1244 adding hello.txt
1245 $ hg qnew -d '0 0' empty
1245 $ hg qnew -d '0 0' empty
1246 $ hg qpop
1246 $ hg qpop
1247 popping empty
1247 popping empty
1248 patch queue now empty
1248 patch queue now empty
1249 $ echo world >> hello.txt
1249 $ echo world >> hello.txt
1250
1250
1251
1251
1252 qpush should fail, local changes
1252 qpush should fail, local changes
1253
1253
1254 $ hg qpush
1254 $ hg qpush
1255 abort: local changes found, refresh first
1255 abort: local changes found, refresh first
1256 [255]
1256 [255]
1257
1257
1258
1258
1259 apply force, should not discard changes with empty patch
1259 apply force, should not discard changes with empty patch
1260
1260
1261 $ hg qpush -f
1261 $ hg qpush -f
1262 applying empty
1262 applying empty
1263 patch empty is empty
1263 patch empty is empty
1264 now at: empty
1264 now at: empty
1265 $ hg diff --config diff.nodates=True
1265 $ hg diff --config diff.nodates=True
1266 diff -r bf5fc3f07a0a hello.txt
1266 diff -r bf5fc3f07a0a hello.txt
1267 --- a/hello.txt
1267 --- a/hello.txt
1268 +++ b/hello.txt
1268 +++ b/hello.txt
1269 @@ -1,1 +1,2 @@
1269 @@ -1,1 +1,2 @@
1270 hello
1270 hello
1271 +world
1271 +world
1272 $ hg qdiff --config diff.nodates=True
1272 $ hg qdiff --config diff.nodates=True
1273 diff -r 9ecee4f634e3 hello.txt
1273 diff -r 9ecee4f634e3 hello.txt
1274 --- a/hello.txt
1274 --- a/hello.txt
1275 +++ b/hello.txt
1275 +++ b/hello.txt
1276 @@ -1,1 +1,2 @@
1276 @@ -1,1 +1,2 @@
1277 hello
1277 hello
1278 +world
1278 +world
1279 $ hg log -l1 -p
1279 $ hg log -l1 -p
1280 changeset: 1:bf5fc3f07a0a
1280 changeset: 1:bf5fc3f07a0a
1281 tag: empty
1281 tag: empty
1282 tag: qbase
1282 tag: qbase
1283 tag: qtip
1283 tag: qtip
1284 tag: tip
1284 tag: tip
1285 user: test
1285 user: test
1286 date: Thu Jan 01 00:00:00 1970 +0000
1286 date: Thu Jan 01 00:00:00 1970 +0000
1287 summary: imported patch empty
1287 summary: imported patch empty
1288
1288
1289
1289
1290 $ hg qref -d '0 0'
1290 $ hg qref -d '0 0'
1291 $ hg qpop
1291 $ hg qpop
1292 popping empty
1292 popping empty
1293 patch queue now empty
1293 patch queue now empty
1294 $ echo universe >> hello.txt
1294 $ echo universe >> hello.txt
1295 $ echo universe >> bye.txt
1295 $ echo universe >> bye.txt
1296
1296
1297
1297
1298 qpush should fail, local changes
1298 qpush should fail, local changes
1299
1299
1300 $ hg qpush
1300 $ hg qpush
1301 abort: local changes found, refresh first
1301 abort: local changes found, refresh first
1302 [255]
1302 [255]
1303
1303
1304
1304
1305 apply force, should discard changes in hello, but not bye
1305 apply force, should discard changes in hello, but not bye
1306
1306
1307 $ hg qpush -f
1307 $ hg qpush -f
1308 applying empty
1308 applying empty
1309 now at: empty
1309 now at: empty
1310 $ hg st
1310 $ hg st
1311 M bye.txt
1311 M bye.txt
1312 $ hg diff --config diff.nodates=True
1312 $ hg diff --config diff.nodates=True
1313 diff -r ba252371dbc1 bye.txt
1313 diff -r ba252371dbc1 bye.txt
1314 --- a/bye.txt
1314 --- a/bye.txt
1315 +++ b/bye.txt
1315 +++ b/bye.txt
1316 @@ -1,1 +1,2 @@
1316 @@ -1,1 +1,2 @@
1317 bye
1317 bye
1318 +universe
1318 +universe
1319 $ hg qdiff --config diff.nodates=True
1319 $ hg qdiff --config diff.nodates=True
1320 diff -r 9ecee4f634e3 bye.txt
1320 diff -r 9ecee4f634e3 bye.txt
1321 --- a/bye.txt
1321 --- a/bye.txt
1322 +++ b/bye.txt
1322 +++ b/bye.txt
1323 @@ -1,1 +1,2 @@
1323 @@ -1,1 +1,2 @@
1324 bye
1324 bye
1325 +universe
1325 +universe
1326 diff -r 9ecee4f634e3 hello.txt
1326 diff -r 9ecee4f634e3 hello.txt
1327 --- a/hello.txt
1327 --- a/hello.txt
1328 +++ b/hello.txt
1328 +++ b/hello.txt
1329 @@ -1,1 +1,3 @@
1329 @@ -1,1 +1,3 @@
1330 hello
1330 hello
1331 +world
1331 +world
1332 +universe
1332 +universe
1333
1333
1334
1334
1335 test popping revisions not in working dir ancestry
1335 test popping revisions not in working dir ancestry
1336
1336
1337 $ hg qseries -v
1337 $ hg qseries -v
1338 0 A empty
1338 0 A empty
1339 $ hg up qparent
1339 $ hg up qparent
1340 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1340 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1341 $ hg qpop
1341 $ hg qpop
1342 popping empty
1342 popping empty
1343 patch queue now empty
1343 patch queue now empty
1344
1344
1345 $ cd ..
1345 $ cd ..
1346 $ hg init deletion-order
1346 $ hg init deletion-order
1347 $ cd deletion-order
1347 $ cd deletion-order
1348
1348
1349 $ touch a
1349 $ touch a
1350 $ hg ci -Aqm0
1350 $ hg ci -Aqm0
1351
1351
1352 $ hg qnew rename-dir
1352 $ hg qnew rename-dir
1353 $ hg rm a
1353 $ hg rm a
1354 $ hg qrefresh
1354 $ hg qrefresh
1355
1355
1356 $ mkdir a b
1356 $ mkdir a b
1357 $ touch a/a b/b
1357 $ touch a/a b/b
1358 $ hg add -q a b
1358 $ hg add -q a b
1359 $ hg qrefresh
1359 $ hg qrefresh
1360
1360
1361
1361
1362 test popping must remove files added in subdirectories first
1362 test popping must remove files added in subdirectories first
1363
1363
1364 $ hg qpop
1364 $ hg qpop
1365 popping rename-dir
1365 popping rename-dir
1366 patch queue now empty
1366 patch queue now empty
1367 $ cd ..
1367 $ cd ..
1368
1368
@@ -1,658 +1,677 b''
1 $ rm -rf sub
1 $ rm -rf sub
2 $ mkdir sub
2 $ mkdir sub
3 $ cd sub
3 $ cd sub
4 $ hg init t
4 $ hg init t
5 $ cd t
5 $ cd t
6
6
7 first revision, no sub
7 first revision, no sub
8
8
9 $ echo a > a
9 $ echo a > a
10 $ hg ci -Am0
10 $ hg ci -Am0
11 adding a
11 adding a
12
12
13 add first sub
13 add first sub
14
14
15 $ echo s = s > .hgsub
15 $ echo s = s > .hgsub
16 $ hg add .hgsub
16 $ hg add .hgsub
17 $ hg init s
17 $ hg init s
18 $ echo a > s/a
18 $ echo a > s/a
19
19
20 Issue2232: committing a subrepo without .hgsub
20 Issue2232: committing a subrepo without .hgsub
21
21
22 $ hg ci -mbad s
22 $ hg ci -mbad s
23 abort: can't commit subrepos without .hgsub
23 abort: can't commit subrepos without .hgsub
24 [255]
24 [255]
25
25
26 $ hg -R s ci -Ams0
26 $ hg -R s ci -Ams0
27 adding a
27 adding a
28 $ hg sum
28 $ hg sum
29 parent: 0:f7b1eb17ad24 tip
29 parent: 0:f7b1eb17ad24 tip
30 0
30 0
31 branch: default
31 branch: default
32 commit: 1 added, 1 subrepos
32 commit: 1 added, 1 subrepos
33 update: (current)
33 update: (current)
34 $ hg ci -m1
34 $ hg ci -m1
35 committing subrepository s
35 committing subrepository s
36
36
37 Issue2022: update -C
37 Issue2022: update -C
38
38
39 $ echo b > s/a
39 $ echo b > s/a
40 $ hg sum
40 $ hg sum
41 parent: 1:7cf8cfea66e4 tip
41 parent: 1:7cf8cfea66e4 tip
42 1
42 1
43 branch: default
43 branch: default
44 commit: 1 subrepos
44 commit: 1 subrepos
45 update: (current)
45 update: (current)
46 $ hg co -C 1
46 $ hg co -C 1
47 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
47 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
48 $ hg sum
48 $ hg sum
49 parent: 1:7cf8cfea66e4 tip
49 parent: 1:7cf8cfea66e4 tip
50 1
50 1
51 branch: default
51 branch: default
52 commit: (clean)
52 commit: (clean)
53 update: (current)
53 update: (current)
54
54
55 add sub sub
55 add sub sub
56
56
57 $ echo ss = ss > s/.hgsub
57 $ echo ss = ss > s/.hgsub
58 $ hg init s/ss
58 $ hg init s/ss
59 $ echo a > s/ss/a
59 $ echo a > s/ss/a
60 $ hg -R s add s/.hgsub
60 $ hg -R s add s/.hgsub
61 $ hg -R s/ss add s/ss/a
61 $ hg -R s/ss add s/ss/a
62 $ hg sum
62 $ hg sum
63 parent: 1:7cf8cfea66e4 tip
63 parent: 1:7cf8cfea66e4 tip
64 1
64 1
65 branch: default
65 branch: default
66 commit: 1 subrepos
66 commit: 1 subrepos
67 update: (current)
67 update: (current)
68 $ hg ci -m2
68 $ hg ci -m2
69 committing subrepository s
69 committing subrepository s
70 committing subrepository s/ss
70 committing subrepository s/ss
71 $ hg sum
71 $ hg sum
72 parent: 2:df30734270ae tip
72 parent: 2:df30734270ae tip
73 2
73 2
74 branch: default
74 branch: default
75 commit: (clean)
75 commit: (clean)
76 update: (current)
76 update: (current)
77
77
78 bump sub rev
78 bump sub rev
79
79
80 $ echo b > s/a
80 $ echo b > s/a
81 $ hg -R s ci -ms1
81 $ hg -R s ci -ms1
82 $ hg ci -m3
82 $ hg ci -m3
83 committing subrepository s
83 committing subrepository s
84
84
85 leave sub dirty
85 leave sub dirty
86
86
87 $ echo c > s/a
87 $ echo c > s/a
88 $ hg ci -m4
88 $ hg ci -m4
89 committing subrepository s
89 committing subrepository s
90 $ hg tip -R s
90 $ hg tip -R s
91 changeset: 3:1c833a7a9e3a
91 changeset: 3:1c833a7a9e3a
92 tag: tip
92 tag: tip
93 user: test
93 user: test
94 date: Thu Jan 01 00:00:00 1970 +0000
94 date: Thu Jan 01 00:00:00 1970 +0000
95 summary: 4
95 summary: 4
96
96
97
97
98 check caching
98 check caching
99
99
100 $ hg co 0
100 $ hg co 0
101 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
101 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
102 $ hg debugsub
102 $ hg debugsub
103
103
104 restore
104 restore
105
105
106 $ hg co
106 $ hg co
107 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
107 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
108 $ hg debugsub
108 $ hg debugsub
109 path s
109 path s
110 source s
110 source s
111 revision 1c833a7a9e3a4445c711aaf0f012379cd0d4034e
111 revision 1c833a7a9e3a4445c711aaf0f012379cd0d4034e
112
112
113 new branch for merge tests
113 new branch for merge tests
114
114
115 $ hg co 1
115 $ hg co 1
116 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
116 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
117 $ echo t = t >> .hgsub
117 $ echo t = t >> .hgsub
118 $ hg init t
118 $ hg init t
119 $ echo t > t/t
119 $ echo t > t/t
120 $ hg -R t add t
120 $ hg -R t add t
121 adding t/t
121 adding t/t
122
122
123 5
123 5
124
124
125 $ hg ci -m5 # add sub
125 $ hg ci -m5 # add sub
126 committing subrepository t
126 committing subrepository t
127 created new head
127 created new head
128 $ echo t2 > t/t
128 $ echo t2 > t/t
129
129
130 6
130 6
131
131
132 $ hg st -R s
132 $ hg st -R s
133 $ hg ci -m6 # change sub
133 $ hg ci -m6 # change sub
134 committing subrepository t
134 committing subrepository t
135 $ hg debugsub
135 $ hg debugsub
136 path s
136 path s
137 source s
137 source s
138 revision e4ece1bf43360ddc8f6a96432201a37b7cd27ae4
138 revision e4ece1bf43360ddc8f6a96432201a37b7cd27ae4
139 path t
139 path t
140 source t
140 source t
141 revision 6747d179aa9a688023c4b0cad32e4c92bb7f34ad
141 revision 6747d179aa9a688023c4b0cad32e4c92bb7f34ad
142 $ echo t3 > t/t
142 $ echo t3 > t/t
143
143
144 7
144 7
145
145
146 $ hg ci -m7 # change sub again for conflict test
146 $ hg ci -m7 # change sub again for conflict test
147 committing subrepository t
147 committing subrepository t
148 $ hg rm .hgsub
148 $ hg rm .hgsub
149
149
150 8
150 8
151
151
152 $ hg ci -m8 # remove sub
152 $ hg ci -m8 # remove sub
153
153
154 merge tests
154 merge tests
155
155
156 $ hg co -C 3
156 $ hg co -C 3
157 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
157 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
158 $ hg merge 5 # test adding
158 $ hg merge 5 # test adding
159 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
159 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
160 (branch merge, don't forget to commit)
160 (branch merge, don't forget to commit)
161 $ hg debugsub
161 $ hg debugsub
162 path s
162 path s
163 source s
163 source s
164 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
164 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
165 path t
165 path t
166 source t
166 source t
167 revision 60ca1237c19474e7a3978b0dc1ca4e6f36d51382
167 revision 60ca1237c19474e7a3978b0dc1ca4e6f36d51382
168 $ hg ci -m9
168 $ hg ci -m9
169 created new head
169 created new head
170 $ hg merge 6 --debug # test change
170 $ hg merge 6 --debug # test change
171 searching for copies back to rev 2
171 searching for copies back to rev 2
172 resolving manifests
172 resolving manifests
173 overwrite None partial False
173 overwrite None partial False
174 ancestor 1f14a2e2d3ec local f0d2028bf86d+ remote 1831e14459c4
174 ancestor 1f14a2e2d3ec local f0d2028bf86d+ remote 1831e14459c4
175 .hgsubstate: versions differ -> m
175 .hgsubstate: versions differ -> m
176 updating: .hgsubstate 1/1 files (100.00%)
176 updating: .hgsubstate 1/1 files (100.00%)
177 subrepo merge f0d2028bf86d+ 1831e14459c4 1f14a2e2d3ec
177 subrepo merge f0d2028bf86d+ 1831e14459c4 1f14a2e2d3ec
178 subrepo t: other changed, get t:6747d179aa9a688023c4b0cad32e4c92bb7f34ad:hg
178 subrepo t: other changed, get t:6747d179aa9a688023c4b0cad32e4c92bb7f34ad:hg
179 getting subrepo t
179 getting subrepo t
180 resolving manifests
180 resolving manifests
181 overwrite True partial False
181 overwrite True partial False
182 ancestor 60ca1237c194+ local 60ca1237c194+ remote 6747d179aa9a
182 ancestor 60ca1237c194+ local 60ca1237c194+ remote 6747d179aa9a
183 t: remote is newer -> g
183 t: remote is newer -> g
184 updating: t 1/1 files (100.00%)
184 updating: t 1/1 files (100.00%)
185 getting t
185 getting t
186 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
186 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
187 (branch merge, don't forget to commit)
187 (branch merge, don't forget to commit)
188 $ hg debugsub
188 $ hg debugsub
189 path s
189 path s
190 source s
190 source s
191 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
191 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
192 path t
192 path t
193 source t
193 source t
194 revision 6747d179aa9a688023c4b0cad32e4c92bb7f34ad
194 revision 6747d179aa9a688023c4b0cad32e4c92bb7f34ad
195 $ echo conflict > t/t
195 $ echo conflict > t/t
196 $ hg ci -m10
196 $ hg ci -m10
197 committing subrepository t
197 committing subrepository t
198 $ HGMERGE=internal:merge hg merge --debug 7 # test conflict
198 $ HGMERGE=internal:merge hg merge --debug 7 # test conflict
199 searching for copies back to rev 2
199 searching for copies back to rev 2
200 resolving manifests
200 resolving manifests
201 overwrite None partial False
201 overwrite None partial False
202 ancestor 1831e14459c4 local e45c8b14af55+ remote f94576341bcf
202 ancestor 1831e14459c4 local e45c8b14af55+ remote f94576341bcf
203 .hgsubstate: versions differ -> m
203 .hgsubstate: versions differ -> m
204 updating: .hgsubstate 1/1 files (100.00%)
204 updating: .hgsubstate 1/1 files (100.00%)
205 subrepo merge e45c8b14af55+ f94576341bcf 1831e14459c4
205 subrepo merge e45c8b14af55+ f94576341bcf 1831e14459c4
206 subrepo t: both sides changed, merge with t:7af322bc1198a32402fe903e0b7ebcfc5c9bf8f4:hg
206 subrepo t: both sides changed, merge with t:7af322bc1198a32402fe903e0b7ebcfc5c9bf8f4:hg
207 merging subrepo t
207 merging subrepo t
208 searching for copies back to rev 2
208 searching for copies back to rev 2
209 resolving manifests
209 resolving manifests
210 overwrite None partial False
210 overwrite None partial False
211 ancestor 6747d179aa9a local 20a0db6fbf6c+ remote 7af322bc1198
211 ancestor 6747d179aa9a local 20a0db6fbf6c+ remote 7af322bc1198
212 t: versions differ -> m
212 t: versions differ -> m
213 preserving t for resolve of t
213 preserving t for resolve of t
214 updating: t 1/1 files (100.00%)
214 updating: t 1/1 files (100.00%)
215 picked tool 'internal:merge' for t (binary False symlink False)
215 picked tool 'internal:merge' for t (binary False symlink False)
216 merging t
216 merging t
217 my t@20a0db6fbf6c+ other t@7af322bc1198 ancestor t@6747d179aa9a
217 my t@20a0db6fbf6c+ other t@7af322bc1198 ancestor t@6747d179aa9a
218 warning: conflicts during merge.
218 warning: conflicts during merge.
219 merging t failed!
219 merging t failed!
220 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
220 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
221 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
221 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
222 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
222 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
223 (branch merge, don't forget to commit)
223 (branch merge, don't forget to commit)
224
224
225 should conflict
225 should conflict
226
226
227 $ cat t/t
227 $ cat t/t
228 <<<<<<< local
228 <<<<<<< local
229 conflict
229 conflict
230 =======
230 =======
231 t3
231 t3
232 >>>>>>> other
232 >>>>>>> other
233
233
234 clone
234 clone
235
235
236 $ cd ..
236 $ cd ..
237 $ hg clone t tc
237 $ hg clone t tc
238 updating to branch default
238 updating to branch default
239 pulling subrepo s from $TESTTMP/sub/t/s
239 pulling subrepo s from $TESTTMP/sub/t/s
240 requesting all changes
240 requesting all changes
241 adding changesets
241 adding changesets
242 adding manifests
242 adding manifests
243 adding file changes
243 adding file changes
244 added 4 changesets with 5 changes to 3 files
244 added 4 changesets with 5 changes to 3 files
245 pulling subrepo s/ss from $TESTTMP/sub/t/s/ss
245 pulling subrepo s/ss from $TESTTMP/sub/t/s/ss
246 requesting all changes
246 requesting all changes
247 adding changesets
247 adding changesets
248 adding manifests
248 adding manifests
249 adding file changes
249 adding file changes
250 added 1 changesets with 1 changes to 1 files
250 added 1 changesets with 1 changes to 1 files
251 pulling subrepo t from $TESTTMP/sub/t/t
251 pulling subrepo t from $TESTTMP/sub/t/t
252 requesting all changes
252 requesting all changes
253 adding changesets
253 adding changesets
254 adding manifests
254 adding manifests
255 adding file changes
255 adding file changes
256 added 4 changesets with 4 changes to 1 files (+1 heads)
256 added 4 changesets with 4 changes to 1 files (+1 heads)
257 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
257 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
258 $ cd tc
258 $ cd tc
259 $ hg debugsub
259 $ hg debugsub
260 path s
260 path s
261 source s
261 source s
262 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
262 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
263 path t
263 path t
264 source t
264 source t
265 revision 20a0db6fbf6c3d2836e6519a642ae929bfc67c0e
265 revision 20a0db6fbf6c3d2836e6519a642ae929bfc67c0e
266
266
267 push
267 push
268
268
269 $ echo bah > t/t
269 $ echo bah > t/t
270 $ hg ci -m11
270 $ hg ci -m11
271 committing subrepository t
271 committing subrepository t
272 $ hg push
272 $ hg push
273 pushing to $TESTTMP/sub/t
273 pushing to $TESTTMP/sub/t
274 pushing subrepo s/ss to $TESTTMP/sub/t/s/ss
274 pushing subrepo s/ss to $TESTTMP/sub/t/s/ss
275 searching for changes
275 searching for changes
276 no changes found
276 no changes found
277 pushing subrepo s to $TESTTMP/sub/t/s
277 pushing subrepo s to $TESTTMP/sub/t/s
278 searching for changes
278 searching for changes
279 no changes found
279 no changes found
280 pushing subrepo t to $TESTTMP/sub/t/t
280 pushing subrepo t to $TESTTMP/sub/t/t
281 searching for changes
281 searching for changes
282 adding changesets
282 adding changesets
283 adding manifests
283 adding manifests
284 adding file changes
284 adding file changes
285 added 1 changesets with 1 changes to 1 files
285 added 1 changesets with 1 changes to 1 files
286 searching for changes
286 searching for changes
287 adding changesets
287 adding changesets
288 adding manifests
288 adding manifests
289 adding file changes
289 adding file changes
290 added 1 changesets with 1 changes to 1 files
290 added 1 changesets with 1 changes to 1 files
291
291
292 push -f
292 push -f
293
293
294 $ echo bah > s/a
294 $ echo bah > s/a
295 $ hg ci -m12
295 $ hg ci -m12
296 committing subrepository s
296 committing subrepository s
297 $ hg push
297 $ hg push
298 pushing to $TESTTMP/sub/t
298 pushing to $TESTTMP/sub/t
299 pushing subrepo s/ss to $TESTTMP/sub/t/s/ss
299 pushing subrepo s/ss to $TESTTMP/sub/t/s/ss
300 searching for changes
300 searching for changes
301 no changes found
301 no changes found
302 pushing subrepo s to $TESTTMP/sub/t/s
302 pushing subrepo s to $TESTTMP/sub/t/s
303 searching for changes
303 searching for changes
304 abort: push creates new remote heads on branch 'default'!
304 abort: push creates new remote heads on branch 'default'!
305 (did you forget to merge? use push -f to force)
305 (did you forget to merge? use push -f to force)
306 [255]
306 [255]
307 $ hg push -f
307 $ hg push -f
308 pushing to $TESTTMP/sub/t
308 pushing to $TESTTMP/sub/t
309 pushing subrepo s/ss to $TESTTMP/sub/t/s/ss
309 pushing subrepo s/ss to $TESTTMP/sub/t/s/ss
310 searching for changes
310 searching for changes
311 no changes found
311 no changes found
312 pushing subrepo s to $TESTTMP/sub/t/s
312 pushing subrepo s to $TESTTMP/sub/t/s
313 searching for changes
313 searching for changes
314 adding changesets
314 adding changesets
315 adding manifests
315 adding manifests
316 adding file changes
316 adding file changes
317 added 1 changesets with 1 changes to 1 files (+1 heads)
317 added 1 changesets with 1 changes to 1 files (+1 heads)
318 pushing subrepo t to $TESTTMP/sub/t/t
318 pushing subrepo t to $TESTTMP/sub/t/t
319 searching for changes
319 searching for changes
320 no changes found
320 no changes found
321 searching for changes
321 searching for changes
322 adding changesets
322 adding changesets
323 adding manifests
323 adding manifests
324 adding file changes
324 adding file changes
325 added 1 changesets with 1 changes to 1 files
325 added 1 changesets with 1 changes to 1 files
326
326
327 update
327 update
328
328
329 $ cd ../t
329 $ cd ../t
330 $ hg up -C # discard our earlier merge
330 $ hg up -C # discard our earlier merge
331 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
331 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
332 $ echo blah > t/t
332 $ echo blah > t/t
333 $ hg ci -m13
333 $ hg ci -m13
334 committing subrepository t
334 committing subrepository t
335
335
336 pull
336 pull
337
337
338 $ cd ../tc
338 $ cd ../tc
339 $ hg pull
339 $ hg pull
340 pulling from $TESTTMP/sub/t
340 pulling from $TESTTMP/sub/t
341 searching for changes
341 searching for changes
342 adding changesets
342 adding changesets
343 adding manifests
343 adding manifests
344 adding file changes
344 adding file changes
345 added 1 changesets with 1 changes to 1 files
345 added 1 changesets with 1 changes to 1 files
346 (run 'hg update' to get a working copy)
346 (run 'hg update' to get a working copy)
347
347
348 should pull t
348 should pull t
349
349
350 $ hg up
350 $ hg up
351 pulling subrepo t from $TESTTMP/sub/t/t
351 pulling subrepo t from $TESTTMP/sub/t/t
352 searching for changes
352 searching for changes
353 adding changesets
353 adding changesets
354 adding manifests
354 adding manifests
355 adding file changes
355 adding file changes
356 added 1 changesets with 1 changes to 1 files
356 added 1 changesets with 1 changes to 1 files
357 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
357 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
358 $ cat t/t
358 $ cat t/t
359 blah
359 blah
360
360
361 bogus subrepo path aborts
361 bogus subrepo path aborts
362
362
363 $ echo 'bogus=[boguspath' >> .hgsub
363 $ echo 'bogus=[boguspath' >> .hgsub
364 $ hg ci -m 'bogus subrepo path'
364 $ hg ci -m 'bogus subrepo path'
365 abort: missing ] in subrepo source
365 abort: missing ] in subrepo source
366 [255]
366 [255]
367
367
368 Issue1986: merge aborts when trying to merge a subrepo that
368 Issue1986: merge aborts when trying to merge a subrepo that
369 shouldn't need merging
369 shouldn't need merging
370
370
371 # subrepo layout
371 # subrepo layout
372 #
372 #
373 # o 5 br
373 # o 5 br
374 # /|
374 # /|
375 # o | 4 default
375 # o | 4 default
376 # | |
376 # | |
377 # | o 3 br
377 # | o 3 br
378 # |/|
378 # |/|
379 # o | 2 default
379 # o | 2 default
380 # | |
380 # | |
381 # | o 1 br
381 # | o 1 br
382 # |/
382 # |/
383 # o 0 default
383 # o 0 default
384
384
385 $ cd ..
385 $ cd ..
386 $ rm -rf sub
386 $ rm -rf sub
387 $ hg init main
387 $ hg init main
388 $ cd main
388 $ cd main
389 $ hg init s
389 $ hg init s
390 $ cd s
390 $ cd s
391 $ echo a > a
391 $ echo a > a
392 $ hg ci -Am1
392 $ hg ci -Am1
393 adding a
393 adding a
394 $ hg branch br
394 $ hg branch br
395 marked working directory as branch br
395 marked working directory as branch br
396 $ echo a >> a
396 $ echo a >> a
397 $ hg ci -m1
397 $ hg ci -m1
398 $ hg up default
398 $ hg up default
399 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
399 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
400 $ echo b > b
400 $ echo b > b
401 $ hg ci -Am1
401 $ hg ci -Am1
402 adding b
402 adding b
403 $ hg up br
403 $ hg up br
404 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
404 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
405 $ hg merge tip
405 $ hg merge tip
406 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
406 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
407 (branch merge, don't forget to commit)
407 (branch merge, don't forget to commit)
408 $ hg ci -m1
408 $ hg ci -m1
409 $ hg up 2
409 $ hg up 2
410 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
410 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
411 $ echo c > c
411 $ echo c > c
412 $ hg ci -Am1
412 $ hg ci -Am1
413 adding c
413 adding c
414 $ hg up 3
414 $ hg up 3
415 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
415 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
416 $ hg merge 4
416 $ hg merge 4
417 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
417 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
418 (branch merge, don't forget to commit)
418 (branch merge, don't forget to commit)
419 $ hg ci -m1
419 $ hg ci -m1
420
420
421 # main repo layout:
421 # main repo layout:
422 #
422 #
423 # * <-- try to merge default into br again
423 # * <-- try to merge default into br again
424 # .`|
424 # .`|
425 # . o 5 br --> substate = 5
425 # . o 5 br --> substate = 5
426 # . |
426 # . |
427 # o | 4 default --> substate = 4
427 # o | 4 default --> substate = 4
428 # | |
428 # | |
429 # | o 3 br --> substate = 2
429 # | o 3 br --> substate = 2
430 # |/|
430 # |/|
431 # o | 2 default --> substate = 2
431 # o | 2 default --> substate = 2
432 # | |
432 # | |
433 # | o 1 br --> substate = 3
433 # | o 1 br --> substate = 3
434 # |/
434 # |/
435 # o 0 default --> substate = 2
435 # o 0 default --> substate = 2
436
436
437 $ cd ..
437 $ cd ..
438 $ echo 's = s' > .hgsub
438 $ echo 's = s' > .hgsub
439 $ hg -R s up 2
439 $ hg -R s up 2
440 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
440 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
441 $ hg ci -Am1
441 $ hg ci -Am1
442 adding .hgsub
442 adding .hgsub
443 committing subrepository s
443 committing subrepository s
444 $ hg branch br
444 $ hg branch br
445 marked working directory as branch br
445 marked working directory as branch br
446 $ echo b > b
446 $ echo b > b
447 $ hg -R s up 3
447 $ hg -R s up 3
448 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
448 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
449 $ hg ci -Am1
449 $ hg ci -Am1
450 adding b
450 adding b
451 committing subrepository s
451 committing subrepository s
452 $ hg up default
452 $ hg up default
453 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
453 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
454 $ echo c > c
454 $ echo c > c
455 $ hg ci -Am1
455 $ hg ci -Am1
456 adding c
456 adding c
457 $ hg up 1
457 $ hg up 1
458 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
458 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
459 $ hg merge 2
459 $ hg merge 2
460 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
460 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
461 (branch merge, don't forget to commit)
461 (branch merge, don't forget to commit)
462 $ hg ci -m1
462 $ hg ci -m1
463 $ hg up 2
463 $ hg up 2
464 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
464 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
465 $ hg -R s up 4
465 $ hg -R s up 4
466 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
466 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
467 $ echo d > d
467 $ echo d > d
468 $ hg ci -Am1
468 $ hg ci -Am1
469 adding d
469 adding d
470 committing subrepository s
470 committing subrepository s
471 $ hg up 3
471 $ hg up 3
472 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
472 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
473 $ hg -R s up 5
473 $ hg -R s up 5
474 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
474 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
475 $ echo e > e
475 $ echo e > e
476 $ hg ci -Am1
476 $ hg ci -Am1
477 adding e
477 adding e
478 committing subrepository s
478 committing subrepository s
479
479
480 $ hg up 5
480 $ hg up 5
481 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
481 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
482 $ hg merge 4 # try to merge default into br again
482 $ hg merge 4 # try to merge default into br again
483 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
483 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
484 (branch merge, don't forget to commit)
484 (branch merge, don't forget to commit)
485 $ cd ..
485 $ cd ..
486
486
487 test subrepo delete from .hgsubstate
487 test subrepo delete from .hgsubstate
488
488
489 $ hg init testdelete
489 $ hg init testdelete
490 $ mkdir testdelete/nested testdelete/nested2
490 $ mkdir testdelete/nested testdelete/nested2
491 $ hg init testdelete/nested
491 $ hg init testdelete/nested
492 $ hg init testdelete/nested2
492 $ hg init testdelete/nested2
493 $ echo test > testdelete/nested/foo
493 $ echo test > testdelete/nested/foo
494 $ echo test > testdelete/nested2/foo
494 $ echo test > testdelete/nested2/foo
495 $ hg -R testdelete/nested add
495 $ hg -R testdelete/nested add
496 adding testdelete/nested/foo
496 adding testdelete/nested/foo
497 $ hg -R testdelete/nested2 add
497 $ hg -R testdelete/nested2 add
498 adding testdelete/nested2/foo
498 adding testdelete/nested2/foo
499 $ hg -R testdelete/nested ci -m test
499 $ hg -R testdelete/nested ci -m test
500 $ hg -R testdelete/nested2 ci -m test
500 $ hg -R testdelete/nested2 ci -m test
501 $ echo nested = nested > testdelete/.hgsub
501 $ echo nested = nested > testdelete/.hgsub
502 $ echo nested2 = nested2 >> testdelete/.hgsub
502 $ echo nested2 = nested2 >> testdelete/.hgsub
503 $ hg -R testdelete add
503 $ hg -R testdelete add
504 adding testdelete/.hgsub
504 adding testdelete/.hgsub
505 $ hg -R testdelete ci -m "nested 1 & 2 added"
505 $ hg -R testdelete ci -m "nested 1 & 2 added"
506 committing subrepository nested
506 committing subrepository nested
507 committing subrepository nested2
507 committing subrepository nested2
508 $ echo nested = nested > testdelete/.hgsub
508 $ echo nested = nested > testdelete/.hgsub
509 $ hg -R testdelete ci -m "nested 2 deleted"
509 $ hg -R testdelete ci -m "nested 2 deleted"
510 $ cat testdelete/.hgsubstate
510 $ cat testdelete/.hgsubstate
511 bdf5c9a3103743d900b12ae0db3ffdcfd7b0d878 nested
511 bdf5c9a3103743d900b12ae0db3ffdcfd7b0d878 nested
512 $ hg -R testdelete remove testdelete/.hgsub
512 $ hg -R testdelete remove testdelete/.hgsub
513 $ hg -R testdelete ci -m ".hgsub deleted"
513 $ hg -R testdelete ci -m ".hgsub deleted"
514 $ cat testdelete/.hgsubstate
514 $ cat testdelete/.hgsubstate
515
515
516 test repository cloning
516 test repository cloning
517
517
518 $ mkdir mercurial mercurial2
518 $ mkdir mercurial mercurial2
519 $ hg init nested_absolute
519 $ hg init nested_absolute
520 $ echo test > nested_absolute/foo
520 $ echo test > nested_absolute/foo
521 $ hg -R nested_absolute add
521 $ hg -R nested_absolute add
522 adding nested_absolute/foo
522 adding nested_absolute/foo
523 $ hg -R nested_absolute ci -mtest
523 $ hg -R nested_absolute ci -mtest
524 $ cd mercurial
524 $ cd mercurial
525 $ hg init nested_relative
525 $ hg init nested_relative
526 $ echo test2 > nested_relative/foo2
526 $ echo test2 > nested_relative/foo2
527 $ hg -R nested_relative add
527 $ hg -R nested_relative add
528 adding nested_relative/foo2
528 adding nested_relative/foo2
529 $ hg -R nested_relative ci -mtest2
529 $ hg -R nested_relative ci -mtest2
530 $ hg init main
530 $ hg init main
531 $ echo "nested_relative = ../nested_relative" > main/.hgsub
531 $ echo "nested_relative = ../nested_relative" > main/.hgsub
532 $ echo "nested_absolute = `pwd`/nested_absolute" >> main/.hgsub
532 $ echo "nested_absolute = `pwd`/nested_absolute" >> main/.hgsub
533 $ hg -R main add
533 $ hg -R main add
534 adding main/.hgsub
534 adding main/.hgsub
535 $ hg -R main ci -m "add subrepos"
535 $ hg -R main ci -m "add subrepos"
536 committing subrepository nested_absolute
536 committing subrepository nested_absolute
537 committing subrepository nested_relative
537 committing subrepository nested_relative
538 $ cd ..
538 $ cd ..
539 $ hg clone mercurial/main mercurial2/main
539 $ hg clone mercurial/main mercurial2/main
540 updating to branch default
540 updating to branch default
541 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
541 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
542 $ cat mercurial2/main/nested_absolute/.hg/hgrc \
542 $ cat mercurial2/main/nested_absolute/.hg/hgrc \
543 > mercurial2/main/nested_relative/.hg/hgrc
543 > mercurial2/main/nested_relative/.hg/hgrc
544 [paths]
544 [paths]
545 default = $TESTTMP/sub/mercurial/nested_absolute
545 default = $TESTTMP/sub/mercurial/nested_absolute
546 [paths]
546 [paths]
547 default = $TESTTMP/sub/mercurial/nested_relative
547 default = $TESTTMP/sub/mercurial/nested_relative
548 $ rm -rf mercurial mercurial2
548 $ rm -rf mercurial mercurial2
549
549
550 Issue1977: multirepo push should fail if subrepo push fails
550 Issue1977: multirepo push should fail if subrepo push fails
551
551
552 $ hg init repo
552 $ hg init repo
553 $ hg init repo/s
553 $ hg init repo/s
554 $ echo a > repo/s/a
554 $ echo a > repo/s/a
555 $ hg -R repo/s ci -Am0
555 $ hg -R repo/s ci -Am0
556 adding a
556 adding a
557 $ echo s = s > repo/.hgsub
557 $ echo s = s > repo/.hgsub
558 $ hg -R repo ci -Am1
558 $ hg -R repo ci -Am1
559 adding .hgsub
559 adding .hgsub
560 committing subrepository s
560 committing subrepository s
561 $ hg clone repo repo2
561 $ hg clone repo repo2
562 updating to branch default
562 updating to branch default
563 pulling subrepo s from $TESTTMP/sub/repo/s
563 pulling subrepo s from $TESTTMP/sub/repo/s
564 requesting all changes
564 requesting all changes
565 adding changesets
565 adding changesets
566 adding manifests
566 adding manifests
567 adding file changes
567 adding file changes
568 added 1 changesets with 1 changes to 1 files
568 added 1 changesets with 1 changes to 1 files
569 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
569 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
570 $ hg -q -R repo2 pull -u
570 $ hg -q -R repo2 pull -u
571 $ echo 1 > repo2/s/a
571 $ echo 1 > repo2/s/a
572 $ hg -R repo2/s ci -m2
572 $ hg -R repo2/s ci -m2
573 $ hg -q -R repo2/s push
573 $ hg -q -R repo2/s push
574 $ hg -R repo2/s up -C 0
574 $ hg -R repo2/s up -C 0
575 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
575 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
576 $ echo 2 > repo2/s/a
576 $ echo 2 > repo2/s/a
577 $ hg -R repo2/s ci -m3
577 $ hg -R repo2/s ci -m3
578 created new head
578 created new head
579 $ hg -R repo2 ci -m3
579 $ hg -R repo2 ci -m3
580 committing subrepository s
580 committing subrepository s
581 $ hg -q -R repo2 push
581 $ hg -q -R repo2 push
582 abort: push creates new remote heads on branch 'default'!
582 abort: push creates new remote heads on branch 'default'!
583 (did you forget to merge? use push -f to force)
583 (did you forget to merge? use push -f to force)
584 [255]
584 [255]
585 $ hg -R repo update
585 $ hg -R repo update
586 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
586 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
587 $ rm -rf repo2 repo
587 $ rm -rf repo2 repo
588
588
589
589
590 Issue1852 subrepos with relative paths always push/pull relative to default
590 Issue1852 subrepos with relative paths always push/pull relative to default
591
591
592 Prepare a repo with subrepo
592 Prepare a repo with subrepo
593
593
594 $ hg init issue1852a
594 $ hg init issue1852a
595 $ cd issue1852a
595 $ cd issue1852a
596 $ hg init sub/repo
596 $ hg init sub/repo
597 $ echo test > sub/repo/foo
597 $ echo test > sub/repo/foo
598 $ hg -R sub/repo add sub/repo/foo
598 $ hg -R sub/repo add sub/repo/foo
599 $ echo sub/repo = sub/repo > .hgsub
599 $ echo sub/repo = sub/repo > .hgsub
600 $ hg add .hgsub
600 $ hg add .hgsub
601 $ hg ci -mtest
601 $ hg ci -mtest
602 committing subrepository sub/repo
602 committing subrepository sub/repo
603 $ echo test >> sub/repo/foo
603 $ echo test >> sub/repo/foo
604 $ hg ci -mtest
604 $ hg ci -mtest
605 committing subrepository sub/repo
605 committing subrepository sub/repo
606 $ cd ..
606 $ cd ..
607
607
608 Create repo without default path, pull top repo, and see what happens on update
608 Create repo without default path, pull top repo, and see what happens on update
609
609
610 $ hg init issue1852b
610 $ hg init issue1852b
611 $ hg -R issue1852b pull issue1852a
611 $ hg -R issue1852b pull issue1852a
612 pulling from issue1852a
612 pulling from issue1852a
613 requesting all changes
613 requesting all changes
614 adding changesets
614 adding changesets
615 adding manifests
615 adding manifests
616 adding file changes
616 adding file changes
617 added 2 changesets with 3 changes to 2 files
617 added 2 changesets with 3 changes to 2 files
618 (run 'hg update' to get a working copy)
618 (run 'hg update' to get a working copy)
619 $ hg -R issue1852b update
619 $ hg -R issue1852b update
620 abort: default path for subrepository sub/repo not found
620 abort: default path for subrepository sub/repo not found
621 [255]
621 [255]
622
622
623 Pull -u now doesn't help
623 Pull -u now doesn't help
624
624
625 $ hg -R issue1852b pull -u issue1852a
625 $ hg -R issue1852b pull -u issue1852a
626 pulling from issue1852a
626 pulling from issue1852a
627 searching for changes
627 searching for changes
628 no changes found
628 no changes found
629
629
630 Try the same, but with pull -u
630 Try the same, but with pull -u
631
631
632 $ hg init issue1852c
632 $ hg init issue1852c
633 $ hg -R issue1852c pull -r0 -u issue1852a
633 $ hg -R issue1852c pull -r0 -u issue1852a
634 pulling from issue1852a
634 pulling from issue1852a
635 adding changesets
635 adding changesets
636 adding manifests
636 adding manifests
637 adding file changes
637 adding file changes
638 added 1 changesets with 2 changes to 2 files
638 added 1 changesets with 2 changes to 2 files
639 pulling subrepo sub/repo from issue1852a/sub/repo
639 pulling subrepo sub/repo from issue1852a/sub/repo
640 requesting all changes
640 requesting all changes
641 adding changesets
641 adding changesets
642 adding manifests
642 adding manifests
643 adding file changes
643 adding file changes
644 added 2 changesets with 2 changes to 1 files
644 added 2 changesets with 2 changes to 1 files
645 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
645 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
646
646
647 Try to push from the other side
647 Try to push from the other side
648
648
649 $ hg -R issue1852a push `pwd`/issue1852c
649 $ hg -R issue1852a push `pwd`/issue1852c
650 pushing to $TESTTMP/sub/issue1852c
650 pushing to $TESTTMP/sub/issue1852c
651 pushing subrepo sub/repo to $TESTTMP/sub/issue1852c/sub/repo
651 pushing subrepo sub/repo to $TESTTMP/sub/issue1852c/sub/repo
652 searching for changes
652 searching for changes
653 no changes found
653 no changes found
654 searching for changes
654 searching for changes
655 adding changesets
655 adding changesets
656 adding manifests
656 adding manifests
657 adding file changes
657 adding file changes
658 added 1 changesets with 1 changes to 1 files
658 added 1 changesets with 1 changes to 1 files
659
660 Check status of files when none of them belong to the first
661 subrepository:
662
663 $ hg init subrepo-status
664 $ cd subrepo-status
665 $ hg init subrepo-1
666 $ hg init subrepo-2
667 $ cd subrepo-2
668 $ touch file
669 $ hg add file
670 $ cd ..
671 $ echo subrepo-1 = subrepo-1 > .hgsub
672 $ echo subrepo-2 = subrepo-2 >> .hgsub
673 $ hg add .hgsub
674 $ hg ci -m 'Added subrepos'
675 committing subrepository subrepo-1
676 committing subrepository subrepo-2
677 $ hg st subrepo-2/file
General Comments 0
You need to be logged in to leave comments. Login now