##// END OF EJS Templates
patch: fix eolmode=auto with new files...
Patrick Mezard -
r10127:d8214e94 default
parent child Browse files
Show More
@@ -1,958 +1,959 b''
1 ======
1 ======
2 hgrc
2 hgrc
3 ======
3 ======
4
4
5 ---------------------------------
5 ---------------------------------
6 configuration files for Mercurial
6 configuration files for Mercurial
7 ---------------------------------
7 ---------------------------------
8
8
9 :Author: Bryan O'Sullivan <bos@serpentine.com>
9 :Author: Bryan O'Sullivan <bos@serpentine.com>
10 :Organization: Mercurial
10 :Organization: Mercurial
11 :Manual section: 5
11 :Manual section: 5
12 :Manual group: Mercurial Manual
12 :Manual group: Mercurial Manual
13
13
14 .. contents::
14 .. contents::
15 :backlinks: top
15 :backlinks: top
16 :class: htmlonly
16 :class: htmlonly
17
17
18
18
19 Synopsis
19 Synopsis
20 --------
20 --------
21
21
22 The Mercurial system uses a set of configuration files to control
22 The Mercurial system uses a set of configuration files to control
23 aspects of its behavior.
23 aspects of its behavior.
24
24
25 Files
25 Files
26 -----
26 -----
27
27
28 Mercurial reads configuration data from several files, if they exist.
28 Mercurial reads configuration data from several files, if they exist.
29 The names of these files depend on the system on which Mercurial is
29 The names of these files depend on the system on which Mercurial is
30 installed. ``*.rc`` files from a single directory are read in
30 installed. ``*.rc`` files from a single directory are read in
31 alphabetical order, later ones overriding earlier ones. Where multiple
31 alphabetical order, later ones overriding earlier ones. Where multiple
32 paths are given below, settings from earlier paths override later
32 paths are given below, settings from earlier paths override later
33 ones.
33 ones.
34
34
35 | (Unix, Windows) ``<repo>/.hg/hgrc``
35 | (Unix, Windows) ``<repo>/.hg/hgrc``
36
36
37 Per-repository configuration options that only apply in a
37 Per-repository configuration options that only apply in a
38 particular repository. This file is not version-controlled, and
38 particular repository. This file is not version-controlled, and
39 will not get transferred during a "clone" operation. Options in
39 will not get transferred during a "clone" operation. Options in
40 this file override options in all other configuration files. On
40 this file override options in all other configuration files. On
41 Unix, most of this file will be ignored if it doesn't belong to a
41 Unix, most of this file will be ignored if it doesn't belong to a
42 trusted user or to a trusted group. See the documentation for the
42 trusted user or to a trusted group. See the documentation for the
43 trusted_ section below for more details.
43 trusted_ section below for more details.
44
44
45 | (Unix) ``$HOME/.hgrc``
45 | (Unix) ``$HOME/.hgrc``
46 | (Windows) ``%USERPROFILE%\.hgrc``
46 | (Windows) ``%USERPROFILE%\.hgrc``
47 | (Windows) ``%USERPROFILE%\Mercurial.ini``
47 | (Windows) ``%USERPROFILE%\Mercurial.ini``
48 | (Windows) ``%HOME%\.hgrc``
48 | (Windows) ``%HOME%\.hgrc``
49 | (Windows) ``%HOME%\Mercurial.ini``
49 | (Windows) ``%HOME%\Mercurial.ini``
50
50
51 Per-user configuration file(s), for the user running Mercurial. On
51 Per-user configuration file(s), for the user running Mercurial. On
52 Windows 9x, ``%HOME%`` is replaced by ``%APPDATA%``. Options in these
52 Windows 9x, ``%HOME%`` is replaced by ``%APPDATA%``. Options in these
53 files apply to all Mercurial commands executed by this user in any
53 files apply to all Mercurial commands executed by this user in any
54 directory. Options in these files override per-system and per-installation
54 directory. Options in these files override per-system and per-installation
55 options.
55 options.
56
56
57 | (Unix) ``/etc/mercurial/hgrc``
57 | (Unix) ``/etc/mercurial/hgrc``
58 | (Unix) ``/etc/mercurial/hgrc.d/*.rc``
58 | (Unix) ``/etc/mercurial/hgrc.d/*.rc``
59
59
60 Per-system configuration files, for the system on which Mercurial
60 Per-system configuration files, for the system on which Mercurial
61 is running. Options in these files apply to all Mercurial commands
61 is running. Options in these files apply to all Mercurial commands
62 executed by any user in any directory. Options in these files
62 executed by any user in any directory. Options in these files
63 override per-installation options.
63 override per-installation options.
64
64
65 | (Unix) ``<install-root>/etc/mercurial/hgrc``
65 | (Unix) ``<install-root>/etc/mercurial/hgrc``
66 | (Unix) ``<install-root>/etc/mercurial/hgrc.d/*.rc``
66 | (Unix) ``<install-root>/etc/mercurial/hgrc.d/*.rc``
67
67
68 Per-installation configuration files, searched for in the
68 Per-installation configuration files, searched for in the
69 directory where Mercurial is installed. ``<install-root>`` is the
69 directory where Mercurial is installed. ``<install-root>`` is the
70 parent directory of the **hg** executable (or symlink) being run. For
70 parent directory of the **hg** executable (or symlink) being run. For
71 example, if installed in ``/shared/tools/bin/hg``, Mercurial will look
71 example, if installed in ``/shared/tools/bin/hg``, Mercurial will look
72 in ``/shared/tools/etc/mercurial/hgrc``. Options in these files apply
72 in ``/shared/tools/etc/mercurial/hgrc``. Options in these files apply
73 to all Mercurial commands executed by any user in any directory.
73 to all Mercurial commands executed by any user in any directory.
74
74
75 | (Windows) ``C:\Mercurial\Mercurial.ini``
75 | (Windows) ``C:\Mercurial\Mercurial.ini``
76 | (Windows) ``HKEY_LOCAL_MACHINE\SOFTWARE\Mercurial``
76 | (Windows) ``HKEY_LOCAL_MACHINE\SOFTWARE\Mercurial``
77 | (Windows) ``<install-dir>\Mercurial.ini``
77 | (Windows) ``<install-dir>\Mercurial.ini``
78
78
79 Per-installation/system configuration files, for the system on
79 Per-installation/system configuration files, for the system on
80 which Mercurial is running. Options in these files apply to all
80 which Mercurial is running. Options in these files apply to all
81 Mercurial commands executed by any user in any directory. Registry
81 Mercurial commands executed by any user in any directory. Registry
82 keys contain PATH-like strings, every part of which must reference
82 keys contain PATH-like strings, every part of which must reference
83 a ``Mercurial.ini`` file or be a directory where ``*.rc`` files will
83 a ``Mercurial.ini`` file or be a directory where ``*.rc`` files will
84 be read.
84 be read.
85
85
86 Syntax
86 Syntax
87 ------
87 ------
88
88
89 A configuration file consists of sections, led by a ``[section]`` header
89 A configuration file consists of sections, led by a ``[section]`` header
90 and followed by ``name = value`` entries::
90 and followed by ``name = value`` entries::
91
91
92 [spam]
92 [spam]
93 eggs=ham
93 eggs=ham
94 green=
94 green=
95 eggs
95 eggs
96
96
97 Each line contains one entry. If the lines that follow are indented,
97 Each line contains one entry. If the lines that follow are indented,
98 they are treated as continuations of that entry. Leading whitespace is
98 they are treated as continuations of that entry. Leading whitespace is
99 removed from values. Empty lines are skipped. Lines beginning with
99 removed from values. Empty lines are skipped. Lines beginning with
100 ``#`` or ``;`` are ignored and may be used to provide comments.
100 ``#`` or ``;`` are ignored and may be used to provide comments.
101
101
102 A line of the form ``%include file`` will include ``file`` into the
102 A line of the form ``%include file`` will include ``file`` into the
103 current configuration file. The inclusion is recursive, which means
103 current configuration file. The inclusion is recursive, which means
104 that included files can include other files. Filenames are relative to
104 that included files can include other files. Filenames are relative to
105 the configuration file in which the ``%include`` directive is found.
105 the configuration file in which the ``%include`` directive is found.
106
106
107 A line with ``%unset name`` will remove ``name`` from the current
107 A line with ``%unset name`` will remove ``name`` from the current
108 section, if it has been set previously.
108 section, if it has been set previously.
109
109
110
110
111 Sections
111 Sections
112 --------
112 --------
113
113
114 This section describes the different sections that may appear in a
114 This section describes the different sections that may appear in a
115 Mercurial "hgrc" file, the purpose of each section, its possible keys,
115 Mercurial "hgrc" file, the purpose of each section, its possible keys,
116 and their possible values.
116 and their possible values.
117
117
118 ``alias``
118 ``alias``
119 """""""""
119 """""""""
120 Defines command aliases.
120 Defines command aliases.
121 Aliases allow you to define your own commands in terms of other
121 Aliases allow you to define your own commands in terms of other
122 commands (or aliases), optionally including arguments.
122 commands (or aliases), optionally including arguments.
123
123
124 Alias definitions consist of lines of the form::
124 Alias definitions consist of lines of the form::
125
125
126 <alias> = <command> [<argument]...
126 <alias> = <command> [<argument]...
127
127
128 For example, this definition::
128 For example, this definition::
129
129
130 latest = log --limit 5
130 latest = log --limit 5
131
131
132 creates a new command ``latest`` that shows only the five most recent
132 creates a new command ``latest`` that shows only the five most recent
133 changesets. You can define subsequent aliases using earlier ones::
133 changesets. You can define subsequent aliases using earlier ones::
134
134
135 stable5 = latest -b stable
135 stable5 = latest -b stable
136
136
137 .. note:: It is possible to create aliases with the same names as
137 .. note:: It is possible to create aliases with the same names as
138 existing commands, which will then override the original
138 existing commands, which will then override the original
139 definitions. This is almost always a bad idea!
139 definitions. This is almost always a bad idea!
140
140
141
141
142 ``auth``
142 ``auth``
143 """"""""
143 """"""""
144 Authentication credentials for HTTP authentication. Each line has
144 Authentication credentials for HTTP authentication. Each line has
145 the following format::
145 the following format::
146
146
147 <name>.<argument> = <value>
147 <name>.<argument> = <value>
148
148
149 where ``<name>`` is used to group arguments into authentication
149 where ``<name>`` is used to group arguments into authentication
150 entries. Example::
150 entries. Example::
151
151
152 foo.prefix = hg.intevation.org/mercurial
152 foo.prefix = hg.intevation.org/mercurial
153 foo.username = foo
153 foo.username = foo
154 foo.password = bar
154 foo.password = bar
155 foo.schemes = http https
155 foo.schemes = http https
156
156
157 bar.prefix = secure.example.org
157 bar.prefix = secure.example.org
158 bar.key = path/to/file.key
158 bar.key = path/to/file.key
159 bar.cert = path/to/file.cert
159 bar.cert = path/to/file.cert
160 bar.schemes = https
160 bar.schemes = https
161
161
162 Supported arguments:
162 Supported arguments:
163
163
164 ``prefix``
164 ``prefix``
165 Either ``*`` or a URI prefix with or without the scheme part.
165 Either ``*`` or a URI prefix with or without the scheme part.
166 The authentication entry with the longest matching prefix is used
166 The authentication entry with the longest matching prefix is used
167 (where ``*`` matches everything and counts as a match of length
167 (where ``*`` matches everything and counts as a match of length
168 1). If the prefix doesn't include a scheme, the match is performed
168 1). If the prefix doesn't include a scheme, the match is performed
169 against the URI with its scheme stripped as well, and the schemes
169 against the URI with its scheme stripped as well, and the schemes
170 argument, q.v., is then subsequently consulted.
170 argument, q.v., is then subsequently consulted.
171 ``username``
171 ``username``
172 Optional. Username to authenticate with. If not given, and the
172 Optional. Username to authenticate with. If not given, and the
173 remote site requires basic or digest authentication, the user
173 remote site requires basic or digest authentication, the user
174 will be prompted for it.
174 will be prompted for it.
175 ``password``
175 ``password``
176 Optional. Password to authenticate with. If not given, and the
176 Optional. Password to authenticate with. If not given, and the
177 remote site requires basic or digest authentication, the user
177 remote site requires basic or digest authentication, the user
178 will be prompted for it.
178 will be prompted for it.
179 ``key``
179 ``key``
180 Optional. PEM encoded client certificate key file.
180 Optional. PEM encoded client certificate key file.
181 ``cert``
181 ``cert``
182 Optional. PEM encoded client certificate chain file.
182 Optional. PEM encoded client certificate chain file.
183 ``schemes``
183 ``schemes``
184 Optional. Space separated list of URI schemes to use this
184 Optional. Space separated list of URI schemes to use this
185 authentication entry with. Only used if the prefix doesn't include
185 authentication entry with. Only used if the prefix doesn't include
186 a scheme. Supported schemes are http and https. They will match
186 a scheme. Supported schemes are http and https. They will match
187 static-http and static-https respectively, as well.
187 static-http and static-https respectively, as well.
188 Default: https.
188 Default: https.
189
189
190 If no suitable authentication entry is found, the user is prompted
190 If no suitable authentication entry is found, the user is prompted
191 for credentials as usual if required by the remote.
191 for credentials as usual if required by the remote.
192
192
193
193
194 ``decode/encode``
194 ``decode/encode``
195 """""""""""""""""
195 """""""""""""""""
196 Filters for transforming files on checkout/checkin. This would
196 Filters for transforming files on checkout/checkin. This would
197 typically be used for newline processing or other
197 typically be used for newline processing or other
198 localization/canonicalization of files.
198 localization/canonicalization of files.
199
199
200 Filters consist of a filter pattern followed by a filter command.
200 Filters consist of a filter pattern followed by a filter command.
201 Filter patterns are globs by default, rooted at the repository root.
201 Filter patterns are globs by default, rooted at the repository root.
202 For example, to match any file ending in ``.txt`` in the root
202 For example, to match any file ending in ``.txt`` in the root
203 directory only, use the pattern ``*.txt``. To match any file ending
203 directory only, use the pattern ``*.txt``. To match any file ending
204 in ``.c`` anywhere in the repository, use the pattern ``**.c``.
204 in ``.c`` anywhere in the repository, use the pattern ``**.c``.
205
205
206 The filter command can start with a specifier, either ``pipe:`` or
206 The filter command can start with a specifier, either ``pipe:`` or
207 ``tempfile:``. If no specifier is given, ``pipe:`` is used by default.
207 ``tempfile:``. If no specifier is given, ``pipe:`` is used by default.
208
208
209 A ``pipe:`` command must accept data on stdin and return the transformed
209 A ``pipe:`` command must accept data on stdin and return the transformed
210 data on stdout.
210 data on stdout.
211
211
212 Pipe example::
212 Pipe example::
213
213
214 [encode]
214 [encode]
215 # uncompress gzip files on checkin to improve delta compression
215 # uncompress gzip files on checkin to improve delta compression
216 # note: not necessarily a good idea, just an example
216 # note: not necessarily a good idea, just an example
217 *.gz = pipe: gunzip
217 *.gz = pipe: gunzip
218
218
219 [decode]
219 [decode]
220 # recompress gzip files when writing them to the working dir (we
220 # recompress gzip files when writing them to the working dir (we
221 # can safely omit "pipe:", because it's the default)
221 # can safely omit "pipe:", because it's the default)
222 *.gz = gzip
222 *.gz = gzip
223
223
224 A ``tempfile:`` command is a template. The string ``INFILE`` is replaced
224 A ``tempfile:`` command is a template. The string ``INFILE`` is replaced
225 with the name of a temporary file that contains the data to be
225 with the name of a temporary file that contains the data to be
226 filtered by the command. The string ``OUTFILE`` is replaced with the name
226 filtered by the command. The string ``OUTFILE`` is replaced with the name
227 of an empty temporary file, where the filtered data must be written by
227 of an empty temporary file, where the filtered data must be written by
228 the command.
228 the command.
229
229
230 .. note:: The tempfile mechanism is recommended for Windows systems,
230 .. note:: The tempfile mechanism is recommended for Windows systems,
231 where the standard shell I/O redirection operators often have
231 where the standard shell I/O redirection operators often have
232 strange effects and may corrupt the contents of your files.
232 strange effects and may corrupt the contents of your files.
233
233
234 The most common usage is for LF <-> CRLF translation on Windows. For
234 The most common usage is for LF <-> CRLF translation on Windows. For
235 this, use the "smart" converters which check for binary files::
235 this, use the "smart" converters which check for binary files::
236
236
237 [extensions]
237 [extensions]
238 hgext.win32text =
238 hgext.win32text =
239 [encode]
239 [encode]
240 ** = cleverencode:
240 ** = cleverencode:
241 [decode]
241 [decode]
242 ** = cleverdecode:
242 ** = cleverdecode:
243
243
244 or if you only want to translate certain files::
244 or if you only want to translate certain files::
245
245
246 [extensions]
246 [extensions]
247 hgext.win32text =
247 hgext.win32text =
248 [encode]
248 [encode]
249 **.txt = dumbencode:
249 **.txt = dumbencode:
250 [decode]
250 [decode]
251 **.txt = dumbdecode:
251 **.txt = dumbdecode:
252
252
253
253
254 ``defaults``
254 ``defaults``
255 """"""""""""
255 """"""""""""
256
256
257 (defaults are deprecated. Don't use them. Use aliases instead)
257 (defaults are deprecated. Don't use them. Use aliases instead)
258
258
259 Use the ``[defaults]`` section to define command defaults, i.e. the
259 Use the ``[defaults]`` section to define command defaults, i.e. the
260 default options/arguments to pass to the specified commands.
260 default options/arguments to pass to the specified commands.
261
261
262 The following example makes ``hg log`` run in verbose mode, and ``hg
262 The following example makes ``hg log`` run in verbose mode, and ``hg
263 status`` show only the modified files, by default::
263 status`` show only the modified files, by default::
264
264
265 [defaults]
265 [defaults]
266 log = -v
266 log = -v
267 status = -m
267 status = -m
268
268
269 The actual commands, instead of their aliases, must be used when
269 The actual commands, instead of their aliases, must be used when
270 defining command defaults. The command defaults will also be applied
270 defining command defaults. The command defaults will also be applied
271 to the aliases of the commands defined.
271 to the aliases of the commands defined.
272
272
273
273
274 ``diff``
274 ``diff``
275 """"""""
275 """"""""
276
276
277 Settings used when displaying diffs. They are all Boolean and
277 Settings used when displaying diffs. They are all Boolean and
278 defaults to False.
278 defaults to False.
279
279
280 ``git``
280 ``git``
281 Use git extended diff format.
281 Use git extended diff format.
282 ``nodates``
282 ``nodates``
283 Don't include dates in diff headers.
283 Don't include dates in diff headers.
284 ``showfunc``
284 ``showfunc``
285 Show which function each change is in.
285 Show which function each change is in.
286 ``ignorews``
286 ``ignorews``
287 Ignore white space when comparing lines.
287 Ignore white space when comparing lines.
288 ``ignorewsamount``
288 ``ignorewsamount``
289 Ignore changes in the amount of white space.
289 Ignore changes in the amount of white space.
290 ``ignoreblanklines``
290 ``ignoreblanklines``
291 Ignore changes whose lines are all blank.
291 Ignore changes whose lines are all blank.
292
292
293 ``email``
293 ``email``
294 """""""""
294 """""""""
295 Settings for extensions that send email messages.
295 Settings for extensions that send email messages.
296
296
297 ``from``
297 ``from``
298 Optional. Email address to use in "From" header and SMTP envelope
298 Optional. Email address to use in "From" header and SMTP envelope
299 of outgoing messages.
299 of outgoing messages.
300 ``to``
300 ``to``
301 Optional. Comma-separated list of recipients' email addresses.
301 Optional. Comma-separated list of recipients' email addresses.
302 ``cc``
302 ``cc``
303 Optional. Comma-separated list of carbon copy recipients'
303 Optional. Comma-separated list of carbon copy recipients'
304 email addresses.
304 email addresses.
305 ``bcc``
305 ``bcc``
306 Optional. Comma-separated list of blind carbon copy recipients'
306 Optional. Comma-separated list of blind carbon copy recipients'
307 email addresses. Cannot be set interactively.
307 email addresses. Cannot be set interactively.
308 ``method``
308 ``method``
309 Optional. Method to use to send email messages. If value is ``smtp``
309 Optional. Method to use to send email messages. If value is ``smtp``
310 (default), use SMTP (see the SMTP_ section for configuration).
310 (default), use SMTP (see the SMTP_ section for configuration).
311 Otherwise, use as name of program to run that acts like sendmail
311 Otherwise, use as name of program to run that acts like sendmail
312 (takes ``-f`` option for sender, list of recipients on command line,
312 (takes ``-f`` option for sender, list of recipients on command line,
313 message on stdin). Normally, setting this to ``sendmail`` or
313 message on stdin). Normally, setting this to ``sendmail`` or
314 ``/usr/sbin/sendmail`` is enough to use sendmail to send messages.
314 ``/usr/sbin/sendmail`` is enough to use sendmail to send messages.
315 ``charsets``
315 ``charsets``
316 Optional. Comma-separated list of character sets considered
316 Optional. Comma-separated list of character sets considered
317 convenient for recipients. Addresses, headers, and parts not
317 convenient for recipients. Addresses, headers, and parts not
318 containing patches of outgoing messages will be encoded in the
318 containing patches of outgoing messages will be encoded in the
319 first character set to which conversion from local encoding
319 first character set to which conversion from local encoding
320 (``$HGENCODING``, ``ui.fallbackencoding``) succeeds. If correct
320 (``$HGENCODING``, ``ui.fallbackencoding``) succeeds. If correct
321 conversion fails, the text in question is sent as is. Defaults to
321 conversion fails, the text in question is sent as is. Defaults to
322 empty (explicit) list.
322 empty (explicit) list.
323
323
324 Order of outgoing email character sets:
324 Order of outgoing email character sets:
325
325
326 1. ``us-ascii``: always first, regardless of settings
326 1. ``us-ascii``: always first, regardless of settings
327 2. ``email.charsets``: in order given by user
327 2. ``email.charsets``: in order given by user
328 3. ``ui.fallbackencoding``: if not in email.charsets
328 3. ``ui.fallbackencoding``: if not in email.charsets
329 4. ``$HGENCODING``: if not in email.charsets
329 4. ``$HGENCODING``: if not in email.charsets
330 5. ``utf-8``: always last, regardless of settings
330 5. ``utf-8``: always last, regardless of settings
331
331
332 Email example::
332 Email example::
333
333
334 [email]
334 [email]
335 from = Joseph User <joe.user@example.com>
335 from = Joseph User <joe.user@example.com>
336 method = /usr/sbin/sendmail
336 method = /usr/sbin/sendmail
337 # charsets for western Europeans
337 # charsets for western Europeans
338 # us-ascii, utf-8 omitted, as they are tried first and last
338 # us-ascii, utf-8 omitted, as they are tried first and last
339 charsets = iso-8859-1, iso-8859-15, windows-1252
339 charsets = iso-8859-1, iso-8859-15, windows-1252
340
340
341
341
342 ``extensions``
342 ``extensions``
343 """"""""""""""
343 """"""""""""""
344
344
345 Mercurial has an extension mechanism for adding new features. To
345 Mercurial has an extension mechanism for adding new features. To
346 enable an extension, create an entry for it in this section.
346 enable an extension, create an entry for it in this section.
347
347
348 If you know that the extension is already in Python's search path,
348 If you know that the extension is already in Python's search path,
349 you can give the name of the module, followed by ``=``, with nothing
349 you can give the name of the module, followed by ``=``, with nothing
350 after the ``=``.
350 after the ``=``.
351
351
352 Otherwise, give a name that you choose, followed by ``=``, followed by
352 Otherwise, give a name that you choose, followed by ``=``, followed by
353 the path to the ``.py`` file (including the file name extension) that
353 the path to the ``.py`` file (including the file name extension) that
354 defines the extension.
354 defines the extension.
355
355
356 To explicitly disable an extension that is enabled in an hgrc of
356 To explicitly disable an extension that is enabled in an hgrc of
357 broader scope, prepend its path with ``!``, as in
357 broader scope, prepend its path with ``!``, as in
358 ``hgext.foo = !/ext/path`` or ``hgext.foo = !`` when path is not
358 ``hgext.foo = !/ext/path`` or ``hgext.foo = !`` when path is not
359 supplied.
359 supplied.
360
360
361 Example for ``~/.hgrc``::
361 Example for ``~/.hgrc``::
362
362
363 [extensions]
363 [extensions]
364 # (the mq extension will get loaded from Mercurial's path)
364 # (the mq extension will get loaded from Mercurial's path)
365 hgext.mq =
365 hgext.mq =
366 # (this extension will get loaded from the file specified)
366 # (this extension will get loaded from the file specified)
367 myfeature = ~/.hgext/myfeature.py
367 myfeature = ~/.hgext/myfeature.py
368
368
369
369
370 ``format``
370 ``format``
371 """"""""""
371 """"""""""
372
372
373 ``usestore``
373 ``usestore``
374 Enable or disable the "store" repository format which improves
374 Enable or disable the "store" repository format which improves
375 compatibility with systems that fold case or otherwise mangle
375 compatibility with systems that fold case or otherwise mangle
376 filenames. Enabled by default. Disabling this option will allow
376 filenames. Enabled by default. Disabling this option will allow
377 you to store longer filenames in some situations at the expense of
377 you to store longer filenames in some situations at the expense of
378 compatibility and ensures that the on-disk format of newly created
378 compatibility and ensures that the on-disk format of newly created
379 repositories will be compatible with Mercurial before version 0.9.4.
379 repositories will be compatible with Mercurial before version 0.9.4.
380
380
381 ``usefncache``
381 ``usefncache``
382 Enable or disable the "fncache" repository format which enhances
382 Enable or disable the "fncache" repository format which enhances
383 the "store" repository format (which has to be enabled to use
383 the "store" repository format (which has to be enabled to use
384 fncache) to allow longer filenames and avoids using Windows
384 fncache) to allow longer filenames and avoids using Windows
385 reserved names, e.g. "nul". Enabled by default. Disabling this
385 reserved names, e.g. "nul". Enabled by default. Disabling this
386 option ensures that the on-disk format of newly created
386 option ensures that the on-disk format of newly created
387 repositories will be compatible with Mercurial before version 1.1.
387 repositories will be compatible with Mercurial before version 1.1.
388
388
389 ``merge-patterns``
389 ``merge-patterns``
390 """"""""""""""""""
390 """"""""""""""""""
391
391
392 This section specifies merge tools to associate with particular file
392 This section specifies merge tools to associate with particular file
393 patterns. Tools matched here will take precedence over the default
393 patterns. Tools matched here will take precedence over the default
394 merge tool. Patterns are globs by default, rooted at the repository
394 merge tool. Patterns are globs by default, rooted at the repository
395 root.
395 root.
396
396
397 Example::
397 Example::
398
398
399 [merge-patterns]
399 [merge-patterns]
400 **.c = kdiff3
400 **.c = kdiff3
401 **.jpg = myimgmerge
401 **.jpg = myimgmerge
402
402
403 ``merge-tools``
403 ``merge-tools``
404 """""""""""""""
404 """""""""""""""
405
405
406 This section configures external merge tools to use for file-level
406 This section configures external merge tools to use for file-level
407 merges.
407 merges.
408
408
409 Example ``~/.hgrc``::
409 Example ``~/.hgrc``::
410
410
411 [merge-tools]
411 [merge-tools]
412 # Override stock tool location
412 # Override stock tool location
413 kdiff3.executable = ~/bin/kdiff3
413 kdiff3.executable = ~/bin/kdiff3
414 # Specify command line
414 # Specify command line
415 kdiff3.args = $base $local $other -o $output
415 kdiff3.args = $base $local $other -o $output
416 # Give higher priority
416 # Give higher priority
417 kdiff3.priority = 1
417 kdiff3.priority = 1
418
418
419 # Define new tool
419 # Define new tool
420 myHtmlTool.args = -m $local $other $base $output
420 myHtmlTool.args = -m $local $other $base $output
421 myHtmlTool.regkey = Software\FooSoftware\HtmlMerge
421 myHtmlTool.regkey = Software\FooSoftware\HtmlMerge
422 myHtmlTool.priority = 1
422 myHtmlTool.priority = 1
423
423
424 Supported arguments:
424 Supported arguments:
425
425
426 ``priority``
426 ``priority``
427 The priority in which to evaluate this tool.
427 The priority in which to evaluate this tool.
428 Default: 0.
428 Default: 0.
429 ``executable``
429 ``executable``
430 Either just the name of the executable or its pathname.
430 Either just the name of the executable or its pathname.
431 Default: the tool name.
431 Default: the tool name.
432 ``args``
432 ``args``
433 The arguments to pass to the tool executable. You can refer to the
433 The arguments to pass to the tool executable. You can refer to the
434 files being merged as well as the output file through these
434 files being merged as well as the output file through these
435 variables: ``$base``, ``$local``, ``$other``, ``$output``.
435 variables: ``$base``, ``$local``, ``$other``, ``$output``.
436 Default: ``$local $base $other``
436 Default: ``$local $base $other``
437 ``premerge``
437 ``premerge``
438 Attempt to run internal non-interactive 3-way merge tool before
438 Attempt to run internal non-interactive 3-way merge tool before
439 launching external tool.
439 launching external tool.
440 Default: True
440 Default: True
441 ``binary``
441 ``binary``
442 This tool can merge binary files. Defaults to False, unless tool
442 This tool can merge binary files. Defaults to False, unless tool
443 was selected by file pattern match.
443 was selected by file pattern match.
444 ``symlink``
444 ``symlink``
445 This tool can merge symlinks. Defaults to False, even if tool was
445 This tool can merge symlinks. Defaults to False, even if tool was
446 selected by file pattern match.
446 selected by file pattern match.
447 ``checkconflicts``
447 ``checkconflicts``
448 Check whether there are conflicts even though the tool reported
448 Check whether there are conflicts even though the tool reported
449 success.
449 success.
450 Default: False
450 Default: False
451 ``checkchanged``
451 ``checkchanged``
452 Check whether outputs were written even though the tool reported
452 Check whether outputs were written even though the tool reported
453 success.
453 success.
454 Default: False
454 Default: False
455 ``fixeol``
455 ``fixeol``
456 Attempt to fix up EOL changes caused by the merge tool.
456 Attempt to fix up EOL changes caused by the merge tool.
457 Default: False
457 Default: False
458 ``gui``
458 ``gui``
459 This tool requires a graphical interface to run. Default: False
459 This tool requires a graphical interface to run. Default: False
460 ``regkey``
460 ``regkey``
461 Windows registry key which describes install location of this
461 Windows registry key which describes install location of this
462 tool. Mercurial will search for this key first under
462 tool. Mercurial will search for this key first under
463 ``HKEY_CURRENT_USER`` and then under ``HKEY_LOCAL_MACHINE``.
463 ``HKEY_CURRENT_USER`` and then under ``HKEY_LOCAL_MACHINE``.
464 Default: None
464 Default: None
465 ``regname``
465 ``regname``
466 Name of value to read from specified registry key. Defaults to the
466 Name of value to read from specified registry key. Defaults to the
467 unnamed (default) value.
467 unnamed (default) value.
468 ``regappend``
468 ``regappend``
469 String to append to the value read from the registry, typically
469 String to append to the value read from the registry, typically
470 the executable name of the tool.
470 the executable name of the tool.
471 Default: None
471 Default: None
472
472
473
473
474 ``hooks``
474 ``hooks``
475 """""""""
475 """""""""
476 Commands or Python functions that get automatically executed by
476 Commands or Python functions that get automatically executed by
477 various actions such as starting or finishing a commit. Multiple
477 various actions such as starting or finishing a commit. Multiple
478 hooks can be run for the same action by appending a suffix to the
478 hooks can be run for the same action by appending a suffix to the
479 action. Overriding a site-wide hook can be done by changing its
479 action. Overriding a site-wide hook can be done by changing its
480 value or setting it to an empty string.
480 value or setting it to an empty string.
481
481
482 Example ``.hg/hgrc``::
482 Example ``.hg/hgrc``::
483
483
484 [hooks]
484 [hooks]
485 # update working directory after adding changesets
485 # update working directory after adding changesets
486 changegroup.update = hg update
486 changegroup.update = hg update
487 # do not use the site-wide hook
487 # do not use the site-wide hook
488 incoming =
488 incoming =
489 incoming.email = /my/email/hook
489 incoming.email = /my/email/hook
490 incoming.autobuild = /my/build/hook
490 incoming.autobuild = /my/build/hook
491
491
492 Most hooks are run with environment variables set that give useful
492 Most hooks are run with environment variables set that give useful
493 additional information. For each hook below, the environment
493 additional information. For each hook below, the environment
494 variables it is passed are listed with names of the form ``$HG_foo``.
494 variables it is passed are listed with names of the form ``$HG_foo``.
495
495
496 ``changegroup``
496 ``changegroup``
497 Run after a changegroup has been added via push, pull or unbundle.
497 Run after a changegroup has been added via push, pull or unbundle.
498 ID of the first new changeset is in ``$HG_NODE``. URL from which
498 ID of the first new changeset is in ``$HG_NODE``. URL from which
499 changes came is in ``$HG_URL``.
499 changes came is in ``$HG_URL``.
500 ``commit``
500 ``commit``
501 Run after a changeset has been created in the local repository. ID
501 Run after a changeset has been created in the local repository. ID
502 of the newly created changeset is in ``$HG_NODE``. Parent changeset
502 of the newly created changeset is in ``$HG_NODE``. Parent changeset
503 IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
503 IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
504 ``incoming``
504 ``incoming``
505 Run after a changeset has been pulled, pushed, or unbundled into
505 Run after a changeset has been pulled, pushed, or unbundled into
506 the local repository. The ID of the newly arrived changeset is in
506 the local repository. The ID of the newly arrived changeset is in
507 ``$HG_NODE``. URL that was source of changes came is in ``$HG_URL``.
507 ``$HG_NODE``. URL that was source of changes came is in ``$HG_URL``.
508 ``outgoing``
508 ``outgoing``
509 Run after sending changes from local repository to another. ID of
509 Run after sending changes from local repository to another. ID of
510 first changeset sent is in ``$HG_NODE``. Source of operation is in
510 first changeset sent is in ``$HG_NODE``. Source of operation is in
511 ``$HG_SOURCE``; see "preoutgoing" hook for description.
511 ``$HG_SOURCE``; see "preoutgoing" hook for description.
512 ``post-<command>``
512 ``post-<command>``
513 Run after successful invocations of the associated command. The
513 Run after successful invocations of the associated command. The
514 contents of the command line are passed as ``$HG_ARGS`` and the result
514 contents of the command line are passed as ``$HG_ARGS`` and the result
515 code in ``$HG_RESULT``. Hook failure is ignored.
515 code in ``$HG_RESULT``. Hook failure is ignored.
516 ``pre-<command>``
516 ``pre-<command>``
517 Run before executing the associated command. The contents of the
517 Run before executing the associated command. The contents of the
518 command line are passed as ``$HG_ARGS``. If the hook returns failure,
518 command line are passed as ``$HG_ARGS``. If the hook returns failure,
519 the command doesn't execute and Mercurial returns the failure
519 the command doesn't execute and Mercurial returns the failure
520 code.
520 code.
521 ``prechangegroup``
521 ``prechangegroup``
522 Run before a changegroup is added via push, pull or unbundle. Exit
522 Run before a changegroup is added via push, pull or unbundle. Exit
523 status 0 allows the changegroup to proceed. Non-zero status will
523 status 0 allows the changegroup to proceed. Non-zero status will
524 cause the push, pull or unbundle to fail. URL from which changes
524 cause the push, pull or unbundle to fail. URL from which changes
525 will come is in ``$HG_URL``.
525 will come is in ``$HG_URL``.
526 ``precommit``
526 ``precommit``
527 Run before starting a local commit. Exit status 0 allows the
527 Run before starting a local commit. Exit status 0 allows the
528 commit to proceed. Non-zero status will cause the commit to fail.
528 commit to proceed. Non-zero status will cause the commit to fail.
529 Parent changeset IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
529 Parent changeset IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
530 ``preoutgoing``
530 ``preoutgoing``
531 Run before collecting changes to send from the local repository to
531 Run before collecting changes to send from the local repository to
532 another. Non-zero status will cause failure. This lets you prevent
532 another. Non-zero status will cause failure. This lets you prevent
533 pull over HTTP or SSH. Also prevents against local pull, push
533 pull over HTTP or SSH. Also prevents against local pull, push
534 (outbound) or bundle commands, but not effective, since you can
534 (outbound) or bundle commands, but not effective, since you can
535 just copy files instead then. Source of operation is in
535 just copy files instead then. Source of operation is in
536 ``$HG_SOURCE``. If "serve", operation is happening on behalf of remote
536 ``$HG_SOURCE``. If "serve", operation is happening on behalf of remote
537 SSH or HTTP repository. If "push", "pull" or "bundle", operation
537 SSH or HTTP repository. If "push", "pull" or "bundle", operation
538 is happening on behalf of repository on same system.
538 is happening on behalf of repository on same system.
539 ``pretag``
539 ``pretag``
540 Run before creating a tag. Exit status 0 allows the tag to be
540 Run before creating a tag. Exit status 0 allows the tag to be
541 created. Non-zero status will cause the tag to fail. ID of
541 created. Non-zero status will cause the tag to fail. ID of
542 changeset to tag is in ``$HG_NODE``. Name of tag is in ``$HG_TAG``. Tag is
542 changeset to tag is in ``$HG_NODE``. Name of tag is in ``$HG_TAG``. Tag is
543 local if ``$HG_LOCAL=1``, in repository if ``$HG_LOCAL=0``.
543 local if ``$HG_LOCAL=1``, in repository if ``$HG_LOCAL=0``.
544 ``pretxnchangegroup``
544 ``pretxnchangegroup``
545 Run after a changegroup has been added via push, pull or unbundle,
545 Run after a changegroup has been added via push, pull or unbundle,
546 but before the transaction has been committed. Changegroup is
546 but before the transaction has been committed. Changegroup is
547 visible to hook program. This lets you validate incoming changes
547 visible to hook program. This lets you validate incoming changes
548 before accepting them. Passed the ID of the first new changeset in
548 before accepting them. Passed the ID of the first new changeset in
549 ``$HG_NODE``. Exit status 0 allows the transaction to commit. Non-zero
549 ``$HG_NODE``. Exit status 0 allows the transaction to commit. Non-zero
550 status will cause the transaction to be rolled back and the push,
550 status will cause the transaction to be rolled back and the push,
551 pull or unbundle will fail. URL that was source of changes is in
551 pull or unbundle will fail. URL that was source of changes is in
552 ``$HG_URL``.
552 ``$HG_URL``.
553 ``pretxncommit``
553 ``pretxncommit``
554 Run after a changeset has been created but the transaction not yet
554 Run after a changeset has been created but the transaction not yet
555 committed. Changeset is visible to hook program. This lets you
555 committed. Changeset is visible to hook program. This lets you
556 validate commit message and changes. Exit status 0 allows the
556 validate commit message and changes. Exit status 0 allows the
557 commit to proceed. Non-zero status will cause the transaction to
557 commit to proceed. Non-zero status will cause the transaction to
558 be rolled back. ID of changeset is in ``$HG_NODE``. Parent changeset
558 be rolled back. ID of changeset is in ``$HG_NODE``. Parent changeset
559 IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
559 IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
560 ``preupdate``
560 ``preupdate``
561 Run before updating the working directory. Exit status 0 allows
561 Run before updating the working directory. Exit status 0 allows
562 the update to proceed. Non-zero status will prevent the update.
562 the update to proceed. Non-zero status will prevent the update.
563 Changeset ID of first new parent is in ``$HG_PARENT1``. If merge, ID
563 Changeset ID of first new parent is in ``$HG_PARENT1``. If merge, ID
564 of second new parent is in ``$HG_PARENT2``.
564 of second new parent is in ``$HG_PARENT2``.
565 ``tag``
565 ``tag``
566 Run after a tag is created. ID of tagged changeset is in ``$HG_NODE``.
566 Run after a tag is created. ID of tagged changeset is in ``$HG_NODE``.
567 Name of tag is in ``$HG_TAG``. Tag is local if ``$HG_LOCAL=1``, in
567 Name of tag is in ``$HG_TAG``. Tag is local if ``$HG_LOCAL=1``, in
568 repository if ``$HG_LOCAL=0``.
568 repository if ``$HG_LOCAL=0``.
569 ``update``
569 ``update``
570 Run after updating the working directory. Changeset ID of first
570 Run after updating the working directory. Changeset ID of first
571 new parent is in ``$HG_PARENT1``. If merge, ID of second new parent is
571 new parent is in ``$HG_PARENT1``. If merge, ID of second new parent is
572 in ``$HG_PARENT2``. If the update succeeded, ``$HG_ERROR=0``. If the
572 in ``$HG_PARENT2``. If the update succeeded, ``$HG_ERROR=0``. If the
573 update failed (e.g. because conflicts not resolved), ``$HG_ERROR=1``.
573 update failed (e.g. because conflicts not resolved), ``$HG_ERROR=1``.
574
574
575 .. note:: It is generally better to use standard hooks rather than the
575 .. note:: It is generally better to use standard hooks rather than the
576 generic pre- and post- command hooks as they are guaranteed to be
576 generic pre- and post- command hooks as they are guaranteed to be
577 called in the appropriate contexts for influencing transactions.
577 called in the appropriate contexts for influencing transactions.
578 Also, hooks like "commit" will be called in all contexts that
578 Also, hooks like "commit" will be called in all contexts that
579 generate a commit (e.g. tag) and not just the commit command.
579 generate a commit (e.g. tag) and not just the commit command.
580
580
581 .. note:: Environment variables with empty values may not be passed to
581 .. note:: Environment variables with empty values may not be passed to
582 hooks on platforms such as Windows. As an example, ``$HG_PARENT2``
582 hooks on platforms such as Windows. As an example, ``$HG_PARENT2``
583 will have an empty value under Unix-like platforms for non-merge
583 will have an empty value under Unix-like platforms for non-merge
584 changesets, while it will not be available at all under Windows.
584 changesets, while it will not be available at all under Windows.
585
585
586 The syntax for Python hooks is as follows::
586 The syntax for Python hooks is as follows::
587
587
588 hookname = python:modulename.submodule.callable
588 hookname = python:modulename.submodule.callable
589 hookname = python:/path/to/python/module.py:callable
589 hookname = python:/path/to/python/module.py:callable
590
590
591 Python hooks are run within the Mercurial process. Each hook is
591 Python hooks are run within the Mercurial process. Each hook is
592 called with at least three keyword arguments: a ui object (keyword
592 called with at least three keyword arguments: a ui object (keyword
593 ``ui``), a repository object (keyword ``repo``), and a ``hooktype``
593 ``ui``), a repository object (keyword ``repo``), and a ``hooktype``
594 keyword that tells what kind of hook is used. Arguments listed as
594 keyword that tells what kind of hook is used. Arguments listed as
595 environment variables above are passed as keyword arguments, with no
595 environment variables above are passed as keyword arguments, with no
596 ``HG_`` prefix, and names in lower case.
596 ``HG_`` prefix, and names in lower case.
597
597
598 If a Python hook returns a "true" value or raises an exception, this
598 If a Python hook returns a "true" value or raises an exception, this
599 is treated as a failure.
599 is treated as a failure.
600
600
601
601
602 ``http_proxy``
602 ``http_proxy``
603 """"""""""""""
603 """"""""""""""
604 Used to access web-based Mercurial repositories through a HTTP
604 Used to access web-based Mercurial repositories through a HTTP
605 proxy.
605 proxy.
606
606
607 ``host``
607 ``host``
608 Host name and (optional) port of the proxy server, for example
608 Host name and (optional) port of the proxy server, for example
609 "myproxy:8000".
609 "myproxy:8000".
610 ``no``
610 ``no``
611 Optional. Comma-separated list of host names that should bypass
611 Optional. Comma-separated list of host names that should bypass
612 the proxy.
612 the proxy.
613 ``passwd``
613 ``passwd``
614 Optional. Password to authenticate with at the proxy server.
614 Optional. Password to authenticate with at the proxy server.
615 ``user``
615 ``user``
616 Optional. User name to authenticate with at the proxy server.
616 Optional. User name to authenticate with at the proxy server.
617
617
618 ``smtp``
618 ``smtp``
619 """"""""
619 """"""""
620 Configuration for extensions that need to send email messages.
620 Configuration for extensions that need to send email messages.
621
621
622 ``host``
622 ``host``
623 Host name of mail server, e.g. "mail.example.com".
623 Host name of mail server, e.g. "mail.example.com".
624 ``port``
624 ``port``
625 Optional. Port to connect to on mail server. Default: 25.
625 Optional. Port to connect to on mail server. Default: 25.
626 ``tls``
626 ``tls``
627 Optional. Whether to connect to mail server using TLS. True or
627 Optional. Whether to connect to mail server using TLS. True or
628 False. Default: False.
628 False. Default: False.
629 ``username``
629 ``username``
630 Optional. User name to authenticate to SMTP server with. If
630 Optional. User name to authenticate to SMTP server with. If
631 username is specified, password must also be specified.
631 username is specified, password must also be specified.
632 Default: none.
632 Default: none.
633 ``password``
633 ``password``
634 Optional. Password to authenticate to SMTP server with. If
634 Optional. Password to authenticate to SMTP server with. If
635 username is specified, password must also be specified.
635 username is specified, password must also be specified.
636 Default: none.
636 Default: none.
637 ``local_hostname``
637 ``local_hostname``
638 Optional. It's the hostname that the sender can use to identify
638 Optional. It's the hostname that the sender can use to identify
639 itself to the MTA.
639 itself to the MTA.
640
640
641
641
642 ``patch``
642 ``patch``
643 """""""""
643 """""""""
644 Settings used when applying patches, for instance through the 'import'
644 Settings used when applying patches, for instance through the 'import'
645 command or with Mercurial Queues extension.
645 command or with Mercurial Queues extension.
646
646
647 ``eol``
647 ``eol``
648 When set to 'strict' patch content and patched files end of lines
648 When set to 'strict' patch content and patched files end of lines
649 are preserved. When set to ``lf`` or ``crlf``, both files end of lines
649 are preserved. When set to ``lf`` or ``crlf``, both files end of
650 are ignored when patching and the result line endings are
650 lines are ignored when patching and the result line endings are
651 normalized to either LF (Unix) or CRLF (Windows). When set to
651 normalized to either LF (Unix) or CRLF (Windows). When set to
652 ``auto``, end of lines are again ignored while patching but line
652 ``auto``, end of lines are again ignored while patching but line
653 endings in patched files are normalized to their original setting
653 endings in patched files are normalized to their original setting
654 on a per-file basis.
654 on a per-file basis. If target file does not exist or has no end
655 of line, patch line endings are preserved.
655 Default: strict.
656 Default: strict.
656
657
657
658
658 ``paths``
659 ``paths``
659 """""""""
660 """""""""
660 Assigns symbolic names to repositories. The left side is the
661 Assigns symbolic names to repositories. The left side is the
661 symbolic name, and the right gives the directory or URL that is the
662 symbolic name, and the right gives the directory or URL that is the
662 location of the repository. Default paths can be declared by setting
663 location of the repository. Default paths can be declared by setting
663 the following entries.
664 the following entries.
664
665
665 ``default``
666 ``default``
666 Directory or URL to use when pulling if no source is specified.
667 Directory or URL to use when pulling if no source is specified.
667 Default is set to repository from which the current repository was
668 Default is set to repository from which the current repository was
668 cloned.
669 cloned.
669 ``default-push``
670 ``default-push``
670 Optional. Directory or URL to use when pushing if no destination
671 Optional. Directory or URL to use when pushing if no destination
671 is specified.
672 is specified.
672
673
673
674
674 ``profiling``
675 ``profiling``
675 """""""""""""
676 """""""""""""
676 Specifies profiling format and file output. In this section
677 Specifies profiling format and file output. In this section
677 description, 'profiling data' stands for the raw data collected
678 description, 'profiling data' stands for the raw data collected
678 during profiling, while 'profiling report' stands for a statistical
679 during profiling, while 'profiling report' stands for a statistical
679 text report generated from the profiling data. The profiling is done
680 text report generated from the profiling data. The profiling is done
680 using lsprof.
681 using lsprof.
681
682
682 ``format``
683 ``format``
683 Profiling format.
684 Profiling format.
684 Default: text.
685 Default: text.
685
686
686 ``text``
687 ``text``
687 Generate a profiling report. When saving to a file, it should be
688 Generate a profiling report. When saving to a file, it should be
688 noted that only the report is saved, and the profiling data is
689 noted that only the report is saved, and the profiling data is
689 not kept.
690 not kept.
690 ``kcachegrind``
691 ``kcachegrind``
691 Format profiling data for kcachegrind use: when saving to a
692 Format profiling data for kcachegrind use: when saving to a
692 file, the generated file can directly be loaded into
693 file, the generated file can directly be loaded into
693 kcachegrind.
694 kcachegrind.
694 ``output``
695 ``output``
695 File path where profiling data or report should be saved. If the
696 File path where profiling data or report should be saved. If the
696 file exists, it is replaced. Default: None, data is printed on
697 file exists, it is replaced. Default: None, data is printed on
697 stderr
698 stderr
698
699
699 ``server``
700 ``server``
700 """"""""""
701 """"""""""
701 Controls generic server settings.
702 Controls generic server settings.
702
703
703 ``uncompressed``
704 ``uncompressed``
704 Whether to allow clients to clone a repository using the
705 Whether to allow clients to clone a repository using the
705 uncompressed streaming protocol. This transfers about 40% more
706 uncompressed streaming protocol. This transfers about 40% more
706 data than a regular clone, but uses less memory and CPU on both
707 data than a regular clone, but uses less memory and CPU on both
707 server and client. Over a LAN (100 Mbps or better) or a very fast
708 server and client. Over a LAN (100 Mbps or better) or a very fast
708 WAN, an uncompressed streaming clone is a lot faster (~10x) than a
709 WAN, an uncompressed streaming clone is a lot faster (~10x) than a
709 regular clone. Over most WAN connections (anything slower than
710 regular clone. Over most WAN connections (anything slower than
710 about 6 Mbps), uncompressed streaming is slower, because of the
711 about 6 Mbps), uncompressed streaming is slower, because of the
711 extra data transfer overhead. Default is False.
712 extra data transfer overhead. Default is False.
712
713
713
714
714 ``trusted``
715 ``trusted``
715 """""""""""
716 """""""""""
716 For security reasons, Mercurial will not use the settings in the
717 For security reasons, Mercurial will not use the settings in the
717 ``.hg/hgrc`` file from a repository if it doesn't belong to a trusted
718 ``.hg/hgrc`` file from a repository if it doesn't belong to a trusted
718 user or to a trusted group. The main exception is the web interface,
719 user or to a trusted group. The main exception is the web interface,
719 which automatically uses some safe settings, since it's common to
720 which automatically uses some safe settings, since it's common to
720 serve repositories from different users.
721 serve repositories from different users.
721
722
722 This section specifies what users and groups are trusted. The
723 This section specifies what users and groups are trusted. The
723 current user is always trusted. To trust everybody, list a user or a
724 current user is always trusted. To trust everybody, list a user or a
724 group with name ``*``.
725 group with name ``*``.
725
726
726 ``users``
727 ``users``
727 Comma-separated list of trusted users.
728 Comma-separated list of trusted users.
728 ``groups``
729 ``groups``
729 Comma-separated list of trusted groups.
730 Comma-separated list of trusted groups.
730
731
731
732
732 ``ui``
733 ``ui``
733 """"""
734 """"""
734
735
735 User interface controls.
736 User interface controls.
736
737
737 ``archivemeta``
738 ``archivemeta``
738 Whether to include the .hg_archival.txt file containing meta data
739 Whether to include the .hg_archival.txt file containing meta data
739 (hashes for the repository base and for tip) in archives created
740 (hashes for the repository base and for tip) in archives created
740 by the hg archive command or downloaded via hgweb.
741 by the hg archive command or downloaded via hgweb.
741 Default is True.
742 Default is True.
742 ``askusername``
743 ``askusername``
743 Whether to prompt for a username when committing. If True, and
744 Whether to prompt for a username when committing. If True, and
744 neither ``$HGUSER`` nor ``$EMAIL`` has been specified, then the user will
745 neither ``$HGUSER`` nor ``$EMAIL`` has been specified, then the user will
745 be prompted to enter a username. If no username is entered, the
746 be prompted to enter a username. If no username is entered, the
746 default ``USER@HOST`` is used instead.
747 default ``USER@HOST`` is used instead.
747 Default is False.
748 Default is False.
748 ``debug``
749 ``debug``
749 Print debugging information. True or False. Default is False.
750 Print debugging information. True or False. Default is False.
750 ``editor``
751 ``editor``
751 The editor to use during a commit. Default is ``$EDITOR`` or ``vi``.
752 The editor to use during a commit. Default is ``$EDITOR`` or ``vi``.
752 ``fallbackencoding``
753 ``fallbackencoding``
753 Encoding to try if it's not possible to decode the changelog using
754 Encoding to try if it's not possible to decode the changelog using
754 UTF-8. Default is ISO-8859-1.
755 UTF-8. Default is ISO-8859-1.
755 ``ignore``
756 ``ignore``
756 A file to read per-user ignore patterns from. This file should be
757 A file to read per-user ignore patterns from. This file should be
757 in the same format as a repository-wide .hgignore file. This
758 in the same format as a repository-wide .hgignore file. This
758 option supports hook syntax, so if you want to specify multiple
759 option supports hook syntax, so if you want to specify multiple
759 ignore files, you can do so by setting something like
760 ignore files, you can do so by setting something like
760 ``ignore.other = ~/.hgignore2``. For details of the ignore file
761 ``ignore.other = ~/.hgignore2``. For details of the ignore file
761 format, see the |hgignore(5)|_ man page.
762 format, see the |hgignore(5)|_ man page.
762 ``interactive``
763 ``interactive``
763 Allow to prompt the user. True or False. Default is True.
764 Allow to prompt the user. True or False. Default is True.
764 ``logtemplate``
765 ``logtemplate``
765 Template string for commands that print changesets.
766 Template string for commands that print changesets.
766 ``merge``
767 ``merge``
767 The conflict resolution program to use during a manual merge.
768 The conflict resolution program to use during a manual merge.
768 There are some internal tools available:
769 There are some internal tools available:
769
770
770 ``internal:local``
771 ``internal:local``
771 keep the local version
772 keep the local version
772 ``internal:other``
773 ``internal:other``
773 use the other version
774 use the other version
774 ``internal:merge``
775 ``internal:merge``
775 use the internal non-interactive merge tool
776 use the internal non-interactive merge tool
776 ``internal:fail``
777 ``internal:fail``
777 fail to merge
778 fail to merge
778
779
779 For more information on configuring merge tools see the
780 For more information on configuring merge tools see the
780 merge-tools_ section.
781 merge-tools_ section.
781
782
782 ``patch``
783 ``patch``
783 command to use to apply patches. Look for ``gpatch`` or ``patch`` in
784 command to use to apply patches. Look for ``gpatch`` or ``patch`` in
784 PATH if unset.
785 PATH if unset.
785 ``quiet``
786 ``quiet``
786 Reduce the amount of output printed. True or False. Default is False.
787 Reduce the amount of output printed. True or False. Default is False.
787 ``remotecmd``
788 ``remotecmd``
788 remote command to use for clone/push/pull operations. Default is ``hg``.
789 remote command to use for clone/push/pull operations. Default is ``hg``.
789 ``report_untrusted``
790 ``report_untrusted``
790 Warn if a ``.hg/hgrc`` file is ignored due to not being owned by a
791 Warn if a ``.hg/hgrc`` file is ignored due to not being owned by a
791 trusted user or group. True or False. Default is True.
792 trusted user or group. True or False. Default is True.
792 ``slash``
793 ``slash``
793 Display paths using a slash (``/``) as the path separator. This
794 Display paths using a slash (``/``) as the path separator. This
794 only makes a difference on systems where the default path
795 only makes a difference on systems where the default path
795 separator is not the slash character (e.g. Windows uses the
796 separator is not the slash character (e.g. Windows uses the
796 backslash character (``\``)).
797 backslash character (``\``)).
797 Default is False.
798 Default is False.
798 ``ssh``
799 ``ssh``
799 command to use for SSH connections. Default is ``ssh``.
800 command to use for SSH connections. Default is ``ssh``.
800 ``strict``
801 ``strict``
801 Require exact command names, instead of allowing unambiguous
802 Require exact command names, instead of allowing unambiguous
802 abbreviations. True or False. Default is False.
803 abbreviations. True or False. Default is False.
803 ``style``
804 ``style``
804 Name of style to use for command output.
805 Name of style to use for command output.
805 ``timeout``
806 ``timeout``
806 The timeout used when a lock is held (in seconds), a negative value
807 The timeout used when a lock is held (in seconds), a negative value
807 means no timeout. Default is 600.
808 means no timeout. Default is 600.
808 ``traceback``
809 ``traceback``
809 Mercurial always prints a traceback when an unknown exception
810 Mercurial always prints a traceback when an unknown exception
810 occurs. Setting this to True will make Mercurial print a traceback
811 occurs. Setting this to True will make Mercurial print a traceback
811 on all exceptions, even those recognized by Mercurial (such as
812 on all exceptions, even those recognized by Mercurial (such as
812 IOError or MemoryError). Default is False.
813 IOError or MemoryError). Default is False.
813 ``username``
814 ``username``
814 The committer of a changeset created when running "commit".
815 The committer of a changeset created when running "commit".
815 Typically a person's name and email address, e.g. ``Fred Widget
816 Typically a person's name and email address, e.g. ``Fred Widget
816 <fred@example.com>``. Default is ``$EMAIL`` or ``username@hostname``. If
817 <fred@example.com>``. Default is ``$EMAIL`` or ``username@hostname``. If
817 the username in hgrc is empty, it has to be specified manually or
818 the username in hgrc is empty, it has to be specified manually or
818 in a different hgrc file (e.g. ``$HOME/.hgrc``, if the admin set
819 in a different hgrc file (e.g. ``$HOME/.hgrc``, if the admin set
819 ``username =`` in the system hgrc).
820 ``username =`` in the system hgrc).
820 ``verbose``
821 ``verbose``
821 Increase the amount of output printed. True or False. Default is False.
822 Increase the amount of output printed. True or False. Default is False.
822
823
823
824
824 ``web``
825 ``web``
825 """""""
826 """""""
826 Web interface configuration.
827 Web interface configuration.
827
828
828 ``accesslog``
829 ``accesslog``
829 Where to output the access log. Default is stdout.
830 Where to output the access log. Default is stdout.
830 ``address``
831 ``address``
831 Interface address to bind to. Default is all.
832 Interface address to bind to. Default is all.
832 ``allow_archive``
833 ``allow_archive``
833 List of archive format (bz2, gz, zip) allowed for downloading.
834 List of archive format (bz2, gz, zip) allowed for downloading.
834 Default is empty.
835 Default is empty.
835 ``allowbz2``
836 ``allowbz2``
836 (DEPRECATED) Whether to allow .tar.bz2 downloading of repository
837 (DEPRECATED) Whether to allow .tar.bz2 downloading of repository
837 revisions.
838 revisions.
838 Default is False.
839 Default is False.
839 ``allowgz``
840 ``allowgz``
840 (DEPRECATED) Whether to allow .tar.gz downloading of repository
841 (DEPRECATED) Whether to allow .tar.gz downloading of repository
841 revisions.
842 revisions.
842 Default is False.
843 Default is False.
843 ``allowpull``
844 ``allowpull``
844 Whether to allow pulling from the repository. Default is True.
845 Whether to allow pulling from the repository. Default is True.
845 ``allow_push``
846 ``allow_push``
846 Whether to allow pushing to the repository. If empty or not set,
847 Whether to allow pushing to the repository. If empty or not set,
847 push is not allowed. If the special value ``*``, any remote user can
848 push is not allowed. If the special value ``*``, any remote user can
848 push, including unauthenticated users. Otherwise, the remote user
849 push, including unauthenticated users. Otherwise, the remote user
849 must have been authenticated, and the authenticated user name must
850 must have been authenticated, and the authenticated user name must
850 be present in this list (separated by whitespace or ``,``). The
851 be present in this list (separated by whitespace or ``,``). The
851 contents of the allow_push list are examined after the deny_push
852 contents of the allow_push list are examined after the deny_push
852 list.
853 list.
853 ``allow_read``
854 ``allow_read``
854 If the user has not already been denied repository access due to
855 If the user has not already been denied repository access due to
855 the contents of deny_read, this list determines whether to grant
856 the contents of deny_read, this list determines whether to grant
856 repository access to the user. If this list is not empty, and the
857 repository access to the user. If this list is not empty, and the
857 user is unauthenticated or not present in the list (separated by
858 user is unauthenticated or not present in the list (separated by
858 whitespace or ``,``), then access is denied for the user. If the
859 whitespace or ``,``), then access is denied for the user. If the
859 list is empty or not set, then access is permitted to all users by
860 list is empty or not set, then access is permitted to all users by
860 default. Setting allow_read to the special value ``*`` is equivalent
861 default. Setting allow_read to the special value ``*`` is equivalent
861 to it not being set (i.e. access is permitted to all users). The
862 to it not being set (i.e. access is permitted to all users). The
862 contents of the allow_read list are examined after the deny_read
863 contents of the allow_read list are examined after the deny_read
863 list.
864 list.
864 ``allowzip``
865 ``allowzip``
865 (DEPRECATED) Whether to allow .zip downloading of repository
866 (DEPRECATED) Whether to allow .zip downloading of repository
866 revisions. Default is False. This feature creates temporary files.
867 revisions. Default is False. This feature creates temporary files.
867 ``baseurl``
868 ``baseurl``
868 Base URL to use when publishing URLs in other locations, so
869 Base URL to use when publishing URLs in other locations, so
869 third-party tools like email notification hooks can construct
870 third-party tools like email notification hooks can construct
870 URLs. Example: ``http://hgserver/repos/``.
871 URLs. Example: ``http://hgserver/repos/``.
871 ``contact``
872 ``contact``
872 Name or email address of the person in charge of the repository.
873 Name or email address of the person in charge of the repository.
873 Defaults to ui.username or ``$EMAIL`` or "unknown" if unset or empty.
874 Defaults to ui.username or ``$EMAIL`` or "unknown" if unset or empty.
874 ``deny_push``
875 ``deny_push``
875 Whether to deny pushing to the repository. If empty or not set,
876 Whether to deny pushing to the repository. If empty or not set,
876 push is not denied. If the special value ``*``, all remote users are
877 push is not denied. If the special value ``*``, all remote users are
877 denied push. Otherwise, unauthenticated users are all denied, and
878 denied push. Otherwise, unauthenticated users are all denied, and
878 any authenticated user name present in this list (separated by
879 any authenticated user name present in this list (separated by
879 whitespace or ``,``) is also denied. The contents of the deny_push
880 whitespace or ``,``) is also denied. The contents of the deny_push
880 list are examined before the allow_push list.
881 list are examined before the allow_push list.
881 ``deny_read``
882 ``deny_read``
882 Whether to deny reading/viewing of the repository. If this list is
883 Whether to deny reading/viewing of the repository. If this list is
883 not empty, unauthenticated users are all denied, and any
884 not empty, unauthenticated users are all denied, and any
884 authenticated user name present in this list (separated by
885 authenticated user name present in this list (separated by
885 whitespace or ``,``) is also denied access to the repository. If set
886 whitespace or ``,``) is also denied access to the repository. If set
886 to the special value ``*``, all remote users are denied access
887 to the special value ``*``, all remote users are denied access
887 (rarely needed ;). If deny_read is empty or not set, the
888 (rarely needed ;). If deny_read is empty or not set, the
888 determination of repository access depends on the presence and
889 determination of repository access depends on the presence and
889 content of the allow_read list (see description). If both
890 content of the allow_read list (see description). If both
890 deny_read and allow_read are empty or not set, then access is
891 deny_read and allow_read are empty or not set, then access is
891 permitted to all users by default. If the repository is being
892 permitted to all users by default. If the repository is being
892 served via hgwebdir, denied users will not be able to see it in
893 served via hgwebdir, denied users will not be able to see it in
893 the list of repositories. The contents of the deny_read list have
894 the list of repositories. The contents of the deny_read list have
894 priority over (are examined before) the contents of the allow_read
895 priority over (are examined before) the contents of the allow_read
895 list.
896 list.
896 ``descend``
897 ``descend``
897 hgwebdir indexes will not descend into subdirectories. Only repositories
898 hgwebdir indexes will not descend into subdirectories. Only repositories
898 directly in the current path will be shown (other repositories are still
899 directly in the current path will be shown (other repositories are still
899 available from the index corresponding to their containing path).
900 available from the index corresponding to their containing path).
900 ``description``
901 ``description``
901 Textual description of the repository's purpose or contents.
902 Textual description of the repository's purpose or contents.
902 Default is "unknown".
903 Default is "unknown".
903 ``encoding``
904 ``encoding``
904 Character encoding name.
905 Character encoding name.
905 Example: "UTF-8"
906 Example: "UTF-8"
906 ``errorlog``
907 ``errorlog``
907 Where to output the error log. Default is stderr.
908 Where to output the error log. Default is stderr.
908 ``hidden``
909 ``hidden``
909 Whether to hide the repository in the hgwebdir index.
910 Whether to hide the repository in the hgwebdir index.
910 Default is False.
911 Default is False.
911 ``ipv6``
912 ``ipv6``
912 Whether to use IPv6. Default is False.
913 Whether to use IPv6. Default is False.
913 ``name``
914 ``name``
914 Repository name to use in the web interface. Default is current
915 Repository name to use in the web interface. Default is current
915 working directory.
916 working directory.
916 ``maxchanges``
917 ``maxchanges``
917 Maximum number of changes to list on the changelog. Default is 10.
918 Maximum number of changes to list on the changelog. Default is 10.
918 ``maxfiles``
919 ``maxfiles``
919 Maximum number of files to list per changeset. Default is 10.
920 Maximum number of files to list per changeset. Default is 10.
920 ``port``
921 ``port``
921 Port to listen on. Default is 8000.
922 Port to listen on. Default is 8000.
922 ``prefix``
923 ``prefix``
923 Prefix path to serve from. Default is '' (server root).
924 Prefix path to serve from. Default is '' (server root).
924 ``push_ssl``
925 ``push_ssl``
925 Whether to require that inbound pushes be transported over SSL to
926 Whether to require that inbound pushes be transported over SSL to
926 prevent password sniffing. Default is True.
927 prevent password sniffing. Default is True.
927 ``staticurl``
928 ``staticurl``
928 Base URL to use for static files. If unset, static files (e.g. the
929 Base URL to use for static files. If unset, static files (e.g. the
929 hgicon.png favicon) will be served by the CGI script itself. Use
930 hgicon.png favicon) will be served by the CGI script itself. Use
930 this setting to serve them directly with the HTTP server.
931 this setting to serve them directly with the HTTP server.
931 Example: ``http://hgserver/static/``.
932 Example: ``http://hgserver/static/``.
932 ``stripes``
933 ``stripes``
933 How many lines a "zebra stripe" should span in multiline output.
934 How many lines a "zebra stripe" should span in multiline output.
934 Default is 1; set to 0 to disable.
935 Default is 1; set to 0 to disable.
935 ``style``
936 ``style``
936 Which template map style to use.
937 Which template map style to use.
937 ``templates``
938 ``templates``
938 Where to find the HTML templates. Default is install path.
939 Where to find the HTML templates. Default is install path.
939
940
940
941
941 Author
942 Author
942 ------
943 ------
943 Bryan O'Sullivan <bos@serpentine.com>.
944 Bryan O'Sullivan <bos@serpentine.com>.
944
945
945 Mercurial was written by Matt Mackall <mpm@selenic.com>.
946 Mercurial was written by Matt Mackall <mpm@selenic.com>.
946
947
947 See Also
948 See Also
948 --------
949 --------
949 |hg(1)|_, |hgignore(5)|_
950 |hg(1)|_, |hgignore(5)|_
950
951
951 Copying
952 Copying
952 -------
953 -------
953 This manual page is copyright 2005 Bryan O'Sullivan.
954 This manual page is copyright 2005 Bryan O'Sullivan.
954 Mercurial is copyright 2005-2009 Matt Mackall.
955 Mercurial is copyright 2005-2009 Matt Mackall.
955 Free use of this software is granted under the terms of the GNU General
956 Free use of this software is granted under the terms of the GNU General
956 Public License version 2.
957 Public License version 2.
957
958
958 .. include:: common.txt
959 .. include:: common.txt
@@ -1,1447 +1,1485 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, incorporated herein by reference.
7 # GNU General Public License version 2, incorporated herein by reference.
8
8
9 from i18n import _
9 from i18n import _
10 from node import hex, nullid, short
10 from node import hex, nullid, short
11 import base85, cmdutil, mdiff, util, diffhelpers, copies
11 import base85, cmdutil, mdiff, util, diffhelpers, copies
12 import cStringIO, email.Parser, os, re
12 import cStringIO, email.Parser, os, re
13 import sys, tempfile, zlib
13 import sys, tempfile, zlib
14
14
15 gitre = re.compile('diff --git a/(.*) b/(.*)')
15 gitre = re.compile('diff --git a/(.*) b/(.*)')
16
16
17 class PatchError(Exception):
17 class PatchError(Exception):
18 pass
18 pass
19
19
20 class NoHunks(PatchError):
20 class NoHunks(PatchError):
21 pass
21 pass
22
22
23 # helper functions
23 # helper functions
24
24
25 def copyfile(src, dst, basedir):
25 def copyfile(src, dst, basedir):
26 abssrc, absdst = [util.canonpath(basedir, basedir, x) for x in [src, dst]]
26 abssrc, absdst = [util.canonpath(basedir, basedir, x) for x in [src, dst]]
27 if os.path.exists(absdst):
27 if os.path.exists(absdst):
28 raise util.Abort(_("cannot create %s: destination already exists") %
28 raise util.Abort(_("cannot create %s: destination already exists") %
29 dst)
29 dst)
30
30
31 dstdir = os.path.dirname(absdst)
31 dstdir = os.path.dirname(absdst)
32 if dstdir and not os.path.isdir(dstdir):
32 if dstdir and not os.path.isdir(dstdir):
33 try:
33 try:
34 os.makedirs(dstdir)
34 os.makedirs(dstdir)
35 except IOError:
35 except IOError:
36 raise util.Abort(
36 raise util.Abort(
37 _("cannot create %s: unable to create destination directory")
37 _("cannot create %s: unable to create destination directory")
38 % dst)
38 % dst)
39
39
40 util.copyfile(abssrc, absdst)
40 util.copyfile(abssrc, absdst)
41
41
42 # public functions
42 # public functions
43
43
44 def extract(ui, fileobj):
44 def extract(ui, fileobj):
45 '''extract patch from data read from fileobj.
45 '''extract patch from data read from fileobj.
46
46
47 patch can be a normal patch or contained in an email message.
47 patch can be a normal patch or contained in an email message.
48
48
49 return tuple (filename, message, user, date, node, p1, p2).
49 return tuple (filename, message, user, date, node, p1, p2).
50 Any item in the returned tuple can be None. If filename is None,
50 Any item in the returned tuple can be None. If filename is None,
51 fileobj did not contain a patch. Caller must unlink filename when done.'''
51 fileobj did not contain a patch. Caller must unlink filename when done.'''
52
52
53 # attempt to detect the start of a patch
53 # attempt to detect the start of a patch
54 # (this heuristic is borrowed from quilt)
54 # (this heuristic is borrowed from quilt)
55 diffre = re.compile(r'^(?:Index:[ \t]|diff[ \t]|RCS file: |'
55 diffre = re.compile(r'^(?:Index:[ \t]|diff[ \t]|RCS file: |'
56 r'retrieving revision [0-9]+(\.[0-9]+)*$|'
56 r'retrieving revision [0-9]+(\.[0-9]+)*$|'
57 r'(---|\*\*\*)[ \t])', re.MULTILINE)
57 r'(---|\*\*\*)[ \t])', re.MULTILINE)
58
58
59 fd, tmpname = tempfile.mkstemp(prefix='hg-patch-')
59 fd, tmpname = tempfile.mkstemp(prefix='hg-patch-')
60 tmpfp = os.fdopen(fd, 'w')
60 tmpfp = os.fdopen(fd, 'w')
61 try:
61 try:
62 msg = email.Parser.Parser().parse(fileobj)
62 msg = email.Parser.Parser().parse(fileobj)
63
63
64 subject = msg['Subject']
64 subject = msg['Subject']
65 user = msg['From']
65 user = msg['From']
66 if not subject and not user:
66 if not subject and not user:
67 # Not an email, restore parsed headers if any
67 # Not an email, restore parsed headers if any
68 subject = '\n'.join(': '.join(h) for h in msg.items()) + '\n'
68 subject = '\n'.join(': '.join(h) for h in msg.items()) + '\n'
69
69
70 gitsendmail = 'git-send-email' in msg.get('X-Mailer', '')
70 gitsendmail = 'git-send-email' in msg.get('X-Mailer', '')
71 # should try to parse msg['Date']
71 # should try to parse msg['Date']
72 date = None
72 date = None
73 nodeid = None
73 nodeid = None
74 branch = None
74 branch = None
75 parents = []
75 parents = []
76
76
77 if subject:
77 if subject:
78 if subject.startswith('[PATCH'):
78 if subject.startswith('[PATCH'):
79 pend = subject.find(']')
79 pend = subject.find(']')
80 if pend >= 0:
80 if pend >= 0:
81 subject = subject[pend+1:].lstrip()
81 subject = subject[pend+1:].lstrip()
82 subject = subject.replace('\n\t', ' ')
82 subject = subject.replace('\n\t', ' ')
83 ui.debug('Subject: %s\n' % subject)
83 ui.debug('Subject: %s\n' % subject)
84 if user:
84 if user:
85 ui.debug('From: %s\n' % user)
85 ui.debug('From: %s\n' % user)
86 diffs_seen = 0
86 diffs_seen = 0
87 ok_types = ('text/plain', 'text/x-diff', 'text/x-patch')
87 ok_types = ('text/plain', 'text/x-diff', 'text/x-patch')
88 message = ''
88 message = ''
89 for part in msg.walk():
89 for part in msg.walk():
90 content_type = part.get_content_type()
90 content_type = part.get_content_type()
91 ui.debug('Content-Type: %s\n' % content_type)
91 ui.debug('Content-Type: %s\n' % content_type)
92 if content_type not in ok_types:
92 if content_type not in ok_types:
93 continue
93 continue
94 payload = part.get_payload(decode=True)
94 payload = part.get_payload(decode=True)
95 m = diffre.search(payload)
95 m = diffre.search(payload)
96 if m:
96 if m:
97 hgpatch = False
97 hgpatch = False
98 ignoretext = False
98 ignoretext = False
99
99
100 ui.debug('found patch at byte %d\n' % m.start(0))
100 ui.debug('found patch at byte %d\n' % m.start(0))
101 diffs_seen += 1
101 diffs_seen += 1
102 cfp = cStringIO.StringIO()
102 cfp = cStringIO.StringIO()
103 for line in payload[:m.start(0)].splitlines():
103 for line in payload[:m.start(0)].splitlines():
104 if line.startswith('# HG changeset patch'):
104 if line.startswith('# HG changeset patch'):
105 ui.debug('patch generated by hg export\n')
105 ui.debug('patch generated by hg export\n')
106 hgpatch = True
106 hgpatch = True
107 # drop earlier commit message content
107 # drop earlier commit message content
108 cfp.seek(0)
108 cfp.seek(0)
109 cfp.truncate()
109 cfp.truncate()
110 subject = None
110 subject = None
111 elif hgpatch:
111 elif hgpatch:
112 if line.startswith('# User '):
112 if line.startswith('# User '):
113 user = line[7:]
113 user = line[7:]
114 ui.debug('From: %s\n' % user)
114 ui.debug('From: %s\n' % user)
115 elif line.startswith("# Date "):
115 elif line.startswith("# Date "):
116 date = line[7:]
116 date = line[7:]
117 elif line.startswith("# Branch "):
117 elif line.startswith("# Branch "):
118 branch = line[9:]
118 branch = line[9:]
119 elif line.startswith("# Node ID "):
119 elif line.startswith("# Node ID "):
120 nodeid = line[10:]
120 nodeid = line[10:]
121 elif line.startswith("# Parent "):
121 elif line.startswith("# Parent "):
122 parents.append(line[10:])
122 parents.append(line[10:])
123 elif line == '---' and gitsendmail:
123 elif line == '---' and gitsendmail:
124 ignoretext = True
124 ignoretext = True
125 if not line.startswith('# ') and not ignoretext:
125 if not line.startswith('# ') and not ignoretext:
126 cfp.write(line)
126 cfp.write(line)
127 cfp.write('\n')
127 cfp.write('\n')
128 message = cfp.getvalue()
128 message = cfp.getvalue()
129 if tmpfp:
129 if tmpfp:
130 tmpfp.write(payload)
130 tmpfp.write(payload)
131 if not payload.endswith('\n'):
131 if not payload.endswith('\n'):
132 tmpfp.write('\n')
132 tmpfp.write('\n')
133 elif not diffs_seen and message and content_type == 'text/plain':
133 elif not diffs_seen and message and content_type == 'text/plain':
134 message += '\n' + payload
134 message += '\n' + payload
135 except:
135 except:
136 tmpfp.close()
136 tmpfp.close()
137 os.unlink(tmpname)
137 os.unlink(tmpname)
138 raise
138 raise
139
139
140 if subject and not message.startswith(subject):
140 if subject and not message.startswith(subject):
141 message = '%s\n%s' % (subject, message)
141 message = '%s\n%s' % (subject, message)
142 tmpfp.close()
142 tmpfp.close()
143 if not diffs_seen:
143 if not diffs_seen:
144 os.unlink(tmpname)
144 os.unlink(tmpname)
145 return None, message, user, date, branch, None, None, None
145 return None, message, user, date, branch, None, None, None
146 p1 = parents and parents.pop(0) or None
146 p1 = parents and parents.pop(0) or None
147 p2 = parents and parents.pop(0) or None
147 p2 = parents and parents.pop(0) or None
148 return tmpname, message, user, date, branch, nodeid, p1, p2
148 return tmpname, message, user, date, branch, nodeid, p1, p2
149
149
150 GP_PATCH = 1 << 0 # we have to run patch
150 GP_PATCH = 1 << 0 # we have to run patch
151 GP_FILTER = 1 << 1 # there's some copy/rename operation
151 GP_FILTER = 1 << 1 # there's some copy/rename operation
152 GP_BINARY = 1 << 2 # there's a binary patch
152 GP_BINARY = 1 << 2 # there's a binary patch
153
153
154 class patchmeta(object):
154 class patchmeta(object):
155 """Patched file metadata
155 """Patched file metadata
156
156
157 'op' is the performed operation within ADD, DELETE, RENAME, MODIFY
157 'op' is the performed operation within ADD, DELETE, RENAME, MODIFY
158 or COPY. 'path' is patched file path. 'oldpath' is set to the
158 or COPY. 'path' is patched file path. 'oldpath' is set to the
159 origin file when 'op' is either COPY or RENAME, None otherwise. If
159 origin file when 'op' is either COPY or RENAME, None otherwise. If
160 file mode is changed, 'mode' is a tuple (islink, isexec) where
160 file mode is changed, 'mode' is a tuple (islink, isexec) where
161 'islink' is True if the file is a symlink and 'isexec' is True if
161 'islink' is True if the file is a symlink and 'isexec' is True if
162 the file is executable. Otherwise, 'mode' is None.
162 the file is executable. Otherwise, 'mode' is None.
163 """
163 """
164 def __init__(self, path):
164 def __init__(self, path):
165 self.path = path
165 self.path = path
166 self.oldpath = None
166 self.oldpath = None
167 self.mode = None
167 self.mode = None
168 self.op = 'MODIFY'
168 self.op = 'MODIFY'
169 self.lineno = 0
169 self.lineno = 0
170 self.binary = False
170 self.binary = False
171
171
172 def setmode(self, mode):
172 def setmode(self, mode):
173 islink = mode & 020000
173 islink = mode & 020000
174 isexec = mode & 0100
174 isexec = mode & 0100
175 self.mode = (islink, isexec)
175 self.mode = (islink, isexec)
176
176
177 def readgitpatch(lr):
177 def readgitpatch(lr):
178 """extract git-style metadata about patches from <patchname>"""
178 """extract git-style metadata about patches from <patchname>"""
179
179
180 # Filter patch for git information
180 # Filter patch for git information
181 gp = None
181 gp = None
182 gitpatches = []
182 gitpatches = []
183 # Can have a git patch with only metadata, causing patch to complain
183 # Can have a git patch with only metadata, causing patch to complain
184 dopatch = 0
184 dopatch = 0
185
185
186 lineno = 0
186 lineno = 0
187 for line in lr:
187 for line in lr:
188 lineno += 1
188 lineno += 1
189 line = line.rstrip(' \r\n')
189 line = line.rstrip(' \r\n')
190 if line.startswith('diff --git'):
190 if line.startswith('diff --git'):
191 m = gitre.match(line)
191 m = gitre.match(line)
192 if m:
192 if m:
193 if gp:
193 if gp:
194 gitpatches.append(gp)
194 gitpatches.append(gp)
195 dst = m.group(2)
195 dst = m.group(2)
196 gp = patchmeta(dst)
196 gp = patchmeta(dst)
197 gp.lineno = lineno
197 gp.lineno = lineno
198 elif gp:
198 elif gp:
199 if line.startswith('--- '):
199 if line.startswith('--- '):
200 if gp.op in ('COPY', 'RENAME'):
200 if gp.op in ('COPY', 'RENAME'):
201 dopatch |= GP_FILTER
201 dopatch |= GP_FILTER
202 gitpatches.append(gp)
202 gitpatches.append(gp)
203 gp = None
203 gp = None
204 dopatch |= GP_PATCH
204 dopatch |= GP_PATCH
205 continue
205 continue
206 if line.startswith('rename from '):
206 if line.startswith('rename from '):
207 gp.op = 'RENAME'
207 gp.op = 'RENAME'
208 gp.oldpath = line[12:]
208 gp.oldpath = line[12:]
209 elif line.startswith('rename to '):
209 elif line.startswith('rename to '):
210 gp.path = line[10:]
210 gp.path = line[10:]
211 elif line.startswith('copy from '):
211 elif line.startswith('copy from '):
212 gp.op = 'COPY'
212 gp.op = 'COPY'
213 gp.oldpath = line[10:]
213 gp.oldpath = line[10:]
214 elif line.startswith('copy to '):
214 elif line.startswith('copy to '):
215 gp.path = line[8:]
215 gp.path = line[8:]
216 elif line.startswith('deleted file'):
216 elif line.startswith('deleted file'):
217 gp.op = 'DELETE'
217 gp.op = 'DELETE'
218 # is the deleted file a symlink?
218 # is the deleted file a symlink?
219 gp.setmode(int(line[-6:], 8))
219 gp.setmode(int(line[-6:], 8))
220 elif line.startswith('new file mode '):
220 elif line.startswith('new file mode '):
221 gp.op = 'ADD'
221 gp.op = 'ADD'
222 gp.setmode(int(line[-6:], 8))
222 gp.setmode(int(line[-6:], 8))
223 elif line.startswith('new mode '):
223 elif line.startswith('new mode '):
224 gp.setmode(int(line[-6:], 8))
224 gp.setmode(int(line[-6:], 8))
225 elif line.startswith('GIT binary patch'):
225 elif line.startswith('GIT binary patch'):
226 dopatch |= GP_BINARY
226 dopatch |= GP_BINARY
227 gp.binary = True
227 gp.binary = True
228 if gp:
228 if gp:
229 gitpatches.append(gp)
229 gitpatches.append(gp)
230
230
231 if not gitpatches:
231 if not gitpatches:
232 dopatch = GP_PATCH
232 dopatch = GP_PATCH
233
233
234 return (dopatch, gitpatches)
234 return (dopatch, gitpatches)
235
235
236 class linereader(object):
236 class linereader(object):
237 # simple class to allow pushing lines back into the input stream
237 # simple class to allow pushing lines back into the input stream
238 def __init__(self, fp, textmode=False):
238 def __init__(self, fp, textmode=False):
239 self.fp = fp
239 self.fp = fp
240 self.buf = []
240 self.buf = []
241 self.textmode = textmode
241 self.textmode = textmode
242 self.eol = None
242 self.eol = None
243
243
244 def push(self, line):
244 def push(self, line):
245 if line is not None:
245 if line is not None:
246 self.buf.append(line)
246 self.buf.append(line)
247
247
248 def readline(self):
248 def readline(self):
249 if self.buf:
249 if self.buf:
250 l = self.buf[0]
250 l = self.buf[0]
251 del self.buf[0]
251 del self.buf[0]
252 return l
252 return l
253 l = self.fp.readline()
253 l = self.fp.readline()
254 if not self.eol:
254 if not self.eol:
255 if l.endswith('\r\n'):
255 if l.endswith('\r\n'):
256 self.eol = '\r\n'
256 self.eol = '\r\n'
257 elif l.endswith('\n'):
257 elif l.endswith('\n'):
258 self.eol = '\n'
258 self.eol = '\n'
259 if self.textmode and l.endswith('\r\n'):
259 if self.textmode and l.endswith('\r\n'):
260 l = l[:-2] + '\n'
260 l = l[:-2] + '\n'
261 return l
261 return l
262
262
263 def __iter__(self):
263 def __iter__(self):
264 while 1:
264 while 1:
265 l = self.readline()
265 l = self.readline()
266 if not l:
266 if not l:
267 break
267 break
268 yield l
268 yield l
269
269
270 # @@ -start,len +start,len @@ or @@ -start +start @@ if len is 1
270 # @@ -start,len +start,len @@ or @@ -start +start @@ if len is 1
271 unidesc = re.compile('@@ -(\d+)(,(\d+))? \+(\d+)(,(\d+))? @@')
271 unidesc = re.compile('@@ -(\d+)(,(\d+))? \+(\d+)(,(\d+))? @@')
272 contextdesc = re.compile('(---|\*\*\*) (\d+)(,(\d+))? (---|\*\*\*)')
272 contextdesc = re.compile('(---|\*\*\*) (\d+)(,(\d+))? (---|\*\*\*)')
273 eolmodes = ['strict', 'crlf', 'lf', 'auto']
273 eolmodes = ['strict', 'crlf', 'lf', 'auto']
274
274
275 class patchfile(object):
275 class patchfile(object):
276 def __init__(self, ui, fname, opener, missing=False, eolmode='strict'):
276 def __init__(self, ui, fname, opener, missing=False, eolmode='strict'):
277 self.fname = fname
277 self.fname = fname
278 self.eolmode = eolmode
278 self.eolmode = eolmode
279 self.eol = None
279 self.eol = None
280 self.opener = opener
280 self.opener = opener
281 self.ui = ui
281 self.ui = ui
282 self.lines = []
282 self.lines = []
283 self.exists = False
283 self.exists = False
284 self.missing = missing
284 self.missing = missing
285 if not missing:
285 if not missing:
286 try:
286 try:
287 self.lines = self.readlines(fname)
287 self.lines = self.readlines(fname)
288 self.exists = True
288 self.exists = True
289 except IOError:
289 except IOError:
290 pass
290 pass
291 else:
291 else:
292 self.ui.warn(_("unable to find '%s' for patching\n") % self.fname)
292 self.ui.warn(_("unable to find '%s' for patching\n") % self.fname)
293
293
294 self.hash = {}
294 self.hash = {}
295 self.dirty = 0
295 self.dirty = 0
296 self.offset = 0
296 self.offset = 0
297 self.rej = []
297 self.rej = []
298 self.fileprinted = False
298 self.fileprinted = False
299 self.printfile(False)
299 self.printfile(False)
300 self.hunks = 0
300 self.hunks = 0
301
301
302 def readlines(self, fname):
302 def readlines(self, fname):
303 if os.path.islink(fname):
303 if os.path.islink(fname):
304 return [os.readlink(fname)]
304 return [os.readlink(fname)]
305 fp = self.opener(fname, 'r')
305 fp = self.opener(fname, 'r')
306 try:
306 try:
307 lr = linereader(fp, self.eolmode != 'strict')
307 lr = linereader(fp, self.eolmode != 'strict')
308 lines = list(lr)
308 lines = list(lr)
309 self.eol = lr.eol
309 self.eol = lr.eol
310 return lines
310 return lines
311 finally:
311 finally:
312 fp.close()
312 fp.close()
313
313
314 def writelines(self, fname, lines):
314 def writelines(self, fname, lines):
315 # Ensure supplied data ends in fname, being a regular file or
315 # Ensure supplied data ends in fname, being a regular file or
316 # a symlink. updatedir() will -too magically- take care of
316 # a symlink. updatedir() will -too magically- take care of
317 # setting it to the proper type afterwards.
317 # setting it to the proper type afterwards.
318 islink = os.path.islink(fname)
318 islink = os.path.islink(fname)
319 if islink:
319 if islink:
320 fp = cStringIO.StringIO()
320 fp = cStringIO.StringIO()
321 else:
321 else:
322 fp = self.opener(fname, 'w')
322 fp = self.opener(fname, 'w')
323 try:
323 try:
324 if self.eolmode == 'auto' and self.eol:
324 if self.eolmode == 'auto':
325 eol = self.eol
325 eol = self.eol
326 elif self.eolmode == 'crlf':
326 elif self.eolmode == 'crlf':
327 eol = '\r\n'
327 eol = '\r\n'
328 else:
328 else:
329 eol = '\n'
329 eol = '\n'
330
330
331 if self.eolmode != 'strict' and eol != '\n':
331 if self.eolmode != 'strict' and eol and eol != '\n':
332 for l in lines:
332 for l in lines:
333 if l and l[-1] == '\n':
333 if l and l[-1] == '\n':
334 l = l[:-1] + eol
334 l = l[:-1] + eol
335 fp.write(l)
335 fp.write(l)
336 else:
336 else:
337 fp.writelines(lines)
337 fp.writelines(lines)
338 if islink:
338 if islink:
339 self.opener.symlink(fp.getvalue(), fname)
339 self.opener.symlink(fp.getvalue(), fname)
340 finally:
340 finally:
341 fp.close()
341 fp.close()
342
342
343 def unlink(self, fname):
343 def unlink(self, fname):
344 os.unlink(fname)
344 os.unlink(fname)
345
345
346 def printfile(self, warn):
346 def printfile(self, warn):
347 if self.fileprinted:
347 if self.fileprinted:
348 return
348 return
349 if warn or self.ui.verbose:
349 if warn or self.ui.verbose:
350 self.fileprinted = True
350 self.fileprinted = True
351 s = _("patching file %s\n") % self.fname
351 s = _("patching file %s\n") % self.fname
352 if warn:
352 if warn:
353 self.ui.warn(s)
353 self.ui.warn(s)
354 else:
354 else:
355 self.ui.note(s)
355 self.ui.note(s)
356
356
357
357
358 def findlines(self, l, linenum):
358 def findlines(self, l, linenum):
359 # looks through the hash and finds candidate lines. The
359 # looks through the hash and finds candidate lines. The
360 # result is a list of line numbers sorted based on distance
360 # result is a list of line numbers sorted based on distance
361 # from linenum
361 # from linenum
362
362
363 cand = self.hash.get(l, [])
363 cand = self.hash.get(l, [])
364 if len(cand) > 1:
364 if len(cand) > 1:
365 # resort our list of potentials forward then back.
365 # resort our list of potentials forward then back.
366 cand.sort(key=lambda x: abs(x - linenum))
366 cand.sort(key=lambda x: abs(x - linenum))
367 return cand
367 return cand
368
368
369 def hashlines(self):
369 def hashlines(self):
370 self.hash = {}
370 self.hash = {}
371 for x, s in enumerate(self.lines):
371 for x, s in enumerate(self.lines):
372 self.hash.setdefault(s, []).append(x)
372 self.hash.setdefault(s, []).append(x)
373
373
374 def write_rej(self):
374 def write_rej(self):
375 # our rejects are a little different from patch(1). This always
375 # our rejects are a little different from patch(1). This always
376 # creates rejects in the same form as the original patch. A file
376 # creates rejects in the same form as the original patch. A file
377 # header is inserted so that you can run the reject through patch again
377 # header is inserted so that you can run the reject through patch again
378 # without having to type the filename.
378 # without having to type the filename.
379
379
380 if not self.rej:
380 if not self.rej:
381 return
381 return
382
382
383 fname = self.fname + ".rej"
383 fname = self.fname + ".rej"
384 self.ui.warn(
384 self.ui.warn(
385 _("%d out of %d hunks FAILED -- saving rejects to file %s\n") %
385 _("%d out of %d hunks FAILED -- saving rejects to file %s\n") %
386 (len(self.rej), self.hunks, fname))
386 (len(self.rej), self.hunks, fname))
387
387
388 def rejlines():
388 def rejlines():
389 base = os.path.basename(self.fname)
389 base = os.path.basename(self.fname)
390 yield "--- %s\n+++ %s\n" % (base, base)
390 yield "--- %s\n+++ %s\n" % (base, base)
391 for x in self.rej:
391 for x in self.rej:
392 for l in x.hunk:
392 for l in x.hunk:
393 yield l
393 yield l
394 if l[-1] != '\n':
394 if l[-1] != '\n':
395 yield "\n\ No newline at end of file\n"
395 yield "\n\ No newline at end of file\n"
396
396
397 self.writelines(fname, rejlines())
397 self.writelines(fname, rejlines())
398
398
399 def write(self, dest=None):
399 def write(self, dest=None):
400 if not self.dirty:
400 if not self.dirty:
401 return
401 return
402 if not dest:
402 if not dest:
403 dest = self.fname
403 dest = self.fname
404 self.writelines(dest, self.lines)
404 self.writelines(dest, self.lines)
405
405
406 def close(self):
406 def close(self):
407 self.write()
407 self.write()
408 self.write_rej()
408 self.write_rej()
409
409
410 def apply(self, h):
410 def apply(self, h):
411 if not h.complete():
411 if not h.complete():
412 raise PatchError(_("bad hunk #%d %s (%d %d %d %d)") %
412 raise PatchError(_("bad hunk #%d %s (%d %d %d %d)") %
413 (h.number, h.desc, len(h.a), h.lena, len(h.b),
413 (h.number, h.desc, len(h.a), h.lena, len(h.b),
414 h.lenb))
414 h.lenb))
415
415
416 self.hunks += 1
416 self.hunks += 1
417
417
418 if self.missing:
418 if self.missing:
419 self.rej.append(h)
419 self.rej.append(h)
420 return -1
420 return -1
421
421
422 if self.exists and h.createfile():
422 if self.exists and h.createfile():
423 self.ui.warn(_("file %s already exists\n") % self.fname)
423 self.ui.warn(_("file %s already exists\n") % self.fname)
424 self.rej.append(h)
424 self.rej.append(h)
425 return -1
425 return -1
426
426
427 if isinstance(h, binhunk):
427 if isinstance(h, binhunk):
428 if h.rmfile():
428 if h.rmfile():
429 self.unlink(self.fname)
429 self.unlink(self.fname)
430 else:
430 else:
431 self.lines[:] = h.new()
431 self.lines[:] = h.new()
432 self.offset += len(h.new())
432 self.offset += len(h.new())
433 self.dirty = 1
433 self.dirty = 1
434 return 0
434 return 0
435
435
436 horig = h
437 if self.eolmode == 'auto' and self.eol:
438 # If eolmode == 'auto' and target file exists and has line
439 # endings we have to normalize input data before patching.
440 # Otherwise, patchfile operates in 'strict' mode. If
441 # eolmode is set to 'crlf' or 'lf', input hunk is already
442 # normalized to avoid data copy.
443 h = h.getnormalized()
444
436 # fast case first, no offsets, no fuzz
445 # fast case first, no offsets, no fuzz
437 old = h.old()
446 old = h.old()
438 # patch starts counting at 1 unless we are adding the file
447 # patch starts counting at 1 unless we are adding the file
439 if h.starta == 0:
448 if h.starta == 0:
440 start = 0
449 start = 0
441 else:
450 else:
442 start = h.starta + self.offset - 1
451 start = h.starta + self.offset - 1
443 orig_start = start
452 orig_start = start
444 if diffhelpers.testhunk(old, self.lines, start) == 0:
453 if diffhelpers.testhunk(old, self.lines, start) == 0:
445 if h.rmfile():
454 if h.rmfile():
446 self.unlink(self.fname)
455 self.unlink(self.fname)
447 else:
456 else:
448 self.lines[start : start + h.lena] = h.new()
457 self.lines[start : start + h.lena] = h.new()
449 self.offset += h.lenb - h.lena
458 self.offset += h.lenb - h.lena
450 self.dirty = 1
459 self.dirty = 1
451 return 0
460 return 0
452
461
453 # ok, we couldn't match the hunk. Lets look for offsets and fuzz it
462 # ok, we couldn't match the hunk. Lets look for offsets and fuzz it
454 self.hashlines()
463 self.hashlines()
455 if h.hunk[-1][0] != ' ':
464 if h.hunk[-1][0] != ' ':
456 # if the hunk tried to put something at the bottom of the file
465 # if the hunk tried to put something at the bottom of the file
457 # override the start line and use eof here
466 # override the start line and use eof here
458 search_start = len(self.lines)
467 search_start = len(self.lines)
459 else:
468 else:
460 search_start = orig_start
469 search_start = orig_start
461
470
462 for fuzzlen in xrange(3):
471 for fuzzlen in xrange(3):
463 for toponly in [ True, False ]:
472 for toponly in [ True, False ]:
464 old = h.old(fuzzlen, toponly)
473 old = h.old(fuzzlen, toponly)
465
474
466 cand = self.findlines(old[0][1:], search_start)
475 cand = self.findlines(old[0][1:], search_start)
467 for l in cand:
476 for l in cand:
468 if diffhelpers.testhunk(old, self.lines, l) == 0:
477 if diffhelpers.testhunk(old, self.lines, l) == 0:
469 newlines = h.new(fuzzlen, toponly)
478 newlines = h.new(fuzzlen, toponly)
470 self.lines[l : l + len(old)] = newlines
479 self.lines[l : l + len(old)] = newlines
471 self.offset += len(newlines) - len(old)
480 self.offset += len(newlines) - len(old)
472 self.dirty = 1
481 self.dirty = 1
473 if fuzzlen:
482 if fuzzlen:
474 fuzzstr = "with fuzz %d " % fuzzlen
483 fuzzstr = "with fuzz %d " % fuzzlen
475 f = self.ui.warn
484 f = self.ui.warn
476 self.printfile(True)
485 self.printfile(True)
477 else:
486 else:
478 fuzzstr = ""
487 fuzzstr = ""
479 f = self.ui.note
488 f = self.ui.note
480 offset = l - orig_start - fuzzlen
489 offset = l - orig_start - fuzzlen
481 if offset == 1:
490 if offset == 1:
482 msg = _("Hunk #%d succeeded at %d %s"
491 msg = _("Hunk #%d succeeded at %d %s"
483 "(offset %d line).\n")
492 "(offset %d line).\n")
484 else:
493 else:
485 msg = _("Hunk #%d succeeded at %d %s"
494 msg = _("Hunk #%d succeeded at %d %s"
486 "(offset %d lines).\n")
495 "(offset %d lines).\n")
487 f(msg % (h.number, l+1, fuzzstr, offset))
496 f(msg % (h.number, l+1, fuzzstr, offset))
488 return fuzzlen
497 return fuzzlen
489 self.printfile(True)
498 self.printfile(True)
490 self.ui.warn(_("Hunk #%d FAILED at %d\n") % (h.number, orig_start))
499 self.ui.warn(_("Hunk #%d FAILED at %d\n") % (h.number, orig_start))
491 self.rej.append(h)
500 self.rej.append(horig)
492 return -1
501 return -1
493
502
494 class hunk(object):
503 class hunk(object):
495 def __init__(self, desc, num, lr, context, create=False, remove=False):
504 def __init__(self, desc, num, lr, context, create=False, remove=False):
496 self.number = num
505 self.number = num
497 self.desc = desc
506 self.desc = desc
498 self.hunk = [ desc ]
507 self.hunk = [ desc ]
499 self.a = []
508 self.a = []
500 self.b = []
509 self.b = []
501 self.starta = self.lena = None
510 self.starta = self.lena = None
502 self.startb = self.lenb = None
511 self.startb = self.lenb = None
503 if context:
512 if lr is not None:
504 self.read_context_hunk(lr)
513 if context:
505 else:
514 self.read_context_hunk(lr)
506 self.read_unified_hunk(lr)
515 else:
516 self.read_unified_hunk(lr)
507 self.create = create
517 self.create = create
508 self.remove = remove and not create
518 self.remove = remove and not create
509
519
520 def getnormalized(self):
521 """Return a copy with line endings normalized to LF."""
522
523 def normalize(lines):
524 nlines = []
525 for line in lines:
526 if line.endswith('\r\n'):
527 line = line[:-2] + '\n'
528 nlines.append(line)
529 return nlines
530
531 # Dummy object, it is rebuilt manually
532 nh = hunk(self.desc, self.number, None, None, False, False)
533 nh.number = self.number
534 nh.desc = self.desc
535 nh.a = normalize(self.a)
536 nh.b = normalize(self.b)
537 nh.starta = self.starta
538 nh.startb = self.startb
539 nh.lena = self.lena
540 nh.lenb = self.lenb
541 nh.create = self.create
542 nh.remove = self.remove
543 return nh
544
510 def read_unified_hunk(self, lr):
545 def read_unified_hunk(self, lr):
511 m = unidesc.match(self.desc)
546 m = unidesc.match(self.desc)
512 if not m:
547 if not m:
513 raise PatchError(_("bad hunk #%d") % self.number)
548 raise PatchError(_("bad hunk #%d") % self.number)
514 self.starta, foo, self.lena, self.startb, foo2, self.lenb = m.groups()
549 self.starta, foo, self.lena, self.startb, foo2, self.lenb = m.groups()
515 if self.lena is None:
550 if self.lena is None:
516 self.lena = 1
551 self.lena = 1
517 else:
552 else:
518 self.lena = int(self.lena)
553 self.lena = int(self.lena)
519 if self.lenb is None:
554 if self.lenb is None:
520 self.lenb = 1
555 self.lenb = 1
521 else:
556 else:
522 self.lenb = int(self.lenb)
557 self.lenb = int(self.lenb)
523 self.starta = int(self.starta)
558 self.starta = int(self.starta)
524 self.startb = int(self.startb)
559 self.startb = int(self.startb)
525 diffhelpers.addlines(lr, self.hunk, self.lena, self.lenb, self.a, self.b)
560 diffhelpers.addlines(lr, self.hunk, self.lena, self.lenb, self.a, self.b)
526 # if we hit eof before finishing out the hunk, the last line will
561 # if we hit eof before finishing out the hunk, the last line will
527 # be zero length. Lets try to fix it up.
562 # be zero length. Lets try to fix it up.
528 while len(self.hunk[-1]) == 0:
563 while len(self.hunk[-1]) == 0:
529 del self.hunk[-1]
564 del self.hunk[-1]
530 del self.a[-1]
565 del self.a[-1]
531 del self.b[-1]
566 del self.b[-1]
532 self.lena -= 1
567 self.lena -= 1
533 self.lenb -= 1
568 self.lenb -= 1
534
569
535 def read_context_hunk(self, lr):
570 def read_context_hunk(self, lr):
536 self.desc = lr.readline()
571 self.desc = lr.readline()
537 m = contextdesc.match(self.desc)
572 m = contextdesc.match(self.desc)
538 if not m:
573 if not m:
539 raise PatchError(_("bad hunk #%d") % self.number)
574 raise PatchError(_("bad hunk #%d") % self.number)
540 foo, self.starta, foo2, aend, foo3 = m.groups()
575 foo, self.starta, foo2, aend, foo3 = m.groups()
541 self.starta = int(self.starta)
576 self.starta = int(self.starta)
542 if aend is None:
577 if aend is None:
543 aend = self.starta
578 aend = self.starta
544 self.lena = int(aend) - self.starta
579 self.lena = int(aend) - self.starta
545 if self.starta:
580 if self.starta:
546 self.lena += 1
581 self.lena += 1
547 for x in xrange(self.lena):
582 for x in xrange(self.lena):
548 l = lr.readline()
583 l = lr.readline()
549 if l.startswith('---'):
584 if l.startswith('---'):
550 lr.push(l)
585 lr.push(l)
551 break
586 break
552 s = l[2:]
587 s = l[2:]
553 if l.startswith('- ') or l.startswith('! '):
588 if l.startswith('- ') or l.startswith('! '):
554 u = '-' + s
589 u = '-' + s
555 elif l.startswith(' '):
590 elif l.startswith(' '):
556 u = ' ' + s
591 u = ' ' + s
557 else:
592 else:
558 raise PatchError(_("bad hunk #%d old text line %d") %
593 raise PatchError(_("bad hunk #%d old text line %d") %
559 (self.number, x))
594 (self.number, x))
560 self.a.append(u)
595 self.a.append(u)
561 self.hunk.append(u)
596 self.hunk.append(u)
562
597
563 l = lr.readline()
598 l = lr.readline()
564 if l.startswith('\ '):
599 if l.startswith('\ '):
565 s = self.a[-1][:-1]
600 s = self.a[-1][:-1]
566 self.a[-1] = s
601 self.a[-1] = s
567 self.hunk[-1] = s
602 self.hunk[-1] = s
568 l = lr.readline()
603 l = lr.readline()
569 m = contextdesc.match(l)
604 m = contextdesc.match(l)
570 if not m:
605 if not m:
571 raise PatchError(_("bad hunk #%d") % self.number)
606 raise PatchError(_("bad hunk #%d") % self.number)
572 foo, self.startb, foo2, bend, foo3 = m.groups()
607 foo, self.startb, foo2, bend, foo3 = m.groups()
573 self.startb = int(self.startb)
608 self.startb = int(self.startb)
574 if bend is None:
609 if bend is None:
575 bend = self.startb
610 bend = self.startb
576 self.lenb = int(bend) - self.startb
611 self.lenb = int(bend) - self.startb
577 if self.startb:
612 if self.startb:
578 self.lenb += 1
613 self.lenb += 1
579 hunki = 1
614 hunki = 1
580 for x in xrange(self.lenb):
615 for x in xrange(self.lenb):
581 l = lr.readline()
616 l = lr.readline()
582 if l.startswith('\ '):
617 if l.startswith('\ '):
583 s = self.b[-1][:-1]
618 s = self.b[-1][:-1]
584 self.b[-1] = s
619 self.b[-1] = s
585 self.hunk[hunki-1] = s
620 self.hunk[hunki-1] = s
586 continue
621 continue
587 if not l:
622 if not l:
588 lr.push(l)
623 lr.push(l)
589 break
624 break
590 s = l[2:]
625 s = l[2:]
591 if l.startswith('+ ') or l.startswith('! '):
626 if l.startswith('+ ') or l.startswith('! '):
592 u = '+' + s
627 u = '+' + s
593 elif l.startswith(' '):
628 elif l.startswith(' '):
594 u = ' ' + s
629 u = ' ' + s
595 elif len(self.b) == 0:
630 elif len(self.b) == 0:
596 # this can happen when the hunk does not add any lines
631 # this can happen when the hunk does not add any lines
597 lr.push(l)
632 lr.push(l)
598 break
633 break
599 else:
634 else:
600 raise PatchError(_("bad hunk #%d old text line %d") %
635 raise PatchError(_("bad hunk #%d old text line %d") %
601 (self.number, x))
636 (self.number, x))
602 self.b.append(s)
637 self.b.append(s)
603 while True:
638 while True:
604 if hunki >= len(self.hunk):
639 if hunki >= len(self.hunk):
605 h = ""
640 h = ""
606 else:
641 else:
607 h = self.hunk[hunki]
642 h = self.hunk[hunki]
608 hunki += 1
643 hunki += 1
609 if h == u:
644 if h == u:
610 break
645 break
611 elif h.startswith('-'):
646 elif h.startswith('-'):
612 continue
647 continue
613 else:
648 else:
614 self.hunk.insert(hunki-1, u)
649 self.hunk.insert(hunki-1, u)
615 break
650 break
616
651
617 if not self.a:
652 if not self.a:
618 # this happens when lines were only added to the hunk
653 # this happens when lines were only added to the hunk
619 for x in self.hunk:
654 for x in self.hunk:
620 if x.startswith('-') or x.startswith(' '):
655 if x.startswith('-') or x.startswith(' '):
621 self.a.append(x)
656 self.a.append(x)
622 if not self.b:
657 if not self.b:
623 # this happens when lines were only deleted from the hunk
658 # this happens when lines were only deleted from the hunk
624 for x in self.hunk:
659 for x in self.hunk:
625 if x.startswith('+') or x.startswith(' '):
660 if x.startswith('+') or x.startswith(' '):
626 self.b.append(x[1:])
661 self.b.append(x[1:])
627 # @@ -start,len +start,len @@
662 # @@ -start,len +start,len @@
628 self.desc = "@@ -%d,%d +%d,%d @@\n" % (self.starta, self.lena,
663 self.desc = "@@ -%d,%d +%d,%d @@\n" % (self.starta, self.lena,
629 self.startb, self.lenb)
664 self.startb, self.lenb)
630 self.hunk[0] = self.desc
665 self.hunk[0] = self.desc
631
666
632 def fix_newline(self):
667 def fix_newline(self):
633 diffhelpers.fix_newline(self.hunk, self.a, self.b)
668 diffhelpers.fix_newline(self.hunk, self.a, self.b)
634
669
635 def complete(self):
670 def complete(self):
636 return len(self.a) == self.lena and len(self.b) == self.lenb
671 return len(self.a) == self.lena and len(self.b) == self.lenb
637
672
638 def createfile(self):
673 def createfile(self):
639 return self.starta == 0 and self.lena == 0 and self.create
674 return self.starta == 0 and self.lena == 0 and self.create
640
675
641 def rmfile(self):
676 def rmfile(self):
642 return self.startb == 0 and self.lenb == 0 and self.remove
677 return self.startb == 0 and self.lenb == 0 and self.remove
643
678
644 def fuzzit(self, l, fuzz, toponly):
679 def fuzzit(self, l, fuzz, toponly):
645 # this removes context lines from the top and bottom of list 'l'. It
680 # this removes context lines from the top and bottom of list 'l'. It
646 # checks the hunk to make sure only context lines are removed, and then
681 # checks the hunk to make sure only context lines are removed, and then
647 # returns a new shortened list of lines.
682 # returns a new shortened list of lines.
648 fuzz = min(fuzz, len(l)-1)
683 fuzz = min(fuzz, len(l)-1)
649 if fuzz:
684 if fuzz:
650 top = 0
685 top = 0
651 bot = 0
686 bot = 0
652 hlen = len(self.hunk)
687 hlen = len(self.hunk)
653 for x in xrange(hlen-1):
688 for x in xrange(hlen-1):
654 # the hunk starts with the @@ line, so use x+1
689 # the hunk starts with the @@ line, so use x+1
655 if self.hunk[x+1][0] == ' ':
690 if self.hunk[x+1][0] == ' ':
656 top += 1
691 top += 1
657 else:
692 else:
658 break
693 break
659 if not toponly:
694 if not toponly:
660 for x in xrange(hlen-1):
695 for x in xrange(hlen-1):
661 if self.hunk[hlen-bot-1][0] == ' ':
696 if self.hunk[hlen-bot-1][0] == ' ':
662 bot += 1
697 bot += 1
663 else:
698 else:
664 break
699 break
665
700
666 # top and bot now count context in the hunk
701 # top and bot now count context in the hunk
667 # adjust them if either one is short
702 # adjust them if either one is short
668 context = max(top, bot, 3)
703 context = max(top, bot, 3)
669 if bot < context:
704 if bot < context:
670 bot = max(0, fuzz - (context - bot))
705 bot = max(0, fuzz - (context - bot))
671 else:
706 else:
672 bot = min(fuzz, bot)
707 bot = min(fuzz, bot)
673 if top < context:
708 if top < context:
674 top = max(0, fuzz - (context - top))
709 top = max(0, fuzz - (context - top))
675 else:
710 else:
676 top = min(fuzz, top)
711 top = min(fuzz, top)
677
712
678 return l[top:len(l)-bot]
713 return l[top:len(l)-bot]
679 return l
714 return l
680
715
681 def old(self, fuzz=0, toponly=False):
716 def old(self, fuzz=0, toponly=False):
682 return self.fuzzit(self.a, fuzz, toponly)
717 return self.fuzzit(self.a, fuzz, toponly)
683
718
684 def newctrl(self):
719 def newctrl(self):
685 res = []
720 res = []
686 for x in self.hunk:
721 for x in self.hunk:
687 c = x[0]
722 c = x[0]
688 if c == ' ' or c == '+':
723 if c == ' ' or c == '+':
689 res.append(x)
724 res.append(x)
690 return res
725 return res
691
726
692 def new(self, fuzz=0, toponly=False):
727 def new(self, fuzz=0, toponly=False):
693 return self.fuzzit(self.b, fuzz, toponly)
728 return self.fuzzit(self.b, fuzz, toponly)
694
729
695 class binhunk:
730 class binhunk:
696 'A binary patch file. Only understands literals so far.'
731 'A binary patch file. Only understands literals so far.'
697 def __init__(self, gitpatch):
732 def __init__(self, gitpatch):
698 self.gitpatch = gitpatch
733 self.gitpatch = gitpatch
699 self.text = None
734 self.text = None
700 self.hunk = ['GIT binary patch\n']
735 self.hunk = ['GIT binary patch\n']
701
736
702 def createfile(self):
737 def createfile(self):
703 return self.gitpatch.op in ('ADD', 'RENAME', 'COPY')
738 return self.gitpatch.op in ('ADD', 'RENAME', 'COPY')
704
739
705 def rmfile(self):
740 def rmfile(self):
706 return self.gitpatch.op == 'DELETE'
741 return self.gitpatch.op == 'DELETE'
707
742
708 def complete(self):
743 def complete(self):
709 return self.text is not None
744 return self.text is not None
710
745
711 def new(self):
746 def new(self):
712 return [self.text]
747 return [self.text]
713
748
714 def extract(self, lr):
749 def extract(self, lr):
715 line = lr.readline()
750 line = lr.readline()
716 self.hunk.append(line)
751 self.hunk.append(line)
717 while line and not line.startswith('literal '):
752 while line and not line.startswith('literal '):
718 line = lr.readline()
753 line = lr.readline()
719 self.hunk.append(line)
754 self.hunk.append(line)
720 if not line:
755 if not line:
721 raise PatchError(_('could not extract binary patch'))
756 raise PatchError(_('could not extract binary patch'))
722 size = int(line[8:].rstrip())
757 size = int(line[8:].rstrip())
723 dec = []
758 dec = []
724 line = lr.readline()
759 line = lr.readline()
725 self.hunk.append(line)
760 self.hunk.append(line)
726 while len(line) > 1:
761 while len(line) > 1:
727 l = line[0]
762 l = line[0]
728 if l <= 'Z' and l >= 'A':
763 if l <= 'Z' and l >= 'A':
729 l = ord(l) - ord('A') + 1
764 l = ord(l) - ord('A') + 1
730 else:
765 else:
731 l = ord(l) - ord('a') + 27
766 l = ord(l) - ord('a') + 27
732 dec.append(base85.b85decode(line[1:-1])[:l])
767 dec.append(base85.b85decode(line[1:-1])[:l])
733 line = lr.readline()
768 line = lr.readline()
734 self.hunk.append(line)
769 self.hunk.append(line)
735 text = zlib.decompress(''.join(dec))
770 text = zlib.decompress(''.join(dec))
736 if len(text) != size:
771 if len(text) != size:
737 raise PatchError(_('binary patch is %d bytes, not %d') %
772 raise PatchError(_('binary patch is %d bytes, not %d') %
738 len(text), size)
773 len(text), size)
739 self.text = text
774 self.text = text
740
775
741 def parsefilename(str):
776 def parsefilename(str):
742 # --- filename \t|space stuff
777 # --- filename \t|space stuff
743 s = str[4:].rstrip('\r\n')
778 s = str[4:].rstrip('\r\n')
744 i = s.find('\t')
779 i = s.find('\t')
745 if i < 0:
780 if i < 0:
746 i = s.find(' ')
781 i = s.find(' ')
747 if i < 0:
782 if i < 0:
748 return s
783 return s
749 return s[:i]
784 return s[:i]
750
785
751 def selectfile(afile_orig, bfile_orig, hunk, strip):
786 def selectfile(afile_orig, bfile_orig, hunk, strip):
752 def pathstrip(path, count=1):
787 def pathstrip(path, count=1):
753 pathlen = len(path)
788 pathlen = len(path)
754 i = 0
789 i = 0
755 if count == 0:
790 if count == 0:
756 return '', path.rstrip()
791 return '', path.rstrip()
757 while count > 0:
792 while count > 0:
758 i = path.find('/', i)
793 i = path.find('/', i)
759 if i == -1:
794 if i == -1:
760 raise PatchError(_("unable to strip away %d dirs from %s") %
795 raise PatchError(_("unable to strip away %d dirs from %s") %
761 (count, path))
796 (count, path))
762 i += 1
797 i += 1
763 # consume '//' in the path
798 # consume '//' in the path
764 while i < pathlen - 1 and path[i] == '/':
799 while i < pathlen - 1 and path[i] == '/':
765 i += 1
800 i += 1
766 count -= 1
801 count -= 1
767 return path[:i].lstrip(), path[i:].rstrip()
802 return path[:i].lstrip(), path[i:].rstrip()
768
803
769 nulla = afile_orig == "/dev/null"
804 nulla = afile_orig == "/dev/null"
770 nullb = bfile_orig == "/dev/null"
805 nullb = bfile_orig == "/dev/null"
771 abase, afile = pathstrip(afile_orig, strip)
806 abase, afile = pathstrip(afile_orig, strip)
772 gooda = not nulla and util.lexists(afile)
807 gooda = not nulla and util.lexists(afile)
773 bbase, bfile = pathstrip(bfile_orig, strip)
808 bbase, bfile = pathstrip(bfile_orig, strip)
774 if afile == bfile:
809 if afile == bfile:
775 goodb = gooda
810 goodb = gooda
776 else:
811 else:
777 goodb = not nullb and os.path.exists(bfile)
812 goodb = not nullb and os.path.exists(bfile)
778 createfunc = hunk.createfile
813 createfunc = hunk.createfile
779 missing = not goodb and not gooda and not createfunc()
814 missing = not goodb and not gooda and not createfunc()
780
815
781 # some diff programs apparently produce create patches where the
816 # some diff programs apparently produce create patches where the
782 # afile is not /dev/null, but rather the same name as the bfile
817 # afile is not /dev/null, but rather the same name as the bfile
783 if missing and afile == bfile:
818 if missing and afile == bfile:
784 # this isn't very pretty
819 # this isn't very pretty
785 hunk.create = True
820 hunk.create = True
786 if createfunc():
821 if createfunc():
787 missing = False
822 missing = False
788 else:
823 else:
789 hunk.create = False
824 hunk.create = False
790
825
791 # If afile is "a/b/foo" and bfile is "a/b/foo.orig" we assume the
826 # If afile is "a/b/foo" and bfile is "a/b/foo.orig" we assume the
792 # diff is between a file and its backup. In this case, the original
827 # diff is between a file and its backup. In this case, the original
793 # file should be patched (see original mpatch code).
828 # file should be patched (see original mpatch code).
794 isbackup = (abase == bbase and bfile.startswith(afile))
829 isbackup = (abase == bbase and bfile.startswith(afile))
795 fname = None
830 fname = None
796 if not missing:
831 if not missing:
797 if gooda and goodb:
832 if gooda and goodb:
798 fname = isbackup and afile or bfile
833 fname = isbackup and afile or bfile
799 elif gooda:
834 elif gooda:
800 fname = afile
835 fname = afile
801
836
802 if not fname:
837 if not fname:
803 if not nullb:
838 if not nullb:
804 fname = isbackup and afile or bfile
839 fname = isbackup and afile or bfile
805 elif not nulla:
840 elif not nulla:
806 fname = afile
841 fname = afile
807 else:
842 else:
808 raise PatchError(_("undefined source and destination files"))
843 raise PatchError(_("undefined source and destination files"))
809
844
810 return fname, missing
845 return fname, missing
811
846
812 def scangitpatch(lr, firstline):
847 def scangitpatch(lr, firstline):
813 """
848 """
814 Git patches can emit:
849 Git patches can emit:
815 - rename a to b
850 - rename a to b
816 - change b
851 - change b
817 - copy a to c
852 - copy a to c
818 - change c
853 - change c
819
854
820 We cannot apply this sequence as-is, the renamed 'a' could not be
855 We cannot apply this sequence as-is, the renamed 'a' could not be
821 found for it would have been renamed already. And we cannot copy
856 found for it would have been renamed already. And we cannot copy
822 from 'b' instead because 'b' would have been changed already. So
857 from 'b' instead because 'b' would have been changed already. So
823 we scan the git patch for copy and rename commands so we can
858 we scan the git patch for copy and rename commands so we can
824 perform the copies ahead of time.
859 perform the copies ahead of time.
825 """
860 """
826 pos = 0
861 pos = 0
827 try:
862 try:
828 pos = lr.fp.tell()
863 pos = lr.fp.tell()
829 fp = lr.fp
864 fp = lr.fp
830 except IOError:
865 except IOError:
831 fp = cStringIO.StringIO(lr.fp.read())
866 fp = cStringIO.StringIO(lr.fp.read())
832 gitlr = linereader(fp, lr.textmode)
867 gitlr = linereader(fp, lr.textmode)
833 gitlr.push(firstline)
868 gitlr.push(firstline)
834 (dopatch, gitpatches) = readgitpatch(gitlr)
869 (dopatch, gitpatches) = readgitpatch(gitlr)
835 fp.seek(pos)
870 fp.seek(pos)
836 return dopatch, gitpatches
871 return dopatch, gitpatches
837
872
838 def iterhunks(ui, fp, sourcefile=None, textmode=False):
873 def iterhunks(ui, fp, sourcefile=None, textmode=False):
839 """Read a patch and yield the following events:
874 """Read a patch and yield the following events:
840 - ("file", afile, bfile, firsthunk): select a new target file.
875 - ("file", afile, bfile, firsthunk): select a new target file.
841 - ("hunk", hunk): a new hunk is ready to be applied, follows a
876 - ("hunk", hunk): a new hunk is ready to be applied, follows a
842 "file" event.
877 "file" event.
843 - ("git", gitchanges): current diff is in git format, gitchanges
878 - ("git", gitchanges): current diff is in git format, gitchanges
844 maps filenames to gitpatch records. Unique event.
879 maps filenames to gitpatch records. Unique event.
845
880
846 If textmode is True, input line-endings are normalized to LF.
881 If textmode is True, input line-endings are normalized to LF.
847 """
882 """
848 changed = {}
883 changed = {}
849 current_hunk = None
884 current_hunk = None
850 afile = ""
885 afile = ""
851 bfile = ""
886 bfile = ""
852 state = None
887 state = None
853 hunknum = 0
888 hunknum = 0
854 emitfile = False
889 emitfile = False
855 git = False
890 git = False
856
891
857 # our states
892 # our states
858 BFILE = 1
893 BFILE = 1
859 context = None
894 context = None
860 lr = linereader(fp, textmode)
895 lr = linereader(fp, textmode)
861 dopatch = True
896 dopatch = True
862 # gitworkdone is True if a git operation (copy, rename, ...) was
897 # gitworkdone is True if a git operation (copy, rename, ...) was
863 # performed already for the current file. Useful when the file
898 # performed already for the current file. Useful when the file
864 # section may have no hunk.
899 # section may have no hunk.
865 gitworkdone = False
900 gitworkdone = False
866
901
867 while True:
902 while True:
868 newfile = False
903 newfile = False
869 x = lr.readline()
904 x = lr.readline()
870 if not x:
905 if not x:
871 break
906 break
872 if current_hunk:
907 if current_hunk:
873 if x.startswith('\ '):
908 if x.startswith('\ '):
874 current_hunk.fix_newline()
909 current_hunk.fix_newline()
875 yield 'hunk', current_hunk
910 yield 'hunk', current_hunk
876 current_hunk = None
911 current_hunk = None
877 gitworkdone = False
912 gitworkdone = False
878 if ((sourcefile or state == BFILE) and ((not context and x[0] == '@') or
913 if ((sourcefile or state == BFILE) and ((not context and x[0] == '@') or
879 ((context is not False) and x.startswith('***************')))):
914 ((context is not False) and x.startswith('***************')))):
880 try:
915 try:
881 if context is None and x.startswith('***************'):
916 if context is None and x.startswith('***************'):
882 context = True
917 context = True
883 gpatch = changed.get(bfile)
918 gpatch = changed.get(bfile)
884 create = afile == '/dev/null' or gpatch and gpatch.op == 'ADD'
919 create = afile == '/dev/null' or gpatch and gpatch.op == 'ADD'
885 remove = bfile == '/dev/null' or gpatch and gpatch.op == 'DELETE'
920 remove = bfile == '/dev/null' or gpatch and gpatch.op == 'DELETE'
886 current_hunk = hunk(x, hunknum + 1, lr, context, create, remove)
921 current_hunk = hunk(x, hunknum + 1, lr, context, create, remove)
887 except PatchError, err:
922 except PatchError, err:
888 ui.debug(err)
923 ui.debug(err)
889 current_hunk = None
924 current_hunk = None
890 continue
925 continue
891 hunknum += 1
926 hunknum += 1
892 if emitfile:
927 if emitfile:
893 emitfile = False
928 emitfile = False
894 yield 'file', (afile, bfile, current_hunk)
929 yield 'file', (afile, bfile, current_hunk)
895 elif state == BFILE and x.startswith('GIT binary patch'):
930 elif state == BFILE and x.startswith('GIT binary patch'):
896 current_hunk = binhunk(changed[bfile])
931 current_hunk = binhunk(changed[bfile])
897 hunknum += 1
932 hunknum += 1
898 if emitfile:
933 if emitfile:
899 emitfile = False
934 emitfile = False
900 yield 'file', ('a/' + afile, 'b/' + bfile, current_hunk)
935 yield 'file', ('a/' + afile, 'b/' + bfile, current_hunk)
901 current_hunk.extract(lr)
936 current_hunk.extract(lr)
902 elif x.startswith('diff --git'):
937 elif x.startswith('diff --git'):
903 # check for git diff, scanning the whole patch file if needed
938 # check for git diff, scanning the whole patch file if needed
904 m = gitre.match(x)
939 m = gitre.match(x)
905 if m:
940 if m:
906 afile, bfile = m.group(1, 2)
941 afile, bfile = m.group(1, 2)
907 if not git:
942 if not git:
908 git = True
943 git = True
909 dopatch, gitpatches = scangitpatch(lr, x)
944 dopatch, gitpatches = scangitpatch(lr, x)
910 yield 'git', gitpatches
945 yield 'git', gitpatches
911 for gp in gitpatches:
946 for gp in gitpatches:
912 changed[gp.path] = gp
947 changed[gp.path] = gp
913 # else error?
948 # else error?
914 # copy/rename + modify should modify target, not source
949 # copy/rename + modify should modify target, not source
915 gp = changed.get(bfile)
950 gp = changed.get(bfile)
916 if gp and gp.op in ('COPY', 'DELETE', 'RENAME', 'ADD'):
951 if gp and gp.op in ('COPY', 'DELETE', 'RENAME', 'ADD'):
917 afile = bfile
952 afile = bfile
918 gitworkdone = True
953 gitworkdone = True
919 newfile = True
954 newfile = True
920 elif x.startswith('---'):
955 elif x.startswith('---'):
921 # check for a unified diff
956 # check for a unified diff
922 l2 = lr.readline()
957 l2 = lr.readline()
923 if not l2.startswith('+++'):
958 if not l2.startswith('+++'):
924 lr.push(l2)
959 lr.push(l2)
925 continue
960 continue
926 newfile = True
961 newfile = True
927 context = False
962 context = False
928 afile = parsefilename(x)
963 afile = parsefilename(x)
929 bfile = parsefilename(l2)
964 bfile = parsefilename(l2)
930 elif x.startswith('***'):
965 elif x.startswith('***'):
931 # check for a context diff
966 # check for a context diff
932 l2 = lr.readline()
967 l2 = lr.readline()
933 if not l2.startswith('---'):
968 if not l2.startswith('---'):
934 lr.push(l2)
969 lr.push(l2)
935 continue
970 continue
936 l3 = lr.readline()
971 l3 = lr.readline()
937 lr.push(l3)
972 lr.push(l3)
938 if not l3.startswith("***************"):
973 if not l3.startswith("***************"):
939 lr.push(l2)
974 lr.push(l2)
940 continue
975 continue
941 newfile = True
976 newfile = True
942 context = True
977 context = True
943 afile = parsefilename(x)
978 afile = parsefilename(x)
944 bfile = parsefilename(l2)
979 bfile = parsefilename(l2)
945
980
946 if newfile:
981 if newfile:
947 emitfile = True
982 emitfile = True
948 state = BFILE
983 state = BFILE
949 hunknum = 0
984 hunknum = 0
950 if current_hunk:
985 if current_hunk:
951 if current_hunk.complete():
986 if current_hunk.complete():
952 yield 'hunk', current_hunk
987 yield 'hunk', current_hunk
953 else:
988 else:
954 raise PatchError(_("malformed patch %s %s") % (afile,
989 raise PatchError(_("malformed patch %s %s") % (afile,
955 current_hunk.desc))
990 current_hunk.desc))
956
991
957 if hunknum == 0 and dopatch and not gitworkdone:
992 if hunknum == 0 and dopatch and not gitworkdone:
958 raise NoHunks
993 raise NoHunks
959
994
960 def applydiff(ui, fp, changed, strip=1, sourcefile=None, eolmode='strict'):
995 def applydiff(ui, fp, changed, strip=1, sourcefile=None, eolmode='strict'):
961 """
996 """
962 Reads a patch from fp and tries to apply it.
997 Reads a patch from fp and tries to apply it.
963
998
964 The dict 'changed' is filled in with all of the filenames changed
999 The dict 'changed' is filled in with all of the filenames changed
965 by the patch. Returns 0 for a clean patch, -1 if any rejects were
1000 by the patch. Returns 0 for a clean patch, -1 if any rejects were
966 found and 1 if there was any fuzz.
1001 found and 1 if there was any fuzz.
967
1002
968 If 'eolmode' is 'strict', the patch content and patched file are
1003 If 'eolmode' is 'strict', the patch content and patched file are
969 read in binary mode. Otherwise, line endings are ignored when
1004 read in binary mode. Otherwise, line endings are ignored when
970 patching then normalized according to 'eolmode'.
1005 patching then normalized according to 'eolmode'.
971 """
1006 """
972 rejects = 0
1007 rejects = 0
973 err = 0
1008 err = 0
974 current_file = None
1009 current_file = None
975 gitpatches = None
1010 gitpatches = None
976 opener = util.opener(os.getcwd())
1011 opener = util.opener(os.getcwd())
977 textmode = eolmode != 'strict'
1012 # In 'auto' mode, we must preserve original eols if target file
1013 # eols are undefined. Otherwise, hunk data will be normalized
1014 # later.
1015 textmode = eolmode not in ('strict', 'auto')
978
1016
979 def closefile():
1017 def closefile():
980 if not current_file:
1018 if not current_file:
981 return 0
1019 return 0
982 current_file.close()
1020 current_file.close()
983 return len(current_file.rej)
1021 return len(current_file.rej)
984
1022
985 for state, values in iterhunks(ui, fp, sourcefile, textmode):
1023 for state, values in iterhunks(ui, fp, sourcefile, textmode):
986 if state == 'hunk':
1024 if state == 'hunk':
987 if not current_file:
1025 if not current_file:
988 continue
1026 continue
989 current_hunk = values
1027 current_hunk = values
990 ret = current_file.apply(current_hunk)
1028 ret = current_file.apply(current_hunk)
991 if ret >= 0:
1029 if ret >= 0:
992 changed.setdefault(current_file.fname, None)
1030 changed.setdefault(current_file.fname, None)
993 if ret > 0:
1031 if ret > 0:
994 err = 1
1032 err = 1
995 elif state == 'file':
1033 elif state == 'file':
996 rejects += closefile()
1034 rejects += closefile()
997 afile, bfile, first_hunk = values
1035 afile, bfile, first_hunk = values
998 try:
1036 try:
999 if sourcefile:
1037 if sourcefile:
1000 current_file = patchfile(ui, sourcefile, opener, eolmode=eolmode)
1038 current_file = patchfile(ui, sourcefile, opener, eolmode=eolmode)
1001 else:
1039 else:
1002 current_file, missing = selectfile(afile, bfile, first_hunk,
1040 current_file, missing = selectfile(afile, bfile, first_hunk,
1003 strip)
1041 strip)
1004 current_file = patchfile(ui, current_file, opener, missing, eolmode)
1042 current_file = patchfile(ui, current_file, opener, missing, eolmode)
1005 except PatchError, err:
1043 except PatchError, err:
1006 ui.warn(str(err) + '\n')
1044 ui.warn(str(err) + '\n')
1007 current_file, current_hunk = None, None
1045 current_file, current_hunk = None, None
1008 rejects += 1
1046 rejects += 1
1009 continue
1047 continue
1010 elif state == 'git':
1048 elif state == 'git':
1011 gitpatches = values
1049 gitpatches = values
1012 cwd = os.getcwd()
1050 cwd = os.getcwd()
1013 for gp in gitpatches:
1051 for gp in gitpatches:
1014 if gp.op in ('COPY', 'RENAME'):
1052 if gp.op in ('COPY', 'RENAME'):
1015 copyfile(gp.oldpath, gp.path, cwd)
1053 copyfile(gp.oldpath, gp.path, cwd)
1016 changed[gp.path] = gp
1054 changed[gp.path] = gp
1017 else:
1055 else:
1018 raise util.Abort(_('unsupported parser state: %s') % state)
1056 raise util.Abort(_('unsupported parser state: %s') % state)
1019
1057
1020 rejects += closefile()
1058 rejects += closefile()
1021
1059
1022 if rejects:
1060 if rejects:
1023 return -1
1061 return -1
1024 return err
1062 return err
1025
1063
1026 def diffopts(ui, opts=None, untrusted=False):
1064 def diffopts(ui, opts=None, untrusted=False):
1027 def get(key, name=None, getter=ui.configbool):
1065 def get(key, name=None, getter=ui.configbool):
1028 return ((opts and opts.get(key)) or
1066 return ((opts and opts.get(key)) or
1029 getter('diff', name or key, None, untrusted=untrusted))
1067 getter('diff', name or key, None, untrusted=untrusted))
1030 return mdiff.diffopts(
1068 return mdiff.diffopts(
1031 text=opts and opts.get('text'),
1069 text=opts and opts.get('text'),
1032 git=get('git'),
1070 git=get('git'),
1033 nodates=get('nodates'),
1071 nodates=get('nodates'),
1034 showfunc=get('show_function', 'showfunc'),
1072 showfunc=get('show_function', 'showfunc'),
1035 ignorews=get('ignore_all_space', 'ignorews'),
1073 ignorews=get('ignore_all_space', 'ignorews'),
1036 ignorewsamount=get('ignore_space_change', 'ignorewsamount'),
1074 ignorewsamount=get('ignore_space_change', 'ignorewsamount'),
1037 ignoreblanklines=get('ignore_blank_lines', 'ignoreblanklines'),
1075 ignoreblanklines=get('ignore_blank_lines', 'ignoreblanklines'),
1038 context=get('unified', getter=ui.config))
1076 context=get('unified', getter=ui.config))
1039
1077
1040 def updatedir(ui, repo, patches, similarity=0):
1078 def updatedir(ui, repo, patches, similarity=0):
1041 '''Update dirstate after patch application according to metadata'''
1079 '''Update dirstate after patch application according to metadata'''
1042 if not patches:
1080 if not patches:
1043 return
1081 return
1044 copies = []
1082 copies = []
1045 removes = set()
1083 removes = set()
1046 cfiles = patches.keys()
1084 cfiles = patches.keys()
1047 cwd = repo.getcwd()
1085 cwd = repo.getcwd()
1048 if cwd:
1086 if cwd:
1049 cfiles = [util.pathto(repo.root, cwd, f) for f in patches.keys()]
1087 cfiles = [util.pathto(repo.root, cwd, f) for f in patches.keys()]
1050 for f in patches:
1088 for f in patches:
1051 gp = patches[f]
1089 gp = patches[f]
1052 if not gp:
1090 if not gp:
1053 continue
1091 continue
1054 if gp.op == 'RENAME':
1092 if gp.op == 'RENAME':
1055 copies.append((gp.oldpath, gp.path))
1093 copies.append((gp.oldpath, gp.path))
1056 removes.add(gp.oldpath)
1094 removes.add(gp.oldpath)
1057 elif gp.op == 'COPY':
1095 elif gp.op == 'COPY':
1058 copies.append((gp.oldpath, gp.path))
1096 copies.append((gp.oldpath, gp.path))
1059 elif gp.op == 'DELETE':
1097 elif gp.op == 'DELETE':
1060 removes.add(gp.path)
1098 removes.add(gp.path)
1061 for src, dst in copies:
1099 for src, dst in copies:
1062 repo.copy(src, dst)
1100 repo.copy(src, dst)
1063 if (not similarity) and removes:
1101 if (not similarity) and removes:
1064 repo.remove(sorted(removes), True)
1102 repo.remove(sorted(removes), True)
1065 for f in patches:
1103 for f in patches:
1066 gp = patches[f]
1104 gp = patches[f]
1067 if gp and gp.mode:
1105 if gp and gp.mode:
1068 islink, isexec = gp.mode
1106 islink, isexec = gp.mode
1069 dst = repo.wjoin(gp.path)
1107 dst = repo.wjoin(gp.path)
1070 # patch won't create empty files
1108 # patch won't create empty files
1071 if gp.op == 'ADD' and not os.path.exists(dst):
1109 if gp.op == 'ADD' and not os.path.exists(dst):
1072 flags = (isexec and 'x' or '') + (islink and 'l' or '')
1110 flags = (isexec and 'x' or '') + (islink and 'l' or '')
1073 repo.wwrite(gp.path, '', flags)
1111 repo.wwrite(gp.path, '', flags)
1074 elif gp.op != 'DELETE':
1112 elif gp.op != 'DELETE':
1075 util.set_flags(dst, islink, isexec)
1113 util.set_flags(dst, islink, isexec)
1076 cmdutil.addremove(repo, cfiles, similarity=similarity)
1114 cmdutil.addremove(repo, cfiles, similarity=similarity)
1077 files = patches.keys()
1115 files = patches.keys()
1078 files.extend([r for r in removes if r not in files])
1116 files.extend([r for r in removes if r not in files])
1079 return sorted(files)
1117 return sorted(files)
1080
1118
1081 def externalpatch(patcher, args, patchname, ui, strip, cwd, files):
1119 def externalpatch(patcher, args, patchname, ui, strip, cwd, files):
1082 """use <patcher> to apply <patchname> to the working directory.
1120 """use <patcher> to apply <patchname> to the working directory.
1083 returns whether patch was applied with fuzz factor."""
1121 returns whether patch was applied with fuzz factor."""
1084
1122
1085 fuzz = False
1123 fuzz = False
1086 if cwd:
1124 if cwd:
1087 args.append('-d %s' % util.shellquote(cwd))
1125 args.append('-d %s' % util.shellquote(cwd))
1088 fp = util.popen('%s %s -p%d < %s' % (patcher, ' '.join(args), strip,
1126 fp = util.popen('%s %s -p%d < %s' % (patcher, ' '.join(args), strip,
1089 util.shellquote(patchname)))
1127 util.shellquote(patchname)))
1090
1128
1091 for line in fp:
1129 for line in fp:
1092 line = line.rstrip()
1130 line = line.rstrip()
1093 ui.note(line + '\n')
1131 ui.note(line + '\n')
1094 if line.startswith('patching file '):
1132 if line.startswith('patching file '):
1095 pf = util.parse_patch_output(line)
1133 pf = util.parse_patch_output(line)
1096 printed_file = False
1134 printed_file = False
1097 files.setdefault(pf, None)
1135 files.setdefault(pf, None)
1098 elif line.find('with fuzz') >= 0:
1136 elif line.find('with fuzz') >= 0:
1099 fuzz = True
1137 fuzz = True
1100 if not printed_file:
1138 if not printed_file:
1101 ui.warn(pf + '\n')
1139 ui.warn(pf + '\n')
1102 printed_file = True
1140 printed_file = True
1103 ui.warn(line + '\n')
1141 ui.warn(line + '\n')
1104 elif line.find('saving rejects to file') >= 0:
1142 elif line.find('saving rejects to file') >= 0:
1105 ui.warn(line + '\n')
1143 ui.warn(line + '\n')
1106 elif line.find('FAILED') >= 0:
1144 elif line.find('FAILED') >= 0:
1107 if not printed_file:
1145 if not printed_file:
1108 ui.warn(pf + '\n')
1146 ui.warn(pf + '\n')
1109 printed_file = True
1147 printed_file = True
1110 ui.warn(line + '\n')
1148 ui.warn(line + '\n')
1111 code = fp.close()
1149 code = fp.close()
1112 if code:
1150 if code:
1113 raise PatchError(_("patch command failed: %s") %
1151 raise PatchError(_("patch command failed: %s") %
1114 util.explain_exit(code)[0])
1152 util.explain_exit(code)[0])
1115 return fuzz
1153 return fuzz
1116
1154
1117 def internalpatch(patchobj, ui, strip, cwd, files=None, eolmode='strict'):
1155 def internalpatch(patchobj, ui, strip, cwd, files=None, eolmode='strict'):
1118 """use builtin patch to apply <patchobj> to the working directory.
1156 """use builtin patch to apply <patchobj> to the working directory.
1119 returns whether patch was applied with fuzz factor."""
1157 returns whether patch was applied with fuzz factor."""
1120
1158
1121 if files is None:
1159 if files is None:
1122 files = {}
1160 files = {}
1123 if eolmode is None:
1161 if eolmode is None:
1124 eolmode = ui.config('patch', 'eol', 'strict')
1162 eolmode = ui.config('patch', 'eol', 'strict')
1125 if eolmode.lower() not in eolmodes:
1163 if eolmode.lower() not in eolmodes:
1126 raise util.Abort(_('Unsupported line endings type: %s') % eolmode)
1164 raise util.Abort(_('Unsupported line endings type: %s') % eolmode)
1127 eolmode = eolmode.lower()
1165 eolmode = eolmode.lower()
1128
1166
1129 try:
1167 try:
1130 fp = open(patchobj, 'rb')
1168 fp = open(patchobj, 'rb')
1131 except TypeError:
1169 except TypeError:
1132 fp = patchobj
1170 fp = patchobj
1133 if cwd:
1171 if cwd:
1134 curdir = os.getcwd()
1172 curdir = os.getcwd()
1135 os.chdir(cwd)
1173 os.chdir(cwd)
1136 try:
1174 try:
1137 ret = applydiff(ui, fp, files, strip=strip, eolmode=eolmode)
1175 ret = applydiff(ui, fp, files, strip=strip, eolmode=eolmode)
1138 finally:
1176 finally:
1139 if cwd:
1177 if cwd:
1140 os.chdir(curdir)
1178 os.chdir(curdir)
1141 if ret < 0:
1179 if ret < 0:
1142 raise PatchError
1180 raise PatchError
1143 return ret > 0
1181 return ret > 0
1144
1182
1145 def patch(patchname, ui, strip=1, cwd=None, files=None, eolmode='strict'):
1183 def patch(patchname, ui, strip=1, cwd=None, files=None, eolmode='strict'):
1146 """Apply <patchname> to the working directory.
1184 """Apply <patchname> to the working directory.
1147
1185
1148 'eolmode' specifies how end of lines should be handled. It can be:
1186 'eolmode' specifies how end of lines should be handled. It can be:
1149 - 'strict': inputs are read in binary mode, EOLs are preserved
1187 - 'strict': inputs are read in binary mode, EOLs are preserved
1150 - 'crlf': EOLs are ignored when patching and reset to CRLF
1188 - 'crlf': EOLs are ignored when patching and reset to CRLF
1151 - 'lf': EOLs are ignored when patching and reset to LF
1189 - 'lf': EOLs are ignored when patching and reset to LF
1152 - None: get it from user settings, default to 'strict'
1190 - None: get it from user settings, default to 'strict'
1153 'eolmode' is ignored when using an external patcher program.
1191 'eolmode' is ignored when using an external patcher program.
1154
1192
1155 Returns whether patch was applied with fuzz factor.
1193 Returns whether patch was applied with fuzz factor.
1156 """
1194 """
1157 patcher = ui.config('ui', 'patch')
1195 patcher = ui.config('ui', 'patch')
1158 args = []
1196 args = []
1159 if files is None:
1197 if files is None:
1160 files = {}
1198 files = {}
1161 try:
1199 try:
1162 if patcher:
1200 if patcher:
1163 return externalpatch(patcher, args, patchname, ui, strip, cwd,
1201 return externalpatch(patcher, args, patchname, ui, strip, cwd,
1164 files)
1202 files)
1165 else:
1203 else:
1166 try:
1204 try:
1167 return internalpatch(patchname, ui, strip, cwd, files, eolmode)
1205 return internalpatch(patchname, ui, strip, cwd, files, eolmode)
1168 except NoHunks:
1206 except NoHunks:
1169 patcher = util.find_exe('gpatch') or util.find_exe('patch') or 'patch'
1207 patcher = util.find_exe('gpatch') or util.find_exe('patch') or 'patch'
1170 ui.debug('no valid hunks found; trying with %r instead\n' %
1208 ui.debug('no valid hunks found; trying with %r instead\n' %
1171 patcher)
1209 patcher)
1172 if util.needbinarypatch():
1210 if util.needbinarypatch():
1173 args.append('--binary')
1211 args.append('--binary')
1174 return externalpatch(patcher, args, patchname, ui, strip, cwd,
1212 return externalpatch(patcher, args, patchname, ui, strip, cwd,
1175 files)
1213 files)
1176 except PatchError, err:
1214 except PatchError, err:
1177 s = str(err)
1215 s = str(err)
1178 if s:
1216 if s:
1179 raise util.Abort(s)
1217 raise util.Abort(s)
1180 else:
1218 else:
1181 raise util.Abort(_('patch failed to apply'))
1219 raise util.Abort(_('patch failed to apply'))
1182
1220
1183 def b85diff(to, tn):
1221 def b85diff(to, tn):
1184 '''print base85-encoded binary diff'''
1222 '''print base85-encoded binary diff'''
1185 def gitindex(text):
1223 def gitindex(text):
1186 if not text:
1224 if not text:
1187 return '0' * 40
1225 return '0' * 40
1188 l = len(text)
1226 l = len(text)
1189 s = util.sha1('blob %d\0' % l)
1227 s = util.sha1('blob %d\0' % l)
1190 s.update(text)
1228 s.update(text)
1191 return s.hexdigest()
1229 return s.hexdigest()
1192
1230
1193 def fmtline(line):
1231 def fmtline(line):
1194 l = len(line)
1232 l = len(line)
1195 if l <= 26:
1233 if l <= 26:
1196 l = chr(ord('A') + l - 1)
1234 l = chr(ord('A') + l - 1)
1197 else:
1235 else:
1198 l = chr(l - 26 + ord('a') - 1)
1236 l = chr(l - 26 + ord('a') - 1)
1199 return '%c%s\n' % (l, base85.b85encode(line, True))
1237 return '%c%s\n' % (l, base85.b85encode(line, True))
1200
1238
1201 def chunk(text, csize=52):
1239 def chunk(text, csize=52):
1202 l = len(text)
1240 l = len(text)
1203 i = 0
1241 i = 0
1204 while i < l:
1242 while i < l:
1205 yield text[i:i+csize]
1243 yield text[i:i+csize]
1206 i += csize
1244 i += csize
1207
1245
1208 tohash = gitindex(to)
1246 tohash = gitindex(to)
1209 tnhash = gitindex(tn)
1247 tnhash = gitindex(tn)
1210 if tohash == tnhash:
1248 if tohash == tnhash:
1211 return ""
1249 return ""
1212
1250
1213 # TODO: deltas
1251 # TODO: deltas
1214 ret = ['index %s..%s\nGIT binary patch\nliteral %s\n' %
1252 ret = ['index %s..%s\nGIT binary patch\nliteral %s\n' %
1215 (tohash, tnhash, len(tn))]
1253 (tohash, tnhash, len(tn))]
1216 for l in chunk(zlib.compress(tn)):
1254 for l in chunk(zlib.compress(tn)):
1217 ret.append(fmtline(l))
1255 ret.append(fmtline(l))
1218 ret.append('\n')
1256 ret.append('\n')
1219 return ''.join(ret)
1257 return ''.join(ret)
1220
1258
1221 def _addmodehdr(header, omode, nmode):
1259 def _addmodehdr(header, omode, nmode):
1222 if omode != nmode:
1260 if omode != nmode:
1223 header.append('old mode %s\n' % omode)
1261 header.append('old mode %s\n' % omode)
1224 header.append('new mode %s\n' % nmode)
1262 header.append('new mode %s\n' % nmode)
1225
1263
1226 def diff(repo, node1=None, node2=None, match=None, changes=None, opts=None):
1264 def diff(repo, node1=None, node2=None, match=None, changes=None, opts=None):
1227 '''yields diff of changes to files between two nodes, or node and
1265 '''yields diff of changes to files between two nodes, or node and
1228 working directory.
1266 working directory.
1229
1267
1230 if node1 is None, use first dirstate parent instead.
1268 if node1 is None, use first dirstate parent instead.
1231 if node2 is None, compare node1 with working directory.'''
1269 if node2 is None, compare node1 with working directory.'''
1232
1270
1233 if opts is None:
1271 if opts is None:
1234 opts = mdiff.defaultopts
1272 opts = mdiff.defaultopts
1235
1273
1236 if not node1 and not node2:
1274 if not node1 and not node2:
1237 node1 = repo.dirstate.parents()[0]
1275 node1 = repo.dirstate.parents()[0]
1238
1276
1239 def lrugetfilectx():
1277 def lrugetfilectx():
1240 cache = {}
1278 cache = {}
1241 order = []
1279 order = []
1242 def getfilectx(f, ctx):
1280 def getfilectx(f, ctx):
1243 fctx = ctx.filectx(f, filelog=cache.get(f))
1281 fctx = ctx.filectx(f, filelog=cache.get(f))
1244 if f not in cache:
1282 if f not in cache:
1245 if len(cache) > 20:
1283 if len(cache) > 20:
1246 del cache[order.pop(0)]
1284 del cache[order.pop(0)]
1247 cache[f] = fctx.filelog()
1285 cache[f] = fctx.filelog()
1248 else:
1286 else:
1249 order.remove(f)
1287 order.remove(f)
1250 order.append(f)
1288 order.append(f)
1251 return fctx
1289 return fctx
1252 return getfilectx
1290 return getfilectx
1253 getfilectx = lrugetfilectx()
1291 getfilectx = lrugetfilectx()
1254
1292
1255 ctx1 = repo[node1]
1293 ctx1 = repo[node1]
1256 ctx2 = repo[node2]
1294 ctx2 = repo[node2]
1257
1295
1258 if not changes:
1296 if not changes:
1259 changes = repo.status(ctx1, ctx2, match=match)
1297 changes = repo.status(ctx1, ctx2, match=match)
1260 modified, added, removed = changes[:3]
1298 modified, added, removed = changes[:3]
1261
1299
1262 if not modified and not added and not removed:
1300 if not modified and not added and not removed:
1263 return
1301 return
1264
1302
1265 date1 = util.datestr(ctx1.date())
1303 date1 = util.datestr(ctx1.date())
1266 man1 = ctx1.manifest()
1304 man1 = ctx1.manifest()
1267
1305
1268 if repo.ui.quiet:
1306 if repo.ui.quiet:
1269 r = None
1307 r = None
1270 else:
1308 else:
1271 hexfunc = repo.ui.debugflag and hex or short
1309 hexfunc = repo.ui.debugflag and hex or short
1272 r = [hexfunc(node) for node in [node1, node2] if node]
1310 r = [hexfunc(node) for node in [node1, node2] if node]
1273
1311
1274 if opts.git:
1312 if opts.git:
1275 copy, diverge = copies.copies(repo, ctx1, ctx2, repo[nullid])
1313 copy, diverge = copies.copies(repo, ctx1, ctx2, repo[nullid])
1276 copy = copy.copy()
1314 copy = copy.copy()
1277 for k, v in copy.items():
1315 for k, v in copy.items():
1278 copy[v] = k
1316 copy[v] = k
1279
1317
1280 gone = set()
1318 gone = set()
1281 gitmode = {'l': '120000', 'x': '100755', '': '100644'}
1319 gitmode = {'l': '120000', 'x': '100755', '': '100644'}
1282
1320
1283 for f in sorted(modified + added + removed):
1321 for f in sorted(modified + added + removed):
1284 to = None
1322 to = None
1285 tn = None
1323 tn = None
1286 dodiff = True
1324 dodiff = True
1287 header = []
1325 header = []
1288 if f in man1:
1326 if f in man1:
1289 to = getfilectx(f, ctx1).data()
1327 to = getfilectx(f, ctx1).data()
1290 if f not in removed:
1328 if f not in removed:
1291 tn = getfilectx(f, ctx2).data()
1329 tn = getfilectx(f, ctx2).data()
1292 a, b = f, f
1330 a, b = f, f
1293 if opts.git:
1331 if opts.git:
1294 if f in added:
1332 if f in added:
1295 mode = gitmode[ctx2.flags(f)]
1333 mode = gitmode[ctx2.flags(f)]
1296 if f in copy:
1334 if f in copy:
1297 a = copy[f]
1335 a = copy[f]
1298 omode = gitmode[man1.flags(a)]
1336 omode = gitmode[man1.flags(a)]
1299 _addmodehdr(header, omode, mode)
1337 _addmodehdr(header, omode, mode)
1300 if a in removed and a not in gone:
1338 if a in removed and a not in gone:
1301 op = 'rename'
1339 op = 'rename'
1302 gone.add(a)
1340 gone.add(a)
1303 else:
1341 else:
1304 op = 'copy'
1342 op = 'copy'
1305 header.append('%s from %s\n' % (op, a))
1343 header.append('%s from %s\n' % (op, a))
1306 header.append('%s to %s\n' % (op, f))
1344 header.append('%s to %s\n' % (op, f))
1307 to = getfilectx(a, ctx1).data()
1345 to = getfilectx(a, ctx1).data()
1308 else:
1346 else:
1309 header.append('new file mode %s\n' % mode)
1347 header.append('new file mode %s\n' % mode)
1310 if util.binary(tn):
1348 if util.binary(tn):
1311 dodiff = 'binary'
1349 dodiff = 'binary'
1312 elif f in removed:
1350 elif f in removed:
1313 # have we already reported a copy above?
1351 # have we already reported a copy above?
1314 if f in copy and copy[f] in added and copy[copy[f]] == f:
1352 if f in copy and copy[f] in added and copy[copy[f]] == f:
1315 dodiff = False
1353 dodiff = False
1316 else:
1354 else:
1317 header.append('deleted file mode %s\n' %
1355 header.append('deleted file mode %s\n' %
1318 gitmode[man1.flags(f)])
1356 gitmode[man1.flags(f)])
1319 else:
1357 else:
1320 omode = gitmode[man1.flags(f)]
1358 omode = gitmode[man1.flags(f)]
1321 nmode = gitmode[ctx2.flags(f)]
1359 nmode = gitmode[ctx2.flags(f)]
1322 _addmodehdr(header, omode, nmode)
1360 _addmodehdr(header, omode, nmode)
1323 if util.binary(to) or util.binary(tn):
1361 if util.binary(to) or util.binary(tn):
1324 dodiff = 'binary'
1362 dodiff = 'binary'
1325 r = None
1363 r = None
1326 header.insert(0, mdiff.diffline(r, a, b, opts))
1364 header.insert(0, mdiff.diffline(r, a, b, opts))
1327 if dodiff:
1365 if dodiff:
1328 if dodiff == 'binary':
1366 if dodiff == 'binary':
1329 text = b85diff(to, tn)
1367 text = b85diff(to, tn)
1330 else:
1368 else:
1331 text = mdiff.unidiff(to, date1,
1369 text = mdiff.unidiff(to, date1,
1332 # ctx2 date may be dynamic
1370 # ctx2 date may be dynamic
1333 tn, util.datestr(ctx2.date()),
1371 tn, util.datestr(ctx2.date()),
1334 a, b, r, opts=opts)
1372 a, b, r, opts=opts)
1335 if header and (text or len(header) > 1):
1373 if header and (text or len(header) > 1):
1336 yield ''.join(header)
1374 yield ''.join(header)
1337 if text:
1375 if text:
1338 yield text
1376 yield text
1339
1377
1340 def export(repo, revs, template='hg-%h.patch', fp=None, switch_parent=False,
1378 def export(repo, revs, template='hg-%h.patch', fp=None, switch_parent=False,
1341 opts=None):
1379 opts=None):
1342 '''export changesets as hg patches.'''
1380 '''export changesets as hg patches.'''
1343
1381
1344 total = len(revs)
1382 total = len(revs)
1345 revwidth = max([len(str(rev)) for rev in revs])
1383 revwidth = max([len(str(rev)) for rev in revs])
1346
1384
1347 def single(rev, seqno, fp):
1385 def single(rev, seqno, fp):
1348 ctx = repo[rev]
1386 ctx = repo[rev]
1349 node = ctx.node()
1387 node = ctx.node()
1350 parents = [p.node() for p in ctx.parents() if p]
1388 parents = [p.node() for p in ctx.parents() if p]
1351 branch = ctx.branch()
1389 branch = ctx.branch()
1352 if switch_parent:
1390 if switch_parent:
1353 parents.reverse()
1391 parents.reverse()
1354 prev = (parents and parents[0]) or nullid
1392 prev = (parents and parents[0]) or nullid
1355
1393
1356 if not fp:
1394 if not fp:
1357 fp = cmdutil.make_file(repo, template, node, total=total,
1395 fp = cmdutil.make_file(repo, template, node, total=total,
1358 seqno=seqno, revwidth=revwidth,
1396 seqno=seqno, revwidth=revwidth,
1359 mode='ab')
1397 mode='ab')
1360 if fp != sys.stdout and hasattr(fp, 'name'):
1398 if fp != sys.stdout and hasattr(fp, 'name'):
1361 repo.ui.note("%s\n" % fp.name)
1399 repo.ui.note("%s\n" % fp.name)
1362
1400
1363 fp.write("# HG changeset patch\n")
1401 fp.write("# HG changeset patch\n")
1364 fp.write("# User %s\n" % ctx.user())
1402 fp.write("# User %s\n" % ctx.user())
1365 fp.write("# Date %d %d\n" % ctx.date())
1403 fp.write("# Date %d %d\n" % ctx.date())
1366 if branch and (branch != 'default'):
1404 if branch and (branch != 'default'):
1367 fp.write("# Branch %s\n" % branch)
1405 fp.write("# Branch %s\n" % branch)
1368 fp.write("# Node ID %s\n" % hex(node))
1406 fp.write("# Node ID %s\n" % hex(node))
1369 fp.write("# Parent %s\n" % hex(prev))
1407 fp.write("# Parent %s\n" % hex(prev))
1370 if len(parents) > 1:
1408 if len(parents) > 1:
1371 fp.write("# Parent %s\n" % hex(parents[1]))
1409 fp.write("# Parent %s\n" % hex(parents[1]))
1372 fp.write(ctx.description().rstrip())
1410 fp.write(ctx.description().rstrip())
1373 fp.write("\n\n")
1411 fp.write("\n\n")
1374
1412
1375 for chunk in diff(repo, prev, node, opts=opts):
1413 for chunk in diff(repo, prev, node, opts=opts):
1376 fp.write(chunk)
1414 fp.write(chunk)
1377
1415
1378 for seqno, rev in enumerate(revs):
1416 for seqno, rev in enumerate(revs):
1379 single(rev, seqno+1, fp)
1417 single(rev, seqno+1, fp)
1380
1418
1381 def diffstatdata(lines):
1419 def diffstatdata(lines):
1382 filename, adds, removes = None, 0, 0
1420 filename, adds, removes = None, 0, 0
1383 for line in lines:
1421 for line in lines:
1384 if line.startswith('diff'):
1422 if line.startswith('diff'):
1385 if filename:
1423 if filename:
1386 isbinary = adds == 0 and removes == 0
1424 isbinary = adds == 0 and removes == 0
1387 yield (filename, adds, removes, isbinary)
1425 yield (filename, adds, removes, isbinary)
1388 # set numbers to 0 anyway when starting new file
1426 # set numbers to 0 anyway when starting new file
1389 adds, removes = 0, 0
1427 adds, removes = 0, 0
1390 if line.startswith('diff --git'):
1428 if line.startswith('diff --git'):
1391 filename = gitre.search(line).group(1)
1429 filename = gitre.search(line).group(1)
1392 else:
1430 else:
1393 # format: "diff -r ... -r ... filename"
1431 # format: "diff -r ... -r ... filename"
1394 filename = line.split(None, 5)[-1]
1432 filename = line.split(None, 5)[-1]
1395 elif line.startswith('+') and not line.startswith('+++'):
1433 elif line.startswith('+') and not line.startswith('+++'):
1396 adds += 1
1434 adds += 1
1397 elif line.startswith('-') and not line.startswith('---'):
1435 elif line.startswith('-') and not line.startswith('---'):
1398 removes += 1
1436 removes += 1
1399 if filename:
1437 if filename:
1400 isbinary = adds == 0 and removes == 0
1438 isbinary = adds == 0 and removes == 0
1401 yield (filename, adds, removes, isbinary)
1439 yield (filename, adds, removes, isbinary)
1402
1440
1403 def diffstat(lines, width=80, git=False):
1441 def diffstat(lines, width=80, git=False):
1404 output = []
1442 output = []
1405 stats = list(diffstatdata(lines))
1443 stats = list(diffstatdata(lines))
1406
1444
1407 maxtotal, maxname = 0, 0
1445 maxtotal, maxname = 0, 0
1408 totaladds, totalremoves = 0, 0
1446 totaladds, totalremoves = 0, 0
1409 hasbinary = False
1447 hasbinary = False
1410 for filename, adds, removes, isbinary in stats:
1448 for filename, adds, removes, isbinary in stats:
1411 totaladds += adds
1449 totaladds += adds
1412 totalremoves += removes
1450 totalremoves += removes
1413 maxname = max(maxname, len(filename))
1451 maxname = max(maxname, len(filename))
1414 maxtotal = max(maxtotal, adds+removes)
1452 maxtotal = max(maxtotal, adds+removes)
1415 if isbinary:
1453 if isbinary:
1416 hasbinary = True
1454 hasbinary = True
1417
1455
1418 countwidth = len(str(maxtotal))
1456 countwidth = len(str(maxtotal))
1419 if hasbinary and countwidth < 3:
1457 if hasbinary and countwidth < 3:
1420 countwidth = 3
1458 countwidth = 3
1421 graphwidth = width - countwidth - maxname - 6
1459 graphwidth = width - countwidth - maxname - 6
1422 if graphwidth < 10:
1460 if graphwidth < 10:
1423 graphwidth = 10
1461 graphwidth = 10
1424
1462
1425 def scale(i):
1463 def scale(i):
1426 if maxtotal <= graphwidth:
1464 if maxtotal <= graphwidth:
1427 return i
1465 return i
1428 # If diffstat runs out of room it doesn't print anything,
1466 # If diffstat runs out of room it doesn't print anything,
1429 # which isn't very useful, so always print at least one + or -
1467 # which isn't very useful, so always print at least one + or -
1430 # if there were at least some changes.
1468 # if there were at least some changes.
1431 return max(i * graphwidth // maxtotal, int(bool(i)))
1469 return max(i * graphwidth // maxtotal, int(bool(i)))
1432
1470
1433 for filename, adds, removes, isbinary in stats:
1471 for filename, adds, removes, isbinary in stats:
1434 if git and isbinary:
1472 if git and isbinary:
1435 count = 'Bin'
1473 count = 'Bin'
1436 else:
1474 else:
1437 count = adds + removes
1475 count = adds + removes
1438 pluses = '+' * scale(adds)
1476 pluses = '+' * scale(adds)
1439 minuses = '-' * scale(removes)
1477 minuses = '-' * scale(removes)
1440 output.append(' %-*s | %*s %s%s\n' % (maxname, filename, countwidth,
1478 output.append(' %-*s | %*s %s%s\n' % (maxname, filename, countwidth,
1441 count, pluses, minuses))
1479 count, pluses, minuses))
1442
1480
1443 if stats:
1481 if stats:
1444 output.append(_(' %d files changed, %d insertions(+), %d deletions(-)\n')
1482 output.append(_(' %d files changed, %d insertions(+), %d deletions(-)\n')
1445 % (len(stats), totaladds, totalremoves))
1483 % (len(stats), totaladds, totalremoves))
1446
1484
1447 return ''.join(output)
1485 return ''.join(output)
@@ -1,70 +1,85 b''
1 #!/bin/sh
1 #!/bin/sh
2
2
3 cat > makepatch.py <<EOF
3 cat > makepatch.py <<EOF
4 f = file('eol.diff', 'wb')
4 f = file('eol.diff', 'wb')
5 w = f.write
5 w = f.write
6 w('test message\n')
6 w('test message\n')
7 w('diff --git a/a b/a\n')
7 w('diff --git a/a b/a\n')
8 w('--- a/a\n')
8 w('--- a/a\n')
9 w('+++ b/a\n')
9 w('+++ b/a\n')
10 w('@@ -1,5 +1,5 @@\n')
10 w('@@ -1,5 +1,5 @@\n')
11 w(' a\n')
11 w(' a\n')
12 w('-bbb\r\n')
12 w('-bbb\r\n')
13 w('+yyyy\r\n')
13 w('+yyyy\r\n')
14 w(' cc\r\n')
14 w(' cc\r\n')
15 w(' \n')
15 w(' \n')
16 w(' d\n')
16 w(' d\n')
17 w('-e\n')
17 w('-e\n')
18 w('\ No newline at end of file\n')
18 w('\ No newline at end of file\n')
19 w('+z\r\n')
19 w('+z\r\n')
20 w('\ No newline at end of file\r\n')
20 w('\ No newline at end of file\r\n')
21 EOF
21 EOF
22
22
23 hg init repo
23 hg init repo
24 cd repo
24 cd repo
25 echo '\.diff' > .hgignore
25 echo '\.diff' > .hgignore
26
26
27 # Test different --eol values
27 # Test different --eol values
28 python -c 'file("a", "wb").write("a\nbbb\ncc\n\nd\ne")'
28 python -c 'file("a", "wb").write("a\nbbb\ncc\n\nd\ne")'
29 hg ci -Am adda
29 hg ci -Am adda
30 python ../makepatch.py
30 python ../makepatch.py
31
31
32 echo % invalid eol
32 echo % invalid eol
33 hg --config patch.eol='LFCR' import eol.diff
33 hg --config patch.eol='LFCR' import eol.diff
34 hg revert -a
34 hg revert -a
35
35
36 echo % force LF
36 echo % force LF
37 hg --traceback --config patch.eol='LF' import eol.diff
37 hg --traceback --config patch.eol='LF' import eol.diff
38 python -c 'print repr(file("a","rb").read())'
38 python -c 'print repr(file("a","rb").read())'
39 hg st
39 hg st
40
40
41 echo % force CRLF
41 echo % force CRLF
42 hg up -C 0
42 hg up -C 0
43 hg --traceback --config patch.eol='CRLF' import eol.diff
43 hg --traceback --config patch.eol='CRLF' import eol.diff
44 python -c 'print repr(file("a","rb").read())'
44 python -c 'print repr(file("a","rb").read())'
45 hg st
45 hg st
46
46
47 echo % auto EOL on LF file
47 echo % auto EOL on LF file
48 hg up -C 0
48 hg up -C 0
49 hg --traceback --config patch.eol='auto' import eol.diff
49 hg --traceback --config patch.eol='auto' import eol.diff
50 python -c 'print repr(file("a","rb").read())'
50 python -c 'print repr(file("a","rb").read())'
51 hg st
51 hg st
52
52
53 echo % auto EOL on CRLF file
53 echo % auto EOL on CRLF file
54 python -c 'file("a", "wb").write("a\r\nbbb\r\ncc\r\n\r\nd\r\ne")'
54 python -c 'file("a", "wb").write("a\r\nbbb\r\ncc\r\n\r\nd\r\ne")'
55 hg commit -m 'switch EOLs in a'
55 hg commit -m 'switch EOLs in a'
56 hg --traceback --config patch.eol='auto' import eol.diff
56 hg --traceback --config patch.eol='auto' import eol.diff
57 python -c 'print repr(file("a","rb").read())'
57 python -c 'print repr(file("a","rb").read())'
58 hg st
58 hg st
59
59
60 echo % auto EOL on new file or source without any EOL
61 python -c 'file("noeol", "wb").write("noeol")'
62 hg add noeol
63 hg commit -m 'add noeol'
64 python -c 'file("noeol", "wb").write("noeol\r\nnoeol\n")'
65 python -c 'file("neweol", "wb").write("neweol\nneweol\r\n")'
66 hg add neweol
67 hg diff --git > noeol.diff
68 hg revert --no-backup noeol neweol
69 rm neweol
70 hg --traceback --config patch.eol='auto' import -m noeol noeol.diff
71 python -c 'print repr(file("noeol","rb").read())'
72 python -c 'print repr(file("neweol","rb").read())'
73 hg st
74
60 # Test --eol and binary patches
75 # Test --eol and binary patches
61 python -c 'file("b", "wb").write("a\x00\nb")'
76 python -c 'file("b", "wb").write("a\x00\nb")'
62 hg ci -Am addb
77 hg ci -Am addb
63 python -c 'file("b", "wb").write("a\x00\nc")'
78 python -c 'file("b", "wb").write("a\x00\nc")'
64 hg diff --git > bin.diff
79 hg diff --git > bin.diff
65 hg revert --no-backup b
80 hg revert --no-backup b
66 echo % binary patch with --eol
81 echo % binary patch with --eol
67 hg import --config patch.eol='CRLF' -m changeb bin.diff
82 hg import --config patch.eol='CRLF' -m changeb bin.diff
68 python -c 'print repr(file("b","rb").read())'
83 python -c 'print repr(file("b","rb").read())'
69 hg st
84 hg st
70 cd ..
85 cd ..
@@ -1,23 +1,27 b''
1 adding .hgignore
1 adding .hgignore
2 adding a
2 adding a
3 % invalid eol
3 % invalid eol
4 applying eol.diff
4 applying eol.diff
5 abort: Unsupported line endings type: LFCR
5 abort: Unsupported line endings type: LFCR
6 % force LF
6 % force LF
7 applying eol.diff
7 applying eol.diff
8 'a\nyyyy\ncc\n\nd\ne'
8 'a\nyyyy\ncc\n\nd\ne'
9 % force CRLF
9 % force CRLF
10 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
10 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
11 applying eol.diff
11 applying eol.diff
12 'a\r\nyyyy\r\ncc\r\n\r\nd\r\ne'
12 'a\r\nyyyy\r\ncc\r\n\r\nd\r\ne'
13 % auto EOL on LF file
13 % auto EOL on LF file
14 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
14 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
15 applying eol.diff
15 applying eol.diff
16 'a\nyyyy\ncc\n\nd\ne'
16 'a\nyyyy\ncc\n\nd\ne'
17 % auto EOL on CRLF file
17 % auto EOL on CRLF file
18 applying eol.diff
18 applying eol.diff
19 'a\r\nyyyy\r\ncc\r\n\r\nd\r\ne'
19 'a\r\nyyyy\r\ncc\r\n\r\nd\r\ne'
20 % auto EOL on new file or source without any EOL
21 applying noeol.diff
22 'noeol\r\nnoeol\n'
23 'neweol\nneweol\r\n'
20 adding b
24 adding b
21 % binary patch with --eol
25 % binary patch with --eol
22 applying bin.diff
26 applying bin.diff
23 'a\x00\nc'
27 'a\x00\nc'
General Comments 0
You need to be logged in to leave comments. Login now