##// END OF EJS Templates
patch.diffopts: add support for noprefix...
Siddharth Agarwal -
r23297:d7abae94 default
parent child Browse files
Show More
@@ -1,1720 +1,1723 b''
1 The Mercurial system uses a set of configuration files to control
1 The Mercurial system uses a set of configuration files to control
2 aspects of its behavior.
2 aspects of its behavior.
3
3
4 The configuration files use a simple ini-file format. A configuration
4 The configuration files use a simple ini-file format. A configuration
5 file consists of sections, led by a ``[section]`` header and followed
5 file consists of sections, led by a ``[section]`` header and followed
6 by ``name = value`` entries::
6 by ``name = value`` entries::
7
7
8 [ui]
8 [ui]
9 username = Firstname Lastname <firstname.lastname@example.net>
9 username = Firstname Lastname <firstname.lastname@example.net>
10 verbose = True
10 verbose = True
11
11
12 The above entries will be referred to as ``ui.username`` and
12 The above entries will be referred to as ``ui.username`` and
13 ``ui.verbose``, respectively. See the Syntax section below.
13 ``ui.verbose``, respectively. See the Syntax section below.
14
14
15 Files
15 Files
16 =====
16 =====
17
17
18 Mercurial reads configuration data from several files, if they exist.
18 Mercurial reads configuration data from several files, if they exist.
19 These files do not exist by default and you will have to create the
19 These files do not exist by default and you will have to create the
20 appropriate configuration files yourself: global configuration like
20 appropriate configuration files yourself: global configuration like
21 the username setting is typically put into
21 the username setting is typically put into
22 ``%USERPROFILE%\mercurial.ini`` or ``$HOME/.hgrc`` and local
22 ``%USERPROFILE%\mercurial.ini`` or ``$HOME/.hgrc`` and local
23 configuration is put into the per-repository ``<repo>/.hg/hgrc`` file.
23 configuration is put into the per-repository ``<repo>/.hg/hgrc`` file.
24
24
25 The names of these files depend on the system on which Mercurial is
25 The names of these files depend on the system on which Mercurial is
26 installed. ``*.rc`` files from a single directory are read in
26 installed. ``*.rc`` files from a single directory are read in
27 alphabetical order, later ones overriding earlier ones. Where multiple
27 alphabetical order, later ones overriding earlier ones. Where multiple
28 paths are given below, settings from earlier paths override later
28 paths are given below, settings from earlier paths override later
29 ones.
29 ones.
30
30
31 .. container:: verbose.unix
31 .. container:: verbose.unix
32
32
33 On Unix, the following files are consulted:
33 On Unix, the following files are consulted:
34
34
35 - ``<repo>/.hg/hgrc`` (per-repository)
35 - ``<repo>/.hg/hgrc`` (per-repository)
36 - ``$HOME/.hgrc`` (per-user)
36 - ``$HOME/.hgrc`` (per-user)
37 - ``<install-root>/etc/mercurial/hgrc`` (per-installation)
37 - ``<install-root>/etc/mercurial/hgrc`` (per-installation)
38 - ``<install-root>/etc/mercurial/hgrc.d/*.rc`` (per-installation)
38 - ``<install-root>/etc/mercurial/hgrc.d/*.rc`` (per-installation)
39 - ``/etc/mercurial/hgrc`` (per-system)
39 - ``/etc/mercurial/hgrc`` (per-system)
40 - ``/etc/mercurial/hgrc.d/*.rc`` (per-system)
40 - ``/etc/mercurial/hgrc.d/*.rc`` (per-system)
41 - ``<internal>/default.d/*.rc`` (defaults)
41 - ``<internal>/default.d/*.rc`` (defaults)
42
42
43 .. container:: verbose.windows
43 .. container:: verbose.windows
44
44
45 On Windows, the following files are consulted:
45 On Windows, the following files are consulted:
46
46
47 - ``<repo>/.hg/hgrc`` (per-repository)
47 - ``<repo>/.hg/hgrc`` (per-repository)
48 - ``%USERPROFILE%\.hgrc`` (per-user)
48 - ``%USERPROFILE%\.hgrc`` (per-user)
49 - ``%USERPROFILE%\Mercurial.ini`` (per-user)
49 - ``%USERPROFILE%\Mercurial.ini`` (per-user)
50 - ``%HOME%\.hgrc`` (per-user)
50 - ``%HOME%\.hgrc`` (per-user)
51 - ``%HOME%\Mercurial.ini`` (per-user)
51 - ``%HOME%\Mercurial.ini`` (per-user)
52 - ``<install-dir>\Mercurial.ini`` (per-installation)
52 - ``<install-dir>\Mercurial.ini`` (per-installation)
53 - ``<install-dir>\hgrc.d\*.rc`` (per-installation)
53 - ``<install-dir>\hgrc.d\*.rc`` (per-installation)
54 - ``HKEY_LOCAL_MACHINE\SOFTWARE\Mercurial`` (per-installation)
54 - ``HKEY_LOCAL_MACHINE\SOFTWARE\Mercurial`` (per-installation)
55 - ``<internal>/default.d/*.rc`` (defaults)
55 - ``<internal>/default.d/*.rc`` (defaults)
56
56
57 .. note::
57 .. note::
58
58
59 The registry key ``HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Mercurial``
59 The registry key ``HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Mercurial``
60 is used when running 32-bit Python on 64-bit Windows.
60 is used when running 32-bit Python on 64-bit Windows.
61
61
62 .. container:: verbose.plan9
62 .. container:: verbose.plan9
63
63
64 On Plan9, the following files are consulted:
64 On Plan9, the following files are consulted:
65
65
66 - ``<repo>/.hg/hgrc`` (per-repository)
66 - ``<repo>/.hg/hgrc`` (per-repository)
67 - ``$home/lib/hgrc`` (per-user)
67 - ``$home/lib/hgrc`` (per-user)
68 - ``<install-root>/lib/mercurial/hgrc`` (per-installation)
68 - ``<install-root>/lib/mercurial/hgrc`` (per-installation)
69 - ``<install-root>/lib/mercurial/hgrc.d/*.rc`` (per-installation)
69 - ``<install-root>/lib/mercurial/hgrc.d/*.rc`` (per-installation)
70 - ``/lib/mercurial/hgrc`` (per-system)
70 - ``/lib/mercurial/hgrc`` (per-system)
71 - ``/lib/mercurial/hgrc.d/*.rc`` (per-system)
71 - ``/lib/mercurial/hgrc.d/*.rc`` (per-system)
72 - ``<internal>/default.d/*.rc`` (defaults)
72 - ``<internal>/default.d/*.rc`` (defaults)
73
73
74 Per-repository configuration options only apply in a
74 Per-repository configuration options only apply in a
75 particular repository. This file is not version-controlled, and
75 particular repository. This file is not version-controlled, and
76 will not get transferred during a "clone" operation. Options in
76 will not get transferred during a "clone" operation. Options in
77 this file override options in all other configuration files. On
77 this file override options in all other configuration files. On
78 Plan 9 and Unix, most of this file will be ignored if it doesn't
78 Plan 9 and Unix, most of this file will be ignored if it doesn't
79 belong to a trusted user or to a trusted group. See the documentation
79 belong to a trusted user or to a trusted group. See the documentation
80 for the ``[trusted]`` section below for more details.
80 for the ``[trusted]`` section below for more details.
81
81
82 Per-user configuration file(s) are for the user running Mercurial. On
82 Per-user configuration file(s) are for the user running Mercurial. On
83 Windows 9x, ``%HOME%`` is replaced by ``%APPDATA%``. Options in these
83 Windows 9x, ``%HOME%`` is replaced by ``%APPDATA%``. Options in these
84 files apply to all Mercurial commands executed by this user in any
84 files apply to all Mercurial commands executed by this user in any
85 directory. Options in these files override per-system and per-installation
85 directory. Options in these files override per-system and per-installation
86 options.
86 options.
87
87
88 Per-installation configuration files are searched for in the
88 Per-installation configuration files are searched for in the
89 directory where Mercurial is installed. ``<install-root>`` is the
89 directory where Mercurial is installed. ``<install-root>`` is the
90 parent directory of the **hg** executable (or symlink) being run. For
90 parent directory of the **hg** executable (or symlink) being run. For
91 example, if installed in ``/shared/tools/bin/hg``, Mercurial will look
91 example, if installed in ``/shared/tools/bin/hg``, Mercurial will look
92 in ``/shared/tools/etc/mercurial/hgrc``. Options in these files apply
92 in ``/shared/tools/etc/mercurial/hgrc``. Options in these files apply
93 to all Mercurial commands executed by any user in any directory.
93 to all Mercurial commands executed by any user in any directory.
94
94
95 Per-installation configuration files are for the system on
95 Per-installation configuration files are for the system on
96 which Mercurial is running. Options in these files apply to all
96 which Mercurial is running. Options in these files apply to all
97 Mercurial commands executed by any user in any directory. Registry
97 Mercurial commands executed by any user in any directory. Registry
98 keys contain PATH-like strings, every part of which must reference
98 keys contain PATH-like strings, every part of which must reference
99 a ``Mercurial.ini`` file or be a directory where ``*.rc`` files will
99 a ``Mercurial.ini`` file or be a directory where ``*.rc`` files will
100 be read. Mercurial checks each of these locations in the specified
100 be read. Mercurial checks each of these locations in the specified
101 order until one or more configuration files are detected.
101 order until one or more configuration files are detected.
102
102
103 Per-system configuration files are for the system on which Mercurial
103 Per-system configuration files are for the system on which Mercurial
104 is running. Options in these files apply to all Mercurial commands
104 is running. Options in these files apply to all Mercurial commands
105 executed by any user in any directory. Options in these files
105 executed by any user in any directory. Options in these files
106 override per-installation options.
106 override per-installation options.
107
107
108 Mercurial comes with some default configuration. The default configuration
108 Mercurial comes with some default configuration. The default configuration
109 files are installed with Mercurial and will be overwritten on upgrades. Default
109 files are installed with Mercurial and will be overwritten on upgrades. Default
110 configuration files should never be edited by users or administrators but can
110 configuration files should never be edited by users or administrators but can
111 be overridden in other configuration files. So far the directory only contains
111 be overridden in other configuration files. So far the directory only contains
112 merge tool configuration but packagers can also put other default configuration
112 merge tool configuration but packagers can also put other default configuration
113 there.
113 there.
114
114
115 Syntax
115 Syntax
116 ======
116 ======
117
117
118 A configuration file consists of sections, led by a ``[section]`` header
118 A configuration file consists of sections, led by a ``[section]`` header
119 and followed by ``name = value`` entries (sometimes called
119 and followed by ``name = value`` entries (sometimes called
120 ``configuration keys``)::
120 ``configuration keys``)::
121
121
122 [spam]
122 [spam]
123 eggs=ham
123 eggs=ham
124 green=
124 green=
125 eggs
125 eggs
126
126
127 Each line contains one entry. If the lines that follow are indented,
127 Each line contains one entry. If the lines that follow are indented,
128 they are treated as continuations of that entry. Leading whitespace is
128 they are treated as continuations of that entry. Leading whitespace is
129 removed from values. Empty lines are skipped. Lines beginning with
129 removed from values. Empty lines are skipped. Lines beginning with
130 ``#`` or ``;`` are ignored and may be used to provide comments.
130 ``#`` or ``;`` are ignored and may be used to provide comments.
131
131
132 Configuration keys can be set multiple times, in which case Mercurial
132 Configuration keys can be set multiple times, in which case Mercurial
133 will use the value that was configured last. As an example::
133 will use the value that was configured last. As an example::
134
134
135 [spam]
135 [spam]
136 eggs=large
136 eggs=large
137 ham=serrano
137 ham=serrano
138 eggs=small
138 eggs=small
139
139
140 This would set the configuration key named ``eggs`` to ``small``.
140 This would set the configuration key named ``eggs`` to ``small``.
141
141
142 It is also possible to define a section multiple times. A section can
142 It is also possible to define a section multiple times. A section can
143 be redefined on the same and/or on different configuration files. For
143 be redefined on the same and/or on different configuration files. For
144 example::
144 example::
145
145
146 [foo]
146 [foo]
147 eggs=large
147 eggs=large
148 ham=serrano
148 ham=serrano
149 eggs=small
149 eggs=small
150
150
151 [bar]
151 [bar]
152 eggs=ham
152 eggs=ham
153 green=
153 green=
154 eggs
154 eggs
155
155
156 [foo]
156 [foo]
157 ham=prosciutto
157 ham=prosciutto
158 eggs=medium
158 eggs=medium
159 bread=toasted
159 bread=toasted
160
160
161 This would set the ``eggs``, ``ham``, and ``bread`` configuration keys
161 This would set the ``eggs``, ``ham``, and ``bread`` configuration keys
162 of the ``foo`` section to ``medium``, ``prosciutto``, and ``toasted``,
162 of the ``foo`` section to ``medium``, ``prosciutto``, and ``toasted``,
163 respectively. As you can see there only thing that matters is the last
163 respectively. As you can see there only thing that matters is the last
164 value that was set for each of the configuration keys.
164 value that was set for each of the configuration keys.
165
165
166 If a configuration key is set multiple times in different
166 If a configuration key is set multiple times in different
167 configuration files the final value will depend on the order in which
167 configuration files the final value will depend on the order in which
168 the different configuration files are read, with settings from earlier
168 the different configuration files are read, with settings from earlier
169 paths overriding later ones as described on the ``Files`` section
169 paths overriding later ones as described on the ``Files`` section
170 above.
170 above.
171
171
172 A line of the form ``%include file`` will include ``file`` into the
172 A line of the form ``%include file`` will include ``file`` into the
173 current configuration file. The inclusion is recursive, which means
173 current configuration file. The inclusion is recursive, which means
174 that included files can include other files. Filenames are relative to
174 that included files can include other files. Filenames are relative to
175 the configuration file in which the ``%include`` directive is found.
175 the configuration file in which the ``%include`` directive is found.
176 Environment variables and ``~user`` constructs are expanded in
176 Environment variables and ``~user`` constructs are expanded in
177 ``file``. This lets you do something like::
177 ``file``. This lets you do something like::
178
178
179 %include ~/.hgrc.d/$HOST.rc
179 %include ~/.hgrc.d/$HOST.rc
180
180
181 to include a different configuration file on each computer you use.
181 to include a different configuration file on each computer you use.
182
182
183 A line with ``%unset name`` will remove ``name`` from the current
183 A line with ``%unset name`` will remove ``name`` from the current
184 section, if it has been set previously.
184 section, if it has been set previously.
185
185
186 The values are either free-form text strings, lists of text strings,
186 The values are either free-form text strings, lists of text strings,
187 or Boolean values. Boolean values can be set to true using any of "1",
187 or Boolean values. Boolean values can be set to true using any of "1",
188 "yes", "true", or "on" and to false using "0", "no", "false", or "off"
188 "yes", "true", or "on" and to false using "0", "no", "false", or "off"
189 (all case insensitive).
189 (all case insensitive).
190
190
191 List values are separated by whitespace or comma, except when values are
191 List values are separated by whitespace or comma, except when values are
192 placed in double quotation marks::
192 placed in double quotation marks::
193
193
194 allow_read = "John Doe, PhD", brian, betty
194 allow_read = "John Doe, PhD", brian, betty
195
195
196 Quotation marks can be escaped by prefixing them with a backslash. Only
196 Quotation marks can be escaped by prefixing them with a backslash. Only
197 quotation marks at the beginning of a word is counted as a quotation
197 quotation marks at the beginning of a word is counted as a quotation
198 (e.g., ``foo"bar baz`` is the list of ``foo"bar`` and ``baz``).
198 (e.g., ``foo"bar baz`` is the list of ``foo"bar`` and ``baz``).
199
199
200 Sections
200 Sections
201 ========
201 ========
202
202
203 This section describes the different sections that may appear in a
203 This section describes the different sections that may appear in a
204 Mercurial configuration file, the purpose of each section, its possible
204 Mercurial configuration file, the purpose of each section, its possible
205 keys, and their possible values.
205 keys, and their possible values.
206
206
207 ``alias``
207 ``alias``
208 ---------
208 ---------
209
209
210 Defines command aliases.
210 Defines command aliases.
211 Aliases allow you to define your own commands in terms of other
211 Aliases allow you to define your own commands in terms of other
212 commands (or aliases), optionally including arguments. Positional
212 commands (or aliases), optionally including arguments. Positional
213 arguments in the form of ``$1``, ``$2``, etc in the alias definition
213 arguments in the form of ``$1``, ``$2``, etc in the alias definition
214 are expanded by Mercurial before execution. Positional arguments not
214 are expanded by Mercurial before execution. Positional arguments not
215 already used by ``$N`` in the definition are put at the end of the
215 already used by ``$N`` in the definition are put at the end of the
216 command to be executed.
216 command to be executed.
217
217
218 Alias definitions consist of lines of the form::
218 Alias definitions consist of lines of the form::
219
219
220 <alias> = <command> [<argument>]...
220 <alias> = <command> [<argument>]...
221
221
222 For example, this definition::
222 For example, this definition::
223
223
224 latest = log --limit 5
224 latest = log --limit 5
225
225
226 creates a new command ``latest`` that shows only the five most recent
226 creates a new command ``latest`` that shows only the five most recent
227 changesets. You can define subsequent aliases using earlier ones::
227 changesets. You can define subsequent aliases using earlier ones::
228
228
229 stable5 = latest -b stable
229 stable5 = latest -b stable
230
230
231 .. note::
231 .. note::
232
232
233 It is possible to create aliases with the same names as
233 It is possible to create aliases with the same names as
234 existing commands, which will then override the original
234 existing commands, which will then override the original
235 definitions. This is almost always a bad idea!
235 definitions. This is almost always a bad idea!
236
236
237 An alias can start with an exclamation point (``!``) to make it a
237 An alias can start with an exclamation point (``!``) to make it a
238 shell alias. A shell alias is executed with the shell and will let you
238 shell alias. A shell alias is executed with the shell and will let you
239 run arbitrary commands. As an example, ::
239 run arbitrary commands. As an example, ::
240
240
241 echo = !echo $@
241 echo = !echo $@
242
242
243 will let you do ``hg echo foo`` to have ``foo`` printed in your
243 will let you do ``hg echo foo`` to have ``foo`` printed in your
244 terminal. A better example might be::
244 terminal. A better example might be::
245
245
246 purge = !$HG status --no-status --unknown -0 | xargs -0 rm
246 purge = !$HG status --no-status --unknown -0 | xargs -0 rm
247
247
248 which will make ``hg purge`` delete all unknown files in the
248 which will make ``hg purge`` delete all unknown files in the
249 repository in the same manner as the purge extension.
249 repository in the same manner as the purge extension.
250
250
251 Positional arguments like ``$1``, ``$2``, etc. in the alias definition
251 Positional arguments like ``$1``, ``$2``, etc. in the alias definition
252 expand to the command arguments. Unmatched arguments are
252 expand to the command arguments. Unmatched arguments are
253 removed. ``$0`` expands to the alias name and ``$@`` expands to all
253 removed. ``$0`` expands to the alias name and ``$@`` expands to all
254 arguments separated by a space. ``"$@"`` (with quotes) expands to all
254 arguments separated by a space. ``"$@"`` (with quotes) expands to all
255 arguments quoted individually and separated by a space. These expansions
255 arguments quoted individually and separated by a space. These expansions
256 happen before the command is passed to the shell.
256 happen before the command is passed to the shell.
257
257
258 Shell aliases are executed in an environment where ``$HG`` expands to
258 Shell aliases are executed in an environment where ``$HG`` expands to
259 the path of the Mercurial that was used to execute the alias. This is
259 the path of the Mercurial that was used to execute the alias. This is
260 useful when you want to call further Mercurial commands in a shell
260 useful when you want to call further Mercurial commands in a shell
261 alias, as was done above for the purge alias. In addition,
261 alias, as was done above for the purge alias. In addition,
262 ``$HG_ARGS`` expands to the arguments given to Mercurial. In the ``hg
262 ``$HG_ARGS`` expands to the arguments given to Mercurial. In the ``hg
263 echo foo`` call above, ``$HG_ARGS`` would expand to ``echo foo``.
263 echo foo`` call above, ``$HG_ARGS`` would expand to ``echo foo``.
264
264
265 .. note::
265 .. note::
266
266
267 Some global configuration options such as ``-R`` are
267 Some global configuration options such as ``-R`` are
268 processed before shell aliases and will thus not be passed to
268 processed before shell aliases and will thus not be passed to
269 aliases.
269 aliases.
270
270
271
271
272 ``annotate``
272 ``annotate``
273 ------------
273 ------------
274
274
275 Settings used when displaying file annotations. All values are
275 Settings used when displaying file annotations. All values are
276 Booleans and default to False. See ``diff`` section for related
276 Booleans and default to False. See ``diff`` section for related
277 options for the diff command.
277 options for the diff command.
278
278
279 ``ignorews``
279 ``ignorews``
280 Ignore white space when comparing lines.
280 Ignore white space when comparing lines.
281
281
282 ``ignorewsamount``
282 ``ignorewsamount``
283 Ignore changes in the amount of white space.
283 Ignore changes in the amount of white space.
284
284
285 ``ignoreblanklines``
285 ``ignoreblanklines``
286 Ignore changes whose lines are all blank.
286 Ignore changes whose lines are all blank.
287
287
288
288
289 ``auth``
289 ``auth``
290 --------
290 --------
291
291
292 Authentication credentials for HTTP authentication. This section
292 Authentication credentials for HTTP authentication. This section
293 allows you to store usernames and passwords for use when logging
293 allows you to store usernames and passwords for use when logging
294 *into* HTTP servers. See the ``[web]`` configuration section if
294 *into* HTTP servers. See the ``[web]`` configuration section if
295 you want to configure *who* can login to your HTTP server.
295 you want to configure *who* can login to your HTTP server.
296
296
297 Each line has the following format::
297 Each line has the following format::
298
298
299 <name>.<argument> = <value>
299 <name>.<argument> = <value>
300
300
301 where ``<name>`` is used to group arguments into authentication
301 where ``<name>`` is used to group arguments into authentication
302 entries. Example::
302 entries. Example::
303
303
304 foo.prefix = hg.intevation.org/mercurial
304 foo.prefix = hg.intevation.org/mercurial
305 foo.username = foo
305 foo.username = foo
306 foo.password = bar
306 foo.password = bar
307 foo.schemes = http https
307 foo.schemes = http https
308
308
309 bar.prefix = secure.example.org
309 bar.prefix = secure.example.org
310 bar.key = path/to/file.key
310 bar.key = path/to/file.key
311 bar.cert = path/to/file.cert
311 bar.cert = path/to/file.cert
312 bar.schemes = https
312 bar.schemes = https
313
313
314 Supported arguments:
314 Supported arguments:
315
315
316 ``prefix``
316 ``prefix``
317 Either ``*`` or a URI prefix with or without the scheme part.
317 Either ``*`` or a URI prefix with or without the scheme part.
318 The authentication entry with the longest matching prefix is used
318 The authentication entry with the longest matching prefix is used
319 (where ``*`` matches everything and counts as a match of length
319 (where ``*`` matches everything and counts as a match of length
320 1). If the prefix doesn't include a scheme, the match is performed
320 1). If the prefix doesn't include a scheme, the match is performed
321 against the URI with its scheme stripped as well, and the schemes
321 against the URI with its scheme stripped as well, and the schemes
322 argument, q.v., is then subsequently consulted.
322 argument, q.v., is then subsequently consulted.
323
323
324 ``username``
324 ``username``
325 Optional. Username to authenticate with. If not given, and the
325 Optional. Username to authenticate with. If not given, and the
326 remote site requires basic or digest authentication, the user will
326 remote site requires basic or digest authentication, the user will
327 be prompted for it. Environment variables are expanded in the
327 be prompted for it. Environment variables are expanded in the
328 username letting you do ``foo.username = $USER``. If the URI
328 username letting you do ``foo.username = $USER``. If the URI
329 includes a username, only ``[auth]`` entries with a matching
329 includes a username, only ``[auth]`` entries with a matching
330 username or without a username will be considered.
330 username or without a username will be considered.
331
331
332 ``password``
332 ``password``
333 Optional. Password to authenticate with. If not given, and the
333 Optional. Password to authenticate with. If not given, and the
334 remote site requires basic or digest authentication, the user
334 remote site requires basic or digest authentication, the user
335 will be prompted for it.
335 will be prompted for it.
336
336
337 ``key``
337 ``key``
338 Optional. PEM encoded client certificate key file. Environment
338 Optional. PEM encoded client certificate key file. Environment
339 variables are expanded in the filename.
339 variables are expanded in the filename.
340
340
341 ``cert``
341 ``cert``
342 Optional. PEM encoded client certificate chain file. Environment
342 Optional. PEM encoded client certificate chain file. Environment
343 variables are expanded in the filename.
343 variables are expanded in the filename.
344
344
345 ``schemes``
345 ``schemes``
346 Optional. Space separated list of URI schemes to use this
346 Optional. Space separated list of URI schemes to use this
347 authentication entry with. Only used if the prefix doesn't include
347 authentication entry with. Only used if the prefix doesn't include
348 a scheme. Supported schemes are http and https. They will match
348 a scheme. Supported schemes are http and https. They will match
349 static-http and static-https respectively, as well.
349 static-http and static-https respectively, as well.
350 Default: https.
350 Default: https.
351
351
352 If no suitable authentication entry is found, the user is prompted
352 If no suitable authentication entry is found, the user is prompted
353 for credentials as usual if required by the remote.
353 for credentials as usual if required by the remote.
354
354
355
355
356 ``committemplate``
356 ``committemplate``
357 ------------------
357 ------------------
358
358
359 ``changeset`` configuration in this section is used as the template to
359 ``changeset`` configuration in this section is used as the template to
360 customize the text shown in the editor when committing.
360 customize the text shown in the editor when committing.
361
361
362 In addition to pre-defined template keywords, commit log specific one
362 In addition to pre-defined template keywords, commit log specific one
363 below can be used for customization:
363 below can be used for customization:
364
364
365 ``extramsg``
365 ``extramsg``
366 String: Extra message (typically 'Leave message empty to abort
366 String: Extra message (typically 'Leave message empty to abort
367 commit.'). This may be changed by some commands or extensions.
367 commit.'). This may be changed by some commands or extensions.
368
368
369 For example, the template configuration below shows as same text as
369 For example, the template configuration below shows as same text as
370 one shown by default::
370 one shown by default::
371
371
372 [committemplate]
372 [committemplate]
373 changeset = {desc}\n\n
373 changeset = {desc}\n\n
374 HG: Enter commit message. Lines beginning with 'HG:' are removed.
374 HG: Enter commit message. Lines beginning with 'HG:' are removed.
375 HG: {extramsg}
375 HG: {extramsg}
376 HG: --
376 HG: --
377 HG: user: {author}\n{ifeq(p2rev, "-1", "",
377 HG: user: {author}\n{ifeq(p2rev, "-1", "",
378 "HG: branch merge\n")
378 "HG: branch merge\n")
379 }HG: branch '{branch}'\n{if(currentbookmark,
379 }HG: branch '{branch}'\n{if(currentbookmark,
380 "HG: bookmark '{currentbookmark}'\n") }{subrepos %
380 "HG: bookmark '{currentbookmark}'\n") }{subrepos %
381 "HG: subrepo {subrepo}\n" }{file_adds %
381 "HG: subrepo {subrepo}\n" }{file_adds %
382 "HG: added {file}\n" }{file_mods %
382 "HG: added {file}\n" }{file_mods %
383 "HG: changed {file}\n" }{file_dels %
383 "HG: changed {file}\n" }{file_dels %
384 "HG: removed {file}\n" }{if(files, "",
384 "HG: removed {file}\n" }{if(files, "",
385 "HG: no files changed\n")}
385 "HG: no files changed\n")}
386
386
387 .. note::
387 .. note::
388
388
389 For some problematic encodings (see :hg:`help win32mbcs` for
389 For some problematic encodings (see :hg:`help win32mbcs` for
390 detail), this customization should be configured carefully, to
390 detail), this customization should be configured carefully, to
391 avoid showing broken characters.
391 avoid showing broken characters.
392
392
393 For example, if multibyte character ending with backslash (0x5c) is
393 For example, if multibyte character ending with backslash (0x5c) is
394 followed by ASCII character 'n' in the customized template,
394 followed by ASCII character 'n' in the customized template,
395 sequence of backslash and 'n' is treated as line-feed unexpectedly
395 sequence of backslash and 'n' is treated as line-feed unexpectedly
396 (and multibyte character is broken, too).
396 (and multibyte character is broken, too).
397
397
398 Customized template is used for commands below (``--edit`` may be
398 Customized template is used for commands below (``--edit`` may be
399 required):
399 required):
400
400
401 - :hg:`backout`
401 - :hg:`backout`
402 - :hg:`commit`
402 - :hg:`commit`
403 - :hg:`fetch` (for merge commit only)
403 - :hg:`fetch` (for merge commit only)
404 - :hg:`graft`
404 - :hg:`graft`
405 - :hg:`histedit`
405 - :hg:`histedit`
406 - :hg:`import`
406 - :hg:`import`
407 - :hg:`qfold`, :hg:`qnew` and :hg:`qrefresh`
407 - :hg:`qfold`, :hg:`qnew` and :hg:`qrefresh`
408 - :hg:`rebase`
408 - :hg:`rebase`
409 - :hg:`shelve`
409 - :hg:`shelve`
410 - :hg:`sign`
410 - :hg:`sign`
411 - :hg:`tag`
411 - :hg:`tag`
412 - :hg:`transplant`
412 - :hg:`transplant`
413
413
414 Configuring items below instead of ``changeset`` allows showing
414 Configuring items below instead of ``changeset`` allows showing
415 customized message only for specific actions, or showing different
415 customized message only for specific actions, or showing different
416 messages for each action.
416 messages for each action.
417
417
418 - ``changeset.backout`` for :hg:`backout`
418 - ``changeset.backout`` for :hg:`backout`
419 - ``changeset.commit.amend.merge`` for :hg:`commit --amend` on merges
419 - ``changeset.commit.amend.merge`` for :hg:`commit --amend` on merges
420 - ``changeset.commit.amend.normal`` for :hg:`commit --amend` on other
420 - ``changeset.commit.amend.normal`` for :hg:`commit --amend` on other
421 - ``changeset.commit.normal.merge`` for :hg:`commit` on merges
421 - ``changeset.commit.normal.merge`` for :hg:`commit` on merges
422 - ``changeset.commit.normal.normal`` for :hg:`commit` on other
422 - ``changeset.commit.normal.normal`` for :hg:`commit` on other
423 - ``changeset.fetch`` for :hg:`fetch` (impling merge commit)
423 - ``changeset.fetch`` for :hg:`fetch` (impling merge commit)
424 - ``changeset.gpg.sign`` for :hg:`sign`
424 - ``changeset.gpg.sign`` for :hg:`sign`
425 - ``changeset.graft`` for :hg:`graft`
425 - ``changeset.graft`` for :hg:`graft`
426 - ``changeset.histedit.edit`` for ``edit`` of :hg:`histedit`
426 - ``changeset.histedit.edit`` for ``edit`` of :hg:`histedit`
427 - ``changeset.histedit.fold`` for ``fold`` of :hg:`histedit`
427 - ``changeset.histedit.fold`` for ``fold`` of :hg:`histedit`
428 - ``changeset.histedit.mess`` for ``mess`` of :hg:`histedit`
428 - ``changeset.histedit.mess`` for ``mess`` of :hg:`histedit`
429 - ``changeset.histedit.pick`` for ``pick`` of :hg:`histedit`
429 - ``changeset.histedit.pick`` for ``pick`` of :hg:`histedit`
430 - ``changeset.import.bypass`` for :hg:`import --bypass`
430 - ``changeset.import.bypass`` for :hg:`import --bypass`
431 - ``changeset.import.normal.merge`` for :hg:`import` on merges
431 - ``changeset.import.normal.merge`` for :hg:`import` on merges
432 - ``changeset.import.normal.normal`` for :hg:`import` on other
432 - ``changeset.import.normal.normal`` for :hg:`import` on other
433 - ``changeset.mq.qnew`` for :hg:`qnew`
433 - ``changeset.mq.qnew`` for :hg:`qnew`
434 - ``changeset.mq.qfold`` for :hg:`qfold`
434 - ``changeset.mq.qfold`` for :hg:`qfold`
435 - ``changeset.mq.qrefresh`` for :hg:`qrefresh`
435 - ``changeset.mq.qrefresh`` for :hg:`qrefresh`
436 - ``changeset.rebase.collapse`` for :hg:`rebase --collapse`
436 - ``changeset.rebase.collapse`` for :hg:`rebase --collapse`
437 - ``changeset.rebase.merge`` for :hg:`rebase` on merges
437 - ``changeset.rebase.merge`` for :hg:`rebase` on merges
438 - ``changeset.rebase.normal`` for :hg:`rebase` on other
438 - ``changeset.rebase.normal`` for :hg:`rebase` on other
439 - ``changeset.shelve.shelve`` for :hg:`shelve`
439 - ``changeset.shelve.shelve`` for :hg:`shelve`
440 - ``changeset.tag.add`` for :hg:`tag` without ``--remove``
440 - ``changeset.tag.add`` for :hg:`tag` without ``--remove``
441 - ``changeset.tag.remove`` for :hg:`tag --remove`
441 - ``changeset.tag.remove`` for :hg:`tag --remove`
442 - ``changeset.transplant.merge`` for :hg:`transplant` on merges
442 - ``changeset.transplant.merge`` for :hg:`transplant` on merges
443 - ``changeset.transplant.normal`` for :hg:`transplant` on other
443 - ``changeset.transplant.normal`` for :hg:`transplant` on other
444
444
445 These dot-separated lists of names are treated as hierarchical ones.
445 These dot-separated lists of names are treated as hierarchical ones.
446 For example, ``changeset.tag.remove`` customizes the commit message
446 For example, ``changeset.tag.remove`` customizes the commit message
447 only for :hg:`tag --remove`, but ``changeset.tag`` customizes the
447 only for :hg:`tag --remove`, but ``changeset.tag`` customizes the
448 commit message for :hg:`tag` regardless of ``--remove`` option.
448 commit message for :hg:`tag` regardless of ``--remove`` option.
449
449
450 At the external editor invocation for committing, corresponding
450 At the external editor invocation for committing, corresponding
451 dot-separated list of names without ``changeset.`` prefix
451 dot-separated list of names without ``changeset.`` prefix
452 (e.g. ``commit.normal.normal``) is in ``HGEDITFORM`` environment variable.
452 (e.g. ``commit.normal.normal``) is in ``HGEDITFORM`` environment variable.
453
453
454 In this section, items other than ``changeset`` can be referred from
454 In this section, items other than ``changeset`` can be referred from
455 others. For example, the configuration to list committed files up
455 others. For example, the configuration to list committed files up
456 below can be referred as ``{listupfiles}``::
456 below can be referred as ``{listupfiles}``::
457
457
458 [committemplate]
458 [committemplate]
459 listupfiles = {file_adds %
459 listupfiles = {file_adds %
460 "HG: added {file}\n" }{file_mods %
460 "HG: added {file}\n" }{file_mods %
461 "HG: changed {file}\n" }{file_dels %
461 "HG: changed {file}\n" }{file_dels %
462 "HG: removed {file}\n" }{if(files, "",
462 "HG: removed {file}\n" }{if(files, "",
463 "HG: no files changed\n")}
463 "HG: no files changed\n")}
464
464
465 ``decode/encode``
465 ``decode/encode``
466 -----------------
466 -----------------
467
467
468 Filters for transforming files on checkout/checkin. This would
468 Filters for transforming files on checkout/checkin. This would
469 typically be used for newline processing or other
469 typically be used for newline processing or other
470 localization/canonicalization of files.
470 localization/canonicalization of files.
471
471
472 Filters consist of a filter pattern followed by a filter command.
472 Filters consist of a filter pattern followed by a filter command.
473 Filter patterns are globs by default, rooted at the repository root.
473 Filter patterns are globs by default, rooted at the repository root.
474 For example, to match any file ending in ``.txt`` in the root
474 For example, to match any file ending in ``.txt`` in the root
475 directory only, use the pattern ``*.txt``. To match any file ending
475 directory only, use the pattern ``*.txt``. To match any file ending
476 in ``.c`` anywhere in the repository, use the pattern ``**.c``.
476 in ``.c`` anywhere in the repository, use the pattern ``**.c``.
477 For each file only the first matching filter applies.
477 For each file only the first matching filter applies.
478
478
479 The filter command can start with a specifier, either ``pipe:`` or
479 The filter command can start with a specifier, either ``pipe:`` or
480 ``tempfile:``. If no specifier is given, ``pipe:`` is used by default.
480 ``tempfile:``. If no specifier is given, ``pipe:`` is used by default.
481
481
482 A ``pipe:`` command must accept data on stdin and return the transformed
482 A ``pipe:`` command must accept data on stdin and return the transformed
483 data on stdout.
483 data on stdout.
484
484
485 Pipe example::
485 Pipe example::
486
486
487 [encode]
487 [encode]
488 # uncompress gzip files on checkin to improve delta compression
488 # uncompress gzip files on checkin to improve delta compression
489 # note: not necessarily a good idea, just an example
489 # note: not necessarily a good idea, just an example
490 *.gz = pipe: gunzip
490 *.gz = pipe: gunzip
491
491
492 [decode]
492 [decode]
493 # recompress gzip files when writing them to the working dir (we
493 # recompress gzip files when writing them to the working dir (we
494 # can safely omit "pipe:", because it's the default)
494 # can safely omit "pipe:", because it's the default)
495 *.gz = gzip
495 *.gz = gzip
496
496
497 A ``tempfile:`` command is a template. The string ``INFILE`` is replaced
497 A ``tempfile:`` command is a template. The string ``INFILE`` is replaced
498 with the name of a temporary file that contains the data to be
498 with the name of a temporary file that contains the data to be
499 filtered by the command. The string ``OUTFILE`` is replaced with the name
499 filtered by the command. The string ``OUTFILE`` is replaced with the name
500 of an empty temporary file, where the filtered data must be written by
500 of an empty temporary file, where the filtered data must be written by
501 the command.
501 the command.
502
502
503 .. note::
503 .. note::
504
504
505 The tempfile mechanism is recommended for Windows systems,
505 The tempfile mechanism is recommended for Windows systems,
506 where the standard shell I/O redirection operators often have
506 where the standard shell I/O redirection operators often have
507 strange effects and may corrupt the contents of your files.
507 strange effects and may corrupt the contents of your files.
508
508
509 This filter mechanism is used internally by the ``eol`` extension to
509 This filter mechanism is used internally by the ``eol`` extension to
510 translate line ending characters between Windows (CRLF) and Unix (LF)
510 translate line ending characters between Windows (CRLF) and Unix (LF)
511 format. We suggest you use the ``eol`` extension for convenience.
511 format. We suggest you use the ``eol`` extension for convenience.
512
512
513
513
514 ``defaults``
514 ``defaults``
515 ------------
515 ------------
516
516
517 (defaults are deprecated. Don't use them. Use aliases instead)
517 (defaults are deprecated. Don't use them. Use aliases instead)
518
518
519 Use the ``[defaults]`` section to define command defaults, i.e. the
519 Use the ``[defaults]`` section to define command defaults, i.e. the
520 default options/arguments to pass to the specified commands.
520 default options/arguments to pass to the specified commands.
521
521
522 The following example makes :hg:`log` run in verbose mode, and
522 The following example makes :hg:`log` run in verbose mode, and
523 :hg:`status` show only the modified files, by default::
523 :hg:`status` show only the modified files, by default::
524
524
525 [defaults]
525 [defaults]
526 log = -v
526 log = -v
527 status = -m
527 status = -m
528
528
529 The actual commands, instead of their aliases, must be used when
529 The actual commands, instead of their aliases, must be used when
530 defining command defaults. The command defaults will also be applied
530 defining command defaults. The command defaults will also be applied
531 to the aliases of the commands defined.
531 to the aliases of the commands defined.
532
532
533
533
534 ``diff``
534 ``diff``
535 --------
535 --------
536
536
537 Settings used when displaying diffs. Everything except for ``unified``
537 Settings used when displaying diffs. Everything except for ``unified``
538 is a Boolean and defaults to False. See ``annotate`` section for
538 is a Boolean and defaults to False. See ``annotate`` section for
539 related options for the annotate command.
539 related options for the annotate command.
540
540
541 ``git``
541 ``git``
542 Use git extended diff format.
542 Use git extended diff format.
543
543
544 ``nobinary``
544 ``nobinary``
545 Omit git binary patches.
545 Omit git binary patches.
546
546
547 ``nodates``
547 ``nodates``
548 Don't include dates in diff headers.
548 Don't include dates in diff headers.
549
549
550 ``noprefix``
551 Omit 'a/' and 'b/' prefixes from filenames. Ignored in plain mode.
552
550 ``showfunc``
553 ``showfunc``
551 Show which function each change is in.
554 Show which function each change is in.
552
555
553 ``ignorews``
556 ``ignorews``
554 Ignore white space when comparing lines.
557 Ignore white space when comparing lines.
555
558
556 ``ignorewsamount``
559 ``ignorewsamount``
557 Ignore changes in the amount of white space.
560 Ignore changes in the amount of white space.
558
561
559 ``ignoreblanklines``
562 ``ignoreblanklines``
560 Ignore changes whose lines are all blank.
563 Ignore changes whose lines are all blank.
561
564
562 ``unified``
565 ``unified``
563 Number of lines of context to show.
566 Number of lines of context to show.
564
567
565 ``email``
568 ``email``
566 ---------
569 ---------
567
570
568 Settings for extensions that send email messages.
571 Settings for extensions that send email messages.
569
572
570 ``from``
573 ``from``
571 Optional. Email address to use in "From" header and SMTP envelope
574 Optional. Email address to use in "From" header and SMTP envelope
572 of outgoing messages.
575 of outgoing messages.
573
576
574 ``to``
577 ``to``
575 Optional. Comma-separated list of recipients' email addresses.
578 Optional. Comma-separated list of recipients' email addresses.
576
579
577 ``cc``
580 ``cc``
578 Optional. Comma-separated list of carbon copy recipients'
581 Optional. Comma-separated list of carbon copy recipients'
579 email addresses.
582 email addresses.
580
583
581 ``bcc``
584 ``bcc``
582 Optional. Comma-separated list of blind carbon copy recipients'
585 Optional. Comma-separated list of blind carbon copy recipients'
583 email addresses.
586 email addresses.
584
587
585 ``method``
588 ``method``
586 Optional. Method to use to send email messages. If value is ``smtp``
589 Optional. Method to use to send email messages. If value is ``smtp``
587 (default), use SMTP (see the ``[smtp]`` section for configuration).
590 (default), use SMTP (see the ``[smtp]`` section for configuration).
588 Otherwise, use as name of program to run that acts like sendmail
591 Otherwise, use as name of program to run that acts like sendmail
589 (takes ``-f`` option for sender, list of recipients on command line,
592 (takes ``-f`` option for sender, list of recipients on command line,
590 message on stdin). Normally, setting this to ``sendmail`` or
593 message on stdin). Normally, setting this to ``sendmail`` or
591 ``/usr/sbin/sendmail`` is enough to use sendmail to send messages.
594 ``/usr/sbin/sendmail`` is enough to use sendmail to send messages.
592
595
593 ``charsets``
596 ``charsets``
594 Optional. Comma-separated list of character sets considered
597 Optional. Comma-separated list of character sets considered
595 convenient for recipients. Addresses, headers, and parts not
598 convenient for recipients. Addresses, headers, and parts not
596 containing patches of outgoing messages will be encoded in the
599 containing patches of outgoing messages will be encoded in the
597 first character set to which conversion from local encoding
600 first character set to which conversion from local encoding
598 (``$HGENCODING``, ``ui.fallbackencoding``) succeeds. If correct
601 (``$HGENCODING``, ``ui.fallbackencoding``) succeeds. If correct
599 conversion fails, the text in question is sent as is. Defaults to
602 conversion fails, the text in question is sent as is. Defaults to
600 empty (explicit) list.
603 empty (explicit) list.
601
604
602 Order of outgoing email character sets:
605 Order of outgoing email character sets:
603
606
604 1. ``us-ascii``: always first, regardless of settings
607 1. ``us-ascii``: always first, regardless of settings
605 2. ``email.charsets``: in order given by user
608 2. ``email.charsets``: in order given by user
606 3. ``ui.fallbackencoding``: if not in email.charsets
609 3. ``ui.fallbackencoding``: if not in email.charsets
607 4. ``$HGENCODING``: if not in email.charsets
610 4. ``$HGENCODING``: if not in email.charsets
608 5. ``utf-8``: always last, regardless of settings
611 5. ``utf-8``: always last, regardless of settings
609
612
610 Email example::
613 Email example::
611
614
612 [email]
615 [email]
613 from = Joseph User <joe.user@example.com>
616 from = Joseph User <joe.user@example.com>
614 method = /usr/sbin/sendmail
617 method = /usr/sbin/sendmail
615 # charsets for western Europeans
618 # charsets for western Europeans
616 # us-ascii, utf-8 omitted, as they are tried first and last
619 # us-ascii, utf-8 omitted, as they are tried first and last
617 charsets = iso-8859-1, iso-8859-15, windows-1252
620 charsets = iso-8859-1, iso-8859-15, windows-1252
618
621
619
622
620 ``extensions``
623 ``extensions``
621 --------------
624 --------------
622
625
623 Mercurial has an extension mechanism for adding new features. To
626 Mercurial has an extension mechanism for adding new features. To
624 enable an extension, create an entry for it in this section.
627 enable an extension, create an entry for it in this section.
625
628
626 If you know that the extension is already in Python's search path,
629 If you know that the extension is already in Python's search path,
627 you can give the name of the module, followed by ``=``, with nothing
630 you can give the name of the module, followed by ``=``, with nothing
628 after the ``=``.
631 after the ``=``.
629
632
630 Otherwise, give a name that you choose, followed by ``=``, followed by
633 Otherwise, give a name that you choose, followed by ``=``, followed by
631 the path to the ``.py`` file (including the file name extension) that
634 the path to the ``.py`` file (including the file name extension) that
632 defines the extension.
635 defines the extension.
633
636
634 To explicitly disable an extension that is enabled in an hgrc of
637 To explicitly disable an extension that is enabled in an hgrc of
635 broader scope, prepend its path with ``!``, as in ``foo = !/ext/path``
638 broader scope, prepend its path with ``!``, as in ``foo = !/ext/path``
636 or ``foo = !`` when path is not supplied.
639 or ``foo = !`` when path is not supplied.
637
640
638 Example for ``~/.hgrc``::
641 Example for ``~/.hgrc``::
639
642
640 [extensions]
643 [extensions]
641 # (the progress extension will get loaded from Mercurial's path)
644 # (the progress extension will get loaded from Mercurial's path)
642 progress =
645 progress =
643 # (this extension will get loaded from the file specified)
646 # (this extension will get loaded from the file specified)
644 myfeature = ~/.hgext/myfeature.py
647 myfeature = ~/.hgext/myfeature.py
645
648
646
649
647 ``format``
650 ``format``
648 ----------
651 ----------
649
652
650 ``usestore``
653 ``usestore``
651 Enable or disable the "store" repository format which improves
654 Enable or disable the "store" repository format which improves
652 compatibility with systems that fold case or otherwise mangle
655 compatibility with systems that fold case or otherwise mangle
653 filenames. Enabled by default. Disabling this option will allow
656 filenames. Enabled by default. Disabling this option will allow
654 you to store longer filenames in some situations at the expense of
657 you to store longer filenames in some situations at the expense of
655 compatibility and ensures that the on-disk format of newly created
658 compatibility and ensures that the on-disk format of newly created
656 repositories will be compatible with Mercurial before version 0.9.4.
659 repositories will be compatible with Mercurial before version 0.9.4.
657
660
658 ``usefncache``
661 ``usefncache``
659 Enable or disable the "fncache" repository format which enhances
662 Enable or disable the "fncache" repository format which enhances
660 the "store" repository format (which has to be enabled to use
663 the "store" repository format (which has to be enabled to use
661 fncache) to allow longer filenames and avoids using Windows
664 fncache) to allow longer filenames and avoids using Windows
662 reserved names, e.g. "nul". Enabled by default. Disabling this
665 reserved names, e.g. "nul". Enabled by default. Disabling this
663 option ensures that the on-disk format of newly created
666 option ensures that the on-disk format of newly created
664 repositories will be compatible with Mercurial before version 1.1.
667 repositories will be compatible with Mercurial before version 1.1.
665
668
666 ``dotencode``
669 ``dotencode``
667 Enable or disable the "dotencode" repository format which enhances
670 Enable or disable the "dotencode" repository format which enhances
668 the "fncache" repository format (which has to be enabled to use
671 the "fncache" repository format (which has to be enabled to use
669 dotencode) to avoid issues with filenames starting with ._ on
672 dotencode) to avoid issues with filenames starting with ._ on
670 Mac OS X and spaces on Windows. Enabled by default. Disabling this
673 Mac OS X and spaces on Windows. Enabled by default. Disabling this
671 option ensures that the on-disk format of newly created
674 option ensures that the on-disk format of newly created
672 repositories will be compatible with Mercurial before version 1.7.
675 repositories will be compatible with Mercurial before version 1.7.
673
676
674 ``graph``
677 ``graph``
675 ---------
678 ---------
676
679
677 Web graph view configuration. This section let you change graph
680 Web graph view configuration. This section let you change graph
678 elements display properties by branches, for instance to make the
681 elements display properties by branches, for instance to make the
679 ``default`` branch stand out.
682 ``default`` branch stand out.
680
683
681 Each line has the following format::
684 Each line has the following format::
682
685
683 <branch>.<argument> = <value>
686 <branch>.<argument> = <value>
684
687
685 where ``<branch>`` is the name of the branch being
688 where ``<branch>`` is the name of the branch being
686 customized. Example::
689 customized. Example::
687
690
688 [graph]
691 [graph]
689 # 2px width
692 # 2px width
690 default.width = 2
693 default.width = 2
691 # red color
694 # red color
692 default.color = FF0000
695 default.color = FF0000
693
696
694 Supported arguments:
697 Supported arguments:
695
698
696 ``width``
699 ``width``
697 Set branch edges width in pixels.
700 Set branch edges width in pixels.
698
701
699 ``color``
702 ``color``
700 Set branch edges color in hexadecimal RGB notation.
703 Set branch edges color in hexadecimal RGB notation.
701
704
702 ``hooks``
705 ``hooks``
703 ---------
706 ---------
704
707
705 Commands or Python functions that get automatically executed by
708 Commands or Python functions that get automatically executed by
706 various actions such as starting or finishing a commit. Multiple
709 various actions such as starting or finishing a commit. Multiple
707 hooks can be run for the same action by appending a suffix to the
710 hooks can be run for the same action by appending a suffix to the
708 action. Overriding a site-wide hook can be done by changing its
711 action. Overriding a site-wide hook can be done by changing its
709 value or setting it to an empty string. Hooks can be prioritized
712 value or setting it to an empty string. Hooks can be prioritized
710 by adding a prefix of ``priority`` to the hook name on a new line
713 by adding a prefix of ``priority`` to the hook name on a new line
711 and setting the priority. The default priority is 0 if
714 and setting the priority. The default priority is 0 if
712 not specified.
715 not specified.
713
716
714 Example ``.hg/hgrc``::
717 Example ``.hg/hgrc``::
715
718
716 [hooks]
719 [hooks]
717 # update working directory after adding changesets
720 # update working directory after adding changesets
718 changegroup.update = hg update
721 changegroup.update = hg update
719 # do not use the site-wide hook
722 # do not use the site-wide hook
720 incoming =
723 incoming =
721 incoming.email = /my/email/hook
724 incoming.email = /my/email/hook
722 incoming.autobuild = /my/build/hook
725 incoming.autobuild = /my/build/hook
723 # force autobuild hook to run before other incoming hooks
726 # force autobuild hook to run before other incoming hooks
724 priority.incoming.autobuild = 1
727 priority.incoming.autobuild = 1
725
728
726 Most hooks are run with environment variables set that give useful
729 Most hooks are run with environment variables set that give useful
727 additional information. For each hook below, the environment
730 additional information. For each hook below, the environment
728 variables it is passed are listed with names of the form ``$HG_foo``.
731 variables it is passed are listed with names of the form ``$HG_foo``.
729
732
730 ``changegroup``
733 ``changegroup``
731 Run after a changegroup has been added via push, pull or unbundle.
734 Run after a changegroup has been added via push, pull or unbundle.
732 ID of the first new changeset is in ``$HG_NODE``. URL from which
735 ID of the first new changeset is in ``$HG_NODE``. URL from which
733 changes came is in ``$HG_URL``.
736 changes came is in ``$HG_URL``.
734
737
735 ``commit``
738 ``commit``
736 Run after a changeset has been created in the local repository. ID
739 Run after a changeset has been created in the local repository. ID
737 of the newly created changeset is in ``$HG_NODE``. Parent changeset
740 of the newly created changeset is in ``$HG_NODE``. Parent changeset
738 IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
741 IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
739
742
740 ``incoming``
743 ``incoming``
741 Run after a changeset has been pulled, pushed, or unbundled into
744 Run after a changeset has been pulled, pushed, or unbundled into
742 the local repository. The ID of the newly arrived changeset is in
745 the local repository. The ID of the newly arrived changeset is in
743 ``$HG_NODE``. URL that was source of changes came is in ``$HG_URL``.
746 ``$HG_NODE``. URL that was source of changes came is in ``$HG_URL``.
744
747
745 ``outgoing``
748 ``outgoing``
746 Run after sending changes from local repository to another. ID of
749 Run after sending changes from local repository to another. ID of
747 first changeset sent is in ``$HG_NODE``. Source of operation is in
750 first changeset sent is in ``$HG_NODE``. Source of operation is in
748 ``$HG_SOURCE``; see "preoutgoing" hook for description.
751 ``$HG_SOURCE``; see "preoutgoing" hook for description.
749
752
750 ``post-<command>``
753 ``post-<command>``
751 Run after successful invocations of the associated command. The
754 Run after successful invocations of the associated command. The
752 contents of the command line are passed as ``$HG_ARGS`` and the result
755 contents of the command line are passed as ``$HG_ARGS`` and the result
753 code in ``$HG_RESULT``. Parsed command line arguments are passed as
756 code in ``$HG_RESULT``. Parsed command line arguments are passed as
754 ``$HG_PATS`` and ``$HG_OPTS``. These contain string representations of
757 ``$HG_PATS`` and ``$HG_OPTS``. These contain string representations of
755 the python data internally passed to <command>. ``$HG_OPTS`` is a
758 the python data internally passed to <command>. ``$HG_OPTS`` is a
756 dictionary of options (with unspecified options set to their defaults).
759 dictionary of options (with unspecified options set to their defaults).
757 ``$HG_PATS`` is a list of arguments. Hook failure is ignored.
760 ``$HG_PATS`` is a list of arguments. Hook failure is ignored.
758
761
759 ``pre-<command>``
762 ``pre-<command>``
760 Run before executing the associated command. The contents of the
763 Run before executing the associated command. The contents of the
761 command line are passed as ``$HG_ARGS``. Parsed command line arguments
764 command line are passed as ``$HG_ARGS``. Parsed command line arguments
762 are passed as ``$HG_PATS`` and ``$HG_OPTS``. These contain string
765 are passed as ``$HG_PATS`` and ``$HG_OPTS``. These contain string
763 representations of the data internally passed to <command>. ``$HG_OPTS``
766 representations of the data internally passed to <command>. ``$HG_OPTS``
764 is a dictionary of options (with unspecified options set to their
767 is a dictionary of options (with unspecified options set to their
765 defaults). ``$HG_PATS`` is a list of arguments. If the hook returns
768 defaults). ``$HG_PATS`` is a list of arguments. If the hook returns
766 failure, the command doesn't execute and Mercurial returns the failure
769 failure, the command doesn't execute and Mercurial returns the failure
767 code.
770 code.
768
771
769 ``prechangegroup``
772 ``prechangegroup``
770 Run before a changegroup is added via push, pull or unbundle. Exit
773 Run before a changegroup is added via push, pull or unbundle. Exit
771 status 0 allows the changegroup to proceed. Non-zero status will
774 status 0 allows the changegroup to proceed. Non-zero status will
772 cause the push, pull or unbundle to fail. URL from which changes
775 cause the push, pull or unbundle to fail. URL from which changes
773 will come is in ``$HG_URL``.
776 will come is in ``$HG_URL``.
774
777
775 ``precommit``
778 ``precommit``
776 Run before starting a local commit. Exit status 0 allows the
779 Run before starting a local commit. Exit status 0 allows the
777 commit to proceed. Non-zero status will cause the commit to fail.
780 commit to proceed. Non-zero status will cause the commit to fail.
778 Parent changeset IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
781 Parent changeset IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
779
782
780 ``prelistkeys``
783 ``prelistkeys``
781 Run before listing pushkeys (like bookmarks) in the
784 Run before listing pushkeys (like bookmarks) in the
782 repository. Non-zero status will cause failure. The key namespace is
785 repository. Non-zero status will cause failure. The key namespace is
783 in ``$HG_NAMESPACE``.
786 in ``$HG_NAMESPACE``.
784
787
785 ``preoutgoing``
788 ``preoutgoing``
786 Run before collecting changes to send from the local repository to
789 Run before collecting changes to send from the local repository to
787 another. Non-zero status will cause failure. This lets you prevent
790 another. Non-zero status will cause failure. This lets you prevent
788 pull over HTTP or SSH. Also prevents against local pull, push
791 pull over HTTP or SSH. Also prevents against local pull, push
789 (outbound) or bundle commands, but not effective, since you can
792 (outbound) or bundle commands, but not effective, since you can
790 just copy files instead then. Source of operation is in
793 just copy files instead then. Source of operation is in
791 ``$HG_SOURCE``. If "serve", operation is happening on behalf of remote
794 ``$HG_SOURCE``. If "serve", operation is happening on behalf of remote
792 SSH or HTTP repository. If "push", "pull" or "bundle", operation
795 SSH or HTTP repository. If "push", "pull" or "bundle", operation
793 is happening on behalf of repository on same system.
796 is happening on behalf of repository on same system.
794
797
795 ``prepushkey``
798 ``prepushkey``
796 Run before a pushkey (like a bookmark) is added to the
799 Run before a pushkey (like a bookmark) is added to the
797 repository. Non-zero status will cause the key to be rejected. The
800 repository. Non-zero status will cause the key to be rejected. The
798 key namespace is in ``$HG_NAMESPACE``, the key is in ``$HG_KEY``,
801 key namespace is in ``$HG_NAMESPACE``, the key is in ``$HG_KEY``,
799 the old value (if any) is in ``$HG_OLD``, and the new value is in
802 the old value (if any) is in ``$HG_OLD``, and the new value is in
800 ``$HG_NEW``.
803 ``$HG_NEW``.
801
804
802 ``pretag``
805 ``pretag``
803 Run before creating a tag. Exit status 0 allows the tag to be
806 Run before creating a tag. Exit status 0 allows the tag to be
804 created. Non-zero status will cause the tag to fail. ID of
807 created. Non-zero status will cause the tag to fail. ID of
805 changeset to tag is in ``$HG_NODE``. Name of tag is in ``$HG_TAG``. Tag is
808 changeset to tag is in ``$HG_NODE``. Name of tag is in ``$HG_TAG``. Tag is
806 local if ``$HG_LOCAL=1``, in repository if ``$HG_LOCAL=0``.
809 local if ``$HG_LOCAL=1``, in repository if ``$HG_LOCAL=0``.
807
810
808 ``pretxnchangegroup``
811 ``pretxnchangegroup``
809 Run after a changegroup has been added via push, pull or unbundle,
812 Run after a changegroup has been added via push, pull or unbundle,
810 but before the transaction has been committed. Changegroup is
813 but before the transaction has been committed. Changegroup is
811 visible to hook program. This lets you validate incoming changes
814 visible to hook program. This lets you validate incoming changes
812 before accepting them. Passed the ID of the first new changeset in
815 before accepting them. Passed the ID of the first new changeset in
813 ``$HG_NODE``. Exit status 0 allows the transaction to commit. Non-zero
816 ``$HG_NODE``. Exit status 0 allows the transaction to commit. Non-zero
814 status will cause the transaction to be rolled back and the push,
817 status will cause the transaction to be rolled back and the push,
815 pull or unbundle will fail. URL that was source of changes is in
818 pull or unbundle will fail. URL that was source of changes is in
816 ``$HG_URL``.
819 ``$HG_URL``.
817
820
818 ``pretxncommit``
821 ``pretxncommit``
819 Run after a changeset has been created but the transaction not yet
822 Run after a changeset has been created but the transaction not yet
820 committed. Changeset is visible to hook program. This lets you
823 committed. Changeset is visible to hook program. This lets you
821 validate commit message and changes. Exit status 0 allows the
824 validate commit message and changes. Exit status 0 allows the
822 commit to proceed. Non-zero status will cause the transaction to
825 commit to proceed. Non-zero status will cause the transaction to
823 be rolled back. ID of changeset is in ``$HG_NODE``. Parent changeset
826 be rolled back. ID of changeset is in ``$HG_NODE``. Parent changeset
824 IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
827 IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
825
828
826 ``preupdate``
829 ``preupdate``
827 Run before updating the working directory. Exit status 0 allows
830 Run before updating the working directory. Exit status 0 allows
828 the update to proceed. Non-zero status will prevent the update.
831 the update to proceed. Non-zero status will prevent the update.
829 Changeset ID of first new parent is in ``$HG_PARENT1``. If merge, ID
832 Changeset ID of first new parent is in ``$HG_PARENT1``. If merge, ID
830 of second new parent is in ``$HG_PARENT2``.
833 of second new parent is in ``$HG_PARENT2``.
831
834
832 ``listkeys``
835 ``listkeys``
833 Run after listing pushkeys (like bookmarks) in the repository. The
836 Run after listing pushkeys (like bookmarks) in the repository. The
834 key namespace is in ``$HG_NAMESPACE``. ``$HG_VALUES`` is a
837 key namespace is in ``$HG_NAMESPACE``. ``$HG_VALUES`` is a
835 dictionary containing the keys and values.
838 dictionary containing the keys and values.
836
839
837 ``pushkey``
840 ``pushkey``
838 Run after a pushkey (like a bookmark) is added to the
841 Run after a pushkey (like a bookmark) is added to the
839 repository. The key namespace is in ``$HG_NAMESPACE``, the key is in
842 repository. The key namespace is in ``$HG_NAMESPACE``, the key is in
840 ``$HG_KEY``, the old value (if any) is in ``$HG_OLD``, and the new
843 ``$HG_KEY``, the old value (if any) is in ``$HG_OLD``, and the new
841 value is in ``$HG_NEW``.
844 value is in ``$HG_NEW``.
842
845
843 ``tag``
846 ``tag``
844 Run after a tag is created. ID of tagged changeset is in ``$HG_NODE``.
847 Run after a tag is created. ID of tagged changeset is in ``$HG_NODE``.
845 Name of tag is in ``$HG_TAG``. Tag is local if ``$HG_LOCAL=1``, in
848 Name of tag is in ``$HG_TAG``. Tag is local if ``$HG_LOCAL=1``, in
846 repository if ``$HG_LOCAL=0``.
849 repository if ``$HG_LOCAL=0``.
847
850
848 ``update``
851 ``update``
849 Run after updating the working directory. Changeset ID of first
852 Run after updating the working directory. Changeset ID of first
850 new parent is in ``$HG_PARENT1``. If merge, ID of second new parent is
853 new parent is in ``$HG_PARENT1``. If merge, ID of second new parent is
851 in ``$HG_PARENT2``. If the update succeeded, ``$HG_ERROR=0``. If the
854 in ``$HG_PARENT2``. If the update succeeded, ``$HG_ERROR=0``. If the
852 update failed (e.g. because conflicts not resolved), ``$HG_ERROR=1``.
855 update failed (e.g. because conflicts not resolved), ``$HG_ERROR=1``.
853
856
854 .. note::
857 .. note::
855
858
856 It is generally better to use standard hooks rather than the
859 It is generally better to use standard hooks rather than the
857 generic pre- and post- command hooks as they are guaranteed to be
860 generic pre- and post- command hooks as they are guaranteed to be
858 called in the appropriate contexts for influencing transactions.
861 called in the appropriate contexts for influencing transactions.
859 Also, hooks like "commit" will be called in all contexts that
862 Also, hooks like "commit" will be called in all contexts that
860 generate a commit (e.g. tag) and not just the commit command.
863 generate a commit (e.g. tag) and not just the commit command.
861
864
862 .. note::
865 .. note::
863
866
864 Environment variables with empty values may not be passed to
867 Environment variables with empty values may not be passed to
865 hooks on platforms such as Windows. As an example, ``$HG_PARENT2``
868 hooks on platforms such as Windows. As an example, ``$HG_PARENT2``
866 will have an empty value under Unix-like platforms for non-merge
869 will have an empty value under Unix-like platforms for non-merge
867 changesets, while it will not be available at all under Windows.
870 changesets, while it will not be available at all under Windows.
868
871
869 The syntax for Python hooks is as follows::
872 The syntax for Python hooks is as follows::
870
873
871 hookname = python:modulename.submodule.callable
874 hookname = python:modulename.submodule.callable
872 hookname = python:/path/to/python/module.py:callable
875 hookname = python:/path/to/python/module.py:callable
873
876
874 Python hooks are run within the Mercurial process. Each hook is
877 Python hooks are run within the Mercurial process. Each hook is
875 called with at least three keyword arguments: a ui object (keyword
878 called with at least three keyword arguments: a ui object (keyword
876 ``ui``), a repository object (keyword ``repo``), and a ``hooktype``
879 ``ui``), a repository object (keyword ``repo``), and a ``hooktype``
877 keyword that tells what kind of hook is used. Arguments listed as
880 keyword that tells what kind of hook is used. Arguments listed as
878 environment variables above are passed as keyword arguments, with no
881 environment variables above are passed as keyword arguments, with no
879 ``HG_`` prefix, and names in lower case.
882 ``HG_`` prefix, and names in lower case.
880
883
881 If a Python hook returns a "true" value or raises an exception, this
884 If a Python hook returns a "true" value or raises an exception, this
882 is treated as a failure.
885 is treated as a failure.
883
886
884
887
885 ``hostfingerprints``
888 ``hostfingerprints``
886 --------------------
889 --------------------
887
890
888 Fingerprints of the certificates of known HTTPS servers.
891 Fingerprints of the certificates of known HTTPS servers.
889 A HTTPS connection to a server with a fingerprint configured here will
892 A HTTPS connection to a server with a fingerprint configured here will
890 only succeed if the servers certificate matches the fingerprint.
893 only succeed if the servers certificate matches the fingerprint.
891 This is very similar to how ssh known hosts works.
894 This is very similar to how ssh known hosts works.
892 The fingerprint is the SHA-1 hash value of the DER encoded certificate.
895 The fingerprint is the SHA-1 hash value of the DER encoded certificate.
893 The CA chain and web.cacerts is not used for servers with a fingerprint.
896 The CA chain and web.cacerts is not used for servers with a fingerprint.
894
897
895 For example::
898 For example::
896
899
897 [hostfingerprints]
900 [hostfingerprints]
898 hg.intevation.org = fa:1f:d9:48:f1:e7:74:30:38:8d:d8:58:b6:94:b8:58:28:7d:8b:d0
901 hg.intevation.org = fa:1f:d9:48:f1:e7:74:30:38:8d:d8:58:b6:94:b8:58:28:7d:8b:d0
899
902
900 This feature is only supported when using Python 2.6 or later.
903 This feature is only supported when using Python 2.6 or later.
901
904
902
905
903 ``http_proxy``
906 ``http_proxy``
904 --------------
907 --------------
905
908
906 Used to access web-based Mercurial repositories through a HTTP
909 Used to access web-based Mercurial repositories through a HTTP
907 proxy.
910 proxy.
908
911
909 ``host``
912 ``host``
910 Host name and (optional) port of the proxy server, for example
913 Host name and (optional) port of the proxy server, for example
911 "myproxy:8000".
914 "myproxy:8000".
912
915
913 ``no``
916 ``no``
914 Optional. Comma-separated list of host names that should bypass
917 Optional. Comma-separated list of host names that should bypass
915 the proxy.
918 the proxy.
916
919
917 ``passwd``
920 ``passwd``
918 Optional. Password to authenticate with at the proxy server.
921 Optional. Password to authenticate with at the proxy server.
919
922
920 ``user``
923 ``user``
921 Optional. User name to authenticate with at the proxy server.
924 Optional. User name to authenticate with at the proxy server.
922
925
923 ``always``
926 ``always``
924 Optional. Always use the proxy, even for localhost and any entries
927 Optional. Always use the proxy, even for localhost and any entries
925 in ``http_proxy.no``. True or False. Default: False.
928 in ``http_proxy.no``. True or False. Default: False.
926
929
927 ``merge-patterns``
930 ``merge-patterns``
928 ------------------
931 ------------------
929
932
930 This section specifies merge tools to associate with particular file
933 This section specifies merge tools to associate with particular file
931 patterns. Tools matched here will take precedence over the default
934 patterns. Tools matched here will take precedence over the default
932 merge tool. Patterns are globs by default, rooted at the repository
935 merge tool. Patterns are globs by default, rooted at the repository
933 root.
936 root.
934
937
935 Example::
938 Example::
936
939
937 [merge-patterns]
940 [merge-patterns]
938 **.c = kdiff3
941 **.c = kdiff3
939 **.jpg = myimgmerge
942 **.jpg = myimgmerge
940
943
941 ``merge-tools``
944 ``merge-tools``
942 ---------------
945 ---------------
943
946
944 This section configures external merge tools to use for file-level
947 This section configures external merge tools to use for file-level
945 merges. This section has likely been preconfigured at install time.
948 merges. This section has likely been preconfigured at install time.
946 Use :hg:`config merge-tools` to check the existing configuration.
949 Use :hg:`config merge-tools` to check the existing configuration.
947 Also see :hg:`help merge-tools` for more details.
950 Also see :hg:`help merge-tools` for more details.
948
951
949 Example ``~/.hgrc``::
952 Example ``~/.hgrc``::
950
953
951 [merge-tools]
954 [merge-tools]
952 # Override stock tool location
955 # Override stock tool location
953 kdiff3.executable = ~/bin/kdiff3
956 kdiff3.executable = ~/bin/kdiff3
954 # Specify command line
957 # Specify command line
955 kdiff3.args = $base $local $other -o $output
958 kdiff3.args = $base $local $other -o $output
956 # Give higher priority
959 # Give higher priority
957 kdiff3.priority = 1
960 kdiff3.priority = 1
958
961
959 # Changing the priority of preconfigured tool
962 # Changing the priority of preconfigured tool
960 vimdiff.priority = 0
963 vimdiff.priority = 0
961
964
962 # Define new tool
965 # Define new tool
963 myHtmlTool.args = -m $local $other $base $output
966 myHtmlTool.args = -m $local $other $base $output
964 myHtmlTool.regkey = Software\FooSoftware\HtmlMerge
967 myHtmlTool.regkey = Software\FooSoftware\HtmlMerge
965 myHtmlTool.priority = 1
968 myHtmlTool.priority = 1
966
969
967 Supported arguments:
970 Supported arguments:
968
971
969 ``priority``
972 ``priority``
970 The priority in which to evaluate this tool.
973 The priority in which to evaluate this tool.
971 Default: 0.
974 Default: 0.
972
975
973 ``executable``
976 ``executable``
974 Either just the name of the executable or its pathname. On Windows,
977 Either just the name of the executable or its pathname. On Windows,
975 the path can use environment variables with ${ProgramFiles} syntax.
978 the path can use environment variables with ${ProgramFiles} syntax.
976 Default: the tool name.
979 Default: the tool name.
977
980
978 ``args``
981 ``args``
979 The arguments to pass to the tool executable. You can refer to the
982 The arguments to pass to the tool executable. You can refer to the
980 files being merged as well as the output file through these
983 files being merged as well as the output file through these
981 variables: ``$base``, ``$local``, ``$other``, ``$output``. The meaning
984 variables: ``$base``, ``$local``, ``$other``, ``$output``. The meaning
982 of ``$local`` and ``$other`` can vary depending on which action is being
985 of ``$local`` and ``$other`` can vary depending on which action is being
983 performed. During and update or merge, ``$local`` represents the original
986 performed. During and update or merge, ``$local`` represents the original
984 state of the file, while ``$other`` represents the commit you are updating
987 state of the file, while ``$other`` represents the commit you are updating
985 to or the commit you are merging with. During a rebase ``$local``
988 to or the commit you are merging with. During a rebase ``$local``
986 represents the destination of the rebase, and ``$other`` represents the
989 represents the destination of the rebase, and ``$other`` represents the
987 commit being rebased.
990 commit being rebased.
988 Default: ``$local $base $other``
991 Default: ``$local $base $other``
989
992
990 ``premerge``
993 ``premerge``
991 Attempt to run internal non-interactive 3-way merge tool before
994 Attempt to run internal non-interactive 3-way merge tool before
992 launching external tool. Options are ``true``, ``false``, ``keep`` or
995 launching external tool. Options are ``true``, ``false``, ``keep`` or
993 ``keep-merge3``. The ``keep`` option will leave markers in the file if the
996 ``keep-merge3``. The ``keep`` option will leave markers in the file if the
994 premerge fails. The ``keep-merge3`` will do the same but include information
997 premerge fails. The ``keep-merge3`` will do the same but include information
995 about the base of the merge in the marker (see internal :merge3 in
998 about the base of the merge in the marker (see internal :merge3 in
996 :hg:`help merge-tools`).
999 :hg:`help merge-tools`).
997 Default: True
1000 Default: True
998
1001
999 ``binary``
1002 ``binary``
1000 This tool can merge binary files. Defaults to False, unless tool
1003 This tool can merge binary files. Defaults to False, unless tool
1001 was selected by file pattern match.
1004 was selected by file pattern match.
1002
1005
1003 ``symlink``
1006 ``symlink``
1004 This tool can merge symlinks. Defaults to False, even if tool was
1007 This tool can merge symlinks. Defaults to False, even if tool was
1005 selected by file pattern match.
1008 selected by file pattern match.
1006
1009
1007 ``check``
1010 ``check``
1008 A list of merge success-checking options:
1011 A list of merge success-checking options:
1009
1012
1010 ``changed``
1013 ``changed``
1011 Ask whether merge was successful when the merged file shows no changes.
1014 Ask whether merge was successful when the merged file shows no changes.
1012 ``conflicts``
1015 ``conflicts``
1013 Check whether there are conflicts even though the tool reported success.
1016 Check whether there are conflicts even though the tool reported success.
1014 ``prompt``
1017 ``prompt``
1015 Always prompt for merge success, regardless of success reported by tool.
1018 Always prompt for merge success, regardless of success reported by tool.
1016
1019
1017 ``fixeol``
1020 ``fixeol``
1018 Attempt to fix up EOL changes caused by the merge tool.
1021 Attempt to fix up EOL changes caused by the merge tool.
1019 Default: False
1022 Default: False
1020
1023
1021 ``gui``
1024 ``gui``
1022 This tool requires a graphical interface to run. Default: False
1025 This tool requires a graphical interface to run. Default: False
1023
1026
1024 ``regkey``
1027 ``regkey``
1025 Windows registry key which describes install location of this
1028 Windows registry key which describes install location of this
1026 tool. Mercurial will search for this key first under
1029 tool. Mercurial will search for this key first under
1027 ``HKEY_CURRENT_USER`` and then under ``HKEY_LOCAL_MACHINE``.
1030 ``HKEY_CURRENT_USER`` and then under ``HKEY_LOCAL_MACHINE``.
1028 Default: None
1031 Default: None
1029
1032
1030 ``regkeyalt``
1033 ``regkeyalt``
1031 An alternate Windows registry key to try if the first key is not
1034 An alternate Windows registry key to try if the first key is not
1032 found. The alternate key uses the same ``regname`` and ``regappend``
1035 found. The alternate key uses the same ``regname`` and ``regappend``
1033 semantics of the primary key. The most common use for this key
1036 semantics of the primary key. The most common use for this key
1034 is to search for 32bit applications on 64bit operating systems.
1037 is to search for 32bit applications on 64bit operating systems.
1035 Default: None
1038 Default: None
1036
1039
1037 ``regname``
1040 ``regname``
1038 Name of value to read from specified registry key. Defaults to the
1041 Name of value to read from specified registry key. Defaults to the
1039 unnamed (default) value.
1042 unnamed (default) value.
1040
1043
1041 ``regappend``
1044 ``regappend``
1042 String to append to the value read from the registry, typically
1045 String to append to the value read from the registry, typically
1043 the executable name of the tool.
1046 the executable name of the tool.
1044 Default: None
1047 Default: None
1045
1048
1046
1049
1047 ``patch``
1050 ``patch``
1048 ---------
1051 ---------
1049
1052
1050 Settings used when applying patches, for instance through the 'import'
1053 Settings used when applying patches, for instance through the 'import'
1051 command or with Mercurial Queues extension.
1054 command or with Mercurial Queues extension.
1052
1055
1053 ``eol``
1056 ``eol``
1054 When set to 'strict' patch content and patched files end of lines
1057 When set to 'strict' patch content and patched files end of lines
1055 are preserved. When set to ``lf`` or ``crlf``, both files end of
1058 are preserved. When set to ``lf`` or ``crlf``, both files end of
1056 lines are ignored when patching and the result line endings are
1059 lines are ignored when patching and the result line endings are
1057 normalized to either LF (Unix) or CRLF (Windows). When set to
1060 normalized to either LF (Unix) or CRLF (Windows). When set to
1058 ``auto``, end of lines are again ignored while patching but line
1061 ``auto``, end of lines are again ignored while patching but line
1059 endings in patched files are normalized to their original setting
1062 endings in patched files are normalized to their original setting
1060 on a per-file basis. If target file does not exist or has no end
1063 on a per-file basis. If target file does not exist or has no end
1061 of line, patch line endings are preserved.
1064 of line, patch line endings are preserved.
1062 Default: strict.
1065 Default: strict.
1063
1066
1064
1067
1065 ``paths``
1068 ``paths``
1066 ---------
1069 ---------
1067
1070
1068 Assigns symbolic names to repositories. The left side is the
1071 Assigns symbolic names to repositories. The left side is the
1069 symbolic name, and the right gives the directory or URL that is the
1072 symbolic name, and the right gives the directory or URL that is the
1070 location of the repository. Default paths can be declared by setting
1073 location of the repository. Default paths can be declared by setting
1071 the following entries.
1074 the following entries.
1072
1075
1073 ``default``
1076 ``default``
1074 Directory or URL to use when pulling if no source is specified.
1077 Directory or URL to use when pulling if no source is specified.
1075 Default is set to repository from which the current repository was
1078 Default is set to repository from which the current repository was
1076 cloned.
1079 cloned.
1077
1080
1078 ``default-push``
1081 ``default-push``
1079 Optional. Directory or URL to use when pushing if no destination
1082 Optional. Directory or URL to use when pushing if no destination
1080 is specified.
1083 is specified.
1081
1084
1082 Custom paths can be defined by assigning the path to a name that later can be
1085 Custom paths can be defined by assigning the path to a name that later can be
1083 used from the command line. Example::
1086 used from the command line. Example::
1084
1087
1085 [paths]
1088 [paths]
1086 my_path = http://example.com/path
1089 my_path = http://example.com/path
1087
1090
1088 To push to the path defined in ``my_path`` run the command::
1091 To push to the path defined in ``my_path`` run the command::
1089
1092
1090 hg push my_path
1093 hg push my_path
1091
1094
1092
1095
1093 ``phases``
1096 ``phases``
1094 ----------
1097 ----------
1095
1098
1096 Specifies default handling of phases. See :hg:`help phases` for more
1099 Specifies default handling of phases. See :hg:`help phases` for more
1097 information about working with phases.
1100 information about working with phases.
1098
1101
1099 ``publish``
1102 ``publish``
1100 Controls draft phase behavior when working as a server. When true,
1103 Controls draft phase behavior when working as a server. When true,
1101 pushed changesets are set to public in both client and server and
1104 pushed changesets are set to public in both client and server and
1102 pulled or cloned changesets are set to public in the client.
1105 pulled or cloned changesets are set to public in the client.
1103 Default: True
1106 Default: True
1104
1107
1105 ``new-commit``
1108 ``new-commit``
1106 Phase of newly-created commits.
1109 Phase of newly-created commits.
1107 Default: draft
1110 Default: draft
1108
1111
1109 ``checksubrepos``
1112 ``checksubrepos``
1110 Check the phase of the current revision of each subrepository. Allowed
1113 Check the phase of the current revision of each subrepository. Allowed
1111 values are "ignore", "follow" and "abort". For settings other than
1114 values are "ignore", "follow" and "abort". For settings other than
1112 "ignore", the phase of the current revision of each subrepository is
1115 "ignore", the phase of the current revision of each subrepository is
1113 checked before committing the parent repository. If any of those phases is
1116 checked before committing the parent repository. If any of those phases is
1114 greater than the phase of the parent repository (e.g. if a subrepo is in a
1117 greater than the phase of the parent repository (e.g. if a subrepo is in a
1115 "secret" phase while the parent repo is in "draft" phase), the commit is
1118 "secret" phase while the parent repo is in "draft" phase), the commit is
1116 either aborted (if checksubrepos is set to "abort") or the higher phase is
1119 either aborted (if checksubrepos is set to "abort") or the higher phase is
1117 used for the parent repository commit (if set to "follow").
1120 used for the parent repository commit (if set to "follow").
1118 Default: "follow"
1121 Default: "follow"
1119
1122
1120
1123
1121 ``profiling``
1124 ``profiling``
1122 -------------
1125 -------------
1123
1126
1124 Specifies profiling type, format, and file output. Two profilers are
1127 Specifies profiling type, format, and file output. Two profilers are
1125 supported: an instrumenting profiler (named ``ls``), and a sampling
1128 supported: an instrumenting profiler (named ``ls``), and a sampling
1126 profiler (named ``stat``).
1129 profiler (named ``stat``).
1127
1130
1128 In this section description, 'profiling data' stands for the raw data
1131 In this section description, 'profiling data' stands for the raw data
1129 collected during profiling, while 'profiling report' stands for a
1132 collected during profiling, while 'profiling report' stands for a
1130 statistical text report generated from the profiling data. The
1133 statistical text report generated from the profiling data. The
1131 profiling is done using lsprof.
1134 profiling is done using lsprof.
1132
1135
1133 ``type``
1136 ``type``
1134 The type of profiler to use.
1137 The type of profiler to use.
1135 Default: ls.
1138 Default: ls.
1136
1139
1137 ``ls``
1140 ``ls``
1138 Use Python's built-in instrumenting profiler. This profiler
1141 Use Python's built-in instrumenting profiler. This profiler
1139 works on all platforms, but each line number it reports is the
1142 works on all platforms, but each line number it reports is the
1140 first line of a function. This restriction makes it difficult to
1143 first line of a function. This restriction makes it difficult to
1141 identify the expensive parts of a non-trivial function.
1144 identify the expensive parts of a non-trivial function.
1142 ``stat``
1145 ``stat``
1143 Use a third-party statistical profiler, statprof. This profiler
1146 Use a third-party statistical profiler, statprof. This profiler
1144 currently runs only on Unix systems, and is most useful for
1147 currently runs only on Unix systems, and is most useful for
1145 profiling commands that run for longer than about 0.1 seconds.
1148 profiling commands that run for longer than about 0.1 seconds.
1146
1149
1147 ``format``
1150 ``format``
1148 Profiling format. Specific to the ``ls`` instrumenting profiler.
1151 Profiling format. Specific to the ``ls`` instrumenting profiler.
1149 Default: text.
1152 Default: text.
1150
1153
1151 ``text``
1154 ``text``
1152 Generate a profiling report. When saving to a file, it should be
1155 Generate a profiling report. When saving to a file, it should be
1153 noted that only the report is saved, and the profiling data is
1156 noted that only the report is saved, and the profiling data is
1154 not kept.
1157 not kept.
1155 ``kcachegrind``
1158 ``kcachegrind``
1156 Format profiling data for kcachegrind use: when saving to a
1159 Format profiling data for kcachegrind use: when saving to a
1157 file, the generated file can directly be loaded into
1160 file, the generated file can directly be loaded into
1158 kcachegrind.
1161 kcachegrind.
1159
1162
1160 ``frequency``
1163 ``frequency``
1161 Sampling frequency. Specific to the ``stat`` sampling profiler.
1164 Sampling frequency. Specific to the ``stat`` sampling profiler.
1162 Default: 1000.
1165 Default: 1000.
1163
1166
1164 ``output``
1167 ``output``
1165 File path where profiling data or report should be saved. If the
1168 File path where profiling data or report should be saved. If the
1166 file exists, it is replaced. Default: None, data is printed on
1169 file exists, it is replaced. Default: None, data is printed on
1167 stderr
1170 stderr
1168
1171
1169 ``sort``
1172 ``sort``
1170 Sort field. Specific to the ``ls`` instrumenting profiler.
1173 Sort field. Specific to the ``ls`` instrumenting profiler.
1171 One of ``callcount``, ``reccallcount``, ``totaltime`` and
1174 One of ``callcount``, ``reccallcount``, ``totaltime`` and
1172 ``inlinetime``.
1175 ``inlinetime``.
1173 Default: inlinetime.
1176 Default: inlinetime.
1174
1177
1175 ``limit``
1178 ``limit``
1176 Number of lines to show. Specific to the ``ls`` instrumenting profiler.
1179 Number of lines to show. Specific to the ``ls`` instrumenting profiler.
1177 Default: 30.
1180 Default: 30.
1178
1181
1179 ``nested``
1182 ``nested``
1180 Show at most this number of lines of drill-down info after each main entry.
1183 Show at most this number of lines of drill-down info after each main entry.
1181 This can help explain the difference between Total and Inline.
1184 This can help explain the difference between Total and Inline.
1182 Specific to the ``ls`` instrumenting profiler.
1185 Specific to the ``ls`` instrumenting profiler.
1183 Default: 5.
1186 Default: 5.
1184
1187
1185 ``revsetalias``
1188 ``revsetalias``
1186 ---------------
1189 ---------------
1187
1190
1188 Alias definitions for revsets. See :hg:`help revsets` for details.
1191 Alias definitions for revsets. See :hg:`help revsets` for details.
1189
1192
1190 ``server``
1193 ``server``
1191 ----------
1194 ----------
1192
1195
1193 Controls generic server settings.
1196 Controls generic server settings.
1194
1197
1195 ``uncompressed``
1198 ``uncompressed``
1196 Whether to allow clients to clone a repository using the
1199 Whether to allow clients to clone a repository using the
1197 uncompressed streaming protocol. This transfers about 40% more
1200 uncompressed streaming protocol. This transfers about 40% more
1198 data than a regular clone, but uses less memory and CPU on both
1201 data than a regular clone, but uses less memory and CPU on both
1199 server and client. Over a LAN (100 Mbps or better) or a very fast
1202 server and client. Over a LAN (100 Mbps or better) or a very fast
1200 WAN, an uncompressed streaming clone is a lot faster (~10x) than a
1203 WAN, an uncompressed streaming clone is a lot faster (~10x) than a
1201 regular clone. Over most WAN connections (anything slower than
1204 regular clone. Over most WAN connections (anything slower than
1202 about 6 Mbps), uncompressed streaming is slower, because of the
1205 about 6 Mbps), uncompressed streaming is slower, because of the
1203 extra data transfer overhead. This mode will also temporarily hold
1206 extra data transfer overhead. This mode will also temporarily hold
1204 the write lock while determining what data to transfer.
1207 the write lock while determining what data to transfer.
1205 Default is True.
1208 Default is True.
1206
1209
1207 ``preferuncompressed``
1210 ``preferuncompressed``
1208 When set, clients will try to use the uncompressed streaming
1211 When set, clients will try to use the uncompressed streaming
1209 protocol. Default is False.
1212 protocol. Default is False.
1210
1213
1211 ``validate``
1214 ``validate``
1212 Whether to validate the completeness of pushed changesets by
1215 Whether to validate the completeness of pushed changesets by
1213 checking that all new file revisions specified in manifests are
1216 checking that all new file revisions specified in manifests are
1214 present. Default is False.
1217 present. Default is False.
1215
1218
1216 ``smtp``
1219 ``smtp``
1217 --------
1220 --------
1218
1221
1219 Configuration for extensions that need to send email messages.
1222 Configuration for extensions that need to send email messages.
1220
1223
1221 ``host``
1224 ``host``
1222 Host name of mail server, e.g. "mail.example.com".
1225 Host name of mail server, e.g. "mail.example.com".
1223
1226
1224 ``port``
1227 ``port``
1225 Optional. Port to connect to on mail server. Default: 465 (if
1228 Optional. Port to connect to on mail server. Default: 465 (if
1226 ``tls`` is smtps) or 25 (otherwise).
1229 ``tls`` is smtps) or 25 (otherwise).
1227
1230
1228 ``tls``
1231 ``tls``
1229 Optional. Method to enable TLS when connecting to mail server: starttls,
1232 Optional. Method to enable TLS when connecting to mail server: starttls,
1230 smtps or none. Default: none.
1233 smtps or none. Default: none.
1231
1234
1232 ``verifycert``
1235 ``verifycert``
1233 Optional. Verification for the certificate of mail server, when
1236 Optional. Verification for the certificate of mail server, when
1234 ``tls`` is starttls or smtps. "strict", "loose" or False. For
1237 ``tls`` is starttls or smtps. "strict", "loose" or False. For
1235 "strict" or "loose", the certificate is verified as same as the
1238 "strict" or "loose", the certificate is verified as same as the
1236 verification for HTTPS connections (see ``[hostfingerprints]`` and
1239 verification for HTTPS connections (see ``[hostfingerprints]`` and
1237 ``[web] cacerts`` also). For "strict", sending email is also
1240 ``[web] cacerts`` also). For "strict", sending email is also
1238 aborted, if there is no configuration for mail server in
1241 aborted, if there is no configuration for mail server in
1239 ``[hostfingerprints]`` and ``[web] cacerts``. --insecure for
1242 ``[hostfingerprints]`` and ``[web] cacerts``. --insecure for
1240 :hg:`email` overwrites this as "loose". Default: "strict".
1243 :hg:`email` overwrites this as "loose". Default: "strict".
1241
1244
1242 ``username``
1245 ``username``
1243 Optional. User name for authenticating with the SMTP server.
1246 Optional. User name for authenticating with the SMTP server.
1244 Default: none.
1247 Default: none.
1245
1248
1246 ``password``
1249 ``password``
1247 Optional. Password for authenticating with the SMTP server. If not
1250 Optional. Password for authenticating with the SMTP server. If not
1248 specified, interactive sessions will prompt the user for a
1251 specified, interactive sessions will prompt the user for a
1249 password; non-interactive sessions will fail. Default: none.
1252 password; non-interactive sessions will fail. Default: none.
1250
1253
1251 ``local_hostname``
1254 ``local_hostname``
1252 Optional. It's the hostname that the sender can use to identify
1255 Optional. It's the hostname that the sender can use to identify
1253 itself to the MTA.
1256 itself to the MTA.
1254
1257
1255
1258
1256 ``subpaths``
1259 ``subpaths``
1257 ------------
1260 ------------
1258
1261
1259 Subrepository source URLs can go stale if a remote server changes name
1262 Subrepository source URLs can go stale if a remote server changes name
1260 or becomes temporarily unavailable. This section lets you define
1263 or becomes temporarily unavailable. This section lets you define
1261 rewrite rules of the form::
1264 rewrite rules of the form::
1262
1265
1263 <pattern> = <replacement>
1266 <pattern> = <replacement>
1264
1267
1265 where ``pattern`` is a regular expression matching a subrepository
1268 where ``pattern`` is a regular expression matching a subrepository
1266 source URL and ``replacement`` is the replacement string used to
1269 source URL and ``replacement`` is the replacement string used to
1267 rewrite it. Groups can be matched in ``pattern`` and referenced in
1270 rewrite it. Groups can be matched in ``pattern`` and referenced in
1268 ``replacements``. For instance::
1271 ``replacements``. For instance::
1269
1272
1270 http://server/(.*)-hg/ = http://hg.server/\1/
1273 http://server/(.*)-hg/ = http://hg.server/\1/
1271
1274
1272 rewrites ``http://server/foo-hg/`` into ``http://hg.server/foo/``.
1275 rewrites ``http://server/foo-hg/`` into ``http://hg.server/foo/``.
1273
1276
1274 Relative subrepository paths are first made absolute, and the
1277 Relative subrepository paths are first made absolute, and the
1275 rewrite rules are then applied on the full (absolute) path. The rules
1278 rewrite rules are then applied on the full (absolute) path. The rules
1276 are applied in definition order.
1279 are applied in definition order.
1277
1280
1278 ``trusted``
1281 ``trusted``
1279 -----------
1282 -----------
1280
1283
1281 Mercurial will not use the settings in the
1284 Mercurial will not use the settings in the
1282 ``.hg/hgrc`` file from a repository if it doesn't belong to a trusted
1285 ``.hg/hgrc`` file from a repository if it doesn't belong to a trusted
1283 user or to a trusted group, as various hgrc features allow arbitrary
1286 user or to a trusted group, as various hgrc features allow arbitrary
1284 commands to be run. This issue is often encountered when configuring
1287 commands to be run. This issue is often encountered when configuring
1285 hooks or extensions for shared repositories or servers. However,
1288 hooks or extensions for shared repositories or servers. However,
1286 the web interface will use some safe settings from the ``[web]``
1289 the web interface will use some safe settings from the ``[web]``
1287 section.
1290 section.
1288
1291
1289 This section specifies what users and groups are trusted. The
1292 This section specifies what users and groups are trusted. The
1290 current user is always trusted. To trust everybody, list a user or a
1293 current user is always trusted. To trust everybody, list a user or a
1291 group with name ``*``. These settings must be placed in an
1294 group with name ``*``. These settings must be placed in an
1292 *already-trusted file* to take effect, such as ``$HOME/.hgrc`` of the
1295 *already-trusted file* to take effect, such as ``$HOME/.hgrc`` of the
1293 user or service running Mercurial.
1296 user or service running Mercurial.
1294
1297
1295 ``users``
1298 ``users``
1296 Comma-separated list of trusted users.
1299 Comma-separated list of trusted users.
1297
1300
1298 ``groups``
1301 ``groups``
1299 Comma-separated list of trusted groups.
1302 Comma-separated list of trusted groups.
1300
1303
1301
1304
1302 ``ui``
1305 ``ui``
1303 ------
1306 ------
1304
1307
1305 User interface controls.
1308 User interface controls.
1306
1309
1307 ``archivemeta``
1310 ``archivemeta``
1308 Whether to include the .hg_archival.txt file containing meta data
1311 Whether to include the .hg_archival.txt file containing meta data
1309 (hashes for the repository base and for tip) in archives created
1312 (hashes for the repository base and for tip) in archives created
1310 by the :hg:`archive` command or downloaded via hgweb.
1313 by the :hg:`archive` command or downloaded via hgweb.
1311 Default is True.
1314 Default is True.
1312
1315
1313 ``askusername``
1316 ``askusername``
1314 Whether to prompt for a username when committing. If True, and
1317 Whether to prompt for a username when committing. If True, and
1315 neither ``$HGUSER`` nor ``$EMAIL`` has been specified, then the user will
1318 neither ``$HGUSER`` nor ``$EMAIL`` has been specified, then the user will
1316 be prompted to enter a username. If no username is entered, the
1319 be prompted to enter a username. If no username is entered, the
1317 default ``USER@HOST`` is used instead.
1320 default ``USER@HOST`` is used instead.
1318 Default is False.
1321 Default is False.
1319
1322
1320 ``commitsubrepos``
1323 ``commitsubrepos``
1321 Whether to commit modified subrepositories when committing the
1324 Whether to commit modified subrepositories when committing the
1322 parent repository. If False and one subrepository has uncommitted
1325 parent repository. If False and one subrepository has uncommitted
1323 changes, abort the commit.
1326 changes, abort the commit.
1324 Default is False.
1327 Default is False.
1325
1328
1326 ``debug``
1329 ``debug``
1327 Print debugging information. True or False. Default is False.
1330 Print debugging information. True or False. Default is False.
1328
1331
1329 ``editor``
1332 ``editor``
1330 The editor to use during a commit. Default is ``$EDITOR`` or ``vi``.
1333 The editor to use during a commit. Default is ``$EDITOR`` or ``vi``.
1331
1334
1332 ``fallbackencoding``
1335 ``fallbackencoding``
1333 Encoding to try if it's not possible to decode the changelog using
1336 Encoding to try if it's not possible to decode the changelog using
1334 UTF-8. Default is ISO-8859-1.
1337 UTF-8. Default is ISO-8859-1.
1335
1338
1336 ``ignore``
1339 ``ignore``
1337 A file to read per-user ignore patterns from. This file should be
1340 A file to read per-user ignore patterns from. This file should be
1338 in the same format as a repository-wide .hgignore file. This
1341 in the same format as a repository-wide .hgignore file. This
1339 option supports hook syntax, so if you want to specify multiple
1342 option supports hook syntax, so if you want to specify multiple
1340 ignore files, you can do so by setting something like
1343 ignore files, you can do so by setting something like
1341 ``ignore.other = ~/.hgignore2``. For details of the ignore file
1344 ``ignore.other = ~/.hgignore2``. For details of the ignore file
1342 format, see the ``hgignore(5)`` man page.
1345 format, see the ``hgignore(5)`` man page.
1343
1346
1344 ``interactive``
1347 ``interactive``
1345 Allow to prompt the user. True or False. Default is True.
1348 Allow to prompt the user. True or False. Default is True.
1346
1349
1347 ``logtemplate``
1350 ``logtemplate``
1348 Template string for commands that print changesets.
1351 Template string for commands that print changesets.
1349
1352
1350 ``merge``
1353 ``merge``
1351 The conflict resolution program to use during a manual merge.
1354 The conflict resolution program to use during a manual merge.
1352 For more information on merge tools see :hg:`help merge-tools`.
1355 For more information on merge tools see :hg:`help merge-tools`.
1353 For configuring merge tools see the ``[merge-tools]`` section.
1356 For configuring merge tools see the ``[merge-tools]`` section.
1354
1357
1355 ``mergemarkers``
1358 ``mergemarkers``
1356 Sets the merge conflict marker label styling. The ``detailed``
1359 Sets the merge conflict marker label styling. The ``detailed``
1357 style uses the ``mergemarkertemplate`` setting to style the labels.
1360 style uses the ``mergemarkertemplate`` setting to style the labels.
1358 The ``basic`` style just uses 'local' and 'other' as the marker label.
1361 The ``basic`` style just uses 'local' and 'other' as the marker label.
1359 One of ``basic`` or ``detailed``.
1362 One of ``basic`` or ``detailed``.
1360 Default is ``basic``.
1363 Default is ``basic``.
1361
1364
1362 ``mergemarkertemplate``
1365 ``mergemarkertemplate``
1363 The template used to print the commit description next to each conflict
1366 The template used to print the commit description next to each conflict
1364 marker during merge conflicts. See :hg:`help templates` for the template
1367 marker during merge conflicts. See :hg:`help templates` for the template
1365 format.
1368 format.
1366 Defaults to showing the hash, tags, branches, bookmarks, author, and
1369 Defaults to showing the hash, tags, branches, bookmarks, author, and
1367 the first line of the commit description.
1370 the first line of the commit description.
1368 You have to pay attention to encodings of managed files, if you
1371 You have to pay attention to encodings of managed files, if you
1369 use non-ASCII characters in tags, branches, bookmarks, author
1372 use non-ASCII characters in tags, branches, bookmarks, author
1370 and/or commit descriptions. At template expansion, non-ASCII
1373 and/or commit descriptions. At template expansion, non-ASCII
1371 characters use the encoding specified by ``--encoding`` global
1374 characters use the encoding specified by ``--encoding`` global
1372 option, ``HGENCODING`` or other locale setting environment
1375 option, ``HGENCODING`` or other locale setting environment
1373 variables. The difference of encoding between merged file and
1376 variables. The difference of encoding between merged file and
1374 conflict markers causes serious problem.
1377 conflict markers causes serious problem.
1375
1378
1376 ``portablefilenames``
1379 ``portablefilenames``
1377 Check for portable filenames. Can be ``warn``, ``ignore`` or ``abort``.
1380 Check for portable filenames. Can be ``warn``, ``ignore`` or ``abort``.
1378 Default is ``warn``.
1381 Default is ``warn``.
1379 If set to ``warn`` (or ``true``), a warning message is printed on POSIX
1382 If set to ``warn`` (or ``true``), a warning message is printed on POSIX
1380 platforms, if a file with a non-portable filename is added (e.g. a file
1383 platforms, if a file with a non-portable filename is added (e.g. a file
1381 with a name that can't be created on Windows because it contains reserved
1384 with a name that can't be created on Windows because it contains reserved
1382 parts like ``AUX``, reserved characters like ``:``, or would cause a case
1385 parts like ``AUX``, reserved characters like ``:``, or would cause a case
1383 collision with an existing file).
1386 collision with an existing file).
1384 If set to ``ignore`` (or ``false``), no warning is printed.
1387 If set to ``ignore`` (or ``false``), no warning is printed.
1385 If set to ``abort``, the command is aborted.
1388 If set to ``abort``, the command is aborted.
1386 On Windows, this configuration option is ignored and the command aborted.
1389 On Windows, this configuration option is ignored and the command aborted.
1387
1390
1388 ``quiet``
1391 ``quiet``
1389 Reduce the amount of output printed. True or False. Default is False.
1392 Reduce the amount of output printed. True or False. Default is False.
1390
1393
1391 ``remotecmd``
1394 ``remotecmd``
1392 remote command to use for clone/push/pull operations. Default is ``hg``.
1395 remote command to use for clone/push/pull operations. Default is ``hg``.
1393
1396
1394 ``reportoldssl``
1397 ``reportoldssl``
1395 Warn if an SSL certificate is unable to be used due to using Python
1398 Warn if an SSL certificate is unable to be used due to using Python
1396 2.5 or earlier. True or False. Default is True.
1399 2.5 or earlier. True or False. Default is True.
1397
1400
1398 ``report_untrusted``
1401 ``report_untrusted``
1399 Warn if a ``.hg/hgrc`` file is ignored due to not being owned by a
1402 Warn if a ``.hg/hgrc`` file is ignored due to not being owned by a
1400 trusted user or group. True or False. Default is True.
1403 trusted user or group. True or False. Default is True.
1401
1404
1402 ``slash``
1405 ``slash``
1403 Display paths using a slash (``/``) as the path separator. This
1406 Display paths using a slash (``/``) as the path separator. This
1404 only makes a difference on systems where the default path
1407 only makes a difference on systems where the default path
1405 separator is not the slash character (e.g. Windows uses the
1408 separator is not the slash character (e.g. Windows uses the
1406 backslash character (``\``)).
1409 backslash character (``\``)).
1407 Default is False.
1410 Default is False.
1408
1411
1409 ``ssh``
1412 ``ssh``
1410 command to use for SSH connections. Default is ``ssh``.
1413 command to use for SSH connections. Default is ``ssh``.
1411
1414
1412 ``strict``
1415 ``strict``
1413 Require exact command names, instead of allowing unambiguous
1416 Require exact command names, instead of allowing unambiguous
1414 abbreviations. True or False. Default is False.
1417 abbreviations. True or False. Default is False.
1415
1418
1416 ``style``
1419 ``style``
1417 Name of style to use for command output.
1420 Name of style to use for command output.
1418
1421
1419 ``timeout``
1422 ``timeout``
1420 The timeout used when a lock is held (in seconds), a negative value
1423 The timeout used when a lock is held (in seconds), a negative value
1421 means no timeout. Default is 600.
1424 means no timeout. Default is 600.
1422
1425
1423 ``traceback``
1426 ``traceback``
1424 Mercurial always prints a traceback when an unknown exception
1427 Mercurial always prints a traceback when an unknown exception
1425 occurs. Setting this to True will make Mercurial print a traceback
1428 occurs. Setting this to True will make Mercurial print a traceback
1426 on all exceptions, even those recognized by Mercurial (such as
1429 on all exceptions, even those recognized by Mercurial (such as
1427 IOError or MemoryError). Default is False.
1430 IOError or MemoryError). Default is False.
1428
1431
1429 ``username``
1432 ``username``
1430 The committer of a changeset created when running "commit".
1433 The committer of a changeset created when running "commit".
1431 Typically a person's name and email address, e.g. ``Fred Widget
1434 Typically a person's name and email address, e.g. ``Fred Widget
1432 <fred@example.com>``. Default is ``$EMAIL`` or ``username@hostname``. If
1435 <fred@example.com>``. Default is ``$EMAIL`` or ``username@hostname``. If
1433 the username in hgrc is empty, it has to be specified manually or
1436 the username in hgrc is empty, it has to be specified manually or
1434 in a different hgrc file (e.g. ``$HOME/.hgrc``, if the admin set
1437 in a different hgrc file (e.g. ``$HOME/.hgrc``, if the admin set
1435 ``username =`` in the system hgrc). Environment variables in the
1438 ``username =`` in the system hgrc). Environment variables in the
1436 username are expanded.
1439 username are expanded.
1437
1440
1438 ``verbose``
1441 ``verbose``
1439 Increase the amount of output printed. True or False. Default is False.
1442 Increase the amount of output printed. True or False. Default is False.
1440
1443
1441
1444
1442 ``web``
1445 ``web``
1443 -------
1446 -------
1444
1447
1445 Web interface configuration. The settings in this section apply to
1448 Web interface configuration. The settings in this section apply to
1446 both the builtin webserver (started by :hg:`serve`) and the script you
1449 both the builtin webserver (started by :hg:`serve`) and the script you
1447 run through a webserver (``hgweb.cgi`` and the derivatives for FastCGI
1450 run through a webserver (``hgweb.cgi`` and the derivatives for FastCGI
1448 and WSGI).
1451 and WSGI).
1449
1452
1450 The Mercurial webserver does no authentication (it does not prompt for
1453 The Mercurial webserver does no authentication (it does not prompt for
1451 usernames and passwords to validate *who* users are), but it does do
1454 usernames and passwords to validate *who* users are), but it does do
1452 authorization (it grants or denies access for *authenticated users*
1455 authorization (it grants or denies access for *authenticated users*
1453 based on settings in this section). You must either configure your
1456 based on settings in this section). You must either configure your
1454 webserver to do authentication for you, or disable the authorization
1457 webserver to do authentication for you, or disable the authorization
1455 checks.
1458 checks.
1456
1459
1457 For a quick setup in a trusted environment, e.g., a private LAN, where
1460 For a quick setup in a trusted environment, e.g., a private LAN, where
1458 you want it to accept pushes from anybody, you can use the following
1461 you want it to accept pushes from anybody, you can use the following
1459 command line::
1462 command line::
1460
1463
1461 $ hg --config web.allow_push=* --config web.push_ssl=False serve
1464 $ hg --config web.allow_push=* --config web.push_ssl=False serve
1462
1465
1463 Note that this will allow anybody to push anything to the server and
1466 Note that this will allow anybody to push anything to the server and
1464 that this should not be used for public servers.
1467 that this should not be used for public servers.
1465
1468
1466 The full set of options is:
1469 The full set of options is:
1467
1470
1468 ``accesslog``
1471 ``accesslog``
1469 Where to output the access log. Default is stdout.
1472 Where to output the access log. Default is stdout.
1470
1473
1471 ``address``
1474 ``address``
1472 Interface address to bind to. Default is all.
1475 Interface address to bind to. Default is all.
1473
1476
1474 ``allow_archive``
1477 ``allow_archive``
1475 List of archive format (bz2, gz, zip) allowed for downloading.
1478 List of archive format (bz2, gz, zip) allowed for downloading.
1476 Default is empty.
1479 Default is empty.
1477
1480
1478 ``allowbz2``
1481 ``allowbz2``
1479 (DEPRECATED) Whether to allow .tar.bz2 downloading of repository
1482 (DEPRECATED) Whether to allow .tar.bz2 downloading of repository
1480 revisions.
1483 revisions.
1481 Default is False.
1484 Default is False.
1482
1485
1483 ``allowgz``
1486 ``allowgz``
1484 (DEPRECATED) Whether to allow .tar.gz downloading of repository
1487 (DEPRECATED) Whether to allow .tar.gz downloading of repository
1485 revisions.
1488 revisions.
1486 Default is False.
1489 Default is False.
1487
1490
1488 ``allowpull``
1491 ``allowpull``
1489 Whether to allow pulling from the repository. Default is True.
1492 Whether to allow pulling from the repository. Default is True.
1490
1493
1491 ``allow_push``
1494 ``allow_push``
1492 Whether to allow pushing to the repository. If empty or not set,
1495 Whether to allow pushing to the repository. If empty or not set,
1493 push is not allowed. If the special value ``*``, any remote user can
1496 push is not allowed. If the special value ``*``, any remote user can
1494 push, including unauthenticated users. Otherwise, the remote user
1497 push, including unauthenticated users. Otherwise, the remote user
1495 must have been authenticated, and the authenticated user name must
1498 must have been authenticated, and the authenticated user name must
1496 be present in this list. The contents of the allow_push list are
1499 be present in this list. The contents of the allow_push list are
1497 examined after the deny_push list.
1500 examined after the deny_push list.
1498
1501
1499 ``allow_read``
1502 ``allow_read``
1500 If the user has not already been denied repository access due to
1503 If the user has not already been denied repository access due to
1501 the contents of deny_read, this list determines whether to grant
1504 the contents of deny_read, this list determines whether to grant
1502 repository access to the user. If this list is not empty, and the
1505 repository access to the user. If this list is not empty, and the
1503 user is unauthenticated or not present in the list, then access is
1506 user is unauthenticated or not present in the list, then access is
1504 denied for the user. If the list is empty or not set, then access
1507 denied for the user. If the list is empty or not set, then access
1505 is permitted to all users by default. Setting allow_read to the
1508 is permitted to all users by default. Setting allow_read to the
1506 special value ``*`` is equivalent to it not being set (i.e. access
1509 special value ``*`` is equivalent to it not being set (i.e. access
1507 is permitted to all users). The contents of the allow_read list are
1510 is permitted to all users). The contents of the allow_read list are
1508 examined after the deny_read list.
1511 examined after the deny_read list.
1509
1512
1510 ``allowzip``
1513 ``allowzip``
1511 (DEPRECATED) Whether to allow .zip downloading of repository
1514 (DEPRECATED) Whether to allow .zip downloading of repository
1512 revisions. Default is False. This feature creates temporary files.
1515 revisions. Default is False. This feature creates temporary files.
1513
1516
1514 ``archivesubrepos``
1517 ``archivesubrepos``
1515 Whether to recurse into subrepositories when archiving. Default is
1518 Whether to recurse into subrepositories when archiving. Default is
1516 False.
1519 False.
1517
1520
1518 ``baseurl``
1521 ``baseurl``
1519 Base URL to use when publishing URLs in other locations, so
1522 Base URL to use when publishing URLs in other locations, so
1520 third-party tools like email notification hooks can construct
1523 third-party tools like email notification hooks can construct
1521 URLs. Example: ``http://hgserver/repos/``.
1524 URLs. Example: ``http://hgserver/repos/``.
1522
1525
1523 ``cacerts``
1526 ``cacerts``
1524 Path to file containing a list of PEM encoded certificate
1527 Path to file containing a list of PEM encoded certificate
1525 authority certificates. Environment variables and ``~user``
1528 authority certificates. Environment variables and ``~user``
1526 constructs are expanded in the filename. If specified on the
1529 constructs are expanded in the filename. If specified on the
1527 client, then it will verify the identity of remote HTTPS servers
1530 client, then it will verify the identity of remote HTTPS servers
1528 with these certificates.
1531 with these certificates.
1529
1532
1530 This feature is only supported when using Python 2.6 or later. If you wish
1533 This feature is only supported when using Python 2.6 or later. If you wish
1531 to use it with earlier versions of Python, install the backported
1534 to use it with earlier versions of Python, install the backported
1532 version of the ssl library that is available from
1535 version of the ssl library that is available from
1533 ``http://pypi.python.org``.
1536 ``http://pypi.python.org``.
1534
1537
1535 To disable SSL verification temporarily, specify ``--insecure`` from
1538 To disable SSL verification temporarily, specify ``--insecure`` from
1536 command line.
1539 command line.
1537
1540
1538 You can use OpenSSL's CA certificate file if your platform has
1541 You can use OpenSSL's CA certificate file if your platform has
1539 one. On most Linux systems this will be
1542 one. On most Linux systems this will be
1540 ``/etc/ssl/certs/ca-certificates.crt``. Otherwise you will have to
1543 ``/etc/ssl/certs/ca-certificates.crt``. Otherwise you will have to
1541 generate this file manually. The form must be as follows::
1544 generate this file manually. The form must be as follows::
1542
1545
1543 -----BEGIN CERTIFICATE-----
1546 -----BEGIN CERTIFICATE-----
1544 ... (certificate in base64 PEM encoding) ...
1547 ... (certificate in base64 PEM encoding) ...
1545 -----END CERTIFICATE-----
1548 -----END CERTIFICATE-----
1546 -----BEGIN CERTIFICATE-----
1549 -----BEGIN CERTIFICATE-----
1547 ... (certificate in base64 PEM encoding) ...
1550 ... (certificate in base64 PEM encoding) ...
1548 -----END CERTIFICATE-----
1551 -----END CERTIFICATE-----
1549
1552
1550 ``cache``
1553 ``cache``
1551 Whether to support caching in hgweb. Defaults to True.
1554 Whether to support caching in hgweb. Defaults to True.
1552
1555
1553 ``collapse``
1556 ``collapse``
1554 With ``descend`` enabled, repositories in subdirectories are shown at
1557 With ``descend`` enabled, repositories in subdirectories are shown at
1555 a single level alongside repositories in the current path. With
1558 a single level alongside repositories in the current path. With
1556 ``collapse`` also enabled, repositories residing at a deeper level than
1559 ``collapse`` also enabled, repositories residing at a deeper level than
1557 the current path are grouped behind navigable directory entries that
1560 the current path are grouped behind navigable directory entries that
1558 lead to the locations of these repositories. In effect, this setting
1561 lead to the locations of these repositories. In effect, this setting
1559 collapses each collection of repositories found within a subdirectory
1562 collapses each collection of repositories found within a subdirectory
1560 into a single entry for that subdirectory. Default is False.
1563 into a single entry for that subdirectory. Default is False.
1561
1564
1562 ``comparisoncontext``
1565 ``comparisoncontext``
1563 Number of lines of context to show in side-by-side file comparison. If
1566 Number of lines of context to show in side-by-side file comparison. If
1564 negative or the value ``full``, whole files are shown. Default is 5.
1567 negative or the value ``full``, whole files are shown. Default is 5.
1565 This setting can be overridden by a ``context`` request parameter to the
1568 This setting can be overridden by a ``context`` request parameter to the
1566 ``comparison`` command, taking the same values.
1569 ``comparison`` command, taking the same values.
1567
1570
1568 ``contact``
1571 ``contact``
1569 Name or email address of the person in charge of the repository.
1572 Name or email address of the person in charge of the repository.
1570 Defaults to ui.username or ``$EMAIL`` or "unknown" if unset or empty.
1573 Defaults to ui.username or ``$EMAIL`` or "unknown" if unset or empty.
1571
1574
1572 ``deny_push``
1575 ``deny_push``
1573 Whether to deny pushing to the repository. If empty or not set,
1576 Whether to deny pushing to the repository. If empty or not set,
1574 push is not denied. If the special value ``*``, all remote users are
1577 push is not denied. If the special value ``*``, all remote users are
1575 denied push. Otherwise, unauthenticated users are all denied, and
1578 denied push. Otherwise, unauthenticated users are all denied, and
1576 any authenticated user name present in this list is also denied. The
1579 any authenticated user name present in this list is also denied. The
1577 contents of the deny_push list are examined before the allow_push list.
1580 contents of the deny_push list are examined before the allow_push list.
1578
1581
1579 ``deny_read``
1582 ``deny_read``
1580 Whether to deny reading/viewing of the repository. If this list is
1583 Whether to deny reading/viewing of the repository. If this list is
1581 not empty, unauthenticated users are all denied, and any
1584 not empty, unauthenticated users are all denied, and any
1582 authenticated user name present in this list is also denied access to
1585 authenticated user name present in this list is also denied access to
1583 the repository. If set to the special value ``*``, all remote users
1586 the repository. If set to the special value ``*``, all remote users
1584 are denied access (rarely needed ;). If deny_read is empty or not set,
1587 are denied access (rarely needed ;). If deny_read is empty or not set,
1585 the determination of repository access depends on the presence and
1588 the determination of repository access depends on the presence and
1586 content of the allow_read list (see description). If both
1589 content of the allow_read list (see description). If both
1587 deny_read and allow_read are empty or not set, then access is
1590 deny_read and allow_read are empty or not set, then access is
1588 permitted to all users by default. If the repository is being
1591 permitted to all users by default. If the repository is being
1589 served via hgwebdir, denied users will not be able to see it in
1592 served via hgwebdir, denied users will not be able to see it in
1590 the list of repositories. The contents of the deny_read list have
1593 the list of repositories. The contents of the deny_read list have
1591 priority over (are examined before) the contents of the allow_read
1594 priority over (are examined before) the contents of the allow_read
1592 list.
1595 list.
1593
1596
1594 ``descend``
1597 ``descend``
1595 hgwebdir indexes will not descend into subdirectories. Only repositories
1598 hgwebdir indexes will not descend into subdirectories. Only repositories
1596 directly in the current path will be shown (other repositories are still
1599 directly in the current path will be shown (other repositories are still
1597 available from the index corresponding to their containing path).
1600 available from the index corresponding to their containing path).
1598
1601
1599 ``description``
1602 ``description``
1600 Textual description of the repository's purpose or contents.
1603 Textual description of the repository's purpose or contents.
1601 Default is "unknown".
1604 Default is "unknown".
1602
1605
1603 ``encoding``
1606 ``encoding``
1604 Character encoding name. Default is the current locale charset.
1607 Character encoding name. Default is the current locale charset.
1605 Example: "UTF-8"
1608 Example: "UTF-8"
1606
1609
1607 ``errorlog``
1610 ``errorlog``
1608 Where to output the error log. Default is stderr.
1611 Where to output the error log. Default is stderr.
1609
1612
1610 ``guessmime``
1613 ``guessmime``
1611 Control MIME types for raw download of file content.
1614 Control MIME types for raw download of file content.
1612 Set to True to let hgweb guess the content type from the file
1615 Set to True to let hgweb guess the content type from the file
1613 extension. This will serve HTML files as ``text/html`` and might
1616 extension. This will serve HTML files as ``text/html`` and might
1614 allow cross-site scripting attacks when serving untrusted
1617 allow cross-site scripting attacks when serving untrusted
1615 repositories. Default is False.
1618 repositories. Default is False.
1616
1619
1617 ``hidden``
1620 ``hidden``
1618 Whether to hide the repository in the hgwebdir index.
1621 Whether to hide the repository in the hgwebdir index.
1619 Default is False.
1622 Default is False.
1620
1623
1621 ``ipv6``
1624 ``ipv6``
1622 Whether to use IPv6. Default is False.
1625 Whether to use IPv6. Default is False.
1623
1626
1624 ``logoimg``
1627 ``logoimg``
1625 File name of the logo image that some templates display on each page.
1628 File name of the logo image that some templates display on each page.
1626 The file name is relative to ``staticurl``. That is, the full path to
1629 The file name is relative to ``staticurl``. That is, the full path to
1627 the logo image is "staticurl/logoimg".
1630 the logo image is "staticurl/logoimg".
1628 If unset, ``hglogo.png`` will be used.
1631 If unset, ``hglogo.png`` will be used.
1629
1632
1630 ``logourl``
1633 ``logourl``
1631 Base URL to use for logos. If unset, ``http://mercurial.selenic.com/``
1634 Base URL to use for logos. If unset, ``http://mercurial.selenic.com/``
1632 will be used.
1635 will be used.
1633
1636
1634 ``maxchanges``
1637 ``maxchanges``
1635 Maximum number of changes to list on the changelog. Default is 10.
1638 Maximum number of changes to list on the changelog. Default is 10.
1636
1639
1637 ``maxfiles``
1640 ``maxfiles``
1638 Maximum number of files to list per changeset. Default is 10.
1641 Maximum number of files to list per changeset. Default is 10.
1639
1642
1640 ``maxshortchanges``
1643 ``maxshortchanges``
1641 Maximum number of changes to list on the shortlog, graph or filelog
1644 Maximum number of changes to list on the shortlog, graph or filelog
1642 pages. Default is 60.
1645 pages. Default is 60.
1643
1646
1644 ``name``
1647 ``name``
1645 Repository name to use in the web interface. Default is current
1648 Repository name to use in the web interface. Default is current
1646 working directory.
1649 working directory.
1647
1650
1648 ``port``
1651 ``port``
1649 Port to listen on. Default is 8000.
1652 Port to listen on. Default is 8000.
1650
1653
1651 ``prefix``
1654 ``prefix``
1652 Prefix path to serve from. Default is '' (server root).
1655 Prefix path to serve from. Default is '' (server root).
1653
1656
1654 ``push_ssl``
1657 ``push_ssl``
1655 Whether to require that inbound pushes be transported over SSL to
1658 Whether to require that inbound pushes be transported over SSL to
1656 prevent password sniffing. Default is True.
1659 prevent password sniffing. Default is True.
1657
1660
1658 ``staticurl``
1661 ``staticurl``
1659 Base URL to use for static files. If unset, static files (e.g. the
1662 Base URL to use for static files. If unset, static files (e.g. the
1660 hgicon.png favicon) will be served by the CGI script itself. Use
1663 hgicon.png favicon) will be served by the CGI script itself. Use
1661 this setting to serve them directly with the HTTP server.
1664 this setting to serve them directly with the HTTP server.
1662 Example: ``http://hgserver/static/``.
1665 Example: ``http://hgserver/static/``.
1663
1666
1664 ``stripes``
1667 ``stripes``
1665 How many lines a "zebra stripe" should span in multi-line output.
1668 How many lines a "zebra stripe" should span in multi-line output.
1666 Default is 1; set to 0 to disable.
1669 Default is 1; set to 0 to disable.
1667
1670
1668 ``style``
1671 ``style``
1669 Which template map style to use. The available options are the names of
1672 Which template map style to use. The available options are the names of
1670 subdirectories in the HTML templates path. Default is ``paper``.
1673 subdirectories in the HTML templates path. Default is ``paper``.
1671 Example: ``monoblue``
1674 Example: ``monoblue``
1672
1675
1673 ``templates``
1676 ``templates``
1674 Where to find the HTML templates. The default path to the HTML templates
1677 Where to find the HTML templates. The default path to the HTML templates
1675 can be obtained from ``hg debuginstall``.
1678 can be obtained from ``hg debuginstall``.
1676
1679
1677 ``websub``
1680 ``websub``
1678 ----------
1681 ----------
1679
1682
1680 Web substitution filter definition. You can use this section to
1683 Web substitution filter definition. You can use this section to
1681 define a set of regular expression substitution patterns which
1684 define a set of regular expression substitution patterns which
1682 let you automatically modify the hgweb server output.
1685 let you automatically modify the hgweb server output.
1683
1686
1684 The default hgweb templates only apply these substitution patterns
1687 The default hgweb templates only apply these substitution patterns
1685 on the revision description fields. You can apply them anywhere
1688 on the revision description fields. You can apply them anywhere
1686 you want when you create your own templates by adding calls to the
1689 you want when you create your own templates by adding calls to the
1687 "websub" filter (usually after calling the "escape" filter).
1690 "websub" filter (usually after calling the "escape" filter).
1688
1691
1689 This can be used, for example, to convert issue references to links
1692 This can be used, for example, to convert issue references to links
1690 to your issue tracker, or to convert "markdown-like" syntax into
1693 to your issue tracker, or to convert "markdown-like" syntax into
1691 HTML (see the examples below).
1694 HTML (see the examples below).
1692
1695
1693 Each entry in this section names a substitution filter.
1696 Each entry in this section names a substitution filter.
1694 The value of each entry defines the substitution expression itself.
1697 The value of each entry defines the substitution expression itself.
1695 The websub expressions follow the old interhg extension syntax,
1698 The websub expressions follow the old interhg extension syntax,
1696 which in turn imitates the Unix sed replacement syntax::
1699 which in turn imitates the Unix sed replacement syntax::
1697
1700
1698 patternname = s/SEARCH_REGEX/REPLACE_EXPRESSION/[i]
1701 patternname = s/SEARCH_REGEX/REPLACE_EXPRESSION/[i]
1699
1702
1700 You can use any separator other than "/". The final "i" is optional
1703 You can use any separator other than "/". The final "i" is optional
1701 and indicates that the search must be case insensitive.
1704 and indicates that the search must be case insensitive.
1702
1705
1703 Examples::
1706 Examples::
1704
1707
1705 [websub]
1708 [websub]
1706 issues = s|issue(\d+)|<a href="http://bts.example.org/issue\1">issue\1</a>|i
1709 issues = s|issue(\d+)|<a href="http://bts.example.org/issue\1">issue\1</a>|i
1707 italic = s/\b_(\S+)_\b/<i>\1<\/i>/
1710 italic = s/\b_(\S+)_\b/<i>\1<\/i>/
1708 bold = s/\*\b(\S+)\b\*/<b>\1<\/b>/
1711 bold = s/\*\b(\S+)\b\*/<b>\1<\/b>/
1709
1712
1710 ``worker``
1713 ``worker``
1711 ----------
1714 ----------
1712
1715
1713 Parallel master/worker configuration. We currently perform working
1716 Parallel master/worker configuration. We currently perform working
1714 directory updates in parallel on Unix-like systems, which greatly
1717 directory updates in parallel on Unix-like systems, which greatly
1715 helps performance.
1718 helps performance.
1716
1719
1717 ``numcpus``
1720 ``numcpus``
1718 Number of CPUs to use for parallel operations. Default is 4 or the
1721 Number of CPUs to use for parallel operations. Default is 4 or the
1719 number of CPUs on the system, whichever is larger. A zero or
1722 number of CPUs on the system, whichever is larger. A zero or
1720 negative value is treated as ``use the default``.
1723 negative value is treated as ``use the default``.
@@ -1,1951 +1,1952 b''
1 # patch.py - patch file parsing routines
1 # patch.py - patch file parsing routines
2 #
2 #
3 # Copyright 2006 Brendan Cully <brendan@kublai.com>
3 # Copyright 2006 Brendan Cully <brendan@kublai.com>
4 # Copyright 2007 Chris Mason <chris.mason@oracle.com>
4 # Copyright 2007 Chris Mason <chris.mason@oracle.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 import cStringIO, email, os, errno, re, posixpath
9 import cStringIO, email, os, errno, re, posixpath
10 import tempfile, zlib, shutil
10 import tempfile, zlib, shutil
11 # On python2.4 you have to import these by name or they fail to
11 # On python2.4 you have to import these by name or they fail to
12 # load. This was not a problem on Python 2.7.
12 # load. This was not a problem on Python 2.7.
13 import email.Generator
13 import email.Generator
14 import email.Parser
14 import email.Parser
15
15
16 from i18n import _
16 from i18n import _
17 from node import hex, short
17 from node import hex, short
18 import base85, mdiff, scmutil, util, diffhelpers, copies, encoding, error
18 import base85, mdiff, scmutil, util, diffhelpers, copies, encoding, error
19
19
20 gitre = re.compile('diff --git a/(.*) b/(.*)')
20 gitre = re.compile('diff --git a/(.*) b/(.*)')
21 tabsplitter = re.compile(r'(\t+|[^\t]+)')
21 tabsplitter = re.compile(r'(\t+|[^\t]+)')
22
22
23 class PatchError(Exception):
23 class PatchError(Exception):
24 pass
24 pass
25
25
26
26
27 # public functions
27 # public functions
28
28
29 def split(stream):
29 def split(stream):
30 '''return an iterator of individual patches from a stream'''
30 '''return an iterator of individual patches from a stream'''
31 def isheader(line, inheader):
31 def isheader(line, inheader):
32 if inheader and line[0] in (' ', '\t'):
32 if inheader and line[0] in (' ', '\t'):
33 # continuation
33 # continuation
34 return True
34 return True
35 if line[0] in (' ', '-', '+'):
35 if line[0] in (' ', '-', '+'):
36 # diff line - don't check for header pattern in there
36 # diff line - don't check for header pattern in there
37 return False
37 return False
38 l = line.split(': ', 1)
38 l = line.split(': ', 1)
39 return len(l) == 2 and ' ' not in l[0]
39 return len(l) == 2 and ' ' not in l[0]
40
40
41 def chunk(lines):
41 def chunk(lines):
42 return cStringIO.StringIO(''.join(lines))
42 return cStringIO.StringIO(''.join(lines))
43
43
44 def hgsplit(stream, cur):
44 def hgsplit(stream, cur):
45 inheader = True
45 inheader = True
46
46
47 for line in stream:
47 for line in stream:
48 if not line.strip():
48 if not line.strip():
49 inheader = False
49 inheader = False
50 if not inheader and line.startswith('# HG changeset patch'):
50 if not inheader and line.startswith('# HG changeset patch'):
51 yield chunk(cur)
51 yield chunk(cur)
52 cur = []
52 cur = []
53 inheader = True
53 inheader = True
54
54
55 cur.append(line)
55 cur.append(line)
56
56
57 if cur:
57 if cur:
58 yield chunk(cur)
58 yield chunk(cur)
59
59
60 def mboxsplit(stream, cur):
60 def mboxsplit(stream, cur):
61 for line in stream:
61 for line in stream:
62 if line.startswith('From '):
62 if line.startswith('From '):
63 for c in split(chunk(cur[1:])):
63 for c in split(chunk(cur[1:])):
64 yield c
64 yield c
65 cur = []
65 cur = []
66
66
67 cur.append(line)
67 cur.append(line)
68
68
69 if cur:
69 if cur:
70 for c in split(chunk(cur[1:])):
70 for c in split(chunk(cur[1:])):
71 yield c
71 yield c
72
72
73 def mimesplit(stream, cur):
73 def mimesplit(stream, cur):
74 def msgfp(m):
74 def msgfp(m):
75 fp = cStringIO.StringIO()
75 fp = cStringIO.StringIO()
76 g = email.Generator.Generator(fp, mangle_from_=False)
76 g = email.Generator.Generator(fp, mangle_from_=False)
77 g.flatten(m)
77 g.flatten(m)
78 fp.seek(0)
78 fp.seek(0)
79 return fp
79 return fp
80
80
81 for line in stream:
81 for line in stream:
82 cur.append(line)
82 cur.append(line)
83 c = chunk(cur)
83 c = chunk(cur)
84
84
85 m = email.Parser.Parser().parse(c)
85 m = email.Parser.Parser().parse(c)
86 if not m.is_multipart():
86 if not m.is_multipart():
87 yield msgfp(m)
87 yield msgfp(m)
88 else:
88 else:
89 ok_types = ('text/plain', 'text/x-diff', 'text/x-patch')
89 ok_types = ('text/plain', 'text/x-diff', 'text/x-patch')
90 for part in m.walk():
90 for part in m.walk():
91 ct = part.get_content_type()
91 ct = part.get_content_type()
92 if ct not in ok_types:
92 if ct not in ok_types:
93 continue
93 continue
94 yield msgfp(part)
94 yield msgfp(part)
95
95
96 def headersplit(stream, cur):
96 def headersplit(stream, cur):
97 inheader = False
97 inheader = False
98
98
99 for line in stream:
99 for line in stream:
100 if not inheader and isheader(line, inheader):
100 if not inheader and isheader(line, inheader):
101 yield chunk(cur)
101 yield chunk(cur)
102 cur = []
102 cur = []
103 inheader = True
103 inheader = True
104 if inheader and not isheader(line, inheader):
104 if inheader and not isheader(line, inheader):
105 inheader = False
105 inheader = False
106
106
107 cur.append(line)
107 cur.append(line)
108
108
109 if cur:
109 if cur:
110 yield chunk(cur)
110 yield chunk(cur)
111
111
112 def remainder(cur):
112 def remainder(cur):
113 yield chunk(cur)
113 yield chunk(cur)
114
114
115 class fiter(object):
115 class fiter(object):
116 def __init__(self, fp):
116 def __init__(self, fp):
117 self.fp = fp
117 self.fp = fp
118
118
119 def __iter__(self):
119 def __iter__(self):
120 return self
120 return self
121
121
122 def next(self):
122 def next(self):
123 l = self.fp.readline()
123 l = self.fp.readline()
124 if not l:
124 if not l:
125 raise StopIteration
125 raise StopIteration
126 return l
126 return l
127
127
128 inheader = False
128 inheader = False
129 cur = []
129 cur = []
130
130
131 mimeheaders = ['content-type']
131 mimeheaders = ['content-type']
132
132
133 if not util.safehasattr(stream, 'next'):
133 if not util.safehasattr(stream, 'next'):
134 # http responses, for example, have readline but not next
134 # http responses, for example, have readline but not next
135 stream = fiter(stream)
135 stream = fiter(stream)
136
136
137 for line in stream:
137 for line in stream:
138 cur.append(line)
138 cur.append(line)
139 if line.startswith('# HG changeset patch'):
139 if line.startswith('# HG changeset patch'):
140 return hgsplit(stream, cur)
140 return hgsplit(stream, cur)
141 elif line.startswith('From '):
141 elif line.startswith('From '):
142 return mboxsplit(stream, cur)
142 return mboxsplit(stream, cur)
143 elif isheader(line, inheader):
143 elif isheader(line, inheader):
144 inheader = True
144 inheader = True
145 if line.split(':', 1)[0].lower() in mimeheaders:
145 if line.split(':', 1)[0].lower() in mimeheaders:
146 # let email parser handle this
146 # let email parser handle this
147 return mimesplit(stream, cur)
147 return mimesplit(stream, cur)
148 elif line.startswith('--- ') and inheader:
148 elif line.startswith('--- ') and inheader:
149 # No evil headers seen by diff start, split by hand
149 # No evil headers seen by diff start, split by hand
150 return headersplit(stream, cur)
150 return headersplit(stream, cur)
151 # Not enough info, keep reading
151 # Not enough info, keep reading
152
152
153 # if we are here, we have a very plain patch
153 # if we are here, we have a very plain patch
154 return remainder(cur)
154 return remainder(cur)
155
155
156 def extract(ui, fileobj):
156 def extract(ui, fileobj):
157 '''extract patch from data read from fileobj.
157 '''extract patch from data read from fileobj.
158
158
159 patch can be a normal patch or contained in an email message.
159 patch can be a normal patch or contained in an email message.
160
160
161 return tuple (filename, message, user, date, branch, node, p1, p2).
161 return tuple (filename, message, user, date, branch, node, p1, p2).
162 Any item in the returned tuple can be None. If filename is None,
162 Any item in the returned tuple can be None. If filename is None,
163 fileobj did not contain a patch. Caller must unlink filename when done.'''
163 fileobj did not contain a patch. Caller must unlink filename when done.'''
164
164
165 # attempt to detect the start of a patch
165 # attempt to detect the start of a patch
166 # (this heuristic is borrowed from quilt)
166 # (this heuristic is borrowed from quilt)
167 diffre = re.compile(r'^(?:Index:[ \t]|diff[ \t]|RCS file: |'
167 diffre = re.compile(r'^(?:Index:[ \t]|diff[ \t]|RCS file: |'
168 r'retrieving revision [0-9]+(\.[0-9]+)*$|'
168 r'retrieving revision [0-9]+(\.[0-9]+)*$|'
169 r'---[ \t].*?^\+\+\+[ \t]|'
169 r'---[ \t].*?^\+\+\+[ \t]|'
170 r'\*\*\*[ \t].*?^---[ \t])', re.MULTILINE|re.DOTALL)
170 r'\*\*\*[ \t].*?^---[ \t])', re.MULTILINE|re.DOTALL)
171
171
172 fd, tmpname = tempfile.mkstemp(prefix='hg-patch-')
172 fd, tmpname = tempfile.mkstemp(prefix='hg-patch-')
173 tmpfp = os.fdopen(fd, 'w')
173 tmpfp = os.fdopen(fd, 'w')
174 try:
174 try:
175 msg = email.Parser.Parser().parse(fileobj)
175 msg = email.Parser.Parser().parse(fileobj)
176
176
177 subject = msg['Subject']
177 subject = msg['Subject']
178 user = msg['From']
178 user = msg['From']
179 if not subject and not user:
179 if not subject and not user:
180 # Not an email, restore parsed headers if any
180 # Not an email, restore parsed headers if any
181 subject = '\n'.join(': '.join(h) for h in msg.items()) + '\n'
181 subject = '\n'.join(': '.join(h) for h in msg.items()) + '\n'
182
182
183 # should try to parse msg['Date']
183 # should try to parse msg['Date']
184 date = None
184 date = None
185 nodeid = None
185 nodeid = None
186 branch = None
186 branch = None
187 parents = []
187 parents = []
188
188
189 if subject:
189 if subject:
190 if subject.startswith('[PATCH'):
190 if subject.startswith('[PATCH'):
191 pend = subject.find(']')
191 pend = subject.find(']')
192 if pend >= 0:
192 if pend >= 0:
193 subject = subject[pend + 1:].lstrip()
193 subject = subject[pend + 1:].lstrip()
194 subject = re.sub(r'\n[ \t]+', ' ', subject)
194 subject = re.sub(r'\n[ \t]+', ' ', subject)
195 ui.debug('Subject: %s\n' % subject)
195 ui.debug('Subject: %s\n' % subject)
196 if user:
196 if user:
197 ui.debug('From: %s\n' % user)
197 ui.debug('From: %s\n' % user)
198 diffs_seen = 0
198 diffs_seen = 0
199 ok_types = ('text/plain', 'text/x-diff', 'text/x-patch')
199 ok_types = ('text/plain', 'text/x-diff', 'text/x-patch')
200 message = ''
200 message = ''
201 for part in msg.walk():
201 for part in msg.walk():
202 content_type = part.get_content_type()
202 content_type = part.get_content_type()
203 ui.debug('Content-Type: %s\n' % content_type)
203 ui.debug('Content-Type: %s\n' % content_type)
204 if content_type not in ok_types:
204 if content_type not in ok_types:
205 continue
205 continue
206 payload = part.get_payload(decode=True)
206 payload = part.get_payload(decode=True)
207 m = diffre.search(payload)
207 m = diffre.search(payload)
208 if m:
208 if m:
209 hgpatch = False
209 hgpatch = False
210 hgpatchheader = False
210 hgpatchheader = False
211 ignoretext = False
211 ignoretext = False
212
212
213 ui.debug('found patch at byte %d\n' % m.start(0))
213 ui.debug('found patch at byte %d\n' % m.start(0))
214 diffs_seen += 1
214 diffs_seen += 1
215 cfp = cStringIO.StringIO()
215 cfp = cStringIO.StringIO()
216 for line in payload[:m.start(0)].splitlines():
216 for line in payload[:m.start(0)].splitlines():
217 if line.startswith('# HG changeset patch') and not hgpatch:
217 if line.startswith('# HG changeset patch') and not hgpatch:
218 ui.debug('patch generated by hg export\n')
218 ui.debug('patch generated by hg export\n')
219 hgpatch = True
219 hgpatch = True
220 hgpatchheader = True
220 hgpatchheader = True
221 # drop earlier commit message content
221 # drop earlier commit message content
222 cfp.seek(0)
222 cfp.seek(0)
223 cfp.truncate()
223 cfp.truncate()
224 subject = None
224 subject = None
225 elif hgpatchheader:
225 elif hgpatchheader:
226 if line.startswith('# User '):
226 if line.startswith('# User '):
227 user = line[7:]
227 user = line[7:]
228 ui.debug('From: %s\n' % user)
228 ui.debug('From: %s\n' % user)
229 elif line.startswith("# Date "):
229 elif line.startswith("# Date "):
230 date = line[7:]
230 date = line[7:]
231 elif line.startswith("# Branch "):
231 elif line.startswith("# Branch "):
232 branch = line[9:]
232 branch = line[9:]
233 elif line.startswith("# Node ID "):
233 elif line.startswith("# Node ID "):
234 nodeid = line[10:]
234 nodeid = line[10:]
235 elif line.startswith("# Parent "):
235 elif line.startswith("# Parent "):
236 parents.append(line[9:].lstrip())
236 parents.append(line[9:].lstrip())
237 elif not line.startswith("# "):
237 elif not line.startswith("# "):
238 hgpatchheader = False
238 hgpatchheader = False
239 elif line == '---':
239 elif line == '---':
240 ignoretext = True
240 ignoretext = True
241 if not hgpatchheader and not ignoretext:
241 if not hgpatchheader and not ignoretext:
242 cfp.write(line)
242 cfp.write(line)
243 cfp.write('\n')
243 cfp.write('\n')
244 message = cfp.getvalue()
244 message = cfp.getvalue()
245 if tmpfp:
245 if tmpfp:
246 tmpfp.write(payload)
246 tmpfp.write(payload)
247 if not payload.endswith('\n'):
247 if not payload.endswith('\n'):
248 tmpfp.write('\n')
248 tmpfp.write('\n')
249 elif not diffs_seen and message and content_type == 'text/plain':
249 elif not diffs_seen and message and content_type == 'text/plain':
250 message += '\n' + payload
250 message += '\n' + payload
251 except: # re-raises
251 except: # re-raises
252 tmpfp.close()
252 tmpfp.close()
253 os.unlink(tmpname)
253 os.unlink(tmpname)
254 raise
254 raise
255
255
256 if subject and not message.startswith(subject):
256 if subject and not message.startswith(subject):
257 message = '%s\n%s' % (subject, message)
257 message = '%s\n%s' % (subject, message)
258 tmpfp.close()
258 tmpfp.close()
259 if not diffs_seen:
259 if not diffs_seen:
260 os.unlink(tmpname)
260 os.unlink(tmpname)
261 return None, message, user, date, branch, None, None, None
261 return None, message, user, date, branch, None, None, None
262 p1 = parents and parents.pop(0) or None
262 p1 = parents and parents.pop(0) or None
263 p2 = parents and parents.pop(0) or None
263 p2 = parents and parents.pop(0) or None
264 return tmpname, message, user, date, branch, nodeid, p1, p2
264 return tmpname, message, user, date, branch, nodeid, p1, p2
265
265
266 class patchmeta(object):
266 class patchmeta(object):
267 """Patched file metadata
267 """Patched file metadata
268
268
269 'op' is the performed operation within ADD, DELETE, RENAME, MODIFY
269 'op' is the performed operation within ADD, DELETE, RENAME, MODIFY
270 or COPY. 'path' is patched file path. 'oldpath' is set to the
270 or COPY. 'path' is patched file path. 'oldpath' is set to the
271 origin file when 'op' is either COPY or RENAME, None otherwise. If
271 origin file when 'op' is either COPY or RENAME, None otherwise. If
272 file mode is changed, 'mode' is a tuple (islink, isexec) where
272 file mode is changed, 'mode' is a tuple (islink, isexec) where
273 'islink' is True if the file is a symlink and 'isexec' is True if
273 'islink' is True if the file is a symlink and 'isexec' is True if
274 the file is executable. Otherwise, 'mode' is None.
274 the file is executable. Otherwise, 'mode' is None.
275 """
275 """
276 def __init__(self, path):
276 def __init__(self, path):
277 self.path = path
277 self.path = path
278 self.oldpath = None
278 self.oldpath = None
279 self.mode = None
279 self.mode = None
280 self.op = 'MODIFY'
280 self.op = 'MODIFY'
281 self.binary = False
281 self.binary = False
282
282
283 def setmode(self, mode):
283 def setmode(self, mode):
284 islink = mode & 020000
284 islink = mode & 020000
285 isexec = mode & 0100
285 isexec = mode & 0100
286 self.mode = (islink, isexec)
286 self.mode = (islink, isexec)
287
287
288 def copy(self):
288 def copy(self):
289 other = patchmeta(self.path)
289 other = patchmeta(self.path)
290 other.oldpath = self.oldpath
290 other.oldpath = self.oldpath
291 other.mode = self.mode
291 other.mode = self.mode
292 other.op = self.op
292 other.op = self.op
293 other.binary = self.binary
293 other.binary = self.binary
294 return other
294 return other
295
295
296 def _ispatchinga(self, afile):
296 def _ispatchinga(self, afile):
297 if afile == '/dev/null':
297 if afile == '/dev/null':
298 return self.op == 'ADD'
298 return self.op == 'ADD'
299 return afile == 'a/' + (self.oldpath or self.path)
299 return afile == 'a/' + (self.oldpath or self.path)
300
300
301 def _ispatchingb(self, bfile):
301 def _ispatchingb(self, bfile):
302 if bfile == '/dev/null':
302 if bfile == '/dev/null':
303 return self.op == 'DELETE'
303 return self.op == 'DELETE'
304 return bfile == 'b/' + self.path
304 return bfile == 'b/' + self.path
305
305
306 def ispatching(self, afile, bfile):
306 def ispatching(self, afile, bfile):
307 return self._ispatchinga(afile) and self._ispatchingb(bfile)
307 return self._ispatchinga(afile) and self._ispatchingb(bfile)
308
308
309 def __repr__(self):
309 def __repr__(self):
310 return "<patchmeta %s %r>" % (self.op, self.path)
310 return "<patchmeta %s %r>" % (self.op, self.path)
311
311
312 def readgitpatch(lr):
312 def readgitpatch(lr):
313 """extract git-style metadata about patches from <patchname>"""
313 """extract git-style metadata about patches from <patchname>"""
314
314
315 # Filter patch for git information
315 # Filter patch for git information
316 gp = None
316 gp = None
317 gitpatches = []
317 gitpatches = []
318 for line in lr:
318 for line in lr:
319 line = line.rstrip(' \r\n')
319 line = line.rstrip(' \r\n')
320 if line.startswith('diff --git a/'):
320 if line.startswith('diff --git a/'):
321 m = gitre.match(line)
321 m = gitre.match(line)
322 if m:
322 if m:
323 if gp:
323 if gp:
324 gitpatches.append(gp)
324 gitpatches.append(gp)
325 dst = m.group(2)
325 dst = m.group(2)
326 gp = patchmeta(dst)
326 gp = patchmeta(dst)
327 elif gp:
327 elif gp:
328 if line.startswith('--- '):
328 if line.startswith('--- '):
329 gitpatches.append(gp)
329 gitpatches.append(gp)
330 gp = None
330 gp = None
331 continue
331 continue
332 if line.startswith('rename from '):
332 if line.startswith('rename from '):
333 gp.op = 'RENAME'
333 gp.op = 'RENAME'
334 gp.oldpath = line[12:]
334 gp.oldpath = line[12:]
335 elif line.startswith('rename to '):
335 elif line.startswith('rename to '):
336 gp.path = line[10:]
336 gp.path = line[10:]
337 elif line.startswith('copy from '):
337 elif line.startswith('copy from '):
338 gp.op = 'COPY'
338 gp.op = 'COPY'
339 gp.oldpath = line[10:]
339 gp.oldpath = line[10:]
340 elif line.startswith('copy to '):
340 elif line.startswith('copy to '):
341 gp.path = line[8:]
341 gp.path = line[8:]
342 elif line.startswith('deleted file'):
342 elif line.startswith('deleted file'):
343 gp.op = 'DELETE'
343 gp.op = 'DELETE'
344 elif line.startswith('new file mode '):
344 elif line.startswith('new file mode '):
345 gp.op = 'ADD'
345 gp.op = 'ADD'
346 gp.setmode(int(line[-6:], 8))
346 gp.setmode(int(line[-6:], 8))
347 elif line.startswith('new mode '):
347 elif line.startswith('new mode '):
348 gp.setmode(int(line[-6:], 8))
348 gp.setmode(int(line[-6:], 8))
349 elif line.startswith('GIT binary patch'):
349 elif line.startswith('GIT binary patch'):
350 gp.binary = True
350 gp.binary = True
351 if gp:
351 if gp:
352 gitpatches.append(gp)
352 gitpatches.append(gp)
353
353
354 return gitpatches
354 return gitpatches
355
355
356 class linereader(object):
356 class linereader(object):
357 # simple class to allow pushing lines back into the input stream
357 # simple class to allow pushing lines back into the input stream
358 def __init__(self, fp):
358 def __init__(self, fp):
359 self.fp = fp
359 self.fp = fp
360 self.buf = []
360 self.buf = []
361
361
362 def push(self, line):
362 def push(self, line):
363 if line is not None:
363 if line is not None:
364 self.buf.append(line)
364 self.buf.append(line)
365
365
366 def readline(self):
366 def readline(self):
367 if self.buf:
367 if self.buf:
368 l = self.buf[0]
368 l = self.buf[0]
369 del self.buf[0]
369 del self.buf[0]
370 return l
370 return l
371 return self.fp.readline()
371 return self.fp.readline()
372
372
373 def __iter__(self):
373 def __iter__(self):
374 while True:
374 while True:
375 l = self.readline()
375 l = self.readline()
376 if not l:
376 if not l:
377 break
377 break
378 yield l
378 yield l
379
379
380 class abstractbackend(object):
380 class abstractbackend(object):
381 def __init__(self, ui):
381 def __init__(self, ui):
382 self.ui = ui
382 self.ui = ui
383
383
384 def getfile(self, fname):
384 def getfile(self, fname):
385 """Return target file data and flags as a (data, (islink,
385 """Return target file data and flags as a (data, (islink,
386 isexec)) tuple. Data is None if file is missing/deleted.
386 isexec)) tuple. Data is None if file is missing/deleted.
387 """
387 """
388 raise NotImplementedError
388 raise NotImplementedError
389
389
390 def setfile(self, fname, data, mode, copysource):
390 def setfile(self, fname, data, mode, copysource):
391 """Write data to target file fname and set its mode. mode is a
391 """Write data to target file fname and set its mode. mode is a
392 (islink, isexec) tuple. If data is None, the file content should
392 (islink, isexec) tuple. If data is None, the file content should
393 be left unchanged. If the file is modified after being copied,
393 be left unchanged. If the file is modified after being copied,
394 copysource is set to the original file name.
394 copysource is set to the original file name.
395 """
395 """
396 raise NotImplementedError
396 raise NotImplementedError
397
397
398 def unlink(self, fname):
398 def unlink(self, fname):
399 """Unlink target file."""
399 """Unlink target file."""
400 raise NotImplementedError
400 raise NotImplementedError
401
401
402 def writerej(self, fname, failed, total, lines):
402 def writerej(self, fname, failed, total, lines):
403 """Write rejected lines for fname. total is the number of hunks
403 """Write rejected lines for fname. total is the number of hunks
404 which failed to apply and total the total number of hunks for this
404 which failed to apply and total the total number of hunks for this
405 files.
405 files.
406 """
406 """
407 pass
407 pass
408
408
409 def exists(self, fname):
409 def exists(self, fname):
410 raise NotImplementedError
410 raise NotImplementedError
411
411
412 class fsbackend(abstractbackend):
412 class fsbackend(abstractbackend):
413 def __init__(self, ui, basedir):
413 def __init__(self, ui, basedir):
414 super(fsbackend, self).__init__(ui)
414 super(fsbackend, self).__init__(ui)
415 self.opener = scmutil.opener(basedir)
415 self.opener = scmutil.opener(basedir)
416
416
417 def _join(self, f):
417 def _join(self, f):
418 return os.path.join(self.opener.base, f)
418 return os.path.join(self.opener.base, f)
419
419
420 def getfile(self, fname):
420 def getfile(self, fname):
421 if self.opener.islink(fname):
421 if self.opener.islink(fname):
422 return (self.opener.readlink(fname), (True, False))
422 return (self.opener.readlink(fname), (True, False))
423
423
424 isexec = False
424 isexec = False
425 try:
425 try:
426 isexec = self.opener.lstat(fname).st_mode & 0100 != 0
426 isexec = self.opener.lstat(fname).st_mode & 0100 != 0
427 except OSError, e:
427 except OSError, e:
428 if e.errno != errno.ENOENT:
428 if e.errno != errno.ENOENT:
429 raise
429 raise
430 try:
430 try:
431 return (self.opener.read(fname), (False, isexec))
431 return (self.opener.read(fname), (False, isexec))
432 except IOError, e:
432 except IOError, e:
433 if e.errno != errno.ENOENT:
433 if e.errno != errno.ENOENT:
434 raise
434 raise
435 return None, None
435 return None, None
436
436
437 def setfile(self, fname, data, mode, copysource):
437 def setfile(self, fname, data, mode, copysource):
438 islink, isexec = mode
438 islink, isexec = mode
439 if data is None:
439 if data is None:
440 self.opener.setflags(fname, islink, isexec)
440 self.opener.setflags(fname, islink, isexec)
441 return
441 return
442 if islink:
442 if islink:
443 self.opener.symlink(data, fname)
443 self.opener.symlink(data, fname)
444 else:
444 else:
445 self.opener.write(fname, data)
445 self.opener.write(fname, data)
446 if isexec:
446 if isexec:
447 self.opener.setflags(fname, False, True)
447 self.opener.setflags(fname, False, True)
448
448
449 def unlink(self, fname):
449 def unlink(self, fname):
450 self.opener.unlinkpath(fname, ignoremissing=True)
450 self.opener.unlinkpath(fname, ignoremissing=True)
451
451
452 def writerej(self, fname, failed, total, lines):
452 def writerej(self, fname, failed, total, lines):
453 fname = fname + ".rej"
453 fname = fname + ".rej"
454 self.ui.warn(
454 self.ui.warn(
455 _("%d out of %d hunks FAILED -- saving rejects to file %s\n") %
455 _("%d out of %d hunks FAILED -- saving rejects to file %s\n") %
456 (failed, total, fname))
456 (failed, total, fname))
457 fp = self.opener(fname, 'w')
457 fp = self.opener(fname, 'w')
458 fp.writelines(lines)
458 fp.writelines(lines)
459 fp.close()
459 fp.close()
460
460
461 def exists(self, fname):
461 def exists(self, fname):
462 return self.opener.lexists(fname)
462 return self.opener.lexists(fname)
463
463
464 class workingbackend(fsbackend):
464 class workingbackend(fsbackend):
465 def __init__(self, ui, repo, similarity):
465 def __init__(self, ui, repo, similarity):
466 super(workingbackend, self).__init__(ui, repo.root)
466 super(workingbackend, self).__init__(ui, repo.root)
467 self.repo = repo
467 self.repo = repo
468 self.similarity = similarity
468 self.similarity = similarity
469 self.removed = set()
469 self.removed = set()
470 self.changed = set()
470 self.changed = set()
471 self.copied = []
471 self.copied = []
472
472
473 def _checkknown(self, fname):
473 def _checkknown(self, fname):
474 if self.repo.dirstate[fname] == '?' and self.exists(fname):
474 if self.repo.dirstate[fname] == '?' and self.exists(fname):
475 raise PatchError(_('cannot patch %s: file is not tracked') % fname)
475 raise PatchError(_('cannot patch %s: file is not tracked') % fname)
476
476
477 def setfile(self, fname, data, mode, copysource):
477 def setfile(self, fname, data, mode, copysource):
478 self._checkknown(fname)
478 self._checkknown(fname)
479 super(workingbackend, self).setfile(fname, data, mode, copysource)
479 super(workingbackend, self).setfile(fname, data, mode, copysource)
480 if copysource is not None:
480 if copysource is not None:
481 self.copied.append((copysource, fname))
481 self.copied.append((copysource, fname))
482 self.changed.add(fname)
482 self.changed.add(fname)
483
483
484 def unlink(self, fname):
484 def unlink(self, fname):
485 self._checkknown(fname)
485 self._checkknown(fname)
486 super(workingbackend, self).unlink(fname)
486 super(workingbackend, self).unlink(fname)
487 self.removed.add(fname)
487 self.removed.add(fname)
488 self.changed.add(fname)
488 self.changed.add(fname)
489
489
490 def close(self):
490 def close(self):
491 wctx = self.repo[None]
491 wctx = self.repo[None]
492 changed = set(self.changed)
492 changed = set(self.changed)
493 for src, dst in self.copied:
493 for src, dst in self.copied:
494 scmutil.dirstatecopy(self.ui, self.repo, wctx, src, dst)
494 scmutil.dirstatecopy(self.ui, self.repo, wctx, src, dst)
495 if self.removed:
495 if self.removed:
496 wctx.forget(sorted(self.removed))
496 wctx.forget(sorted(self.removed))
497 for f in self.removed:
497 for f in self.removed:
498 if f not in self.repo.dirstate:
498 if f not in self.repo.dirstate:
499 # File was deleted and no longer belongs to the
499 # File was deleted and no longer belongs to the
500 # dirstate, it was probably marked added then
500 # dirstate, it was probably marked added then
501 # deleted, and should not be considered by
501 # deleted, and should not be considered by
502 # marktouched().
502 # marktouched().
503 changed.discard(f)
503 changed.discard(f)
504 if changed:
504 if changed:
505 scmutil.marktouched(self.repo, changed, self.similarity)
505 scmutil.marktouched(self.repo, changed, self.similarity)
506 return sorted(self.changed)
506 return sorted(self.changed)
507
507
508 class filestore(object):
508 class filestore(object):
509 def __init__(self, maxsize=None):
509 def __init__(self, maxsize=None):
510 self.opener = None
510 self.opener = None
511 self.files = {}
511 self.files = {}
512 self.created = 0
512 self.created = 0
513 self.maxsize = maxsize
513 self.maxsize = maxsize
514 if self.maxsize is None:
514 if self.maxsize is None:
515 self.maxsize = 4*(2**20)
515 self.maxsize = 4*(2**20)
516 self.size = 0
516 self.size = 0
517 self.data = {}
517 self.data = {}
518
518
519 def setfile(self, fname, data, mode, copied=None):
519 def setfile(self, fname, data, mode, copied=None):
520 if self.maxsize < 0 or (len(data) + self.size) <= self.maxsize:
520 if self.maxsize < 0 or (len(data) + self.size) <= self.maxsize:
521 self.data[fname] = (data, mode, copied)
521 self.data[fname] = (data, mode, copied)
522 self.size += len(data)
522 self.size += len(data)
523 else:
523 else:
524 if self.opener is None:
524 if self.opener is None:
525 root = tempfile.mkdtemp(prefix='hg-patch-')
525 root = tempfile.mkdtemp(prefix='hg-patch-')
526 self.opener = scmutil.opener(root)
526 self.opener = scmutil.opener(root)
527 # Avoid filename issues with these simple names
527 # Avoid filename issues with these simple names
528 fn = str(self.created)
528 fn = str(self.created)
529 self.opener.write(fn, data)
529 self.opener.write(fn, data)
530 self.created += 1
530 self.created += 1
531 self.files[fname] = (fn, mode, copied)
531 self.files[fname] = (fn, mode, copied)
532
532
533 def getfile(self, fname):
533 def getfile(self, fname):
534 if fname in self.data:
534 if fname in self.data:
535 return self.data[fname]
535 return self.data[fname]
536 if not self.opener or fname not in self.files:
536 if not self.opener or fname not in self.files:
537 return None, None, None
537 return None, None, None
538 fn, mode, copied = self.files[fname]
538 fn, mode, copied = self.files[fname]
539 return self.opener.read(fn), mode, copied
539 return self.opener.read(fn), mode, copied
540
540
541 def close(self):
541 def close(self):
542 if self.opener:
542 if self.opener:
543 shutil.rmtree(self.opener.base)
543 shutil.rmtree(self.opener.base)
544
544
545 class repobackend(abstractbackend):
545 class repobackend(abstractbackend):
546 def __init__(self, ui, repo, ctx, store):
546 def __init__(self, ui, repo, ctx, store):
547 super(repobackend, self).__init__(ui)
547 super(repobackend, self).__init__(ui)
548 self.repo = repo
548 self.repo = repo
549 self.ctx = ctx
549 self.ctx = ctx
550 self.store = store
550 self.store = store
551 self.changed = set()
551 self.changed = set()
552 self.removed = set()
552 self.removed = set()
553 self.copied = {}
553 self.copied = {}
554
554
555 def _checkknown(self, fname):
555 def _checkknown(self, fname):
556 if fname not in self.ctx:
556 if fname not in self.ctx:
557 raise PatchError(_('cannot patch %s: file is not tracked') % fname)
557 raise PatchError(_('cannot patch %s: file is not tracked') % fname)
558
558
559 def getfile(self, fname):
559 def getfile(self, fname):
560 try:
560 try:
561 fctx = self.ctx[fname]
561 fctx = self.ctx[fname]
562 except error.LookupError:
562 except error.LookupError:
563 return None, None
563 return None, None
564 flags = fctx.flags()
564 flags = fctx.flags()
565 return fctx.data(), ('l' in flags, 'x' in flags)
565 return fctx.data(), ('l' in flags, 'x' in flags)
566
566
567 def setfile(self, fname, data, mode, copysource):
567 def setfile(self, fname, data, mode, copysource):
568 if copysource:
568 if copysource:
569 self._checkknown(copysource)
569 self._checkknown(copysource)
570 if data is None:
570 if data is None:
571 data = self.ctx[fname].data()
571 data = self.ctx[fname].data()
572 self.store.setfile(fname, data, mode, copysource)
572 self.store.setfile(fname, data, mode, copysource)
573 self.changed.add(fname)
573 self.changed.add(fname)
574 if copysource:
574 if copysource:
575 self.copied[fname] = copysource
575 self.copied[fname] = copysource
576
576
577 def unlink(self, fname):
577 def unlink(self, fname):
578 self._checkknown(fname)
578 self._checkknown(fname)
579 self.removed.add(fname)
579 self.removed.add(fname)
580
580
581 def exists(self, fname):
581 def exists(self, fname):
582 return fname in self.ctx
582 return fname in self.ctx
583
583
584 def close(self):
584 def close(self):
585 return self.changed | self.removed
585 return self.changed | self.removed
586
586
587 # @@ -start,len +start,len @@ or @@ -start +start @@ if len is 1
587 # @@ -start,len +start,len @@ or @@ -start +start @@ if len is 1
588 unidesc = re.compile('@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@')
588 unidesc = re.compile('@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@')
589 contextdesc = re.compile('(?:---|\*\*\*) (\d+)(?:,(\d+))? (?:---|\*\*\*)')
589 contextdesc = re.compile('(?:---|\*\*\*) (\d+)(?:,(\d+))? (?:---|\*\*\*)')
590 eolmodes = ['strict', 'crlf', 'lf', 'auto']
590 eolmodes = ['strict', 'crlf', 'lf', 'auto']
591
591
592 class patchfile(object):
592 class patchfile(object):
593 def __init__(self, ui, gp, backend, store, eolmode='strict'):
593 def __init__(self, ui, gp, backend, store, eolmode='strict'):
594 self.fname = gp.path
594 self.fname = gp.path
595 self.eolmode = eolmode
595 self.eolmode = eolmode
596 self.eol = None
596 self.eol = None
597 self.backend = backend
597 self.backend = backend
598 self.ui = ui
598 self.ui = ui
599 self.lines = []
599 self.lines = []
600 self.exists = False
600 self.exists = False
601 self.missing = True
601 self.missing = True
602 self.mode = gp.mode
602 self.mode = gp.mode
603 self.copysource = gp.oldpath
603 self.copysource = gp.oldpath
604 self.create = gp.op in ('ADD', 'COPY', 'RENAME')
604 self.create = gp.op in ('ADD', 'COPY', 'RENAME')
605 self.remove = gp.op == 'DELETE'
605 self.remove = gp.op == 'DELETE'
606 if self.copysource is None:
606 if self.copysource is None:
607 data, mode = backend.getfile(self.fname)
607 data, mode = backend.getfile(self.fname)
608 else:
608 else:
609 data, mode = store.getfile(self.copysource)[:2]
609 data, mode = store.getfile(self.copysource)[:2]
610 if data is not None:
610 if data is not None:
611 self.exists = self.copysource is None or backend.exists(self.fname)
611 self.exists = self.copysource is None or backend.exists(self.fname)
612 self.missing = False
612 self.missing = False
613 if data:
613 if data:
614 self.lines = mdiff.splitnewlines(data)
614 self.lines = mdiff.splitnewlines(data)
615 if self.mode is None:
615 if self.mode is None:
616 self.mode = mode
616 self.mode = mode
617 if self.lines:
617 if self.lines:
618 # Normalize line endings
618 # Normalize line endings
619 if self.lines[0].endswith('\r\n'):
619 if self.lines[0].endswith('\r\n'):
620 self.eol = '\r\n'
620 self.eol = '\r\n'
621 elif self.lines[0].endswith('\n'):
621 elif self.lines[0].endswith('\n'):
622 self.eol = '\n'
622 self.eol = '\n'
623 if eolmode != 'strict':
623 if eolmode != 'strict':
624 nlines = []
624 nlines = []
625 for l in self.lines:
625 for l in self.lines:
626 if l.endswith('\r\n'):
626 if l.endswith('\r\n'):
627 l = l[:-2] + '\n'
627 l = l[:-2] + '\n'
628 nlines.append(l)
628 nlines.append(l)
629 self.lines = nlines
629 self.lines = nlines
630 else:
630 else:
631 if self.create:
631 if self.create:
632 self.missing = False
632 self.missing = False
633 if self.mode is None:
633 if self.mode is None:
634 self.mode = (False, False)
634 self.mode = (False, False)
635 if self.missing:
635 if self.missing:
636 self.ui.warn(_("unable to find '%s' for patching\n") % self.fname)
636 self.ui.warn(_("unable to find '%s' for patching\n") % self.fname)
637
637
638 self.hash = {}
638 self.hash = {}
639 self.dirty = 0
639 self.dirty = 0
640 self.offset = 0
640 self.offset = 0
641 self.skew = 0
641 self.skew = 0
642 self.rej = []
642 self.rej = []
643 self.fileprinted = False
643 self.fileprinted = False
644 self.printfile(False)
644 self.printfile(False)
645 self.hunks = 0
645 self.hunks = 0
646
646
647 def writelines(self, fname, lines, mode):
647 def writelines(self, fname, lines, mode):
648 if self.eolmode == 'auto':
648 if self.eolmode == 'auto':
649 eol = self.eol
649 eol = self.eol
650 elif self.eolmode == 'crlf':
650 elif self.eolmode == 'crlf':
651 eol = '\r\n'
651 eol = '\r\n'
652 else:
652 else:
653 eol = '\n'
653 eol = '\n'
654
654
655 if self.eolmode != 'strict' and eol and eol != '\n':
655 if self.eolmode != 'strict' and eol and eol != '\n':
656 rawlines = []
656 rawlines = []
657 for l in lines:
657 for l in lines:
658 if l and l[-1] == '\n':
658 if l and l[-1] == '\n':
659 l = l[:-1] + eol
659 l = l[:-1] + eol
660 rawlines.append(l)
660 rawlines.append(l)
661 lines = rawlines
661 lines = rawlines
662
662
663 self.backend.setfile(fname, ''.join(lines), mode, self.copysource)
663 self.backend.setfile(fname, ''.join(lines), mode, self.copysource)
664
664
665 def printfile(self, warn):
665 def printfile(self, warn):
666 if self.fileprinted:
666 if self.fileprinted:
667 return
667 return
668 if warn or self.ui.verbose:
668 if warn or self.ui.verbose:
669 self.fileprinted = True
669 self.fileprinted = True
670 s = _("patching file %s\n") % self.fname
670 s = _("patching file %s\n") % self.fname
671 if warn:
671 if warn:
672 self.ui.warn(s)
672 self.ui.warn(s)
673 else:
673 else:
674 self.ui.note(s)
674 self.ui.note(s)
675
675
676
676
677 def findlines(self, l, linenum):
677 def findlines(self, l, linenum):
678 # looks through the hash and finds candidate lines. The
678 # looks through the hash and finds candidate lines. The
679 # result is a list of line numbers sorted based on distance
679 # result is a list of line numbers sorted based on distance
680 # from linenum
680 # from linenum
681
681
682 cand = self.hash.get(l, [])
682 cand = self.hash.get(l, [])
683 if len(cand) > 1:
683 if len(cand) > 1:
684 # resort our list of potentials forward then back.
684 # resort our list of potentials forward then back.
685 cand.sort(key=lambda x: abs(x - linenum))
685 cand.sort(key=lambda x: abs(x - linenum))
686 return cand
686 return cand
687
687
688 def write_rej(self):
688 def write_rej(self):
689 # our rejects are a little different from patch(1). This always
689 # our rejects are a little different from patch(1). This always
690 # creates rejects in the same form as the original patch. A file
690 # creates rejects in the same form as the original patch. A file
691 # header is inserted so that you can run the reject through patch again
691 # header is inserted so that you can run the reject through patch again
692 # without having to type the filename.
692 # without having to type the filename.
693 if not self.rej:
693 if not self.rej:
694 return
694 return
695 base = os.path.basename(self.fname)
695 base = os.path.basename(self.fname)
696 lines = ["--- %s\n+++ %s\n" % (base, base)]
696 lines = ["--- %s\n+++ %s\n" % (base, base)]
697 for x in self.rej:
697 for x in self.rej:
698 for l in x.hunk:
698 for l in x.hunk:
699 lines.append(l)
699 lines.append(l)
700 if l[-1] != '\n':
700 if l[-1] != '\n':
701 lines.append("\n\ No newline at end of file\n")
701 lines.append("\n\ No newline at end of file\n")
702 self.backend.writerej(self.fname, len(self.rej), self.hunks, lines)
702 self.backend.writerej(self.fname, len(self.rej), self.hunks, lines)
703
703
704 def apply(self, h):
704 def apply(self, h):
705 if not h.complete():
705 if not h.complete():
706 raise PatchError(_("bad hunk #%d %s (%d %d %d %d)") %
706 raise PatchError(_("bad hunk #%d %s (%d %d %d %d)") %
707 (h.number, h.desc, len(h.a), h.lena, len(h.b),
707 (h.number, h.desc, len(h.a), h.lena, len(h.b),
708 h.lenb))
708 h.lenb))
709
709
710 self.hunks += 1
710 self.hunks += 1
711
711
712 if self.missing:
712 if self.missing:
713 self.rej.append(h)
713 self.rej.append(h)
714 return -1
714 return -1
715
715
716 if self.exists and self.create:
716 if self.exists and self.create:
717 if self.copysource:
717 if self.copysource:
718 self.ui.warn(_("cannot create %s: destination already "
718 self.ui.warn(_("cannot create %s: destination already "
719 "exists\n") % self.fname)
719 "exists\n") % self.fname)
720 else:
720 else:
721 self.ui.warn(_("file %s already exists\n") % self.fname)
721 self.ui.warn(_("file %s already exists\n") % self.fname)
722 self.rej.append(h)
722 self.rej.append(h)
723 return -1
723 return -1
724
724
725 if isinstance(h, binhunk):
725 if isinstance(h, binhunk):
726 if self.remove:
726 if self.remove:
727 self.backend.unlink(self.fname)
727 self.backend.unlink(self.fname)
728 else:
728 else:
729 l = h.new(self.lines)
729 l = h.new(self.lines)
730 self.lines[:] = l
730 self.lines[:] = l
731 self.offset += len(l)
731 self.offset += len(l)
732 self.dirty = True
732 self.dirty = True
733 return 0
733 return 0
734
734
735 horig = h
735 horig = h
736 if (self.eolmode in ('crlf', 'lf')
736 if (self.eolmode in ('crlf', 'lf')
737 or self.eolmode == 'auto' and self.eol):
737 or self.eolmode == 'auto' and self.eol):
738 # If new eols are going to be normalized, then normalize
738 # If new eols are going to be normalized, then normalize
739 # hunk data before patching. Otherwise, preserve input
739 # hunk data before patching. Otherwise, preserve input
740 # line-endings.
740 # line-endings.
741 h = h.getnormalized()
741 h = h.getnormalized()
742
742
743 # fast case first, no offsets, no fuzz
743 # fast case first, no offsets, no fuzz
744 old, oldstart, new, newstart = h.fuzzit(0, False)
744 old, oldstart, new, newstart = h.fuzzit(0, False)
745 oldstart += self.offset
745 oldstart += self.offset
746 orig_start = oldstart
746 orig_start = oldstart
747 # if there's skew we want to emit the "(offset %d lines)" even
747 # if there's skew we want to emit the "(offset %d lines)" even
748 # when the hunk cleanly applies at start + skew, so skip the
748 # when the hunk cleanly applies at start + skew, so skip the
749 # fast case code
749 # fast case code
750 if (self.skew == 0 and
750 if (self.skew == 0 and
751 diffhelpers.testhunk(old, self.lines, oldstart) == 0):
751 diffhelpers.testhunk(old, self.lines, oldstart) == 0):
752 if self.remove:
752 if self.remove:
753 self.backend.unlink(self.fname)
753 self.backend.unlink(self.fname)
754 else:
754 else:
755 self.lines[oldstart:oldstart + len(old)] = new
755 self.lines[oldstart:oldstart + len(old)] = new
756 self.offset += len(new) - len(old)
756 self.offset += len(new) - len(old)
757 self.dirty = True
757 self.dirty = True
758 return 0
758 return 0
759
759
760 # ok, we couldn't match the hunk. Lets look for offsets and fuzz it
760 # ok, we couldn't match the hunk. Lets look for offsets and fuzz it
761 self.hash = {}
761 self.hash = {}
762 for x, s in enumerate(self.lines):
762 for x, s in enumerate(self.lines):
763 self.hash.setdefault(s, []).append(x)
763 self.hash.setdefault(s, []).append(x)
764
764
765 for fuzzlen in xrange(3):
765 for fuzzlen in xrange(3):
766 for toponly in [True, False]:
766 for toponly in [True, False]:
767 old, oldstart, new, newstart = h.fuzzit(fuzzlen, toponly)
767 old, oldstart, new, newstart = h.fuzzit(fuzzlen, toponly)
768 oldstart = oldstart + self.offset + self.skew
768 oldstart = oldstart + self.offset + self.skew
769 oldstart = min(oldstart, len(self.lines))
769 oldstart = min(oldstart, len(self.lines))
770 if old:
770 if old:
771 cand = self.findlines(old[0][1:], oldstart)
771 cand = self.findlines(old[0][1:], oldstart)
772 else:
772 else:
773 # Only adding lines with no or fuzzed context, just
773 # Only adding lines with no or fuzzed context, just
774 # take the skew in account
774 # take the skew in account
775 cand = [oldstart]
775 cand = [oldstart]
776
776
777 for l in cand:
777 for l in cand:
778 if not old or diffhelpers.testhunk(old, self.lines, l) == 0:
778 if not old or diffhelpers.testhunk(old, self.lines, l) == 0:
779 self.lines[l : l + len(old)] = new
779 self.lines[l : l + len(old)] = new
780 self.offset += len(new) - len(old)
780 self.offset += len(new) - len(old)
781 self.skew = l - orig_start
781 self.skew = l - orig_start
782 self.dirty = True
782 self.dirty = True
783 offset = l - orig_start - fuzzlen
783 offset = l - orig_start - fuzzlen
784 if fuzzlen:
784 if fuzzlen:
785 msg = _("Hunk #%d succeeded at %d "
785 msg = _("Hunk #%d succeeded at %d "
786 "with fuzz %d "
786 "with fuzz %d "
787 "(offset %d lines).\n")
787 "(offset %d lines).\n")
788 self.printfile(True)
788 self.printfile(True)
789 self.ui.warn(msg %
789 self.ui.warn(msg %
790 (h.number, l + 1, fuzzlen, offset))
790 (h.number, l + 1, fuzzlen, offset))
791 else:
791 else:
792 msg = _("Hunk #%d succeeded at %d "
792 msg = _("Hunk #%d succeeded at %d "
793 "(offset %d lines).\n")
793 "(offset %d lines).\n")
794 self.ui.note(msg % (h.number, l + 1, offset))
794 self.ui.note(msg % (h.number, l + 1, offset))
795 return fuzzlen
795 return fuzzlen
796 self.printfile(True)
796 self.printfile(True)
797 self.ui.warn(_("Hunk #%d FAILED at %d\n") % (h.number, orig_start))
797 self.ui.warn(_("Hunk #%d FAILED at %d\n") % (h.number, orig_start))
798 self.rej.append(horig)
798 self.rej.append(horig)
799 return -1
799 return -1
800
800
801 def close(self):
801 def close(self):
802 if self.dirty:
802 if self.dirty:
803 self.writelines(self.fname, self.lines, self.mode)
803 self.writelines(self.fname, self.lines, self.mode)
804 self.write_rej()
804 self.write_rej()
805 return len(self.rej)
805 return len(self.rej)
806
806
807 class hunk(object):
807 class hunk(object):
808 def __init__(self, desc, num, lr, context):
808 def __init__(self, desc, num, lr, context):
809 self.number = num
809 self.number = num
810 self.desc = desc
810 self.desc = desc
811 self.hunk = [desc]
811 self.hunk = [desc]
812 self.a = []
812 self.a = []
813 self.b = []
813 self.b = []
814 self.starta = self.lena = None
814 self.starta = self.lena = None
815 self.startb = self.lenb = None
815 self.startb = self.lenb = None
816 if lr is not None:
816 if lr is not None:
817 if context:
817 if context:
818 self.read_context_hunk(lr)
818 self.read_context_hunk(lr)
819 else:
819 else:
820 self.read_unified_hunk(lr)
820 self.read_unified_hunk(lr)
821
821
822 def getnormalized(self):
822 def getnormalized(self):
823 """Return a copy with line endings normalized to LF."""
823 """Return a copy with line endings normalized to LF."""
824
824
825 def normalize(lines):
825 def normalize(lines):
826 nlines = []
826 nlines = []
827 for line in lines:
827 for line in lines:
828 if line.endswith('\r\n'):
828 if line.endswith('\r\n'):
829 line = line[:-2] + '\n'
829 line = line[:-2] + '\n'
830 nlines.append(line)
830 nlines.append(line)
831 return nlines
831 return nlines
832
832
833 # Dummy object, it is rebuilt manually
833 # Dummy object, it is rebuilt manually
834 nh = hunk(self.desc, self.number, None, None)
834 nh = hunk(self.desc, self.number, None, None)
835 nh.number = self.number
835 nh.number = self.number
836 nh.desc = self.desc
836 nh.desc = self.desc
837 nh.hunk = self.hunk
837 nh.hunk = self.hunk
838 nh.a = normalize(self.a)
838 nh.a = normalize(self.a)
839 nh.b = normalize(self.b)
839 nh.b = normalize(self.b)
840 nh.starta = self.starta
840 nh.starta = self.starta
841 nh.startb = self.startb
841 nh.startb = self.startb
842 nh.lena = self.lena
842 nh.lena = self.lena
843 nh.lenb = self.lenb
843 nh.lenb = self.lenb
844 return nh
844 return nh
845
845
846 def read_unified_hunk(self, lr):
846 def read_unified_hunk(self, lr):
847 m = unidesc.match(self.desc)
847 m = unidesc.match(self.desc)
848 if not m:
848 if not m:
849 raise PatchError(_("bad hunk #%d") % self.number)
849 raise PatchError(_("bad hunk #%d") % self.number)
850 self.starta, self.lena, self.startb, self.lenb = m.groups()
850 self.starta, self.lena, self.startb, self.lenb = m.groups()
851 if self.lena is None:
851 if self.lena is None:
852 self.lena = 1
852 self.lena = 1
853 else:
853 else:
854 self.lena = int(self.lena)
854 self.lena = int(self.lena)
855 if self.lenb is None:
855 if self.lenb is None:
856 self.lenb = 1
856 self.lenb = 1
857 else:
857 else:
858 self.lenb = int(self.lenb)
858 self.lenb = int(self.lenb)
859 self.starta = int(self.starta)
859 self.starta = int(self.starta)
860 self.startb = int(self.startb)
860 self.startb = int(self.startb)
861 diffhelpers.addlines(lr, self.hunk, self.lena, self.lenb, self.a,
861 diffhelpers.addlines(lr, self.hunk, self.lena, self.lenb, self.a,
862 self.b)
862 self.b)
863 # if we hit eof before finishing out the hunk, the last line will
863 # if we hit eof before finishing out the hunk, the last line will
864 # be zero length. Lets try to fix it up.
864 # be zero length. Lets try to fix it up.
865 while len(self.hunk[-1]) == 0:
865 while len(self.hunk[-1]) == 0:
866 del self.hunk[-1]
866 del self.hunk[-1]
867 del self.a[-1]
867 del self.a[-1]
868 del self.b[-1]
868 del self.b[-1]
869 self.lena -= 1
869 self.lena -= 1
870 self.lenb -= 1
870 self.lenb -= 1
871 self._fixnewline(lr)
871 self._fixnewline(lr)
872
872
873 def read_context_hunk(self, lr):
873 def read_context_hunk(self, lr):
874 self.desc = lr.readline()
874 self.desc = lr.readline()
875 m = contextdesc.match(self.desc)
875 m = contextdesc.match(self.desc)
876 if not m:
876 if not m:
877 raise PatchError(_("bad hunk #%d") % self.number)
877 raise PatchError(_("bad hunk #%d") % self.number)
878 self.starta, aend = m.groups()
878 self.starta, aend = m.groups()
879 self.starta = int(self.starta)
879 self.starta = int(self.starta)
880 if aend is None:
880 if aend is None:
881 aend = self.starta
881 aend = self.starta
882 self.lena = int(aend) - self.starta
882 self.lena = int(aend) - self.starta
883 if self.starta:
883 if self.starta:
884 self.lena += 1
884 self.lena += 1
885 for x in xrange(self.lena):
885 for x in xrange(self.lena):
886 l = lr.readline()
886 l = lr.readline()
887 if l.startswith('---'):
887 if l.startswith('---'):
888 # lines addition, old block is empty
888 # lines addition, old block is empty
889 lr.push(l)
889 lr.push(l)
890 break
890 break
891 s = l[2:]
891 s = l[2:]
892 if l.startswith('- ') or l.startswith('! '):
892 if l.startswith('- ') or l.startswith('! '):
893 u = '-' + s
893 u = '-' + s
894 elif l.startswith(' '):
894 elif l.startswith(' '):
895 u = ' ' + s
895 u = ' ' + s
896 else:
896 else:
897 raise PatchError(_("bad hunk #%d old text line %d") %
897 raise PatchError(_("bad hunk #%d old text line %d") %
898 (self.number, x))
898 (self.number, x))
899 self.a.append(u)
899 self.a.append(u)
900 self.hunk.append(u)
900 self.hunk.append(u)
901
901
902 l = lr.readline()
902 l = lr.readline()
903 if l.startswith('\ '):
903 if l.startswith('\ '):
904 s = self.a[-1][:-1]
904 s = self.a[-1][:-1]
905 self.a[-1] = s
905 self.a[-1] = s
906 self.hunk[-1] = s
906 self.hunk[-1] = s
907 l = lr.readline()
907 l = lr.readline()
908 m = contextdesc.match(l)
908 m = contextdesc.match(l)
909 if not m:
909 if not m:
910 raise PatchError(_("bad hunk #%d") % self.number)
910 raise PatchError(_("bad hunk #%d") % self.number)
911 self.startb, bend = m.groups()
911 self.startb, bend = m.groups()
912 self.startb = int(self.startb)
912 self.startb = int(self.startb)
913 if bend is None:
913 if bend is None:
914 bend = self.startb
914 bend = self.startb
915 self.lenb = int(bend) - self.startb
915 self.lenb = int(bend) - self.startb
916 if self.startb:
916 if self.startb:
917 self.lenb += 1
917 self.lenb += 1
918 hunki = 1
918 hunki = 1
919 for x in xrange(self.lenb):
919 for x in xrange(self.lenb):
920 l = lr.readline()
920 l = lr.readline()
921 if l.startswith('\ '):
921 if l.startswith('\ '):
922 # XXX: the only way to hit this is with an invalid line range.
922 # XXX: the only way to hit this is with an invalid line range.
923 # The no-eol marker is not counted in the line range, but I
923 # The no-eol marker is not counted in the line range, but I
924 # guess there are diff(1) out there which behave differently.
924 # guess there are diff(1) out there which behave differently.
925 s = self.b[-1][:-1]
925 s = self.b[-1][:-1]
926 self.b[-1] = s
926 self.b[-1] = s
927 self.hunk[hunki - 1] = s
927 self.hunk[hunki - 1] = s
928 continue
928 continue
929 if not l:
929 if not l:
930 # line deletions, new block is empty and we hit EOF
930 # line deletions, new block is empty and we hit EOF
931 lr.push(l)
931 lr.push(l)
932 break
932 break
933 s = l[2:]
933 s = l[2:]
934 if l.startswith('+ ') or l.startswith('! '):
934 if l.startswith('+ ') or l.startswith('! '):
935 u = '+' + s
935 u = '+' + s
936 elif l.startswith(' '):
936 elif l.startswith(' '):
937 u = ' ' + s
937 u = ' ' + s
938 elif len(self.b) == 0:
938 elif len(self.b) == 0:
939 # line deletions, new block is empty
939 # line deletions, new block is empty
940 lr.push(l)
940 lr.push(l)
941 break
941 break
942 else:
942 else:
943 raise PatchError(_("bad hunk #%d old text line %d") %
943 raise PatchError(_("bad hunk #%d old text line %d") %
944 (self.number, x))
944 (self.number, x))
945 self.b.append(s)
945 self.b.append(s)
946 while True:
946 while True:
947 if hunki >= len(self.hunk):
947 if hunki >= len(self.hunk):
948 h = ""
948 h = ""
949 else:
949 else:
950 h = self.hunk[hunki]
950 h = self.hunk[hunki]
951 hunki += 1
951 hunki += 1
952 if h == u:
952 if h == u:
953 break
953 break
954 elif h.startswith('-'):
954 elif h.startswith('-'):
955 continue
955 continue
956 else:
956 else:
957 self.hunk.insert(hunki - 1, u)
957 self.hunk.insert(hunki - 1, u)
958 break
958 break
959
959
960 if not self.a:
960 if not self.a:
961 # this happens when lines were only added to the hunk
961 # this happens when lines were only added to the hunk
962 for x in self.hunk:
962 for x in self.hunk:
963 if x.startswith('-') or x.startswith(' '):
963 if x.startswith('-') or x.startswith(' '):
964 self.a.append(x)
964 self.a.append(x)
965 if not self.b:
965 if not self.b:
966 # this happens when lines were only deleted from the hunk
966 # this happens when lines were only deleted from the hunk
967 for x in self.hunk:
967 for x in self.hunk:
968 if x.startswith('+') or x.startswith(' '):
968 if x.startswith('+') or x.startswith(' '):
969 self.b.append(x[1:])
969 self.b.append(x[1:])
970 # @@ -start,len +start,len @@
970 # @@ -start,len +start,len @@
971 self.desc = "@@ -%d,%d +%d,%d @@\n" % (self.starta, self.lena,
971 self.desc = "@@ -%d,%d +%d,%d @@\n" % (self.starta, self.lena,
972 self.startb, self.lenb)
972 self.startb, self.lenb)
973 self.hunk[0] = self.desc
973 self.hunk[0] = self.desc
974 self._fixnewline(lr)
974 self._fixnewline(lr)
975
975
976 def _fixnewline(self, lr):
976 def _fixnewline(self, lr):
977 l = lr.readline()
977 l = lr.readline()
978 if l.startswith('\ '):
978 if l.startswith('\ '):
979 diffhelpers.fix_newline(self.hunk, self.a, self.b)
979 diffhelpers.fix_newline(self.hunk, self.a, self.b)
980 else:
980 else:
981 lr.push(l)
981 lr.push(l)
982
982
983 def complete(self):
983 def complete(self):
984 return len(self.a) == self.lena and len(self.b) == self.lenb
984 return len(self.a) == self.lena and len(self.b) == self.lenb
985
985
986 def _fuzzit(self, old, new, fuzz, toponly):
986 def _fuzzit(self, old, new, fuzz, toponly):
987 # this removes context lines from the top and bottom of list 'l'. It
987 # this removes context lines from the top and bottom of list 'l'. It
988 # checks the hunk to make sure only context lines are removed, and then
988 # checks the hunk to make sure only context lines are removed, and then
989 # returns a new shortened list of lines.
989 # returns a new shortened list of lines.
990 fuzz = min(fuzz, len(old))
990 fuzz = min(fuzz, len(old))
991 if fuzz:
991 if fuzz:
992 top = 0
992 top = 0
993 bot = 0
993 bot = 0
994 hlen = len(self.hunk)
994 hlen = len(self.hunk)
995 for x in xrange(hlen - 1):
995 for x in xrange(hlen - 1):
996 # the hunk starts with the @@ line, so use x+1
996 # the hunk starts with the @@ line, so use x+1
997 if self.hunk[x + 1][0] == ' ':
997 if self.hunk[x + 1][0] == ' ':
998 top += 1
998 top += 1
999 else:
999 else:
1000 break
1000 break
1001 if not toponly:
1001 if not toponly:
1002 for x in xrange(hlen - 1):
1002 for x in xrange(hlen - 1):
1003 if self.hunk[hlen - bot - 1][0] == ' ':
1003 if self.hunk[hlen - bot - 1][0] == ' ':
1004 bot += 1
1004 bot += 1
1005 else:
1005 else:
1006 break
1006 break
1007
1007
1008 bot = min(fuzz, bot)
1008 bot = min(fuzz, bot)
1009 top = min(fuzz, top)
1009 top = min(fuzz, top)
1010 return old[top:len(old) - bot], new[top:len(new) - bot], top
1010 return old[top:len(old) - bot], new[top:len(new) - bot], top
1011 return old, new, 0
1011 return old, new, 0
1012
1012
1013 def fuzzit(self, fuzz, toponly):
1013 def fuzzit(self, fuzz, toponly):
1014 old, new, top = self._fuzzit(self.a, self.b, fuzz, toponly)
1014 old, new, top = self._fuzzit(self.a, self.b, fuzz, toponly)
1015 oldstart = self.starta + top
1015 oldstart = self.starta + top
1016 newstart = self.startb + top
1016 newstart = self.startb + top
1017 # zero length hunk ranges already have their start decremented
1017 # zero length hunk ranges already have their start decremented
1018 if self.lena and oldstart > 0:
1018 if self.lena and oldstart > 0:
1019 oldstart -= 1
1019 oldstart -= 1
1020 if self.lenb and newstart > 0:
1020 if self.lenb and newstart > 0:
1021 newstart -= 1
1021 newstart -= 1
1022 return old, oldstart, new, newstart
1022 return old, oldstart, new, newstart
1023
1023
1024 class binhunk(object):
1024 class binhunk(object):
1025 'A binary patch file.'
1025 'A binary patch file.'
1026 def __init__(self, lr, fname):
1026 def __init__(self, lr, fname):
1027 self.text = None
1027 self.text = None
1028 self.delta = False
1028 self.delta = False
1029 self.hunk = ['GIT binary patch\n']
1029 self.hunk = ['GIT binary patch\n']
1030 self._fname = fname
1030 self._fname = fname
1031 self._read(lr)
1031 self._read(lr)
1032
1032
1033 def complete(self):
1033 def complete(self):
1034 return self.text is not None
1034 return self.text is not None
1035
1035
1036 def new(self, lines):
1036 def new(self, lines):
1037 if self.delta:
1037 if self.delta:
1038 return [applybindelta(self.text, ''.join(lines))]
1038 return [applybindelta(self.text, ''.join(lines))]
1039 return [self.text]
1039 return [self.text]
1040
1040
1041 def _read(self, lr):
1041 def _read(self, lr):
1042 def getline(lr, hunk):
1042 def getline(lr, hunk):
1043 l = lr.readline()
1043 l = lr.readline()
1044 hunk.append(l)
1044 hunk.append(l)
1045 return l.rstrip('\r\n')
1045 return l.rstrip('\r\n')
1046
1046
1047 size = 0
1047 size = 0
1048 while True:
1048 while True:
1049 line = getline(lr, self.hunk)
1049 line = getline(lr, self.hunk)
1050 if not line:
1050 if not line:
1051 raise PatchError(_('could not extract "%s" binary data')
1051 raise PatchError(_('could not extract "%s" binary data')
1052 % self._fname)
1052 % self._fname)
1053 if line.startswith('literal '):
1053 if line.startswith('literal '):
1054 size = int(line[8:].rstrip())
1054 size = int(line[8:].rstrip())
1055 break
1055 break
1056 if line.startswith('delta '):
1056 if line.startswith('delta '):
1057 size = int(line[6:].rstrip())
1057 size = int(line[6:].rstrip())
1058 self.delta = True
1058 self.delta = True
1059 break
1059 break
1060 dec = []
1060 dec = []
1061 line = getline(lr, self.hunk)
1061 line = getline(lr, self.hunk)
1062 while len(line) > 1:
1062 while len(line) > 1:
1063 l = line[0]
1063 l = line[0]
1064 if l <= 'Z' and l >= 'A':
1064 if l <= 'Z' and l >= 'A':
1065 l = ord(l) - ord('A') + 1
1065 l = ord(l) - ord('A') + 1
1066 else:
1066 else:
1067 l = ord(l) - ord('a') + 27
1067 l = ord(l) - ord('a') + 27
1068 try:
1068 try:
1069 dec.append(base85.b85decode(line[1:])[:l])
1069 dec.append(base85.b85decode(line[1:])[:l])
1070 except ValueError, e:
1070 except ValueError, e:
1071 raise PatchError(_('could not decode "%s" binary patch: %s')
1071 raise PatchError(_('could not decode "%s" binary patch: %s')
1072 % (self._fname, str(e)))
1072 % (self._fname, str(e)))
1073 line = getline(lr, self.hunk)
1073 line = getline(lr, self.hunk)
1074 text = zlib.decompress(''.join(dec))
1074 text = zlib.decompress(''.join(dec))
1075 if len(text) != size:
1075 if len(text) != size:
1076 raise PatchError(_('"%s" length is %d bytes, should be %d')
1076 raise PatchError(_('"%s" length is %d bytes, should be %d')
1077 % (self._fname, len(text), size))
1077 % (self._fname, len(text), size))
1078 self.text = text
1078 self.text = text
1079
1079
1080 def parsefilename(str):
1080 def parsefilename(str):
1081 # --- filename \t|space stuff
1081 # --- filename \t|space stuff
1082 s = str[4:].rstrip('\r\n')
1082 s = str[4:].rstrip('\r\n')
1083 i = s.find('\t')
1083 i = s.find('\t')
1084 if i < 0:
1084 if i < 0:
1085 i = s.find(' ')
1085 i = s.find(' ')
1086 if i < 0:
1086 if i < 0:
1087 return s
1087 return s
1088 return s[:i]
1088 return s[:i]
1089
1089
1090 def pathstrip(path, strip):
1090 def pathstrip(path, strip):
1091 pathlen = len(path)
1091 pathlen = len(path)
1092 i = 0
1092 i = 0
1093 if strip == 0:
1093 if strip == 0:
1094 return '', path.rstrip()
1094 return '', path.rstrip()
1095 count = strip
1095 count = strip
1096 while count > 0:
1096 while count > 0:
1097 i = path.find('/', i)
1097 i = path.find('/', i)
1098 if i == -1:
1098 if i == -1:
1099 raise PatchError(_("unable to strip away %d of %d dirs from %s") %
1099 raise PatchError(_("unable to strip away %d of %d dirs from %s") %
1100 (count, strip, path))
1100 (count, strip, path))
1101 i += 1
1101 i += 1
1102 # consume '//' in the path
1102 # consume '//' in the path
1103 while i < pathlen - 1 and path[i] == '/':
1103 while i < pathlen - 1 and path[i] == '/':
1104 i += 1
1104 i += 1
1105 count -= 1
1105 count -= 1
1106 return path[:i].lstrip(), path[i:].rstrip()
1106 return path[:i].lstrip(), path[i:].rstrip()
1107
1107
1108 def makepatchmeta(backend, afile_orig, bfile_orig, hunk, strip):
1108 def makepatchmeta(backend, afile_orig, bfile_orig, hunk, strip):
1109 nulla = afile_orig == "/dev/null"
1109 nulla = afile_orig == "/dev/null"
1110 nullb = bfile_orig == "/dev/null"
1110 nullb = bfile_orig == "/dev/null"
1111 create = nulla and hunk.starta == 0 and hunk.lena == 0
1111 create = nulla and hunk.starta == 0 and hunk.lena == 0
1112 remove = nullb and hunk.startb == 0 and hunk.lenb == 0
1112 remove = nullb and hunk.startb == 0 and hunk.lenb == 0
1113 abase, afile = pathstrip(afile_orig, strip)
1113 abase, afile = pathstrip(afile_orig, strip)
1114 gooda = not nulla and backend.exists(afile)
1114 gooda = not nulla and backend.exists(afile)
1115 bbase, bfile = pathstrip(bfile_orig, strip)
1115 bbase, bfile = pathstrip(bfile_orig, strip)
1116 if afile == bfile:
1116 if afile == bfile:
1117 goodb = gooda
1117 goodb = gooda
1118 else:
1118 else:
1119 goodb = not nullb and backend.exists(bfile)
1119 goodb = not nullb and backend.exists(bfile)
1120 missing = not goodb and not gooda and not create
1120 missing = not goodb and not gooda and not create
1121
1121
1122 # some diff programs apparently produce patches where the afile is
1122 # some diff programs apparently produce patches where the afile is
1123 # not /dev/null, but afile starts with bfile
1123 # not /dev/null, but afile starts with bfile
1124 abasedir = afile[:afile.rfind('/') + 1]
1124 abasedir = afile[:afile.rfind('/') + 1]
1125 bbasedir = bfile[:bfile.rfind('/') + 1]
1125 bbasedir = bfile[:bfile.rfind('/') + 1]
1126 if (missing and abasedir == bbasedir and afile.startswith(bfile)
1126 if (missing and abasedir == bbasedir and afile.startswith(bfile)
1127 and hunk.starta == 0 and hunk.lena == 0):
1127 and hunk.starta == 0 and hunk.lena == 0):
1128 create = True
1128 create = True
1129 missing = False
1129 missing = False
1130
1130
1131 # If afile is "a/b/foo" and bfile is "a/b/foo.orig" we assume the
1131 # If afile is "a/b/foo" and bfile is "a/b/foo.orig" we assume the
1132 # diff is between a file and its backup. In this case, the original
1132 # diff is between a file and its backup. In this case, the original
1133 # file should be patched (see original mpatch code).
1133 # file should be patched (see original mpatch code).
1134 isbackup = (abase == bbase and bfile.startswith(afile))
1134 isbackup = (abase == bbase and bfile.startswith(afile))
1135 fname = None
1135 fname = None
1136 if not missing:
1136 if not missing:
1137 if gooda and goodb:
1137 if gooda and goodb:
1138 fname = isbackup and afile or bfile
1138 fname = isbackup and afile or bfile
1139 elif gooda:
1139 elif gooda:
1140 fname = afile
1140 fname = afile
1141
1141
1142 if not fname:
1142 if not fname:
1143 if not nullb:
1143 if not nullb:
1144 fname = isbackup and afile or bfile
1144 fname = isbackup and afile or bfile
1145 elif not nulla:
1145 elif not nulla:
1146 fname = afile
1146 fname = afile
1147 else:
1147 else:
1148 raise PatchError(_("undefined source and destination files"))
1148 raise PatchError(_("undefined source and destination files"))
1149
1149
1150 gp = patchmeta(fname)
1150 gp = patchmeta(fname)
1151 if create:
1151 if create:
1152 gp.op = 'ADD'
1152 gp.op = 'ADD'
1153 elif remove:
1153 elif remove:
1154 gp.op = 'DELETE'
1154 gp.op = 'DELETE'
1155 return gp
1155 return gp
1156
1156
1157 def scangitpatch(lr, firstline):
1157 def scangitpatch(lr, firstline):
1158 """
1158 """
1159 Git patches can emit:
1159 Git patches can emit:
1160 - rename a to b
1160 - rename a to b
1161 - change b
1161 - change b
1162 - copy a to c
1162 - copy a to c
1163 - change c
1163 - change c
1164
1164
1165 We cannot apply this sequence as-is, the renamed 'a' could not be
1165 We cannot apply this sequence as-is, the renamed 'a' could not be
1166 found for it would have been renamed already. And we cannot copy
1166 found for it would have been renamed already. And we cannot copy
1167 from 'b' instead because 'b' would have been changed already. So
1167 from 'b' instead because 'b' would have been changed already. So
1168 we scan the git patch for copy and rename commands so we can
1168 we scan the git patch for copy and rename commands so we can
1169 perform the copies ahead of time.
1169 perform the copies ahead of time.
1170 """
1170 """
1171 pos = 0
1171 pos = 0
1172 try:
1172 try:
1173 pos = lr.fp.tell()
1173 pos = lr.fp.tell()
1174 fp = lr.fp
1174 fp = lr.fp
1175 except IOError:
1175 except IOError:
1176 fp = cStringIO.StringIO(lr.fp.read())
1176 fp = cStringIO.StringIO(lr.fp.read())
1177 gitlr = linereader(fp)
1177 gitlr = linereader(fp)
1178 gitlr.push(firstline)
1178 gitlr.push(firstline)
1179 gitpatches = readgitpatch(gitlr)
1179 gitpatches = readgitpatch(gitlr)
1180 fp.seek(pos)
1180 fp.seek(pos)
1181 return gitpatches
1181 return gitpatches
1182
1182
1183 def iterhunks(fp):
1183 def iterhunks(fp):
1184 """Read a patch and yield the following events:
1184 """Read a patch and yield the following events:
1185 - ("file", afile, bfile, firsthunk): select a new target file.
1185 - ("file", afile, bfile, firsthunk): select a new target file.
1186 - ("hunk", hunk): a new hunk is ready to be applied, follows a
1186 - ("hunk", hunk): a new hunk is ready to be applied, follows a
1187 "file" event.
1187 "file" event.
1188 - ("git", gitchanges): current diff is in git format, gitchanges
1188 - ("git", gitchanges): current diff is in git format, gitchanges
1189 maps filenames to gitpatch records. Unique event.
1189 maps filenames to gitpatch records. Unique event.
1190 """
1190 """
1191 afile = ""
1191 afile = ""
1192 bfile = ""
1192 bfile = ""
1193 state = None
1193 state = None
1194 hunknum = 0
1194 hunknum = 0
1195 emitfile = newfile = False
1195 emitfile = newfile = False
1196 gitpatches = None
1196 gitpatches = None
1197
1197
1198 # our states
1198 # our states
1199 BFILE = 1
1199 BFILE = 1
1200 context = None
1200 context = None
1201 lr = linereader(fp)
1201 lr = linereader(fp)
1202
1202
1203 while True:
1203 while True:
1204 x = lr.readline()
1204 x = lr.readline()
1205 if not x:
1205 if not x:
1206 break
1206 break
1207 if state == BFILE and (
1207 if state == BFILE and (
1208 (not context and x[0] == '@')
1208 (not context and x[0] == '@')
1209 or (context is not False and x.startswith('***************'))
1209 or (context is not False and x.startswith('***************'))
1210 or x.startswith('GIT binary patch')):
1210 or x.startswith('GIT binary patch')):
1211 gp = None
1211 gp = None
1212 if (gitpatches and
1212 if (gitpatches and
1213 gitpatches[-1].ispatching(afile, bfile)):
1213 gitpatches[-1].ispatching(afile, bfile)):
1214 gp = gitpatches.pop()
1214 gp = gitpatches.pop()
1215 if x.startswith('GIT binary patch'):
1215 if x.startswith('GIT binary patch'):
1216 h = binhunk(lr, gp.path)
1216 h = binhunk(lr, gp.path)
1217 else:
1217 else:
1218 if context is None and x.startswith('***************'):
1218 if context is None and x.startswith('***************'):
1219 context = True
1219 context = True
1220 h = hunk(x, hunknum + 1, lr, context)
1220 h = hunk(x, hunknum + 1, lr, context)
1221 hunknum += 1
1221 hunknum += 1
1222 if emitfile:
1222 if emitfile:
1223 emitfile = False
1223 emitfile = False
1224 yield 'file', (afile, bfile, h, gp and gp.copy() or None)
1224 yield 'file', (afile, bfile, h, gp and gp.copy() or None)
1225 yield 'hunk', h
1225 yield 'hunk', h
1226 elif x.startswith('diff --git a/'):
1226 elif x.startswith('diff --git a/'):
1227 m = gitre.match(x.rstrip(' \r\n'))
1227 m = gitre.match(x.rstrip(' \r\n'))
1228 if not m:
1228 if not m:
1229 continue
1229 continue
1230 if gitpatches is None:
1230 if gitpatches is None:
1231 # scan whole input for git metadata
1231 # scan whole input for git metadata
1232 gitpatches = scangitpatch(lr, x)
1232 gitpatches = scangitpatch(lr, x)
1233 yield 'git', [g.copy() for g in gitpatches
1233 yield 'git', [g.copy() for g in gitpatches
1234 if g.op in ('COPY', 'RENAME')]
1234 if g.op in ('COPY', 'RENAME')]
1235 gitpatches.reverse()
1235 gitpatches.reverse()
1236 afile = 'a/' + m.group(1)
1236 afile = 'a/' + m.group(1)
1237 bfile = 'b/' + m.group(2)
1237 bfile = 'b/' + m.group(2)
1238 while gitpatches and not gitpatches[-1].ispatching(afile, bfile):
1238 while gitpatches and not gitpatches[-1].ispatching(afile, bfile):
1239 gp = gitpatches.pop()
1239 gp = gitpatches.pop()
1240 yield 'file', ('a/' + gp.path, 'b/' + gp.path, None, gp.copy())
1240 yield 'file', ('a/' + gp.path, 'b/' + gp.path, None, gp.copy())
1241 if not gitpatches:
1241 if not gitpatches:
1242 raise PatchError(_('failed to synchronize metadata for "%s"')
1242 raise PatchError(_('failed to synchronize metadata for "%s"')
1243 % afile[2:])
1243 % afile[2:])
1244 gp = gitpatches[-1]
1244 gp = gitpatches[-1]
1245 newfile = True
1245 newfile = True
1246 elif x.startswith('---'):
1246 elif x.startswith('---'):
1247 # check for a unified diff
1247 # check for a unified diff
1248 l2 = lr.readline()
1248 l2 = lr.readline()
1249 if not l2.startswith('+++'):
1249 if not l2.startswith('+++'):
1250 lr.push(l2)
1250 lr.push(l2)
1251 continue
1251 continue
1252 newfile = True
1252 newfile = True
1253 context = False
1253 context = False
1254 afile = parsefilename(x)
1254 afile = parsefilename(x)
1255 bfile = parsefilename(l2)
1255 bfile = parsefilename(l2)
1256 elif x.startswith('***'):
1256 elif x.startswith('***'):
1257 # check for a context diff
1257 # check for a context diff
1258 l2 = lr.readline()
1258 l2 = lr.readline()
1259 if not l2.startswith('---'):
1259 if not l2.startswith('---'):
1260 lr.push(l2)
1260 lr.push(l2)
1261 continue
1261 continue
1262 l3 = lr.readline()
1262 l3 = lr.readline()
1263 lr.push(l3)
1263 lr.push(l3)
1264 if not l3.startswith("***************"):
1264 if not l3.startswith("***************"):
1265 lr.push(l2)
1265 lr.push(l2)
1266 continue
1266 continue
1267 newfile = True
1267 newfile = True
1268 context = True
1268 context = True
1269 afile = parsefilename(x)
1269 afile = parsefilename(x)
1270 bfile = parsefilename(l2)
1270 bfile = parsefilename(l2)
1271
1271
1272 if newfile:
1272 if newfile:
1273 newfile = False
1273 newfile = False
1274 emitfile = True
1274 emitfile = True
1275 state = BFILE
1275 state = BFILE
1276 hunknum = 0
1276 hunknum = 0
1277
1277
1278 while gitpatches:
1278 while gitpatches:
1279 gp = gitpatches.pop()
1279 gp = gitpatches.pop()
1280 yield 'file', ('a/' + gp.path, 'b/' + gp.path, None, gp.copy())
1280 yield 'file', ('a/' + gp.path, 'b/' + gp.path, None, gp.copy())
1281
1281
1282 def applybindelta(binchunk, data):
1282 def applybindelta(binchunk, data):
1283 """Apply a binary delta hunk
1283 """Apply a binary delta hunk
1284 The algorithm used is the algorithm from git's patch-delta.c
1284 The algorithm used is the algorithm from git's patch-delta.c
1285 """
1285 """
1286 def deltahead(binchunk):
1286 def deltahead(binchunk):
1287 i = 0
1287 i = 0
1288 for c in binchunk:
1288 for c in binchunk:
1289 i += 1
1289 i += 1
1290 if not (ord(c) & 0x80):
1290 if not (ord(c) & 0x80):
1291 return i
1291 return i
1292 return i
1292 return i
1293 out = ""
1293 out = ""
1294 s = deltahead(binchunk)
1294 s = deltahead(binchunk)
1295 binchunk = binchunk[s:]
1295 binchunk = binchunk[s:]
1296 s = deltahead(binchunk)
1296 s = deltahead(binchunk)
1297 binchunk = binchunk[s:]
1297 binchunk = binchunk[s:]
1298 i = 0
1298 i = 0
1299 while i < len(binchunk):
1299 while i < len(binchunk):
1300 cmd = ord(binchunk[i])
1300 cmd = ord(binchunk[i])
1301 i += 1
1301 i += 1
1302 if (cmd & 0x80):
1302 if (cmd & 0x80):
1303 offset = 0
1303 offset = 0
1304 size = 0
1304 size = 0
1305 if (cmd & 0x01):
1305 if (cmd & 0x01):
1306 offset = ord(binchunk[i])
1306 offset = ord(binchunk[i])
1307 i += 1
1307 i += 1
1308 if (cmd & 0x02):
1308 if (cmd & 0x02):
1309 offset |= ord(binchunk[i]) << 8
1309 offset |= ord(binchunk[i]) << 8
1310 i += 1
1310 i += 1
1311 if (cmd & 0x04):
1311 if (cmd & 0x04):
1312 offset |= ord(binchunk[i]) << 16
1312 offset |= ord(binchunk[i]) << 16
1313 i += 1
1313 i += 1
1314 if (cmd & 0x08):
1314 if (cmd & 0x08):
1315 offset |= ord(binchunk[i]) << 24
1315 offset |= ord(binchunk[i]) << 24
1316 i += 1
1316 i += 1
1317 if (cmd & 0x10):
1317 if (cmd & 0x10):
1318 size = ord(binchunk[i])
1318 size = ord(binchunk[i])
1319 i += 1
1319 i += 1
1320 if (cmd & 0x20):
1320 if (cmd & 0x20):
1321 size |= ord(binchunk[i]) << 8
1321 size |= ord(binchunk[i]) << 8
1322 i += 1
1322 i += 1
1323 if (cmd & 0x40):
1323 if (cmd & 0x40):
1324 size |= ord(binchunk[i]) << 16
1324 size |= ord(binchunk[i]) << 16
1325 i += 1
1325 i += 1
1326 if size == 0:
1326 if size == 0:
1327 size = 0x10000
1327 size = 0x10000
1328 offset_end = offset + size
1328 offset_end = offset + size
1329 out += data[offset:offset_end]
1329 out += data[offset:offset_end]
1330 elif cmd != 0:
1330 elif cmd != 0:
1331 offset_end = i + cmd
1331 offset_end = i + cmd
1332 out += binchunk[i:offset_end]
1332 out += binchunk[i:offset_end]
1333 i += cmd
1333 i += cmd
1334 else:
1334 else:
1335 raise PatchError(_('unexpected delta opcode 0'))
1335 raise PatchError(_('unexpected delta opcode 0'))
1336 return out
1336 return out
1337
1337
1338 def applydiff(ui, fp, backend, store, strip=1, eolmode='strict'):
1338 def applydiff(ui, fp, backend, store, strip=1, eolmode='strict'):
1339 """Reads a patch from fp and tries to apply it.
1339 """Reads a patch from fp and tries to apply it.
1340
1340
1341 Returns 0 for a clean patch, -1 if any rejects were found and 1 if
1341 Returns 0 for a clean patch, -1 if any rejects were found and 1 if
1342 there was any fuzz.
1342 there was any fuzz.
1343
1343
1344 If 'eolmode' is 'strict', the patch content and patched file are
1344 If 'eolmode' is 'strict', the patch content and patched file are
1345 read in binary mode. Otherwise, line endings are ignored when
1345 read in binary mode. Otherwise, line endings are ignored when
1346 patching then normalized according to 'eolmode'.
1346 patching then normalized according to 'eolmode'.
1347 """
1347 """
1348 return _applydiff(ui, fp, patchfile, backend, store, strip=strip,
1348 return _applydiff(ui, fp, patchfile, backend, store, strip=strip,
1349 eolmode=eolmode)
1349 eolmode=eolmode)
1350
1350
1351 def _applydiff(ui, fp, patcher, backend, store, strip=1,
1351 def _applydiff(ui, fp, patcher, backend, store, strip=1,
1352 eolmode='strict'):
1352 eolmode='strict'):
1353
1353
1354 def pstrip(p):
1354 def pstrip(p):
1355 return pathstrip(p, strip - 1)[1]
1355 return pathstrip(p, strip - 1)[1]
1356
1356
1357 rejects = 0
1357 rejects = 0
1358 err = 0
1358 err = 0
1359 current_file = None
1359 current_file = None
1360
1360
1361 for state, values in iterhunks(fp):
1361 for state, values in iterhunks(fp):
1362 if state == 'hunk':
1362 if state == 'hunk':
1363 if not current_file:
1363 if not current_file:
1364 continue
1364 continue
1365 ret = current_file.apply(values)
1365 ret = current_file.apply(values)
1366 if ret > 0:
1366 if ret > 0:
1367 err = 1
1367 err = 1
1368 elif state == 'file':
1368 elif state == 'file':
1369 if current_file:
1369 if current_file:
1370 rejects += current_file.close()
1370 rejects += current_file.close()
1371 current_file = None
1371 current_file = None
1372 afile, bfile, first_hunk, gp = values
1372 afile, bfile, first_hunk, gp = values
1373 if gp:
1373 if gp:
1374 gp.path = pstrip(gp.path)
1374 gp.path = pstrip(gp.path)
1375 if gp.oldpath:
1375 if gp.oldpath:
1376 gp.oldpath = pstrip(gp.oldpath)
1376 gp.oldpath = pstrip(gp.oldpath)
1377 else:
1377 else:
1378 gp = makepatchmeta(backend, afile, bfile, first_hunk, strip)
1378 gp = makepatchmeta(backend, afile, bfile, first_hunk, strip)
1379 if gp.op == 'RENAME':
1379 if gp.op == 'RENAME':
1380 backend.unlink(gp.oldpath)
1380 backend.unlink(gp.oldpath)
1381 if not first_hunk:
1381 if not first_hunk:
1382 if gp.op == 'DELETE':
1382 if gp.op == 'DELETE':
1383 backend.unlink(gp.path)
1383 backend.unlink(gp.path)
1384 continue
1384 continue
1385 data, mode = None, None
1385 data, mode = None, None
1386 if gp.op in ('RENAME', 'COPY'):
1386 if gp.op in ('RENAME', 'COPY'):
1387 data, mode = store.getfile(gp.oldpath)[:2]
1387 data, mode = store.getfile(gp.oldpath)[:2]
1388 # FIXME: failing getfile has never been handled here
1388 # FIXME: failing getfile has never been handled here
1389 assert data is not None
1389 assert data is not None
1390 if gp.mode:
1390 if gp.mode:
1391 mode = gp.mode
1391 mode = gp.mode
1392 if gp.op == 'ADD':
1392 if gp.op == 'ADD':
1393 # Added files without content have no hunk and
1393 # Added files without content have no hunk and
1394 # must be created
1394 # must be created
1395 data = ''
1395 data = ''
1396 if data or mode:
1396 if data or mode:
1397 if (gp.op in ('ADD', 'RENAME', 'COPY')
1397 if (gp.op in ('ADD', 'RENAME', 'COPY')
1398 and backend.exists(gp.path)):
1398 and backend.exists(gp.path)):
1399 raise PatchError(_("cannot create %s: destination "
1399 raise PatchError(_("cannot create %s: destination "
1400 "already exists") % gp.path)
1400 "already exists") % gp.path)
1401 backend.setfile(gp.path, data, mode, gp.oldpath)
1401 backend.setfile(gp.path, data, mode, gp.oldpath)
1402 continue
1402 continue
1403 try:
1403 try:
1404 current_file = patcher(ui, gp, backend, store,
1404 current_file = patcher(ui, gp, backend, store,
1405 eolmode=eolmode)
1405 eolmode=eolmode)
1406 except PatchError, inst:
1406 except PatchError, inst:
1407 ui.warn(str(inst) + '\n')
1407 ui.warn(str(inst) + '\n')
1408 current_file = None
1408 current_file = None
1409 rejects += 1
1409 rejects += 1
1410 continue
1410 continue
1411 elif state == 'git':
1411 elif state == 'git':
1412 for gp in values:
1412 for gp in values:
1413 path = pstrip(gp.oldpath)
1413 path = pstrip(gp.oldpath)
1414 data, mode = backend.getfile(path)
1414 data, mode = backend.getfile(path)
1415 if data is None:
1415 if data is None:
1416 # The error ignored here will trigger a getfile()
1416 # The error ignored here will trigger a getfile()
1417 # error in a place more appropriate for error
1417 # error in a place more appropriate for error
1418 # handling, and will not interrupt the patching
1418 # handling, and will not interrupt the patching
1419 # process.
1419 # process.
1420 pass
1420 pass
1421 else:
1421 else:
1422 store.setfile(path, data, mode)
1422 store.setfile(path, data, mode)
1423 else:
1423 else:
1424 raise util.Abort(_('unsupported parser state: %s') % state)
1424 raise util.Abort(_('unsupported parser state: %s') % state)
1425
1425
1426 if current_file:
1426 if current_file:
1427 rejects += current_file.close()
1427 rejects += current_file.close()
1428
1428
1429 if rejects:
1429 if rejects:
1430 return -1
1430 return -1
1431 return err
1431 return err
1432
1432
1433 def _externalpatch(ui, repo, patcher, patchname, strip, files,
1433 def _externalpatch(ui, repo, patcher, patchname, strip, files,
1434 similarity):
1434 similarity):
1435 """use <patcher> to apply <patchname> to the working directory.
1435 """use <patcher> to apply <patchname> to the working directory.
1436 returns whether patch was applied with fuzz factor."""
1436 returns whether patch was applied with fuzz factor."""
1437
1437
1438 fuzz = False
1438 fuzz = False
1439 args = []
1439 args = []
1440 cwd = repo.root
1440 cwd = repo.root
1441 if cwd:
1441 if cwd:
1442 args.append('-d %s' % util.shellquote(cwd))
1442 args.append('-d %s' % util.shellquote(cwd))
1443 fp = util.popen('%s %s -p%d < %s' % (patcher, ' '.join(args), strip,
1443 fp = util.popen('%s %s -p%d < %s' % (patcher, ' '.join(args), strip,
1444 util.shellquote(patchname)))
1444 util.shellquote(patchname)))
1445 try:
1445 try:
1446 for line in fp:
1446 for line in fp:
1447 line = line.rstrip()
1447 line = line.rstrip()
1448 ui.note(line + '\n')
1448 ui.note(line + '\n')
1449 if line.startswith('patching file '):
1449 if line.startswith('patching file '):
1450 pf = util.parsepatchoutput(line)
1450 pf = util.parsepatchoutput(line)
1451 printed_file = False
1451 printed_file = False
1452 files.add(pf)
1452 files.add(pf)
1453 elif line.find('with fuzz') >= 0:
1453 elif line.find('with fuzz') >= 0:
1454 fuzz = True
1454 fuzz = True
1455 if not printed_file:
1455 if not printed_file:
1456 ui.warn(pf + '\n')
1456 ui.warn(pf + '\n')
1457 printed_file = True
1457 printed_file = True
1458 ui.warn(line + '\n')
1458 ui.warn(line + '\n')
1459 elif line.find('saving rejects to file') >= 0:
1459 elif line.find('saving rejects to file') >= 0:
1460 ui.warn(line + '\n')
1460 ui.warn(line + '\n')
1461 elif line.find('FAILED') >= 0:
1461 elif line.find('FAILED') >= 0:
1462 if not printed_file:
1462 if not printed_file:
1463 ui.warn(pf + '\n')
1463 ui.warn(pf + '\n')
1464 printed_file = True
1464 printed_file = True
1465 ui.warn(line + '\n')
1465 ui.warn(line + '\n')
1466 finally:
1466 finally:
1467 if files:
1467 if files:
1468 scmutil.marktouched(repo, files, similarity)
1468 scmutil.marktouched(repo, files, similarity)
1469 code = fp.close()
1469 code = fp.close()
1470 if code:
1470 if code:
1471 raise PatchError(_("patch command failed: %s") %
1471 raise PatchError(_("patch command failed: %s") %
1472 util.explainexit(code)[0])
1472 util.explainexit(code)[0])
1473 return fuzz
1473 return fuzz
1474
1474
1475 def patchbackend(ui, backend, patchobj, strip, files=None, eolmode='strict'):
1475 def patchbackend(ui, backend, patchobj, strip, files=None, eolmode='strict'):
1476 if files is None:
1476 if files is None:
1477 files = set()
1477 files = set()
1478 if eolmode is None:
1478 if eolmode is None:
1479 eolmode = ui.config('patch', 'eol', 'strict')
1479 eolmode = ui.config('patch', 'eol', 'strict')
1480 if eolmode.lower() not in eolmodes:
1480 if eolmode.lower() not in eolmodes:
1481 raise util.Abort(_('unsupported line endings type: %s') % eolmode)
1481 raise util.Abort(_('unsupported line endings type: %s') % eolmode)
1482 eolmode = eolmode.lower()
1482 eolmode = eolmode.lower()
1483
1483
1484 store = filestore()
1484 store = filestore()
1485 try:
1485 try:
1486 fp = open(patchobj, 'rb')
1486 fp = open(patchobj, 'rb')
1487 except TypeError:
1487 except TypeError:
1488 fp = patchobj
1488 fp = patchobj
1489 try:
1489 try:
1490 ret = applydiff(ui, fp, backend, store, strip=strip,
1490 ret = applydiff(ui, fp, backend, store, strip=strip,
1491 eolmode=eolmode)
1491 eolmode=eolmode)
1492 finally:
1492 finally:
1493 if fp != patchobj:
1493 if fp != patchobj:
1494 fp.close()
1494 fp.close()
1495 files.update(backend.close())
1495 files.update(backend.close())
1496 store.close()
1496 store.close()
1497 if ret < 0:
1497 if ret < 0:
1498 raise PatchError(_('patch failed to apply'))
1498 raise PatchError(_('patch failed to apply'))
1499 return ret > 0
1499 return ret > 0
1500
1500
1501 def internalpatch(ui, repo, patchobj, strip, files=None, eolmode='strict',
1501 def internalpatch(ui, repo, patchobj, strip, files=None, eolmode='strict',
1502 similarity=0):
1502 similarity=0):
1503 """use builtin patch to apply <patchobj> to the working directory.
1503 """use builtin patch to apply <patchobj> to the working directory.
1504 returns whether patch was applied with fuzz factor."""
1504 returns whether patch was applied with fuzz factor."""
1505 backend = workingbackend(ui, repo, similarity)
1505 backend = workingbackend(ui, repo, similarity)
1506 return patchbackend(ui, backend, patchobj, strip, files, eolmode)
1506 return patchbackend(ui, backend, patchobj, strip, files, eolmode)
1507
1507
1508 def patchrepo(ui, repo, ctx, store, patchobj, strip, files=None,
1508 def patchrepo(ui, repo, ctx, store, patchobj, strip, files=None,
1509 eolmode='strict'):
1509 eolmode='strict'):
1510 backend = repobackend(ui, repo, ctx, store)
1510 backend = repobackend(ui, repo, ctx, store)
1511 return patchbackend(ui, backend, patchobj, strip, files, eolmode)
1511 return patchbackend(ui, backend, patchobj, strip, files, eolmode)
1512
1512
1513 def patch(ui, repo, patchname, strip=1, files=None, eolmode='strict',
1513 def patch(ui, repo, patchname, strip=1, files=None, eolmode='strict',
1514 similarity=0):
1514 similarity=0):
1515 """Apply <patchname> to the working directory.
1515 """Apply <patchname> to the working directory.
1516
1516
1517 'eolmode' specifies how end of lines should be handled. It can be:
1517 'eolmode' specifies how end of lines should be handled. It can be:
1518 - 'strict': inputs are read in binary mode, EOLs are preserved
1518 - 'strict': inputs are read in binary mode, EOLs are preserved
1519 - 'crlf': EOLs are ignored when patching and reset to CRLF
1519 - 'crlf': EOLs are ignored when patching and reset to CRLF
1520 - 'lf': EOLs are ignored when patching and reset to LF
1520 - 'lf': EOLs are ignored when patching and reset to LF
1521 - None: get it from user settings, default to 'strict'
1521 - None: get it from user settings, default to 'strict'
1522 'eolmode' is ignored when using an external patcher program.
1522 'eolmode' is ignored when using an external patcher program.
1523
1523
1524 Returns whether patch was applied with fuzz factor.
1524 Returns whether patch was applied with fuzz factor.
1525 """
1525 """
1526 patcher = ui.config('ui', 'patch')
1526 patcher = ui.config('ui', 'patch')
1527 if files is None:
1527 if files is None:
1528 files = set()
1528 files = set()
1529 if patcher:
1529 if patcher:
1530 return _externalpatch(ui, repo, patcher, patchname, strip,
1530 return _externalpatch(ui, repo, patcher, patchname, strip,
1531 files, similarity)
1531 files, similarity)
1532 return internalpatch(ui, repo, patchname, strip, files, eolmode,
1532 return internalpatch(ui, repo, patchname, strip, files, eolmode,
1533 similarity)
1533 similarity)
1534
1534
1535 def changedfiles(ui, repo, patchpath, strip=1):
1535 def changedfiles(ui, repo, patchpath, strip=1):
1536 backend = fsbackend(ui, repo.root)
1536 backend = fsbackend(ui, repo.root)
1537 fp = open(patchpath, 'rb')
1537 fp = open(patchpath, 'rb')
1538 try:
1538 try:
1539 changed = set()
1539 changed = set()
1540 for state, values in iterhunks(fp):
1540 for state, values in iterhunks(fp):
1541 if state == 'file':
1541 if state == 'file':
1542 afile, bfile, first_hunk, gp = values
1542 afile, bfile, first_hunk, gp = values
1543 if gp:
1543 if gp:
1544 gp.path = pathstrip(gp.path, strip - 1)[1]
1544 gp.path = pathstrip(gp.path, strip - 1)[1]
1545 if gp.oldpath:
1545 if gp.oldpath:
1546 gp.oldpath = pathstrip(gp.oldpath, strip - 1)[1]
1546 gp.oldpath = pathstrip(gp.oldpath, strip - 1)[1]
1547 else:
1547 else:
1548 gp = makepatchmeta(backend, afile, bfile, first_hunk, strip)
1548 gp = makepatchmeta(backend, afile, bfile, first_hunk, strip)
1549 changed.add(gp.path)
1549 changed.add(gp.path)
1550 if gp.op == 'RENAME':
1550 if gp.op == 'RENAME':
1551 changed.add(gp.oldpath)
1551 changed.add(gp.oldpath)
1552 elif state not in ('hunk', 'git'):
1552 elif state not in ('hunk', 'git'):
1553 raise util.Abort(_('unsupported parser state: %s') % state)
1553 raise util.Abort(_('unsupported parser state: %s') % state)
1554 return changed
1554 return changed
1555 finally:
1555 finally:
1556 fp.close()
1556 fp.close()
1557
1557
1558 class GitDiffRequired(Exception):
1558 class GitDiffRequired(Exception):
1559 pass
1559 pass
1560
1560
1561 def diffopts(ui, opts=None, untrusted=False, section='diff'):
1561 def diffopts(ui, opts=None, untrusted=False, section='diff'):
1562 def get(key, name=None, getter=ui.configbool, forceplain=None):
1562 def get(key, name=None, getter=ui.configbool, forceplain=None):
1563 if opts:
1563 if opts:
1564 v = opts.get(key)
1564 v = opts.get(key)
1565 if v:
1565 if v:
1566 return v
1566 return v
1567 if forceplain is not None and ui.plain():
1567 if forceplain is not None and ui.plain():
1568 return forceplain
1568 return forceplain
1569 return getter(section, name or key, None, untrusted=untrusted)
1569 return getter(section, name or key, None, untrusted=untrusted)
1570
1570
1571 return mdiff.diffopts(
1571 return mdiff.diffopts(
1572 text=opts and opts.get('text'),
1572 text=opts and opts.get('text'),
1573 git=get('git'),
1573 git=get('git'),
1574 nodates=get('nodates'),
1574 nodates=get('nodates'),
1575 nobinary=get('nobinary'),
1575 nobinary=get('nobinary'),
1576 noprefix=get('noprefix', forceplain=False),
1576 showfunc=get('show_function', 'showfunc'),
1577 showfunc=get('show_function', 'showfunc'),
1577 ignorews=get('ignore_all_space', 'ignorews'),
1578 ignorews=get('ignore_all_space', 'ignorews'),
1578 ignorewsamount=get('ignore_space_change', 'ignorewsamount'),
1579 ignorewsamount=get('ignore_space_change', 'ignorewsamount'),
1579 ignoreblanklines=get('ignore_blank_lines', 'ignoreblanklines'),
1580 ignoreblanklines=get('ignore_blank_lines', 'ignoreblanklines'),
1580 context=get('unified', getter=ui.config))
1581 context=get('unified', getter=ui.config))
1581
1582
1582 def diff(repo, node1=None, node2=None, match=None, changes=None, opts=None,
1583 def diff(repo, node1=None, node2=None, match=None, changes=None, opts=None,
1583 losedatafn=None, prefix=''):
1584 losedatafn=None, prefix=''):
1584 '''yields diff of changes to files between two nodes, or node and
1585 '''yields diff of changes to files between two nodes, or node and
1585 working directory.
1586 working directory.
1586
1587
1587 if node1 is None, use first dirstate parent instead.
1588 if node1 is None, use first dirstate parent instead.
1588 if node2 is None, compare node1 with working directory.
1589 if node2 is None, compare node1 with working directory.
1589
1590
1590 losedatafn(**kwarg) is a callable run when opts.upgrade=True and
1591 losedatafn(**kwarg) is a callable run when opts.upgrade=True and
1591 every time some change cannot be represented with the current
1592 every time some change cannot be represented with the current
1592 patch format. Return False to upgrade to git patch format, True to
1593 patch format. Return False to upgrade to git patch format, True to
1593 accept the loss or raise an exception to abort the diff. It is
1594 accept the loss or raise an exception to abort the diff. It is
1594 called with the name of current file being diffed as 'fn'. If set
1595 called with the name of current file being diffed as 'fn'. If set
1595 to None, patches will always be upgraded to git format when
1596 to None, patches will always be upgraded to git format when
1596 necessary.
1597 necessary.
1597
1598
1598 prefix is a filename prefix that is prepended to all filenames on
1599 prefix is a filename prefix that is prepended to all filenames on
1599 display (used for subrepos).
1600 display (used for subrepos).
1600 '''
1601 '''
1601
1602
1602 if opts is None:
1603 if opts is None:
1603 opts = mdiff.defaultopts
1604 opts = mdiff.defaultopts
1604
1605
1605 if not node1 and not node2:
1606 if not node1 and not node2:
1606 node1 = repo.dirstate.p1()
1607 node1 = repo.dirstate.p1()
1607
1608
1608 def lrugetfilectx():
1609 def lrugetfilectx():
1609 cache = {}
1610 cache = {}
1610 order = util.deque()
1611 order = util.deque()
1611 def getfilectx(f, ctx):
1612 def getfilectx(f, ctx):
1612 fctx = ctx.filectx(f, filelog=cache.get(f))
1613 fctx = ctx.filectx(f, filelog=cache.get(f))
1613 if f not in cache:
1614 if f not in cache:
1614 if len(cache) > 20:
1615 if len(cache) > 20:
1615 del cache[order.popleft()]
1616 del cache[order.popleft()]
1616 cache[f] = fctx.filelog()
1617 cache[f] = fctx.filelog()
1617 else:
1618 else:
1618 order.remove(f)
1619 order.remove(f)
1619 order.append(f)
1620 order.append(f)
1620 return fctx
1621 return fctx
1621 return getfilectx
1622 return getfilectx
1622 getfilectx = lrugetfilectx()
1623 getfilectx = lrugetfilectx()
1623
1624
1624 ctx1 = repo[node1]
1625 ctx1 = repo[node1]
1625 ctx2 = repo[node2]
1626 ctx2 = repo[node2]
1626
1627
1627 if not changes:
1628 if not changes:
1628 changes = repo.status(ctx1, ctx2, match=match)
1629 changes = repo.status(ctx1, ctx2, match=match)
1629 modified, added, removed = changes[:3]
1630 modified, added, removed = changes[:3]
1630
1631
1631 if not modified and not added and not removed:
1632 if not modified and not added and not removed:
1632 return []
1633 return []
1633
1634
1634 revs = None
1635 revs = None
1635 hexfunc = repo.ui.debugflag and hex or short
1636 hexfunc = repo.ui.debugflag and hex or short
1636 revs = [hexfunc(node) for node in [ctx1.node(), ctx2.node()] if node]
1637 revs = [hexfunc(node) for node in [ctx1.node(), ctx2.node()] if node]
1637
1638
1638 copy = {}
1639 copy = {}
1639 if opts.git or opts.upgrade:
1640 if opts.git or opts.upgrade:
1640 copy = copies.pathcopies(ctx1, ctx2)
1641 copy = copies.pathcopies(ctx1, ctx2)
1641
1642
1642 def difffn(opts, losedata):
1643 def difffn(opts, losedata):
1643 return trydiff(repo, revs, ctx1, ctx2, modified, added, removed,
1644 return trydiff(repo, revs, ctx1, ctx2, modified, added, removed,
1644 copy, getfilectx, opts, losedata, prefix)
1645 copy, getfilectx, opts, losedata, prefix)
1645 if opts.upgrade and not opts.git:
1646 if opts.upgrade and not opts.git:
1646 try:
1647 try:
1647 def losedata(fn):
1648 def losedata(fn):
1648 if not losedatafn or not losedatafn(fn=fn):
1649 if not losedatafn or not losedatafn(fn=fn):
1649 raise GitDiffRequired
1650 raise GitDiffRequired
1650 # Buffer the whole output until we are sure it can be generated
1651 # Buffer the whole output until we are sure it can be generated
1651 return list(difffn(opts.copy(git=False), losedata))
1652 return list(difffn(opts.copy(git=False), losedata))
1652 except GitDiffRequired:
1653 except GitDiffRequired:
1653 return difffn(opts.copy(git=True), None)
1654 return difffn(opts.copy(git=True), None)
1654 else:
1655 else:
1655 return difffn(opts, None)
1656 return difffn(opts, None)
1656
1657
1657 def difflabel(func, *args, **kw):
1658 def difflabel(func, *args, **kw):
1658 '''yields 2-tuples of (output, label) based on the output of func()'''
1659 '''yields 2-tuples of (output, label) based on the output of func()'''
1659 headprefixes = [('diff', 'diff.diffline'),
1660 headprefixes = [('diff', 'diff.diffline'),
1660 ('copy', 'diff.extended'),
1661 ('copy', 'diff.extended'),
1661 ('rename', 'diff.extended'),
1662 ('rename', 'diff.extended'),
1662 ('old', 'diff.extended'),
1663 ('old', 'diff.extended'),
1663 ('new', 'diff.extended'),
1664 ('new', 'diff.extended'),
1664 ('deleted', 'diff.extended'),
1665 ('deleted', 'diff.extended'),
1665 ('---', 'diff.file_a'),
1666 ('---', 'diff.file_a'),
1666 ('+++', 'diff.file_b')]
1667 ('+++', 'diff.file_b')]
1667 textprefixes = [('@', 'diff.hunk'),
1668 textprefixes = [('@', 'diff.hunk'),
1668 ('-', 'diff.deleted'),
1669 ('-', 'diff.deleted'),
1669 ('+', 'diff.inserted')]
1670 ('+', 'diff.inserted')]
1670 head = False
1671 head = False
1671 for chunk in func(*args, **kw):
1672 for chunk in func(*args, **kw):
1672 lines = chunk.split('\n')
1673 lines = chunk.split('\n')
1673 for i, line in enumerate(lines):
1674 for i, line in enumerate(lines):
1674 if i != 0:
1675 if i != 0:
1675 yield ('\n', '')
1676 yield ('\n', '')
1676 if head:
1677 if head:
1677 if line.startswith('@'):
1678 if line.startswith('@'):
1678 head = False
1679 head = False
1679 else:
1680 else:
1680 if line and line[0] not in ' +-@\\':
1681 if line and line[0] not in ' +-@\\':
1681 head = True
1682 head = True
1682 stripline = line
1683 stripline = line
1683 diffline = False
1684 diffline = False
1684 if not head and line and line[0] in '+-':
1685 if not head and line and line[0] in '+-':
1685 # highlight tabs and trailing whitespace, but only in
1686 # highlight tabs and trailing whitespace, but only in
1686 # changed lines
1687 # changed lines
1687 stripline = line.rstrip()
1688 stripline = line.rstrip()
1688 diffline = True
1689 diffline = True
1689
1690
1690 prefixes = textprefixes
1691 prefixes = textprefixes
1691 if head:
1692 if head:
1692 prefixes = headprefixes
1693 prefixes = headprefixes
1693 for prefix, label in prefixes:
1694 for prefix, label in prefixes:
1694 if stripline.startswith(prefix):
1695 if stripline.startswith(prefix):
1695 if diffline:
1696 if diffline:
1696 for token in tabsplitter.findall(stripline):
1697 for token in tabsplitter.findall(stripline):
1697 if '\t' == token[0]:
1698 if '\t' == token[0]:
1698 yield (token, 'diff.tab')
1699 yield (token, 'diff.tab')
1699 else:
1700 else:
1700 yield (token, label)
1701 yield (token, label)
1701 else:
1702 else:
1702 yield (stripline, label)
1703 yield (stripline, label)
1703 break
1704 break
1704 else:
1705 else:
1705 yield (line, '')
1706 yield (line, '')
1706 if line != stripline:
1707 if line != stripline:
1707 yield (line[len(stripline):], 'diff.trailingwhitespace')
1708 yield (line[len(stripline):], 'diff.trailingwhitespace')
1708
1709
1709 def diffui(*args, **kw):
1710 def diffui(*args, **kw):
1710 '''like diff(), but yields 2-tuples of (output, label) for ui.write()'''
1711 '''like diff(), but yields 2-tuples of (output, label) for ui.write()'''
1711 return difflabel(diff, *args, **kw)
1712 return difflabel(diff, *args, **kw)
1712
1713
1713 def trydiff(repo, revs, ctx1, ctx2, modified, added, removed,
1714 def trydiff(repo, revs, ctx1, ctx2, modified, added, removed,
1714 copy, getfilectx, opts, losedatafn, prefix):
1715 copy, getfilectx, opts, losedatafn, prefix):
1715
1716
1716 def join(f):
1717 def join(f):
1717 return posixpath.join(prefix, f)
1718 return posixpath.join(prefix, f)
1718
1719
1719 def addmodehdr(header, omode, nmode):
1720 def addmodehdr(header, omode, nmode):
1720 if omode != nmode:
1721 if omode != nmode:
1721 header.append('old mode %s\n' % omode)
1722 header.append('old mode %s\n' % omode)
1722 header.append('new mode %s\n' % nmode)
1723 header.append('new mode %s\n' % nmode)
1723
1724
1724 def addindexmeta(meta, revs):
1725 def addindexmeta(meta, revs):
1725 if opts.git:
1726 if opts.git:
1726 i = len(revs)
1727 i = len(revs)
1727 if i==2:
1728 if i==2:
1728 meta.append('index %s..%s\n' % tuple(revs))
1729 meta.append('index %s..%s\n' % tuple(revs))
1729 elif i==3:
1730 elif i==3:
1730 meta.append('index %s,%s..%s\n' % tuple(revs))
1731 meta.append('index %s,%s..%s\n' % tuple(revs))
1731
1732
1732 def gitindex(text):
1733 def gitindex(text):
1733 if not text:
1734 if not text:
1734 text = ""
1735 text = ""
1735 l = len(text)
1736 l = len(text)
1736 s = util.sha1('blob %d\0' % l)
1737 s = util.sha1('blob %d\0' % l)
1737 s.update(text)
1738 s.update(text)
1738 return s.hexdigest()
1739 return s.hexdigest()
1739
1740
1740 def diffline(a, b, revs):
1741 def diffline(a, b, revs):
1741 if opts.git:
1742 if opts.git:
1742 line = 'diff --git a/%s b/%s\n' % (a, b)
1743 line = 'diff --git a/%s b/%s\n' % (a, b)
1743 elif not repo.ui.quiet:
1744 elif not repo.ui.quiet:
1744 if revs:
1745 if revs:
1745 revinfo = ' '.join(["-r %s" % rev for rev in revs])
1746 revinfo = ' '.join(["-r %s" % rev for rev in revs])
1746 line = 'diff %s %s\n' % (revinfo, a)
1747 line = 'diff %s %s\n' % (revinfo, a)
1747 else:
1748 else:
1748 line = 'diff %s\n' % a
1749 line = 'diff %s\n' % a
1749 else:
1750 else:
1750 line = ''
1751 line = ''
1751 return line
1752 return line
1752
1753
1753 date1 = util.datestr(ctx1.date())
1754 date1 = util.datestr(ctx1.date())
1754 man1 = ctx1.manifest()
1755 man1 = ctx1.manifest()
1755
1756
1756 gone = set()
1757 gone = set()
1757 gitmode = {'l': '120000', 'x': '100755', '': '100644'}
1758 gitmode = {'l': '120000', 'x': '100755', '': '100644'}
1758
1759
1759 copyto = dict([(v, k) for k, v in copy.items()])
1760 copyto = dict([(v, k) for k, v in copy.items()])
1760
1761
1761 if opts.git:
1762 if opts.git:
1762 revs = None
1763 revs = None
1763
1764
1764 for f in sorted(modified + added + removed):
1765 for f in sorted(modified + added + removed):
1765 to = None
1766 to = None
1766 tn = None
1767 tn = None
1767 dodiff = True
1768 dodiff = True
1768 header = []
1769 header = []
1769 if f in man1:
1770 if f in man1:
1770 to = getfilectx(f, ctx1).data()
1771 to = getfilectx(f, ctx1).data()
1771 if f not in removed:
1772 if f not in removed:
1772 tn = getfilectx(f, ctx2).data()
1773 tn = getfilectx(f, ctx2).data()
1773 a, b = f, f
1774 a, b = f, f
1774 if opts.git or losedatafn:
1775 if opts.git or losedatafn:
1775 if f in added or (f in modified and to is None):
1776 if f in added or (f in modified and to is None):
1776 mode = gitmode[ctx2.flags(f)]
1777 mode = gitmode[ctx2.flags(f)]
1777 if f in copy or f in copyto:
1778 if f in copy or f in copyto:
1778 if opts.git:
1779 if opts.git:
1779 if f in copy:
1780 if f in copy:
1780 a = copy[f]
1781 a = copy[f]
1781 else:
1782 else:
1782 a = copyto[f]
1783 a = copyto[f]
1783 omode = gitmode[man1.flags(a)]
1784 omode = gitmode[man1.flags(a)]
1784 addmodehdr(header, omode, mode)
1785 addmodehdr(header, omode, mode)
1785 if a in removed and a not in gone:
1786 if a in removed and a not in gone:
1786 op = 'rename'
1787 op = 'rename'
1787 gone.add(a)
1788 gone.add(a)
1788 else:
1789 else:
1789 op = 'copy'
1790 op = 'copy'
1790 header.append('%s from %s\n' % (op, join(a)))
1791 header.append('%s from %s\n' % (op, join(a)))
1791 header.append('%s to %s\n' % (op, join(f)))
1792 header.append('%s to %s\n' % (op, join(f)))
1792 to = getfilectx(a, ctx1).data()
1793 to = getfilectx(a, ctx1).data()
1793 else:
1794 else:
1794 losedatafn(f)
1795 losedatafn(f)
1795 else:
1796 else:
1796 if opts.git:
1797 if opts.git:
1797 header.append('new file mode %s\n' % mode)
1798 header.append('new file mode %s\n' % mode)
1798 elif ctx2.flags(f):
1799 elif ctx2.flags(f):
1799 losedatafn(f)
1800 losedatafn(f)
1800 # In theory, if tn was copied or renamed we should check
1801 # In theory, if tn was copied or renamed we should check
1801 # if the source is binary too but the copy record already
1802 # if the source is binary too but the copy record already
1802 # forces git mode.
1803 # forces git mode.
1803 if util.binary(tn):
1804 if util.binary(tn):
1804 if opts.git:
1805 if opts.git:
1805 dodiff = 'binary'
1806 dodiff = 'binary'
1806 else:
1807 else:
1807 losedatafn(f)
1808 losedatafn(f)
1808 if not opts.git and not tn:
1809 if not opts.git and not tn:
1809 # regular diffs cannot represent new empty file
1810 # regular diffs cannot represent new empty file
1810 losedatafn(f)
1811 losedatafn(f)
1811 elif f in removed or (f in modified and tn is None):
1812 elif f in removed or (f in modified and tn is None):
1812 if opts.git:
1813 if opts.git:
1813 # have we already reported a copy above?
1814 # have we already reported a copy above?
1814 if ((f in copy and copy[f] in added
1815 if ((f in copy and copy[f] in added
1815 and copyto[copy[f]] == f) or
1816 and copyto[copy[f]] == f) or
1816 (f in copyto and copyto[f] in added
1817 (f in copyto and copyto[f] in added
1817 and copy[copyto[f]] == f)):
1818 and copy[copyto[f]] == f)):
1818 dodiff = False
1819 dodiff = False
1819 else:
1820 else:
1820 header.append('deleted file mode %s\n' %
1821 header.append('deleted file mode %s\n' %
1821 gitmode[man1.flags(f)])
1822 gitmode[man1.flags(f)])
1822 if util.binary(to):
1823 if util.binary(to):
1823 dodiff = 'binary'
1824 dodiff = 'binary'
1824 elif not to or util.binary(to):
1825 elif not to or util.binary(to):
1825 # regular diffs cannot represent empty file deletion
1826 # regular diffs cannot represent empty file deletion
1826 losedatafn(f)
1827 losedatafn(f)
1827 else:
1828 else:
1828 oflag = man1.flags(f)
1829 oflag = man1.flags(f)
1829 nflag = ctx2.flags(f)
1830 nflag = ctx2.flags(f)
1830 binary = util.binary(to) or util.binary(tn)
1831 binary = util.binary(to) or util.binary(tn)
1831 if opts.git:
1832 if opts.git:
1832 addmodehdr(header, gitmode[oflag], gitmode[nflag])
1833 addmodehdr(header, gitmode[oflag], gitmode[nflag])
1833 if binary:
1834 if binary:
1834 dodiff = 'binary'
1835 dodiff = 'binary'
1835 elif binary or nflag != oflag:
1836 elif binary or nflag != oflag:
1836 losedatafn(f)
1837 losedatafn(f)
1837
1838
1838 if dodiff:
1839 if dodiff:
1839 if opts.git or revs:
1840 if opts.git or revs:
1840 header.insert(0, diffline(join(a), join(b), revs))
1841 header.insert(0, diffline(join(a), join(b), revs))
1841 if dodiff == 'binary' and not opts.nobinary:
1842 if dodiff == 'binary' and not opts.nobinary:
1842 text = mdiff.b85diff(to, tn)
1843 text = mdiff.b85diff(to, tn)
1843 if text:
1844 if text:
1844 addindexmeta(header, [gitindex(to), gitindex(tn)])
1845 addindexmeta(header, [gitindex(to), gitindex(tn)])
1845 else:
1846 else:
1846 text = mdiff.unidiff(to, date1,
1847 text = mdiff.unidiff(to, date1,
1847 # ctx2 date may be dynamic
1848 # ctx2 date may be dynamic
1848 tn, util.datestr(ctx2.date()),
1849 tn, util.datestr(ctx2.date()),
1849 join(a), join(b), opts=opts)
1850 join(a), join(b), opts=opts)
1850 if header and (text or len(header) > 1):
1851 if header and (text or len(header) > 1):
1851 yield ''.join(header)
1852 yield ''.join(header)
1852 if text:
1853 if text:
1853 yield text
1854 yield text
1854
1855
1855 def diffstatsum(stats):
1856 def diffstatsum(stats):
1856 maxfile, maxtotal, addtotal, removetotal, binary = 0, 0, 0, 0, False
1857 maxfile, maxtotal, addtotal, removetotal, binary = 0, 0, 0, 0, False
1857 for f, a, r, b in stats:
1858 for f, a, r, b in stats:
1858 maxfile = max(maxfile, encoding.colwidth(f))
1859 maxfile = max(maxfile, encoding.colwidth(f))
1859 maxtotal = max(maxtotal, a + r)
1860 maxtotal = max(maxtotal, a + r)
1860 addtotal += a
1861 addtotal += a
1861 removetotal += r
1862 removetotal += r
1862 binary = binary or b
1863 binary = binary or b
1863
1864
1864 return maxfile, maxtotal, addtotal, removetotal, binary
1865 return maxfile, maxtotal, addtotal, removetotal, binary
1865
1866
1866 def diffstatdata(lines):
1867 def diffstatdata(lines):
1867 diffre = re.compile('^diff .*-r [a-z0-9]+\s(.*)$')
1868 diffre = re.compile('^diff .*-r [a-z0-9]+\s(.*)$')
1868
1869
1869 results = []
1870 results = []
1870 filename, adds, removes, isbinary = None, 0, 0, False
1871 filename, adds, removes, isbinary = None, 0, 0, False
1871
1872
1872 def addresult():
1873 def addresult():
1873 if filename:
1874 if filename:
1874 results.append((filename, adds, removes, isbinary))
1875 results.append((filename, adds, removes, isbinary))
1875
1876
1876 for line in lines:
1877 for line in lines:
1877 if line.startswith('diff'):
1878 if line.startswith('diff'):
1878 addresult()
1879 addresult()
1879 # set numbers to 0 anyway when starting new file
1880 # set numbers to 0 anyway when starting new file
1880 adds, removes, isbinary = 0, 0, False
1881 adds, removes, isbinary = 0, 0, False
1881 if line.startswith('diff --git a/'):
1882 if line.startswith('diff --git a/'):
1882 filename = gitre.search(line).group(2)
1883 filename = gitre.search(line).group(2)
1883 elif line.startswith('diff -r'):
1884 elif line.startswith('diff -r'):
1884 # format: "diff -r ... -r ... filename"
1885 # format: "diff -r ... -r ... filename"
1885 filename = diffre.search(line).group(1)
1886 filename = diffre.search(line).group(1)
1886 elif line.startswith('+') and not line.startswith('+++ '):
1887 elif line.startswith('+') and not line.startswith('+++ '):
1887 adds += 1
1888 adds += 1
1888 elif line.startswith('-') and not line.startswith('--- '):
1889 elif line.startswith('-') and not line.startswith('--- '):
1889 removes += 1
1890 removes += 1
1890 elif (line.startswith('GIT binary patch') or
1891 elif (line.startswith('GIT binary patch') or
1891 line.startswith('Binary file')):
1892 line.startswith('Binary file')):
1892 isbinary = True
1893 isbinary = True
1893 addresult()
1894 addresult()
1894 return results
1895 return results
1895
1896
1896 def diffstat(lines, width=80, git=False):
1897 def diffstat(lines, width=80, git=False):
1897 output = []
1898 output = []
1898 stats = diffstatdata(lines)
1899 stats = diffstatdata(lines)
1899 maxname, maxtotal, totaladds, totalremoves, hasbinary = diffstatsum(stats)
1900 maxname, maxtotal, totaladds, totalremoves, hasbinary = diffstatsum(stats)
1900
1901
1901 countwidth = len(str(maxtotal))
1902 countwidth = len(str(maxtotal))
1902 if hasbinary and countwidth < 3:
1903 if hasbinary and countwidth < 3:
1903 countwidth = 3
1904 countwidth = 3
1904 graphwidth = width - countwidth - maxname - 6
1905 graphwidth = width - countwidth - maxname - 6
1905 if graphwidth < 10:
1906 if graphwidth < 10:
1906 graphwidth = 10
1907 graphwidth = 10
1907
1908
1908 def scale(i):
1909 def scale(i):
1909 if maxtotal <= graphwidth:
1910 if maxtotal <= graphwidth:
1910 return i
1911 return i
1911 # If diffstat runs out of room it doesn't print anything,
1912 # If diffstat runs out of room it doesn't print anything,
1912 # which isn't very useful, so always print at least one + or -
1913 # which isn't very useful, so always print at least one + or -
1913 # if there were at least some changes.
1914 # if there were at least some changes.
1914 return max(i * graphwidth // maxtotal, int(bool(i)))
1915 return max(i * graphwidth // maxtotal, int(bool(i)))
1915
1916
1916 for filename, adds, removes, isbinary in stats:
1917 for filename, adds, removes, isbinary in stats:
1917 if isbinary:
1918 if isbinary:
1918 count = 'Bin'
1919 count = 'Bin'
1919 else:
1920 else:
1920 count = adds + removes
1921 count = adds + removes
1921 pluses = '+' * scale(adds)
1922 pluses = '+' * scale(adds)
1922 minuses = '-' * scale(removes)
1923 minuses = '-' * scale(removes)
1923 output.append(' %s%s | %*s %s%s\n' %
1924 output.append(' %s%s | %*s %s%s\n' %
1924 (filename, ' ' * (maxname - encoding.colwidth(filename)),
1925 (filename, ' ' * (maxname - encoding.colwidth(filename)),
1925 countwidth, count, pluses, minuses))
1926 countwidth, count, pluses, minuses))
1926
1927
1927 if stats:
1928 if stats:
1928 output.append(_(' %d files changed, %d insertions(+), '
1929 output.append(_(' %d files changed, %d insertions(+), '
1929 '%d deletions(-)\n')
1930 '%d deletions(-)\n')
1930 % (len(stats), totaladds, totalremoves))
1931 % (len(stats), totaladds, totalremoves))
1931
1932
1932 return ''.join(output)
1933 return ''.join(output)
1933
1934
1934 def diffstatui(*args, **kw):
1935 def diffstatui(*args, **kw):
1935 '''like diffstat(), but yields 2-tuples of (output, label) for
1936 '''like diffstat(), but yields 2-tuples of (output, label) for
1936 ui.write()
1937 ui.write()
1937 '''
1938 '''
1938
1939
1939 for line in diffstat(*args, **kw).splitlines():
1940 for line in diffstat(*args, **kw).splitlines():
1940 if line and line[-1] in '+-':
1941 if line and line[-1] in '+-':
1941 name, graph = line.rsplit(' ', 1)
1942 name, graph = line.rsplit(' ', 1)
1942 yield (name + ' ', '')
1943 yield (name + ' ', '')
1943 m = re.search(r'\++', graph)
1944 m = re.search(r'\++', graph)
1944 if m:
1945 if m:
1945 yield (m.group(0), 'diffstat.inserted')
1946 yield (m.group(0), 'diffstat.inserted')
1946 m = re.search(r'-+', graph)
1947 m = re.search(r'-+', graph)
1947 if m:
1948 if m:
1948 yield (m.group(0), 'diffstat.deleted')
1949 yield (m.group(0), 'diffstat.deleted')
1949 else:
1950 else:
1950 yield (line, '')
1951 yield (line, '')
1951 yield ('\n', '')
1952 yield ('\n', '')
@@ -1,198 +1,254 b''
1 $ hg init repo
1 $ hg init repo
2 $ cd repo
2 $ cd repo
3 $ cat > a <<EOF
3 $ cat > a <<EOF
4 > c
4 > c
5 > c
5 > c
6 > a
6 > a
7 > a
7 > a
8 > b
8 > b
9 > a
9 > a
10 > a
10 > a
11 > c
11 > c
12 > c
12 > c
13 > EOF
13 > EOF
14 $ hg ci -Am adda
14 $ hg ci -Am adda
15 adding a
15 adding a
16
16
17 $ cat > a <<EOF
17 $ cat > a <<EOF
18 > c
18 > c
19 > c
19 > c
20 > a
20 > a
21 > a
21 > a
22 > dd
22 > dd
23 > a
23 > a
24 > a
24 > a
25 > c
25 > c
26 > c
26 > c
27 > EOF
27 > EOF
28
28
29 default context
29 default context
30
30
31 $ hg diff --nodates
31 $ hg diff --nodates
32 diff -r cf9f4ba66af2 a
32 diff -r cf9f4ba66af2 a
33 --- a/a
33 --- a/a
34 +++ b/a
34 +++ b/a
35 @@ -2,7 +2,7 @@
35 @@ -2,7 +2,7 @@
36 c
36 c
37 a
37 a
38 a
38 a
39 -b
39 -b
40 +dd
40 +dd
41 a
41 a
42 a
42 a
43 c
43 c
44
44
45 invalid --unified
45 invalid --unified
46
46
47 $ hg diff --nodates -U foo
47 $ hg diff --nodates -U foo
48 abort: diff context lines count must be an integer, not 'foo'
48 abort: diff context lines count must be an integer, not 'foo'
49 [255]
49 [255]
50
50
51
51
52 $ hg diff --nodates -U 2
52 $ hg diff --nodates -U 2
53 diff -r cf9f4ba66af2 a
53 diff -r cf9f4ba66af2 a
54 --- a/a
54 --- a/a
55 +++ b/a
55 +++ b/a
56 @@ -3,5 +3,5 @@
56 @@ -3,5 +3,5 @@
57 a
57 a
58 a
58 a
59 -b
59 -b
60 +dd
60 +dd
61 a
61 a
62 a
62 a
63
63
64 $ hg --config diff.unified=2 diff --nodates
64 $ hg --config diff.unified=2 diff --nodates
65 diff -r cf9f4ba66af2 a
65 diff -r cf9f4ba66af2 a
66 --- a/a
66 --- a/a
67 +++ b/a
67 +++ b/a
68 @@ -3,5 +3,5 @@
68 @@ -3,5 +3,5 @@
69 a
69 a
70 a
70 a
71 -b
71 -b
72 +dd
72 +dd
73 a
73 a
74 a
74 a
75
75
76 $ hg diff --nodates -U 1
76 $ hg diff --nodates -U 1
77 diff -r cf9f4ba66af2 a
77 diff -r cf9f4ba66af2 a
78 --- a/a
78 --- a/a
79 +++ b/a
79 +++ b/a
80 @@ -4,3 +4,3 @@
80 @@ -4,3 +4,3 @@
81 a
81 a
82 -b
82 -b
83 +dd
83 +dd
84 a
84 a
85
85
86 invalid diff.unified
86 invalid diff.unified
87
87
88 $ hg --config diff.unified=foo diff --nodates
88 $ hg --config diff.unified=foo diff --nodates
89 abort: diff context lines count must be an integer, not 'foo'
89 abort: diff context lines count must be an integer, not 'foo'
90 [255]
90 [255]
91
91
92 noprefix config
93
94 $ hg --config diff.noprefix=True diff --nodates
95 diff -r cf9f4ba66af2 a
96 --- a/a
97 +++ b/a
98 @@ -2,7 +2,7 @@
99 c
100 a
101 a
102 -b
103 +dd
104 a
105 a
106 c
107
108 noprefix disabled in plain mode
109
110 $ HGPLAIN=1 hg --config diff.noprefix=True diff --nodates
111 diff -r cf9f4ba66af2 a
112 --- a/a
113 +++ b/a
114 @@ -2,7 +2,7 @@
115 c
116 a
117 a
118 -b
119 +dd
120 a
121 a
122 c
123
92 $ cd ..
124 $ cd ..
93
125
94
126
95 0 lines of context hunk header matches gnu diff hunk header
127 0 lines of context hunk header matches gnu diff hunk header
96
128
97 $ hg init diffzero
129 $ hg init diffzero
98 $ cd diffzero
130 $ cd diffzero
99 $ cat > f1 << EOF
131 $ cat > f1 << EOF
100 > c2
132 > c2
101 > c4
133 > c4
102 > c5
134 > c5
103 > EOF
135 > EOF
104 $ hg commit -Am0
136 $ hg commit -Am0
105 adding f1
137 adding f1
106
138
107 $ cat > f2 << EOF
139 $ cat > f2 << EOF
108 > c1
140 > c1
109 > c2
141 > c2
110 > c3
142 > c3
111 > c4
143 > c4
112 > EOF
144 > EOF
113 $ mv f2 f1
145 $ mv f2 f1
114 $ hg diff -U0 --nodates
146 $ hg diff -U0 --nodates
115 diff -r 55d8ff78db23 f1
147 diff -r 55d8ff78db23 f1
116 --- a/f1
148 --- a/f1
117 +++ b/f1
149 +++ b/f1
118 @@ -0,0 +1,1 @@
150 @@ -0,0 +1,1 @@
119 +c1
151 +c1
120 @@ -1,0 +3,1 @@
152 @@ -1,0 +3,1 @@
121 +c3
153 +c3
122 @@ -3,1 +4,0 @@
154 @@ -3,1 +4,0 @@
123 -c5
155 -c5
124
156
125 $ hg diff -U0 --nodates --git
157 $ hg diff -U0 --nodates --git
126 diff --git a/f1 b/f1
158 diff --git a/f1 b/f1
127 --- a/f1
159 --- a/f1
128 +++ b/f1
160 +++ b/f1
129 @@ -0,0 +1,1 @@
161 @@ -0,0 +1,1 @@
130 +c1
162 +c1
131 @@ -1,0 +3,1 @@
163 @@ -1,0 +3,1 @@
132 +c3
164 +c3
133 @@ -3,1 +4,0 @@
165 @@ -3,1 +4,0 @@
134 -c5
166 -c5
135
167
136 $ hg diff -U0 --nodates -p
168 $ hg diff -U0 --nodates -p
137 diff -r 55d8ff78db23 f1
169 diff -r 55d8ff78db23 f1
138 --- a/f1
170 --- a/f1
139 +++ b/f1
171 +++ b/f1
140 @@ -0,0 +1,1 @@
172 @@ -0,0 +1,1 @@
141 +c1
173 +c1
142 @@ -1,0 +3,1 @@ c2
174 @@ -1,0 +3,1 @@ c2
143 +c3
175 +c3
144 @@ -3,1 +4,0 @@ c4
176 @@ -3,1 +4,0 @@ c4
145 -c5
177 -c5
146
178
147 $ echo a > f1
179 $ echo a > f1
148 $ hg ci -m movef2
180 $ hg ci -m movef2
149
181
150 Test diff headers terminating with TAB when necessary (issue3357)
182 Test diff headers terminating with TAB when necessary (issue3357)
151 Regular diff --nodates, file creation
183 Regular diff --nodates, file creation
152
184
153 $ hg mv f1 'f 1'
185 $ hg mv f1 'f 1'
154 $ echo b > 'f 1'
186 $ echo b > 'f 1'
155 $ hg diff --nodates 'f 1'
187 $ hg diff --nodates 'f 1'
156 diff -r 7574207d0d15 f 1
188 diff -r 7574207d0d15 f 1
157 --- /dev/null
189 --- /dev/null
158 +++ b/f 1
190 +++ b/f 1
159 @@ -0,0 +1,1 @@
191 @@ -0,0 +1,1 @@
160 +b
192 +b
161
193
162 Git diff, adding space
194 Git diff, adding space
163
195
164 $ hg diff --git
196 $ hg diff --git
165 diff --git a/f1 b/f 1
197 diff --git a/f1 b/f 1
166 rename from f1
198 rename from f1
167 rename to f 1
199 rename to f 1
168 --- a/f1
200 --- a/f1
169 +++ b/f 1
201 +++ b/f 1
170 @@ -1,1 +1,1 @@
202 @@ -1,1 +1,1 @@
171 -a
203 -a
172 +b
204 +b
173
205
206 Git diff with noprefix
207
208 $ hg --config diff.noprefix=True diff --git --nodates
209 diff --git a/f1 b/f 1
210 rename from f1
211 rename to f 1
212 --- a/f1
213 +++ b/f 1
214 @@ -1,1 +1,1 @@
215 -a
216 +b
217
218 noprefix config disabled in plain mode
219
220 $ HGPLAIN=1 hg --config diff.noprefix=True diff --git --nodates
221 diff --git a/f1 b/f 1
222 rename from f1
223 rename to f 1
224 --- a/f1
225 +++ b/f 1
226 @@ -1,1 +1,1 @@
227 -a
228 +b
229
174 Regular diff --nodates, file deletion
230 Regular diff --nodates, file deletion
175
231
176 $ hg ci -m addspace
232 $ hg ci -m addspace
177 $ hg mv 'f 1' f1
233 $ hg mv 'f 1' f1
178 $ echo a > f1
234 $ echo a > f1
179 $ hg diff --nodates 'f 1'
235 $ hg diff --nodates 'f 1'
180 diff -r ca50fe67c9c7 f 1
236 diff -r ca50fe67c9c7 f 1
181 --- a/f 1
237 --- a/f 1
182 +++ /dev/null
238 +++ /dev/null
183 @@ -1,1 +0,0 @@
239 @@ -1,1 +0,0 @@
184 -b
240 -b
185
241
186 Git diff, removing space
242 Git diff, removing space
187
243
188 $ hg diff --git
244 $ hg diff --git
189 diff --git a/f 1 b/f1
245 diff --git a/f 1 b/f1
190 rename from f 1
246 rename from f 1
191 rename to f1
247 rename to f1
192 --- a/f 1
248 --- a/f 1
193 +++ b/f1
249 +++ b/f1
194 @@ -1,1 +1,1 @@
250 @@ -1,1 +1,1 @@
195 -b
251 -b
196 +a
252 +a
197
253
198 $ cd ..
254 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now