##// END OF EJS Templates
Expand '~' in path to extensions.
Markus F.X.J. Oberhumer -
r2387:62ce297f default
parent child Browse files
Show More
@@ -1,420 +1,428 b''
1 HGRC(5)
1 HGRC(5)
2 =======
2 =======
3 Bryan O'Sullivan <bos@serpentine.com>
3 Bryan O'Sullivan <bos@serpentine.com>
4
4
5 NAME
5 NAME
6 ----
6 ----
7 hgrc - configuration files for Mercurial
7 hgrc - configuration files for Mercurial
8
8
9 SYNOPSIS
9 SYNOPSIS
10 --------
10 --------
11
11
12 The Mercurial system uses a set of configuration files to control
12 The Mercurial system uses a set of configuration files to control
13 aspects of its behaviour.
13 aspects of its behaviour.
14
14
15 FILES
15 FILES
16 -----
16 -----
17
17
18 Mercurial reads configuration data from several files, if they exist.
18 Mercurial reads configuration data from several files, if they exist.
19 The names of these files depend on the system on which Mercurial is
19 The names of these files depend on the system on which Mercurial is
20 installed.
20 installed.
21
21
22 (Unix) <install-root>/etc/mercurial/hgrc.d/*.rc::
22 (Unix) <install-root>/etc/mercurial/hgrc.d/*.rc::
23 (Unix) <install-root>/etc/mercurial/hgrc::
23 (Unix) <install-root>/etc/mercurial/hgrc::
24 Per-installation configuration files, searched for in the
24 Per-installation configuration files, searched for in the
25 directory where Mercurial is installed. For example, if installed
25 directory where Mercurial is installed. For example, if installed
26 in /shared/tools, Mercurial will look in
26 in /shared/tools, Mercurial will look in
27 /shared/tools/etc/mercurial/hgrc. Options in these files apply to
27 /shared/tools/etc/mercurial/hgrc. Options in these files apply to
28 all Mercurial commands executed by any user in any directory.
28 all Mercurial commands executed by any user in any directory.
29
29
30 (Unix) /etc/mercurial/hgrc.d/*.rc::
30 (Unix) /etc/mercurial/hgrc.d/*.rc::
31 (Unix) /etc/mercurial/hgrc::
31 (Unix) /etc/mercurial/hgrc::
32 (Windows) C:\Mercurial\Mercurial.ini::
32 (Windows) C:\Mercurial\Mercurial.ini::
33 Per-system configuration files, for the system on which Mercurial
33 Per-system configuration files, for the system on which Mercurial
34 is running. Options in these files apply to all Mercurial
34 is running. Options in these files apply to all Mercurial
35 commands executed by any user in any directory. Options in these
35 commands executed by any user in any directory. Options in these
36 files override per-installation options.
36 files override per-installation options.
37
37
38 (Unix) $HOME/.hgrc::
38 (Unix) $HOME/.hgrc::
39 (Windows) C:\Documents and Settings\USERNAME\Mercurial.ini::
39 (Windows) C:\Documents and Settings\USERNAME\Mercurial.ini::
40 (Windows) $HOME\Mercurial.ini::
40 (Windows) $HOME\Mercurial.ini::
41 Per-user configuration file, for the user running Mercurial.
41 Per-user configuration file, for the user running Mercurial.
42 Options in this file apply to all Mercurial commands executed by
42 Options in this file apply to all Mercurial commands executed by
43 any user in any directory. Options in this file override
43 any user in any directory. Options in this file override
44 per-installation and per-system options.
44 per-installation and per-system options.
45 On Windows system, one of these is chosen exclusively according
45 On Windows system, one of these is chosen exclusively according
46 to definition of HOME environment variable.
46 to definition of HOME environment variable.
47
47
48 (Unix, Windows) <repo>/.hg/hgrc::
48 (Unix, Windows) <repo>/.hg/hgrc::
49 Per-repository configuration options that only apply in a
49 Per-repository configuration options that only apply in a
50 particular repository. This file is not version-controlled, and
50 particular repository. This file is not version-controlled, and
51 will not get transferred during a "clone" operation. Options in
51 will not get transferred during a "clone" operation. Options in
52 this file override options in all other configuration files.
52 this file override options in all other configuration files.
53
53
54 SYNTAX
54 SYNTAX
55 ------
55 ------
56
56
57 A configuration file consists of sections, led by a "[section]" header
57 A configuration file consists of sections, led by a "[section]" header
58 and followed by "name: value" entries; "name=value" is also accepted.
58 and followed by "name: value" entries; "name=value" is also accepted.
59
59
60 [spam]
60 [spam]
61 eggs=ham
61 eggs=ham
62 green=
62 green=
63 eggs
63 eggs
64
64
65 Each line contains one entry. If the lines that follow are indented,
65 Each line contains one entry. If the lines that follow are indented,
66 they are treated as continuations of that entry.
66 they are treated as continuations of that entry.
67
67
68 Leading whitespace is removed from values. Empty lines are skipped.
68 Leading whitespace is removed from values. Empty lines are skipped.
69
69
70 The optional values can contain format strings which refer to other
70 The optional values can contain format strings which refer to other
71 values in the same section, or values in a special DEFAULT section.
71 values in the same section, or values in a special DEFAULT section.
72
72
73 Lines beginning with "#" or ";" are ignored and may be used to provide
73 Lines beginning with "#" or ";" are ignored and may be used to provide
74 comments.
74 comments.
75
75
76 SECTIONS
76 SECTIONS
77 --------
77 --------
78
78
79 This section describes the different sections that may appear in a
79 This section describes the different sections that may appear in a
80 Mercurial "hgrc" file, the purpose of each section, its possible
80 Mercurial "hgrc" file, the purpose of each section, its possible
81 keys, and their possible values.
81 keys, and their possible values.
82
82
83 decode/encode::
83 decode/encode::
84 Filters for transforming files on checkout/checkin. This would
84 Filters for transforming files on checkout/checkin. This would
85 typically be used for newline processing or other
85 typically be used for newline processing or other
86 localization/canonicalization of files.
86 localization/canonicalization of files.
87
87
88 Filters consist of a filter pattern followed by a filter command.
88 Filters consist of a filter pattern followed by a filter command.
89 Filter patterns are globs by default, rooted at the repository
89 Filter patterns are globs by default, rooted at the repository
90 root. For example, to match any file ending in ".txt" in the root
90 root. For example, to match any file ending in ".txt" in the root
91 directory only, use the pattern "*.txt". To match any file ending
91 directory only, use the pattern "*.txt". To match any file ending
92 in ".c" anywhere in the repository, use the pattern "**.c".
92 in ".c" anywhere in the repository, use the pattern "**.c".
93
93
94 The filter command can start with a specifier, either "pipe:" or
94 The filter command can start with a specifier, either "pipe:" or
95 "tempfile:". If no specifier is given, "pipe:" is used by default.
95 "tempfile:". If no specifier is given, "pipe:" is used by default.
96
96
97 A "pipe:" command must accept data on stdin and return the
97 A "pipe:" command must accept data on stdin and return the
98 transformed data on stdout.
98 transformed data on stdout.
99
99
100 Pipe example:
100 Pipe example:
101
101
102 [encode]
102 [encode]
103 # uncompress gzip files on checkin to improve delta compression
103 # uncompress gzip files on checkin to improve delta compression
104 # note: not necessarily a good idea, just an example
104 # note: not necessarily a good idea, just an example
105 *.gz = pipe: gunzip
105 *.gz = pipe: gunzip
106
106
107 [decode]
107 [decode]
108 # recompress gzip files when writing them to the working dir (we
108 # recompress gzip files when writing them to the working dir (we
109 # can safely omit "pipe:", because it's the default)
109 # can safely omit "pipe:", because it's the default)
110 *.gz = gzip
110 *.gz = gzip
111
111
112 A "tempfile:" command is a template. The string INFILE is replaced
112 A "tempfile:" command is a template. The string INFILE is replaced
113 with the name of a temporary file that contains the data to be
113 with the name of a temporary file that contains the data to be
114 filtered by the command. The string OUTFILE is replaced with the
114 filtered by the command. The string OUTFILE is replaced with the
115 name of an empty temporary file, where the filtered data must be
115 name of an empty temporary file, where the filtered data must be
116 written by the command.
116 written by the command.
117
117
118 NOTE: the tempfile mechanism is recommended for Windows systems,
118 NOTE: the tempfile mechanism is recommended for Windows systems,
119 where the standard shell I/O redirection operators often have
119 where the standard shell I/O redirection operators often have
120 strange effects. In particular, if you are doing line ending
120 strange effects. In particular, if you are doing line ending
121 conversion on Windows using the popular dos2unix and unix2dos
121 conversion on Windows using the popular dos2unix and unix2dos
122 programs, you *must* use the tempfile mechanism, as using pipes will
122 programs, you *must* use the tempfile mechanism, as using pipes will
123 corrupt the contents of your files.
123 corrupt the contents of your files.
124
124
125 Tempfile example:
125 Tempfile example:
126
126
127 [encode]
127 [encode]
128 # convert files to unix line ending conventions on checkin
128 # convert files to unix line ending conventions on checkin
129 **.txt = tempfile: dos2unix -n INFILE OUTFILE
129 **.txt = tempfile: dos2unix -n INFILE OUTFILE
130
130
131 [decode]
131 [decode]
132 # convert files to windows line ending conventions when writing
132 # convert files to windows line ending conventions when writing
133 # them to the working dir
133 # them to the working dir
134 **.txt = tempfile: unix2dos -n INFILE OUTFILE
134 **.txt = tempfile: unix2dos -n INFILE OUTFILE
135
135
136 email::
136 email::
137 Settings for extensions that send email messages.
137 Settings for extensions that send email messages.
138 from;;
138 from;;
139 Optional. Email address to use in "From" header and SMTP envelope
139 Optional. Email address to use in "From" header and SMTP envelope
140 of outgoing messages.
140 of outgoing messages.
141 method;;
141 method;;
142 Optional. Method to use to send email messages. If value is
142 Optional. Method to use to send email messages. If value is
143 "smtp" (default), use SMTP (see section "[mail]" for
143 "smtp" (default), use SMTP (see section "[mail]" for
144 configuration). Otherwise, use as name of program to run that
144 configuration). Otherwise, use as name of program to run that
145 acts like sendmail (takes "-f" option for sender, list of
145 acts like sendmail (takes "-f" option for sender, list of
146 recipients on command line, message on stdin). Normally, setting
146 recipients on command line, message on stdin). Normally, setting
147 this to "sendmail" or "/usr/sbin/sendmail" is enough to use
147 this to "sendmail" or "/usr/sbin/sendmail" is enough to use
148 sendmail to send messages.
148 sendmail to send messages.
149
149
150 Email example:
150 Email example:
151
151
152 [email]
152 [email]
153 from = Joseph User <joe.user@example.com>
153 from = Joseph User <joe.user@example.com>
154 method = /usr/sbin/sendmail
154 method = /usr/sbin/sendmail
155
155
156 extensions::
156 extensions::
157 Mercurial has an extension mechanism for adding new features. To
157 Mercurial has an extension mechanism for adding new features. To
158 enable an extension, create an entry for it in this section.
158 enable an extension, create an entry for it in this section.
159
159
160 If you know that the extension is already in Python's search path,
160 If you know that the extension is already in Python's search path,
161 you can give the name of the module, followed by "=", with nothing
161 you can give the name of the module, followed by "=", with nothing
162 after the "=".
162 after the "=".
163
163
164 Otherwise, give a name that you choose, followed by "=", followed by
164 Otherwise, give a name that you choose, followed by "=", followed by
165 the path to the ".py" file (including the file name extension) that
165 the path to the ".py" file (including the file name extension) that
166 defines the extension.
166 defines the extension.
167
167
168 Example for ~/.hgrc:
169
170 [extensions]
171 # (the mq extension will get loaded from mercurial's path)
172 hgext.mq =
173 # (this extension will get loaded from the file specified)
174 myfeature = ~/.hgext/myfeature.py
175
168 hooks::
176 hooks::
169 Commands or Python functions that get automatically executed by
177 Commands or Python functions that get automatically executed by
170 various actions such as starting or finishing a commit. Multiple
178 various actions such as starting or finishing a commit. Multiple
171 hooks can be run for the same action by appending a suffix to the
179 hooks can be run for the same action by appending a suffix to the
172 action. Overriding a site-wide hook can be done by changing its
180 action. Overriding a site-wide hook can be done by changing its
173 value or setting it to an empty string.
181 value or setting it to an empty string.
174
182
175 Example .hg/hgrc:
183 Example .hg/hgrc:
176
184
177 [hooks]
185 [hooks]
178 # do not use the site-wide hook
186 # do not use the site-wide hook
179 incoming =
187 incoming =
180 incoming.email = /my/email/hook
188 incoming.email = /my/email/hook
181 incoming.autobuild = /my/build/hook
189 incoming.autobuild = /my/build/hook
182
190
183 Most hooks are run with environment variables set that give added
191 Most hooks are run with environment variables set that give added
184 useful information. For each hook below, the environment variables
192 useful information. For each hook below, the environment variables
185 it is passed are listed with names of the form "$HG_foo".
193 it is passed are listed with names of the form "$HG_foo".
186
194
187 changegroup;;
195 changegroup;;
188 Run after a changegroup has been added via push, pull or
196 Run after a changegroup has been added via push, pull or
189 unbundle. ID of the first new changeset is in $HG_NODE.
197 unbundle. ID of the first new changeset is in $HG_NODE.
190 commit;;
198 commit;;
191 Run after a changeset has been created in the local repository.
199 Run after a changeset has been created in the local repository.
192 ID of the newly created changeset is in $HG_NODE. Parent
200 ID of the newly created changeset is in $HG_NODE. Parent
193 changeset IDs are in $HG_PARENT1 and $HG_PARENT2.
201 changeset IDs are in $HG_PARENT1 and $HG_PARENT2.
194 incoming;;
202 incoming;;
195 Run after a changeset has been pulled, pushed, or unbundled into
203 Run after a changeset has been pulled, pushed, or unbundled into
196 the local repository. The ID of the newly arrived changeset is in
204 the local repository. The ID of the newly arrived changeset is in
197 $HG_NODE.
205 $HG_NODE.
198 outgoing;;
206 outgoing;;
199 Run after sending changes from local repository to another. ID of
207 Run after sending changes from local repository to another. ID of
200 first changeset sent is in $HG_NODE. Source of operation is in
208 first changeset sent is in $HG_NODE. Source of operation is in
201 $HG_SOURCE; see "preoutgoing" hook for description.
209 $HG_SOURCE; see "preoutgoing" hook for description.
202 prechangegroup;;
210 prechangegroup;;
203 Run before a changegroup is added via push, pull or unbundle.
211 Run before a changegroup is added via push, pull or unbundle.
204 Exit status 0 allows the changegroup to proceed. Non-zero status
212 Exit status 0 allows the changegroup to proceed. Non-zero status
205 will cause the push, pull or unbundle to fail.
213 will cause the push, pull or unbundle to fail.
206 precommit;;
214 precommit;;
207 Run before starting a local commit. Exit status 0 allows the
215 Run before starting a local commit. Exit status 0 allows the
208 commit to proceed. Non-zero status will cause the commit to fail.
216 commit to proceed. Non-zero status will cause the commit to fail.
209 Parent changeset IDs are in $HG_PARENT1 and $HG_PARENT2.
217 Parent changeset IDs are in $HG_PARENT1 and $HG_PARENT2.
210 preoutgoing;;
218 preoutgoing;;
211 Run before computing changes to send from the local repository to
219 Run before computing changes to send from the local repository to
212 another. Non-zero status will cause failure. This lets you
220 another. Non-zero status will cause failure. This lets you
213 prevent pull over http or ssh. Also prevents against local pull,
221 prevent pull over http or ssh. Also prevents against local pull,
214 push (outbound) or bundle commands, but not effective, since you
222 push (outbound) or bundle commands, but not effective, since you
215 can just copy files instead then. Source of operation is in
223 can just copy files instead then. Source of operation is in
216 $HG_SOURCE. If "serve", operation is happening on behalf of
224 $HG_SOURCE. If "serve", operation is happening on behalf of
217 remote ssh or http repository. If "push", "pull" or "bundle",
225 remote ssh or http repository. If "push", "pull" or "bundle",
218 operation is happening on behalf of repository on same system.
226 operation is happening on behalf of repository on same system.
219 pretag;;
227 pretag;;
220 Run before creating a tag. Exit status 0 allows the tag to be
228 Run before creating a tag. Exit status 0 allows the tag to be
221 created. Non-zero status will cause the tag to fail. ID of
229 created. Non-zero status will cause the tag to fail. ID of
222 changeset to tag is in $HG_NODE. Name of tag is in $HG_TAG. Tag
230 changeset to tag is in $HG_NODE. Name of tag is in $HG_TAG. Tag
223 is local if $HG_LOCAL=1, in repo if $HG_LOCAL=0.
231 is local if $HG_LOCAL=1, in repo if $HG_LOCAL=0.
224 pretxnchangegroup;;
232 pretxnchangegroup;;
225 Run after a changegroup has been added via push, pull or unbundle,
233 Run after a changegroup has been added via push, pull or unbundle,
226 but before the transaction has been committed. Changegroup is
234 but before the transaction has been committed. Changegroup is
227 visible to hook program. This lets you validate incoming changes
235 visible to hook program. This lets you validate incoming changes
228 before accepting them. Passed the ID of the first new changeset
236 before accepting them. Passed the ID of the first new changeset
229 in $HG_NODE. Exit status 0 allows the transaction to commit.
237 in $HG_NODE. Exit status 0 allows the transaction to commit.
230 Non-zero status will cause the transaction to be rolled back and
238 Non-zero status will cause the transaction to be rolled back and
231 the push, pull or unbundle will fail.
239 the push, pull or unbundle will fail.
232 pretxncommit;;
240 pretxncommit;;
233 Run after a changeset has been created but the transaction not yet
241 Run after a changeset has been created but the transaction not yet
234 committed. Changeset is visible to hook program. This lets you
242 committed. Changeset is visible to hook program. This lets you
235 validate commit message and changes. Exit status 0 allows the
243 validate commit message and changes. Exit status 0 allows the
236 commit to proceed. Non-zero status will cause the transaction to
244 commit to proceed. Non-zero status will cause the transaction to
237 be rolled back. ID of changeset is in $HG_NODE. Parent changeset
245 be rolled back. ID of changeset is in $HG_NODE. Parent changeset
238 IDs are in $HG_PARENT1 and $HG_PARENT2.
246 IDs are in $HG_PARENT1 and $HG_PARENT2.
239 preupdate;;
247 preupdate;;
240 Run before updating the working directory. Exit status 0 allows
248 Run before updating the working directory. Exit status 0 allows
241 the update to proceed. Non-zero status will prevent the update.
249 the update to proceed. Non-zero status will prevent the update.
242 Changeset ID of first new parent is in $HG_PARENT1. If merge, ID
250 Changeset ID of first new parent is in $HG_PARENT1. If merge, ID
243 of second new parent is in $HG_PARENT2.
251 of second new parent is in $HG_PARENT2.
244 tag;;
252 tag;;
245 Run after a tag is created. ID of tagged changeset is in
253 Run after a tag is created. ID of tagged changeset is in
246 $HG_NODE. Name of tag is in $HG_TAG. Tag is local if
254 $HG_NODE. Name of tag is in $HG_TAG. Tag is local if
247 $HG_LOCAL=1, in repo if $HG_LOCAL=0.
255 $HG_LOCAL=1, in repo if $HG_LOCAL=0.
248 update;;
256 update;;
249 Run after updating the working directory. Changeset ID of first
257 Run after updating the working directory. Changeset ID of first
250 new parent is in $HG_PARENT1. If merge, ID of second new parent
258 new parent is in $HG_PARENT1. If merge, ID of second new parent
251 is in $HG_PARENT2. If update succeeded, $HG_ERROR=0. If update
259 is in $HG_PARENT2. If update succeeded, $HG_ERROR=0. If update
252 failed (e.g. because conflicts not resolved), $HG_ERROR=1.
260 failed (e.g. because conflicts not resolved), $HG_ERROR=1.
253
261
254 Note: In earlier releases, the names of hook environment variables
262 Note: In earlier releases, the names of hook environment variables
255 did not have a "HG_" prefix. The old unprefixed names are no longer
263 did not have a "HG_" prefix. The old unprefixed names are no longer
256 provided in the environment.
264 provided in the environment.
257
265
258 The syntax for Python hooks is as follows:
266 The syntax for Python hooks is as follows:
259
267
260 hookname = python:modulename.submodule.callable
268 hookname = python:modulename.submodule.callable
261
269
262 Python hooks are run within the Mercurial process. Each hook is
270 Python hooks are run within the Mercurial process. Each hook is
263 called with at least three keyword arguments: a ui object (keyword
271 called with at least three keyword arguments: a ui object (keyword
264 "ui"), a repository object (keyword "repo"), and a "hooktype"
272 "ui"), a repository object (keyword "repo"), and a "hooktype"
265 keyword that tells what kind of hook is used. Arguments listed as
273 keyword that tells what kind of hook is used. Arguments listed as
266 environment variables above are passed as keyword arguments, with no
274 environment variables above are passed as keyword arguments, with no
267 "HG_" prefix, and names in lower case.
275 "HG_" prefix, and names in lower case.
268
276
269 A Python hook must return a "true" value to succeed. Returning a
277 A Python hook must return a "true" value to succeed. Returning a
270 "false" value or raising an exception is treated as failure of the
278 "false" value or raising an exception is treated as failure of the
271 hook.
279 hook.
272
280
273 http_proxy::
281 http_proxy::
274 Used to access web-based Mercurial repositories through a HTTP
282 Used to access web-based Mercurial repositories through a HTTP
275 proxy.
283 proxy.
276 host;;
284 host;;
277 Host name and (optional) port of the proxy server, for example
285 Host name and (optional) port of the proxy server, for example
278 "myproxy:8000".
286 "myproxy:8000".
279 no;;
287 no;;
280 Optional. Comma-separated list of host names that should bypass
288 Optional. Comma-separated list of host names that should bypass
281 the proxy.
289 the proxy.
282 passwd;;
290 passwd;;
283 Optional. Password to authenticate with at the proxy server.
291 Optional. Password to authenticate with at the proxy server.
284 user;;
292 user;;
285 Optional. User name to authenticate with at the proxy server.
293 Optional. User name to authenticate with at the proxy server.
286
294
287 smtp::
295 smtp::
288 Configuration for extensions that need to send email messages.
296 Configuration for extensions that need to send email messages.
289 host;;
297 host;;
290 Optional. Host name of mail server. Default: "mail".
298 Optional. Host name of mail server. Default: "mail".
291 port;;
299 port;;
292 Optional. Port to connect to on mail server. Default: 25.
300 Optional. Port to connect to on mail server. Default: 25.
293 tls;;
301 tls;;
294 Optional. Whether to connect to mail server using TLS. True or
302 Optional. Whether to connect to mail server using TLS. True or
295 False. Default: False.
303 False. Default: False.
296 username;;
304 username;;
297 Optional. User name to authenticate to SMTP server with.
305 Optional. User name to authenticate to SMTP server with.
298 If username is specified, password must also be specified.
306 If username is specified, password must also be specified.
299 Default: none.
307 Default: none.
300 password;;
308 password;;
301 Optional. Password to authenticate to SMTP server with.
309 Optional. Password to authenticate to SMTP server with.
302 If username is specified, password must also be specified.
310 If username is specified, password must also be specified.
303 Default: none.
311 Default: none.
304
312
305 paths::
313 paths::
306 Assigns symbolic names to repositories. The left side is the
314 Assigns symbolic names to repositories. The left side is the
307 symbolic name, and the right gives the directory or URL that is the
315 symbolic name, and the right gives the directory or URL that is the
308 location of the repository. Default paths can be declared by
316 location of the repository. Default paths can be declared by
309 setting the following entries.
317 setting the following entries.
310 default;;
318 default;;
311 Directory or URL to use when pulling if no source is specified.
319 Directory or URL to use when pulling if no source is specified.
312 Default is set to repository from which the current repository
320 Default is set to repository from which the current repository
313 was cloned.
321 was cloned.
314 default-push;;
322 default-push;;
315 Optional. Directory or URL to use when pushing if no destination
323 Optional. Directory or URL to use when pushing if no destination
316 is specified.
324 is specified.
317
325
318 ui::
326 ui::
319 User interface controls.
327 User interface controls.
320 debug;;
328 debug;;
321 Print debugging information. True or False. Default is False.
329 Print debugging information. True or False. Default is False.
322 editor;;
330 editor;;
323 The editor to use during a commit. Default is $EDITOR or "vi".
331 The editor to use during a commit. Default is $EDITOR or "vi".
324 ignore;;
332 ignore;;
325 A file to read per-user ignore patterns from. This file should be in
333 A file to read per-user ignore patterns from. This file should be in
326 the same format as a repository-wide .hgignore file. This option
334 the same format as a repository-wide .hgignore file. This option
327 supports hook syntax, so if you want to specify multiple ignore
335 supports hook syntax, so if you want to specify multiple ignore
328 files, you can do so by setting something like
336 files, you can do so by setting something like
329 "ignore.other = ~/.hgignore2". For details of the ignore file
337 "ignore.other = ~/.hgignore2". For details of the ignore file
330 format, see the hgignore(5) man page.
338 format, see the hgignore(5) man page.
331 interactive;;
339 interactive;;
332 Allow to prompt the user. True or False. Default is True.
340 Allow to prompt the user. True or False. Default is True.
333 logtemplate;;
341 logtemplate;;
334 Template string for commands that print changesets.
342 Template string for commands that print changesets.
335 style;;
343 style;;
336 Name of style to use for command output.
344 Name of style to use for command output.
337 merge;;
345 merge;;
338 The conflict resolution program to use during a manual merge.
346 The conflict resolution program to use during a manual merge.
339 Default is "hgmerge".
347 Default is "hgmerge".
340 quiet;;
348 quiet;;
341 Reduce the amount of output printed. True or False. Default is False.
349 Reduce the amount of output printed. True or False. Default is False.
342 remotecmd;;
350 remotecmd;;
343 remote command to use for clone/push/pull operations. Default is 'hg'.
351 remote command to use for clone/push/pull operations. Default is 'hg'.
344 ssh;;
352 ssh;;
345 command to use for SSH connections. Default is 'ssh'.
353 command to use for SSH connections. Default is 'ssh'.
346 timeout;;
354 timeout;;
347 The timeout used when a lock is held (in seconds), a negative value
355 The timeout used when a lock is held (in seconds), a negative value
348 means no timeout. Default is 600.
356 means no timeout. Default is 600.
349 username;;
357 username;;
350 The committer of a changeset created when running "commit".
358 The committer of a changeset created when running "commit".
351 Typically a person's name and email address, e.g. "Fred Widget
359 Typically a person's name and email address, e.g. "Fred Widget
352 <fred@example.com>". Default is $EMAIL or username@hostname, unless
360 <fred@example.com>". Default is $EMAIL or username@hostname, unless
353 username is set to an empty string, which enforces specifying the
361 username is set to an empty string, which enforces specifying the
354 username manually.
362 username manually.
355 verbose;;
363 verbose;;
356 Increase the amount of output printed. True or False. Default is False.
364 Increase the amount of output printed. True or False. Default is False.
357
365
358
366
359 web::
367 web::
360 Web interface configuration.
368 Web interface configuration.
361 accesslog;;
369 accesslog;;
362 Where to output the access log. Default is stdout.
370 Where to output the access log. Default is stdout.
363 address;;
371 address;;
364 Interface address to bind to. Default is all.
372 Interface address to bind to. Default is all.
365 allow_archive;;
373 allow_archive;;
366 List of archive format (bz2, gz, zip) allowed for downloading.
374 List of archive format (bz2, gz, zip) allowed for downloading.
367 Default is empty.
375 Default is empty.
368 allowbz2;;
376 allowbz2;;
369 (DEPRECATED) Whether to allow .tar.bz2 downloading of repo revisions.
377 (DEPRECATED) Whether to allow .tar.bz2 downloading of repo revisions.
370 Default is false.
378 Default is false.
371 allowgz;;
379 allowgz;;
372 (DEPRECATED) Whether to allow .tar.gz downloading of repo revisions.
380 (DEPRECATED) Whether to allow .tar.gz downloading of repo revisions.
373 Default is false.
381 Default is false.
374 allowpull;;
382 allowpull;;
375 Whether to allow pulling from the repository. Default is true.
383 Whether to allow pulling from the repository. Default is true.
376 allowzip;;
384 allowzip;;
377 (DEPRECATED) Whether to allow .zip downloading of repo revisions.
385 (DEPRECATED) Whether to allow .zip downloading of repo revisions.
378 Default is false. This feature creates temporary files.
386 Default is false. This feature creates temporary files.
379 baseurl;;
387 baseurl;;
380 Base URL to use when publishing URLs in other locations, so
388 Base URL to use when publishing URLs in other locations, so
381 third-party tools like email notification hooks can construct URLs.
389 third-party tools like email notification hooks can construct URLs.
382 Example: "http://hgserver/repos/"
390 Example: "http://hgserver/repos/"
383 description;;
391 description;;
384 Textual description of the repository's purpose or contents.
392 Textual description of the repository's purpose or contents.
385 Default is "unknown".
393 Default is "unknown".
386 errorlog;;
394 errorlog;;
387 Where to output the error log. Default is stderr.
395 Where to output the error log. Default is stderr.
388 ipv6;;
396 ipv6;;
389 Whether to use IPv6. Default is false.
397 Whether to use IPv6. Default is false.
390 name;;
398 name;;
391 Repository name to use in the web interface. Default is current
399 Repository name to use in the web interface. Default is current
392 working directory.
400 working directory.
393 maxchanges;;
401 maxchanges;;
394 Maximum number of changes to list on the changelog. Default is 10.
402 Maximum number of changes to list on the changelog. Default is 10.
395 maxfiles;;
403 maxfiles;;
396 Maximum number of files to list per changeset. Default is 10.
404 Maximum number of files to list per changeset. Default is 10.
397 port;;
405 port;;
398 Port to listen on. Default is 8000.
406 Port to listen on. Default is 8000.
399 style;;
407 style;;
400 Which template map style to use.
408 Which template map style to use.
401 templates;;
409 templates;;
402 Where to find the HTML templates. Default is install path.
410 Where to find the HTML templates. Default is install path.
403
411
404
412
405 AUTHOR
413 AUTHOR
406 ------
414 ------
407 Bryan O'Sullivan <bos@serpentine.com>.
415 Bryan O'Sullivan <bos@serpentine.com>.
408
416
409 Mercurial was written by Matt Mackall <mpm@selenic.com>.
417 Mercurial was written by Matt Mackall <mpm@selenic.com>.
410
418
411 SEE ALSO
419 SEE ALSO
412 --------
420 --------
413 hg(1), hgignore(5)
421 hg(1), hgignore(5)
414
422
415 COPYING
423 COPYING
416 -------
424 -------
417 This manual page is copyright 2005 Bryan O'Sullivan.
425 This manual page is copyright 2005 Bryan O'Sullivan.
418 Mercurial is copyright 2005, 2006 Matt Mackall.
426 Mercurial is copyright 2005, 2006 Matt Mackall.
419 Free use of this software is granted under the terms of the GNU General
427 Free use of this software is granted under the terms of the GNU General
420 Public License (GPL).
428 Public License (GPL).
@@ -1,349 +1,352 b''
1 # ui.py - user interface bits for mercurial
1 # ui.py - user interface bits for mercurial
2 #
2 #
3 # Copyright 2005 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms
5 # This software may be used and distributed according to the terms
6 # of the GNU General Public License, incorporated herein by reference.
6 # of the GNU General Public License, incorporated herein by reference.
7
7
8 import ConfigParser
8 import ConfigParser
9 from i18n import gettext as _
9 from i18n import gettext as _
10 from demandload import *
10 from demandload import *
11 demandload(globals(), "errno getpass os re smtplib socket sys tempfile")
11 demandload(globals(), "errno getpass os re smtplib socket sys tempfile")
12 demandload(globals(), "templater traceback util")
12 demandload(globals(), "templater traceback util")
13
13
14 class ui(object):
14 class ui(object):
15 def __init__(self, verbose=False, debug=False, quiet=False,
15 def __init__(self, verbose=False, debug=False, quiet=False,
16 interactive=True, traceback=False, parentui=None):
16 interactive=True, traceback=False, parentui=None):
17 self.overlay = {}
17 self.overlay = {}
18 if parentui is None:
18 if parentui is None:
19 # this is the parent of all ui children
19 # this is the parent of all ui children
20 self.parentui = None
20 self.parentui = None
21 self.cdata = ConfigParser.SafeConfigParser()
21 self.cdata = ConfigParser.SafeConfigParser()
22 self.readconfig(util.rcpath())
22 self.readconfig(util.rcpath())
23
23
24 self.quiet = self.configbool("ui", "quiet")
24 self.quiet = self.configbool("ui", "quiet")
25 self.verbose = self.configbool("ui", "verbose")
25 self.verbose = self.configbool("ui", "verbose")
26 self.debugflag = self.configbool("ui", "debug")
26 self.debugflag = self.configbool("ui", "debug")
27 self.interactive = self.configbool("ui", "interactive", True)
27 self.interactive = self.configbool("ui", "interactive", True)
28 self.traceback = traceback
28 self.traceback = traceback
29
29
30 self.updateopts(verbose, debug, quiet, interactive)
30 self.updateopts(verbose, debug, quiet, interactive)
31 self.diffcache = None
31 self.diffcache = None
32 self.header = []
32 self.header = []
33 self.prev_header = []
33 self.prev_header = []
34 self.revlogopts = self.configrevlog()
34 self.revlogopts = self.configrevlog()
35 else:
35 else:
36 # parentui may point to an ui object which is already a child
36 # parentui may point to an ui object which is already a child
37 self.parentui = parentui.parentui or parentui
37 self.parentui = parentui.parentui or parentui
38 parent_cdata = self.parentui.cdata
38 parent_cdata = self.parentui.cdata
39 self.cdata = ConfigParser.SafeConfigParser(parent_cdata.defaults())
39 self.cdata = ConfigParser.SafeConfigParser(parent_cdata.defaults())
40 # make interpolation work
40 # make interpolation work
41 for section in parent_cdata.sections():
41 for section in parent_cdata.sections():
42 self.cdata.add_section(section)
42 self.cdata.add_section(section)
43 for name, value in parent_cdata.items(section, raw=True):
43 for name, value in parent_cdata.items(section, raw=True):
44 self.cdata.set(section, name, value)
44 self.cdata.set(section, name, value)
45
45
46 def __getattr__(self, key):
46 def __getattr__(self, key):
47 return getattr(self.parentui, key)
47 return getattr(self.parentui, key)
48
48
49 def updateopts(self, verbose=False, debug=False, quiet=False,
49 def updateopts(self, verbose=False, debug=False, quiet=False,
50 interactive=True, traceback=False, config=[]):
50 interactive=True, traceback=False, config=[]):
51 self.quiet = (self.quiet or quiet) and not verbose and not debug
51 self.quiet = (self.quiet or quiet) and not verbose and not debug
52 self.verbose = (self.verbose or verbose) or debug
52 self.verbose = (self.verbose or verbose) or debug
53 self.debugflag = (self.debugflag or debug)
53 self.debugflag = (self.debugflag or debug)
54 self.interactive = (self.interactive and interactive)
54 self.interactive = (self.interactive and interactive)
55 self.traceback = self.traceback or traceback
55 self.traceback = self.traceback or traceback
56 for cfg in config:
56 for cfg in config:
57 try:
57 try:
58 name, value = cfg.split('=', 1)
58 name, value = cfg.split('=', 1)
59 section, name = name.split('.', 1)
59 section, name = name.split('.', 1)
60 if not self.cdata.has_section(section):
60 if not self.cdata.has_section(section):
61 self.cdata.add_section(section)
61 self.cdata.add_section(section)
62 if not section or not name:
62 if not section or not name:
63 raise IndexError
63 raise IndexError
64 self.cdata.set(section, name, value)
64 self.cdata.set(section, name, value)
65 except (IndexError, ValueError):
65 except (IndexError, ValueError):
66 raise util.Abort(_('malformed --config option: %s') % cfg)
66 raise util.Abort(_('malformed --config option: %s') % cfg)
67
67
68 def readconfig(self, fn, root=None):
68 def readconfig(self, fn, root=None):
69 if isinstance(fn, basestring):
69 if isinstance(fn, basestring):
70 fn = [fn]
70 fn = [fn]
71 for f in fn:
71 for f in fn:
72 try:
72 try:
73 self.cdata.read(f)
73 self.cdata.read(f)
74 except ConfigParser.ParsingError, inst:
74 except ConfigParser.ParsingError, inst:
75 raise util.Abort(_("Failed to parse %s\n%s") % (f, inst))
75 raise util.Abort(_("Failed to parse %s\n%s") % (f, inst))
76 # translate paths relative to root (or home) into absolute paths
76 # translate paths relative to root (or home) into absolute paths
77 if root is None:
77 if root is None:
78 root = os.path.expanduser('~')
78 root = os.path.expanduser('~')
79 for name, path in self.configitems("paths"):
79 for name, path in self.configitems("paths"):
80 if path and path.find("://") == -1 and not os.path.isabs(path):
80 if path and path.find("://") == -1 and not os.path.isabs(path):
81 self.cdata.set("paths", name, os.path.join(root, path))
81 self.cdata.set("paths", name, os.path.join(root, path))
82
82
83 def setconfig(self, section, name, val):
83 def setconfig(self, section, name, val):
84 self.overlay[(section, name)] = val
84 self.overlay[(section, name)] = val
85
85
86 def config(self, section, name, default=None):
86 def config(self, section, name, default=None):
87 if self.overlay.has_key((section, name)):
87 if self.overlay.has_key((section, name)):
88 return self.overlay[(section, name)]
88 return self.overlay[(section, name)]
89 if self.cdata.has_option(section, name):
89 if self.cdata.has_option(section, name):
90 try:
90 try:
91 return self.cdata.get(section, name)
91 return self.cdata.get(section, name)
92 except ConfigParser.InterpolationError, inst:
92 except ConfigParser.InterpolationError, inst:
93 raise util.Abort(_("Error in configuration:\n%s") % inst)
93 raise util.Abort(_("Error in configuration:\n%s") % inst)
94 if self.parentui is None:
94 if self.parentui is None:
95 return default
95 return default
96 else:
96 else:
97 return self.parentui.config(section, name, default)
97 return self.parentui.config(section, name, default)
98
98
99 def configbool(self, section, name, default=False):
99 def configbool(self, section, name, default=False):
100 if self.overlay.has_key((section, name)):
100 if self.overlay.has_key((section, name)):
101 return self.overlay[(section, name)]
101 return self.overlay[(section, name)]
102 if self.cdata.has_option(section, name):
102 if self.cdata.has_option(section, name):
103 try:
103 try:
104 return self.cdata.getboolean(section, name)
104 return self.cdata.getboolean(section, name)
105 except ConfigParser.InterpolationError, inst:
105 except ConfigParser.InterpolationError, inst:
106 raise util.Abort(_("Error in configuration:\n%s") % inst)
106 raise util.Abort(_("Error in configuration:\n%s") % inst)
107 if self.parentui is None:
107 if self.parentui is None:
108 return default
108 return default
109 else:
109 else:
110 return self.parentui.configbool(section, name, default)
110 return self.parentui.configbool(section, name, default)
111
111
112 def has_config(self, section):
112 def has_config(self, section):
113 '''tell whether section exists in config.'''
113 '''tell whether section exists in config.'''
114 return self.cdata.has_section(section)
114 return self.cdata.has_section(section)
115
115
116 def configitems(self, section):
116 def configitems(self, section):
117 items = {}
117 items = {}
118 if self.parentui is not None:
118 if self.parentui is not None:
119 items = dict(self.parentui.configitems(section))
119 items = dict(self.parentui.configitems(section))
120 if self.cdata.has_section(section):
120 if self.cdata.has_section(section):
121 try:
121 try:
122 items.update(dict(self.cdata.items(section)))
122 items.update(dict(self.cdata.items(section)))
123 except ConfigParser.InterpolationError, inst:
123 except ConfigParser.InterpolationError, inst:
124 raise util.Abort(_("Error in configuration:\n%s") % inst)
124 raise util.Abort(_("Error in configuration:\n%s") % inst)
125 x = items.items()
125 x = items.items()
126 x.sort()
126 x.sort()
127 return x
127 return x
128
128
129 def walkconfig(self, seen=None):
129 def walkconfig(self, seen=None):
130 if seen is None:
130 if seen is None:
131 seen = {}
131 seen = {}
132 for (section, name), value in self.overlay.iteritems():
132 for (section, name), value in self.overlay.iteritems():
133 yield section, name, value
133 yield section, name, value
134 seen[section, name] = 1
134 seen[section, name] = 1
135 for section in self.cdata.sections():
135 for section in self.cdata.sections():
136 for name, value in self.cdata.items(section):
136 for name, value in self.cdata.items(section):
137 if (section, name) in seen: continue
137 if (section, name) in seen: continue
138 yield section, name, value.replace('\n', '\\n')
138 yield section, name, value.replace('\n', '\\n')
139 seen[section, name] = 1
139 seen[section, name] = 1
140 if self.parentui is not None:
140 if self.parentui is not None:
141 for parent in self.parentui.walkconfig(seen):
141 for parent in self.parentui.walkconfig(seen):
142 yield parent
142 yield parent
143
143
144 def extensions(self):
144 def extensions(self):
145 return self.configitems("extensions")
145 ret = self.configitems("extensions")
146 for i, (k, v) in enumerate(ret):
147 if v: ret[i] = (k, os.path.expanduser(v))
148 return ret
146
149
147 def hgignorefiles(self):
150 def hgignorefiles(self):
148 result = []
151 result = []
149 cfgitems = self.configitems("ui")
152 cfgitems = self.configitems("ui")
150 for key, value in cfgitems:
153 for key, value in cfgitems:
151 if key == 'ignore' or key.startswith('ignore.'):
154 if key == 'ignore' or key.startswith('ignore.'):
152 path = os.path.expanduser(value)
155 path = os.path.expanduser(value)
153 result.append(path)
156 result.append(path)
154 return result
157 return result
155
158
156 def configrevlog(self):
159 def configrevlog(self):
157 ret = {}
160 ret = {}
158 for x in self.configitems("revlog"):
161 for x in self.configitems("revlog"):
159 k = x[0].lower()
162 k = x[0].lower()
160 ret[k] = x[1]
163 ret[k] = x[1]
161 return ret
164 return ret
162 def diffopts(self):
165 def diffopts(self):
163 if self.diffcache:
166 if self.diffcache:
164 return self.diffcache
167 return self.diffcache
165 ret = { 'showfunc' : True, 'ignorews' : False}
168 ret = { 'showfunc' : True, 'ignorews' : False}
166 for x in self.configitems("diff"):
169 for x in self.configitems("diff"):
167 k = x[0].lower()
170 k = x[0].lower()
168 v = x[1]
171 v = x[1]
169 if v:
172 if v:
170 v = v.lower()
173 v = v.lower()
171 if v == 'true':
174 if v == 'true':
172 value = True
175 value = True
173 else:
176 else:
174 value = False
177 value = False
175 ret[k] = value
178 ret[k] = value
176 self.diffcache = ret
179 self.diffcache = ret
177 return ret
180 return ret
178
181
179 def username(self):
182 def username(self):
180 """Return default username to be used in commits.
183 """Return default username to be used in commits.
181
184
182 Searched in this order: $HGUSER, [ui] section of hgrcs, $EMAIL
185 Searched in this order: $HGUSER, [ui] section of hgrcs, $EMAIL
183 and stop searching if one of these is set.
186 and stop searching if one of these is set.
184 Abort if found username is an empty string to force specifying
187 Abort if found username is an empty string to force specifying
185 the commit user elsewhere, e.g. with line option or repo hgrc.
188 the commit user elsewhere, e.g. with line option or repo hgrc.
186 If not found, use ($LOGNAME or $USER or $LNAME or
189 If not found, use ($LOGNAME or $USER or $LNAME or
187 $USERNAME) +"@full.hostname".
190 $USERNAME) +"@full.hostname".
188 """
191 """
189 user = os.environ.get("HGUSER")
192 user = os.environ.get("HGUSER")
190 if user is None:
193 if user is None:
191 user = self.config("ui", "username")
194 user = self.config("ui", "username")
192 if user is None:
195 if user is None:
193 user = os.environ.get("EMAIL")
196 user = os.environ.get("EMAIL")
194 if user is None:
197 if user is None:
195 try:
198 try:
196 user = '%s@%s' % (getpass.getuser(), socket.getfqdn())
199 user = '%s@%s' % (getpass.getuser(), socket.getfqdn())
197 except KeyError:
200 except KeyError:
198 raise util.Abort(_("Please specify a username."))
201 raise util.Abort(_("Please specify a username."))
199 return user
202 return user
200
203
201 def shortuser(self, user):
204 def shortuser(self, user):
202 """Return a short representation of a user name or email address."""
205 """Return a short representation of a user name or email address."""
203 if not self.verbose: user = util.shortuser(user)
206 if not self.verbose: user = util.shortuser(user)
204 return user
207 return user
205
208
206 def expandpath(self, loc):
209 def expandpath(self, loc):
207 """Return repository location relative to cwd or from [paths]"""
210 """Return repository location relative to cwd or from [paths]"""
208 if loc.find("://") != -1 or os.path.exists(loc):
211 if loc.find("://") != -1 or os.path.exists(loc):
209 return loc
212 return loc
210
213
211 return self.config("paths", loc, loc)
214 return self.config("paths", loc, loc)
212
215
213 def write(self, *args):
216 def write(self, *args):
214 if self.header:
217 if self.header:
215 if self.header != self.prev_header:
218 if self.header != self.prev_header:
216 self.prev_header = self.header
219 self.prev_header = self.header
217 self.write(*self.header)
220 self.write(*self.header)
218 self.header = []
221 self.header = []
219 for a in args:
222 for a in args:
220 sys.stdout.write(str(a))
223 sys.stdout.write(str(a))
221
224
222 def write_header(self, *args):
225 def write_header(self, *args):
223 for a in args:
226 for a in args:
224 self.header.append(str(a))
227 self.header.append(str(a))
225
228
226 def write_err(self, *args):
229 def write_err(self, *args):
227 try:
230 try:
228 if not sys.stdout.closed: sys.stdout.flush()
231 if not sys.stdout.closed: sys.stdout.flush()
229 for a in args:
232 for a in args:
230 sys.stderr.write(str(a))
233 sys.stderr.write(str(a))
231 except IOError, inst:
234 except IOError, inst:
232 if inst.errno != errno.EPIPE:
235 if inst.errno != errno.EPIPE:
233 raise
236 raise
234
237
235 def flush(self):
238 def flush(self):
236 try: sys.stdout.flush()
239 try: sys.stdout.flush()
237 except: pass
240 except: pass
238 try: sys.stderr.flush()
241 try: sys.stderr.flush()
239 except: pass
242 except: pass
240
243
241 def readline(self):
244 def readline(self):
242 return sys.stdin.readline()[:-1]
245 return sys.stdin.readline()[:-1]
243 def prompt(self, msg, pat=None, default="y"):
246 def prompt(self, msg, pat=None, default="y"):
244 if not self.interactive: return default
247 if not self.interactive: return default
245 while 1:
248 while 1:
246 self.write(msg, " ")
249 self.write(msg, " ")
247 r = self.readline()
250 r = self.readline()
248 if not pat or re.match(pat, r):
251 if not pat or re.match(pat, r):
249 return r
252 return r
250 else:
253 else:
251 self.write(_("unrecognized response\n"))
254 self.write(_("unrecognized response\n"))
252 def getpass(self, prompt=None, default=None):
255 def getpass(self, prompt=None, default=None):
253 if not self.interactive: return default
256 if not self.interactive: return default
254 return getpass.getpass(prompt or _('password: '))
257 return getpass.getpass(prompt or _('password: '))
255 def status(self, *msg):
258 def status(self, *msg):
256 if not self.quiet: self.write(*msg)
259 if not self.quiet: self.write(*msg)
257 def warn(self, *msg):
260 def warn(self, *msg):
258 self.write_err(*msg)
261 self.write_err(*msg)
259 def note(self, *msg):
262 def note(self, *msg):
260 if self.verbose: self.write(*msg)
263 if self.verbose: self.write(*msg)
261 def debug(self, *msg):
264 def debug(self, *msg):
262 if self.debugflag: self.write(*msg)
265 if self.debugflag: self.write(*msg)
263 def edit(self, text, user):
266 def edit(self, text, user):
264 (fd, name) = tempfile.mkstemp(prefix="hg-editor-", suffix=".txt",
267 (fd, name) = tempfile.mkstemp(prefix="hg-editor-", suffix=".txt",
265 text=True)
268 text=True)
266 try:
269 try:
267 f = os.fdopen(fd, "w")
270 f = os.fdopen(fd, "w")
268 f.write(text)
271 f.write(text)
269 f.close()
272 f.close()
270
273
271 editor = (os.environ.get("HGEDITOR") or
274 editor = (os.environ.get("HGEDITOR") or
272 self.config("ui", "editor") or
275 self.config("ui", "editor") or
273 os.environ.get("EDITOR", "vi"))
276 os.environ.get("EDITOR", "vi"))
274
277
275 util.system("%s \"%s\"" % (editor, name),
278 util.system("%s \"%s\"" % (editor, name),
276 environ={'HGUSER': user},
279 environ={'HGUSER': user},
277 onerr=util.Abort, errprefix=_("edit failed"))
280 onerr=util.Abort, errprefix=_("edit failed"))
278
281
279 f = open(name)
282 f = open(name)
280 t = f.read()
283 t = f.read()
281 f.close()
284 f.close()
282 t = re.sub("(?m)^HG:.*\n", "", t)
285 t = re.sub("(?m)^HG:.*\n", "", t)
283 finally:
286 finally:
284 os.unlink(name)
287 os.unlink(name)
285
288
286 return t
289 return t
287
290
288 def sendmail(self):
291 def sendmail(self):
289 '''send mail message. object returned has one method, sendmail.
292 '''send mail message. object returned has one method, sendmail.
290 call as sendmail(sender, list-of-recipients, msg).'''
293 call as sendmail(sender, list-of-recipients, msg).'''
291
294
292 def smtp():
295 def smtp():
293 '''send mail using smtp.'''
296 '''send mail using smtp.'''
294
297
295 s = smtplib.SMTP()
298 s = smtplib.SMTP()
296 mailhost = self.config('smtp', 'host')
299 mailhost = self.config('smtp', 'host')
297 if not mailhost:
300 if not mailhost:
298 raise util.Abort(_('no [smtp]host in hgrc - cannot send mail'))
301 raise util.Abort(_('no [smtp]host in hgrc - cannot send mail'))
299 mailport = int(self.config('smtp', 'port', 25))
302 mailport = int(self.config('smtp', 'port', 25))
300 self.note(_('sending mail: smtp host %s, port %s\n') %
303 self.note(_('sending mail: smtp host %s, port %s\n') %
301 (mailhost, mailport))
304 (mailhost, mailport))
302 s.connect(host=mailhost, port=mailport)
305 s.connect(host=mailhost, port=mailport)
303 if self.configbool('smtp', 'tls'):
306 if self.configbool('smtp', 'tls'):
304 self.note(_('(using tls)\n'))
307 self.note(_('(using tls)\n'))
305 s.ehlo()
308 s.ehlo()
306 s.starttls()
309 s.starttls()
307 s.ehlo()
310 s.ehlo()
308 username = self.config('smtp', 'username')
311 username = self.config('smtp', 'username')
309 password = self.config('smtp', 'password')
312 password = self.config('smtp', 'password')
310 if username and password:
313 if username and password:
311 self.note(_('(authenticating to mail server as %s)\n') %
314 self.note(_('(authenticating to mail server as %s)\n') %
312 (username))
315 (username))
313 s.login(username, password)
316 s.login(username, password)
314 return s
317 return s
315
318
316 class sendmail(object):
319 class sendmail(object):
317 '''send mail using sendmail.'''
320 '''send mail using sendmail.'''
318
321
319 def __init__(self, ui, program):
322 def __init__(self, ui, program):
320 self.ui = ui
323 self.ui = ui
321 self.program = program
324 self.program = program
322
325
323 def sendmail(self, sender, recipients, msg):
326 def sendmail(self, sender, recipients, msg):
324 cmdline = '%s -f %s %s' % (
327 cmdline = '%s -f %s %s' % (
325 self.program, templater.email(sender),
328 self.program, templater.email(sender),
326 ' '.join(map(templater.email, recipients)))
329 ' '.join(map(templater.email, recipients)))
327 self.ui.note(_('sending mail: %s\n') % cmdline)
330 self.ui.note(_('sending mail: %s\n') % cmdline)
328 fp = os.popen(cmdline, 'w')
331 fp = os.popen(cmdline, 'w')
329 fp.write(msg)
332 fp.write(msg)
330 ret = fp.close()
333 ret = fp.close()
331 if ret:
334 if ret:
332 raise util.Abort('%s %s' % (
335 raise util.Abort('%s %s' % (
333 os.path.basename(self.program.split(None, 1)[0]),
336 os.path.basename(self.program.split(None, 1)[0]),
334 util.explain_exit(ret)[0]))
337 util.explain_exit(ret)[0]))
335
338
336 method = self.config('email', 'method', 'smtp')
339 method = self.config('email', 'method', 'smtp')
337 if method == 'smtp':
340 if method == 'smtp':
338 mail = smtp()
341 mail = smtp()
339 else:
342 else:
340 mail = sendmail(self, method)
343 mail = sendmail(self, method)
341 return mail
344 return mail
342
345
343 def print_exc(self):
346 def print_exc(self):
344 '''print exception traceback if traceback printing enabled.
347 '''print exception traceback if traceback printing enabled.
345 only to call in exception handler. returns true if traceback
348 only to call in exception handler. returns true if traceback
346 printed.'''
349 printed.'''
347 if self.traceback:
350 if self.traceback:
348 traceback.print_exc()
351 traceback.print_exc()
349 return self.traceback
352 return self.traceback
General Comments 0
You need to be logged in to leave comments. Login now