##// END OF EJS Templates
adding local_hostname option to smtp configuration
Valentino Volonghi aka dialtone -
r2583:6e542744 default
parent child Browse files
Show More
@@ -1,449 +1,452 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:
168 Example for ~/.hgrc:
169
169
170 [extensions]
170 [extensions]
171 # (the mq extension will get loaded from mercurial's path)
171 # (the mq extension will get loaded from mercurial's path)
172 hgext.mq =
172 hgext.mq =
173 # (this extension will get loaded from the file specified)
173 # (this extension will get loaded from the file specified)
174 myfeature = ~/.hgext/myfeature.py
174 myfeature = ~/.hgext/myfeature.py
175
175
176 hooks::
176 hooks::
177 Commands or Python functions that get automatically executed by
177 Commands or Python functions that get automatically executed by
178 various actions such as starting or finishing a commit. Multiple
178 various actions such as starting or finishing a commit. Multiple
179 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
180 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
181 value or setting it to an empty string.
181 value or setting it to an empty string.
182
182
183 Example .hg/hgrc:
183 Example .hg/hgrc:
184
184
185 [hooks]
185 [hooks]
186 # do not use the site-wide hook
186 # do not use the site-wide hook
187 incoming =
187 incoming =
188 incoming.email = /my/email/hook
188 incoming.email = /my/email/hook
189 incoming.autobuild = /my/build/hook
189 incoming.autobuild = /my/build/hook
190
190
191 Most hooks are run with environment variables set that give added
191 Most hooks are run with environment variables set that give added
192 useful information. For each hook below, the environment variables
192 useful information. For each hook below, the environment variables
193 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".
194
194
195 changegroup;;
195 changegroup;;
196 Run after a changegroup has been added via push, pull or
196 Run after a changegroup has been added via push, pull or
197 unbundle. ID of the first new changeset is in $HG_NODE.
197 unbundle. ID of the first new changeset is in $HG_NODE.
198 commit;;
198 commit;;
199 Run after a changeset has been created in the local repository.
199 Run after a changeset has been created in the local repository.
200 ID of the newly created changeset is in $HG_NODE. Parent
200 ID of the newly created changeset is in $HG_NODE. Parent
201 changeset IDs are in $HG_PARENT1 and $HG_PARENT2.
201 changeset IDs are in $HG_PARENT1 and $HG_PARENT2.
202 incoming;;
202 incoming;;
203 Run after a changeset has been pulled, pushed, or unbundled into
203 Run after a changeset has been pulled, pushed, or unbundled into
204 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
205 $HG_NODE.
205 $HG_NODE.
206 outgoing;;
206 outgoing;;
207 Run after sending changes from local repository to another. ID of
207 Run after sending changes from local repository to another. ID of
208 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
209 $HG_SOURCE; see "preoutgoing" hook for description.
209 $HG_SOURCE; see "preoutgoing" hook for description.
210 prechangegroup;;
210 prechangegroup;;
211 Run before a changegroup is added via push, pull or unbundle.
211 Run before a changegroup is added via push, pull or unbundle.
212 Exit status 0 allows the changegroup to proceed. Non-zero status
212 Exit status 0 allows the changegroup to proceed. Non-zero status
213 will cause the push, pull or unbundle to fail.
213 will cause the push, pull or unbundle to fail.
214 precommit;;
214 precommit;;
215 Run before starting a local commit. Exit status 0 allows the
215 Run before starting a local commit. Exit status 0 allows the
216 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.
217 Parent changeset IDs are in $HG_PARENT1 and $HG_PARENT2.
217 Parent changeset IDs are in $HG_PARENT1 and $HG_PARENT2.
218 preoutgoing;;
218 preoutgoing;;
219 Run before computing changes to send from the local repository to
219 Run before computing changes to send from the local repository to
220 another. Non-zero status will cause failure. This lets you
220 another. Non-zero status will cause failure. This lets you
221 prevent pull over http or ssh. Also prevents against local pull,
221 prevent pull over http or ssh. Also prevents against local pull,
222 push (outbound) or bundle commands, but not effective, since you
222 push (outbound) or bundle commands, but not effective, since you
223 can just copy files instead then. Source of operation is in
223 can just copy files instead then. Source of operation is in
224 $HG_SOURCE. If "serve", operation is happening on behalf of
224 $HG_SOURCE. If "serve", operation is happening on behalf of
225 remote ssh or http repository. If "push", "pull" or "bundle",
225 remote ssh or http repository. If "push", "pull" or "bundle",
226 operation is happening on behalf of repository on same system.
226 operation is happening on behalf of repository on same system.
227 pretag;;
227 pretag;;
228 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
229 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
230 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
231 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.
232 pretxnchangegroup;;
232 pretxnchangegroup;;
233 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,
234 but before the transaction has been committed. Changegroup is
234 but before the transaction has been committed. Changegroup is
235 visible to hook program. This lets you validate incoming changes
235 visible to hook program. This lets you validate incoming changes
236 before accepting them. Passed the ID of the first new changeset
236 before accepting them. Passed the ID of the first new changeset
237 in $HG_NODE. Exit status 0 allows the transaction to commit.
237 in $HG_NODE. Exit status 0 allows the transaction to commit.
238 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
239 the push, pull or unbundle will fail.
239 the push, pull or unbundle will fail.
240 pretxncommit;;
240 pretxncommit;;
241 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
242 committed. Changeset is visible to hook program. This lets you
242 committed. Changeset is visible to hook program. This lets you
243 validate commit message and changes. Exit status 0 allows the
243 validate commit message and changes. Exit status 0 allows the
244 commit to proceed. Non-zero status will cause the transaction to
244 commit to proceed. Non-zero status will cause the transaction to
245 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
246 IDs are in $HG_PARENT1 and $HG_PARENT2.
246 IDs are in $HG_PARENT1 and $HG_PARENT2.
247 preupdate;;
247 preupdate;;
248 Run before updating the working directory. Exit status 0 allows
248 Run before updating the working directory. Exit status 0 allows
249 the update to proceed. Non-zero status will prevent the update.
249 the update to proceed. Non-zero status will prevent the update.
250 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
251 of second new parent is in $HG_PARENT2.
251 of second new parent is in $HG_PARENT2.
252 tag;;
252 tag;;
253 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
254 $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
255 $HG_LOCAL=1, in repo if $HG_LOCAL=0.
255 $HG_LOCAL=1, in repo if $HG_LOCAL=0.
256 update;;
256 update;;
257 Run after updating the working directory. Changeset ID of first
257 Run after updating the working directory. Changeset ID of first
258 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
259 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
260 failed (e.g. because conflicts not resolved), $HG_ERROR=1.
260 failed (e.g. because conflicts not resolved), $HG_ERROR=1.
261
261
262 Note: In earlier releases, the names of hook environment variables
262 Note: In earlier releases, the names of hook environment variables
263 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
264 provided in the environment.
264 provided in the environment.
265
265
266 The syntax for Python hooks is as follows:
266 The syntax for Python hooks is as follows:
267
267
268 hookname = python:modulename.submodule.callable
268 hookname = python:modulename.submodule.callable
269
269
270 Python hooks are run within the Mercurial process. Each hook is
270 Python hooks are run within the Mercurial process. Each hook is
271 called with at least three keyword arguments: a ui object (keyword
271 called with at least three keyword arguments: a ui object (keyword
272 "ui"), a repository object (keyword "repo"), and a "hooktype"
272 "ui"), a repository object (keyword "repo"), and a "hooktype"
273 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
274 environment variables above are passed as keyword arguments, with no
274 environment variables above are passed as keyword arguments, with no
275 "HG_" prefix, and names in lower case.
275 "HG_" prefix, and names in lower case.
276
276
277 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
278 "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
279 hook.
279 hook.
280
280
281 http_proxy::
281 http_proxy::
282 Used to access web-based Mercurial repositories through a HTTP
282 Used to access web-based Mercurial repositories through a HTTP
283 proxy.
283 proxy.
284 host;;
284 host;;
285 Host name and (optional) port of the proxy server, for example
285 Host name and (optional) port of the proxy server, for example
286 "myproxy:8000".
286 "myproxy:8000".
287 no;;
287 no;;
288 Optional. Comma-separated list of host names that should bypass
288 Optional. Comma-separated list of host names that should bypass
289 the proxy.
289 the proxy.
290 passwd;;
290 passwd;;
291 Optional. Password to authenticate with at the proxy server.
291 Optional. Password to authenticate with at the proxy server.
292 user;;
292 user;;
293 Optional. User name to authenticate with at the proxy server.
293 Optional. User name to authenticate with at the proxy server.
294
294
295 smtp::
295 smtp::
296 Configuration for extensions that need to send email messages.
296 Configuration for extensions that need to send email messages.
297 host;;
297 host;;
298 Optional. Host name of mail server. Default: "mail".
298 Optional. Host name of mail server. Default: "mail".
299 port;;
299 port;;
300 Optional. Port to connect to on mail server. Default: 25.
300 Optional. Port to connect to on mail server. Default: 25.
301 tls;;
301 tls;;
302 Optional. Whether to connect to mail server using TLS. True or
302 Optional. Whether to connect to mail server using TLS. True or
303 False. Default: False.
303 False. Default: False.
304 username;;
304 username;;
305 Optional. User name to authenticate to SMTP server with.
305 Optional. User name to authenticate to SMTP server with.
306 If username is specified, password must also be specified.
306 If username is specified, password must also be specified.
307 Default: none.
307 Default: none.
308 password;;
308 password;;
309 Optional. Password to authenticate to SMTP server with.
309 Optional. Password to authenticate to SMTP server with.
310 If username is specified, password must also be specified.
310 If username is specified, password must also be specified.
311 Default: none.
311 Default: none.
312 local_hostname;;
313 Optional. It's the hostname that the sender can use to identify itself
314 to the MTA.
312
315
313 paths::
316 paths::
314 Assigns symbolic names to repositories. The left side is the
317 Assigns symbolic names to repositories. The left side is the
315 symbolic name, and the right gives the directory or URL that is the
318 symbolic name, and the right gives the directory or URL that is the
316 location of the repository. Default paths can be declared by
319 location of the repository. Default paths can be declared by
317 setting the following entries.
320 setting the following entries.
318 default;;
321 default;;
319 Directory or URL to use when pulling if no source is specified.
322 Directory or URL to use when pulling if no source is specified.
320 Default is set to repository from which the current repository
323 Default is set to repository from which the current repository
321 was cloned.
324 was cloned.
322 default-push;;
325 default-push;;
323 Optional. Directory or URL to use when pushing if no destination
326 Optional. Directory or URL to use when pushing if no destination
324 is specified.
327 is specified.
325
328
326 ui::
329 ui::
327 User interface controls.
330 User interface controls.
328 debug;;
331 debug;;
329 Print debugging information. True or False. Default is False.
332 Print debugging information. True or False. Default is False.
330 editor;;
333 editor;;
331 The editor to use during a commit. Default is $EDITOR or "vi".
334 The editor to use during a commit. Default is $EDITOR or "vi".
332 ignore;;
335 ignore;;
333 A file to read per-user ignore patterns from. This file should be in
336 A file to read per-user ignore patterns from. This file should be in
334 the same format as a repository-wide .hgignore file. This option
337 the same format as a repository-wide .hgignore file. This option
335 supports hook syntax, so if you want to specify multiple ignore
338 supports hook syntax, so if you want to specify multiple ignore
336 files, you can do so by setting something like
339 files, you can do so by setting something like
337 "ignore.other = ~/.hgignore2". For details of the ignore file
340 "ignore.other = ~/.hgignore2". For details of the ignore file
338 format, see the hgignore(5) man page.
341 format, see the hgignore(5) man page.
339 interactive;;
342 interactive;;
340 Allow to prompt the user. True or False. Default is True.
343 Allow to prompt the user. True or False. Default is True.
341 logtemplate;;
344 logtemplate;;
342 Template string for commands that print changesets.
345 Template string for commands that print changesets.
343 style;;
346 style;;
344 Name of style to use for command output.
347 Name of style to use for command output.
345 merge;;
348 merge;;
346 The conflict resolution program to use during a manual merge.
349 The conflict resolution program to use during a manual merge.
347 Default is "hgmerge".
350 Default is "hgmerge".
348 quiet;;
351 quiet;;
349 Reduce the amount of output printed. True or False. Default is False.
352 Reduce the amount of output printed. True or False. Default is False.
350 remotecmd;;
353 remotecmd;;
351 remote command to use for clone/push/pull operations. Default is 'hg'.
354 remote command to use for clone/push/pull operations. Default is 'hg'.
352 ssh;;
355 ssh;;
353 command to use for SSH connections. Default is 'ssh'.
356 command to use for SSH connections. Default is 'ssh'.
354 timeout;;
357 timeout;;
355 The timeout used when a lock is held (in seconds), a negative value
358 The timeout used when a lock is held (in seconds), a negative value
356 means no timeout. Default is 600.
359 means no timeout. Default is 600.
357 username;;
360 username;;
358 The committer of a changeset created when running "commit".
361 The committer of a changeset created when running "commit".
359 Typically a person's name and email address, e.g. "Fred Widget
362 Typically a person's name and email address, e.g. "Fred Widget
360 <fred@example.com>". Default is $EMAIL or username@hostname, unless
363 <fred@example.com>". Default is $EMAIL or username@hostname, unless
361 username is set to an empty string, which enforces specifying the
364 username is set to an empty string, which enforces specifying the
362 username manually.
365 username manually.
363 verbose;;
366 verbose;;
364 Increase the amount of output printed. True or False. Default is False.
367 Increase the amount of output printed. True or False. Default is False.
365
368
366
369
367 web::
370 web::
368 Web interface configuration.
371 Web interface configuration.
369 accesslog;;
372 accesslog;;
370 Where to output the access log. Default is stdout.
373 Where to output the access log. Default is stdout.
371 address;;
374 address;;
372 Interface address to bind to. Default is all.
375 Interface address to bind to. Default is all.
373 allow_archive;;
376 allow_archive;;
374 List of archive format (bz2, gz, zip) allowed for downloading.
377 List of archive format (bz2, gz, zip) allowed for downloading.
375 Default is empty.
378 Default is empty.
376 allowbz2;;
379 allowbz2;;
377 (DEPRECATED) Whether to allow .tar.bz2 downloading of repo revisions.
380 (DEPRECATED) Whether to allow .tar.bz2 downloading of repo revisions.
378 Default is false.
381 Default is false.
379 allowgz;;
382 allowgz;;
380 (DEPRECATED) Whether to allow .tar.gz downloading of repo revisions.
383 (DEPRECATED) Whether to allow .tar.gz downloading of repo revisions.
381 Default is false.
384 Default is false.
382 allowpull;;
385 allowpull;;
383 Whether to allow pulling from the repository. Default is true.
386 Whether to allow pulling from the repository. Default is true.
384 allow_push;;
387 allow_push;;
385 Whether to allow pushing to the repository. If empty or not set,
388 Whether to allow pushing to the repository. If empty or not set,
386 push is not allowed. If the special value "*", any remote user
389 push is not allowed. If the special value "*", any remote user
387 can push, including unauthenticated users. Otherwise, the remote
390 can push, including unauthenticated users. Otherwise, the remote
388 user must have been authenticated, and the authenticated user name
391 user must have been authenticated, and the authenticated user name
389 must be present in this list (separated by whitespace or ",").
392 must be present in this list (separated by whitespace or ",").
390 The contents of the allow_push list are examined after the
393 The contents of the allow_push list are examined after the
391 deny_push list.
394 deny_push list.
392 allowzip;;
395 allowzip;;
393 (DEPRECATED) Whether to allow .zip downloading of repo revisions.
396 (DEPRECATED) Whether to allow .zip downloading of repo revisions.
394 Default is false. This feature creates temporary files.
397 Default is false. This feature creates temporary files.
395 baseurl;;
398 baseurl;;
396 Base URL to use when publishing URLs in other locations, so
399 Base URL to use when publishing URLs in other locations, so
397 third-party tools like email notification hooks can construct URLs.
400 third-party tools like email notification hooks can construct URLs.
398 Example: "http://hgserver/repos/"
401 Example: "http://hgserver/repos/"
399 contact;;
402 contact;;
400 Name or email address of the person in charge of the repository.
403 Name or email address of the person in charge of the repository.
401 Default is "unknown".
404 Default is "unknown".
402 deny_push;;
405 deny_push;;
403 Whether to deny pushing to the repository. If empty or not set,
406 Whether to deny pushing to the repository. If empty or not set,
404 push is not denied. If the special value "*", all remote users
407 push is not denied. If the special value "*", all remote users
405 are denied push. Otherwise, unauthenticated users are all denied,
408 are denied push. Otherwise, unauthenticated users are all denied,
406 and any authenticated user name present in this list (separated by
409 and any authenticated user name present in this list (separated by
407 whitespace or ",") is also denied. The contents of the deny_push
410 whitespace or ",") is also denied. The contents of the deny_push
408 list are examined before the allow_push list.
411 list are examined before the allow_push list.
409 description;;
412 description;;
410 Textual description of the repository's purpose or contents.
413 Textual description of the repository's purpose or contents.
411 Default is "unknown".
414 Default is "unknown".
412 errorlog;;
415 errorlog;;
413 Where to output the error log. Default is stderr.
416 Where to output the error log. Default is stderr.
414 ipv6;;
417 ipv6;;
415 Whether to use IPv6. Default is false.
418 Whether to use IPv6. Default is false.
416 name;;
419 name;;
417 Repository name to use in the web interface. Default is current
420 Repository name to use in the web interface. Default is current
418 working directory.
421 working directory.
419 maxchanges;;
422 maxchanges;;
420 Maximum number of changes to list on the changelog. Default is 10.
423 Maximum number of changes to list on the changelog. Default is 10.
421 maxfiles;;
424 maxfiles;;
422 Maximum number of files to list per changeset. Default is 10.
425 Maximum number of files to list per changeset. Default is 10.
423 port;;
426 port;;
424 Port to listen on. Default is 8000.
427 Port to listen on. Default is 8000.
425 push_ssl;;
428 push_ssl;;
426 Whether to require that inbound pushes be transported over SSL to
429 Whether to require that inbound pushes be transported over SSL to
427 prevent password sniffing. Default is true.
430 prevent password sniffing. Default is true.
428 style;;
431 style;;
429 Which template map style to use.
432 Which template map style to use.
430 templates;;
433 templates;;
431 Where to find the HTML templates. Default is install path.
434 Where to find the HTML templates. Default is install path.
432
435
433
436
434 AUTHOR
437 AUTHOR
435 ------
438 ------
436 Bryan O'Sullivan <bos@serpentine.com>.
439 Bryan O'Sullivan <bos@serpentine.com>.
437
440
438 Mercurial was written by Matt Mackall <mpm@selenic.com>.
441 Mercurial was written by Matt Mackall <mpm@selenic.com>.
439
442
440 SEE ALSO
443 SEE ALSO
441 --------
444 --------
442 hg(1), hgignore(5)
445 hg(1), hgignore(5)
443
446
444 COPYING
447 COPYING
445 -------
448 -------
446 This manual page is copyright 2005 Bryan O'Sullivan.
449 This manual page is copyright 2005 Bryan O'Sullivan.
447 Mercurial is copyright 2005, 2006 Matt Mackall.
450 Mercurial is copyright 2005, 2006 Matt Mackall.
448 Free use of this software is granted under the terms of the GNU General
451 Free use of this software is granted under the terms of the GNU General
449 Public License (GPL).
452 Public License (GPL).
@@ -1,355 +1,356 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 from i18n import gettext as _
8 from i18n import gettext as _
9 from demandload import *
9 from demandload import *
10 demandload(globals(), "errno getpass os re smtplib socket sys tempfile")
10 demandload(globals(), "errno getpass os re smtplib socket sys tempfile")
11 demandload(globals(), "ConfigParser templater traceback util")
11 demandload(globals(), "ConfigParser templater traceback util")
12
12
13 class ui(object):
13 class ui(object):
14 def __init__(self, verbose=False, debug=False, quiet=False,
14 def __init__(self, verbose=False, debug=False, quiet=False,
15 interactive=True, traceback=False, parentui=None):
15 interactive=True, traceback=False, parentui=None):
16 self.overlay = {}
16 self.overlay = {}
17 if parentui is None:
17 if parentui is None:
18 # this is the parent of all ui children
18 # this is the parent of all ui children
19 self.parentui = None
19 self.parentui = None
20 self.cdata = ConfigParser.SafeConfigParser()
20 self.cdata = ConfigParser.SafeConfigParser()
21 self.readconfig(util.rcpath())
21 self.readconfig(util.rcpath())
22
22
23 self.quiet = self.configbool("ui", "quiet")
23 self.quiet = self.configbool("ui", "quiet")
24 self.verbose = self.configbool("ui", "verbose")
24 self.verbose = self.configbool("ui", "verbose")
25 self.debugflag = self.configbool("ui", "debug")
25 self.debugflag = self.configbool("ui", "debug")
26 self.interactive = self.configbool("ui", "interactive", True)
26 self.interactive = self.configbool("ui", "interactive", True)
27 self.traceback = traceback
27 self.traceback = traceback
28
28
29 self.updateopts(verbose, debug, quiet, interactive)
29 self.updateopts(verbose, debug, quiet, interactive)
30 self.diffcache = None
30 self.diffcache = None
31 self.header = []
31 self.header = []
32 self.prev_header = []
32 self.prev_header = []
33 self.revlogopts = self.configrevlog()
33 self.revlogopts = self.configrevlog()
34 else:
34 else:
35 # parentui may point to an ui object which is already a child
35 # parentui may point to an ui object which is already a child
36 self.parentui = parentui.parentui or parentui
36 self.parentui = parentui.parentui or parentui
37 parent_cdata = self.parentui.cdata
37 parent_cdata = self.parentui.cdata
38 self.cdata = ConfigParser.SafeConfigParser(parent_cdata.defaults())
38 self.cdata = ConfigParser.SafeConfigParser(parent_cdata.defaults())
39 # make interpolation work
39 # make interpolation work
40 for section in parent_cdata.sections():
40 for section in parent_cdata.sections():
41 self.cdata.add_section(section)
41 self.cdata.add_section(section)
42 for name, value in parent_cdata.items(section, raw=True):
42 for name, value in parent_cdata.items(section, raw=True):
43 self.cdata.set(section, name, value)
43 self.cdata.set(section, name, value)
44
44
45 def __getattr__(self, key):
45 def __getattr__(self, key):
46 return getattr(self.parentui, key)
46 return getattr(self.parentui, key)
47
47
48 def updateopts(self, verbose=False, debug=False, quiet=False,
48 def updateopts(self, verbose=False, debug=False, quiet=False,
49 interactive=True, traceback=False, config=[]):
49 interactive=True, traceback=False, config=[]):
50 self.quiet = (self.quiet or quiet) and not verbose and not debug
50 self.quiet = (self.quiet or quiet) and not verbose and not debug
51 self.verbose = (self.verbose or verbose) or debug
51 self.verbose = (self.verbose or verbose) or debug
52 self.debugflag = (self.debugflag or debug)
52 self.debugflag = (self.debugflag or debug)
53 self.interactive = (self.interactive and interactive)
53 self.interactive = (self.interactive and interactive)
54 self.traceback = self.traceback or traceback
54 self.traceback = self.traceback or traceback
55 for cfg in config:
55 for cfg in config:
56 try:
56 try:
57 name, value = cfg.split('=', 1)
57 name, value = cfg.split('=', 1)
58 section, name = name.split('.', 1)
58 section, name = name.split('.', 1)
59 if not self.cdata.has_section(section):
59 if not self.cdata.has_section(section):
60 self.cdata.add_section(section)
60 self.cdata.add_section(section)
61 if not section or not name:
61 if not section or not name:
62 raise IndexError
62 raise IndexError
63 self.cdata.set(section, name, value)
63 self.cdata.set(section, name, value)
64 except (IndexError, ValueError):
64 except (IndexError, ValueError):
65 raise util.Abort(_('malformed --config option: %s') % cfg)
65 raise util.Abort(_('malformed --config option: %s') % cfg)
66
66
67 def readconfig(self, fn, root=None):
67 def readconfig(self, fn, root=None):
68 if isinstance(fn, basestring):
68 if isinstance(fn, basestring):
69 fn = [fn]
69 fn = [fn]
70 for f in fn:
70 for f in fn:
71 try:
71 try:
72 self.cdata.read(f)
72 self.cdata.read(f)
73 except ConfigParser.ParsingError, inst:
73 except ConfigParser.ParsingError, inst:
74 raise util.Abort(_("Failed to parse %s\n%s") % (f, inst))
74 raise util.Abort(_("Failed to parse %s\n%s") % (f, inst))
75 # translate paths relative to root (or home) into absolute paths
75 # translate paths relative to root (or home) into absolute paths
76 if root is None:
76 if root is None:
77 root = os.path.expanduser('~')
77 root = os.path.expanduser('~')
78 for name, path in self.configitems("paths"):
78 for name, path in self.configitems("paths"):
79 if path and path.find("://") == -1 and not os.path.isabs(path):
79 if path and path.find("://") == -1 and not os.path.isabs(path):
80 self.cdata.set("paths", name, os.path.join(root, path))
80 self.cdata.set("paths", name, os.path.join(root, path))
81
81
82 def setconfig(self, section, name, val):
82 def setconfig(self, section, name, val):
83 self.overlay[(section, name)] = val
83 self.overlay[(section, name)] = val
84
84
85 def config(self, section, name, default=None):
85 def config(self, section, name, default=None):
86 if self.overlay.has_key((section, name)):
86 if self.overlay.has_key((section, name)):
87 return self.overlay[(section, name)]
87 return self.overlay[(section, name)]
88 if self.cdata.has_option(section, name):
88 if self.cdata.has_option(section, name):
89 try:
89 try:
90 return self.cdata.get(section, name)
90 return self.cdata.get(section, name)
91 except ConfigParser.InterpolationError, inst:
91 except ConfigParser.InterpolationError, inst:
92 raise util.Abort(_("Error in configuration:\n%s") % inst)
92 raise util.Abort(_("Error in configuration:\n%s") % inst)
93 if self.parentui is None:
93 if self.parentui is None:
94 return default
94 return default
95 else:
95 else:
96 return self.parentui.config(section, name, default)
96 return self.parentui.config(section, name, default)
97
97
98 def configlist(self, section, name, default=None):
98 def configlist(self, section, name, default=None):
99 """Return a list of comma/space separated strings"""
99 """Return a list of comma/space separated strings"""
100 result = self.config(section, name)
100 result = self.config(section, name)
101 if result is None:
101 if result is None:
102 result = default or []
102 result = default or []
103 if isinstance(result, basestring):
103 if isinstance(result, basestring):
104 result = result.replace(",", " ").split()
104 result = result.replace(",", " ").split()
105 return result
105 return result
106
106
107 def configbool(self, section, name, default=False):
107 def configbool(self, section, name, default=False):
108 if self.overlay.has_key((section, name)):
108 if self.overlay.has_key((section, name)):
109 return self.overlay[(section, name)]
109 return self.overlay[(section, name)]
110 if self.cdata.has_option(section, name):
110 if self.cdata.has_option(section, name):
111 try:
111 try:
112 return self.cdata.getboolean(section, name)
112 return self.cdata.getboolean(section, name)
113 except ConfigParser.InterpolationError, inst:
113 except ConfigParser.InterpolationError, inst:
114 raise util.Abort(_("Error in configuration:\n%s") % inst)
114 raise util.Abort(_("Error in configuration:\n%s") % inst)
115 if self.parentui is None:
115 if self.parentui is None:
116 return default
116 return default
117 else:
117 else:
118 return self.parentui.configbool(section, name, default)
118 return self.parentui.configbool(section, name, default)
119
119
120 def has_config(self, section):
120 def has_config(self, section):
121 '''tell whether section exists in config.'''
121 '''tell whether section exists in config.'''
122 return self.cdata.has_section(section)
122 return self.cdata.has_section(section)
123
123
124 def configitems(self, section):
124 def configitems(self, section):
125 items = {}
125 items = {}
126 if self.parentui is not None:
126 if self.parentui is not None:
127 items = dict(self.parentui.configitems(section))
127 items = dict(self.parentui.configitems(section))
128 if self.cdata.has_section(section):
128 if self.cdata.has_section(section):
129 try:
129 try:
130 items.update(dict(self.cdata.items(section)))
130 items.update(dict(self.cdata.items(section)))
131 except ConfigParser.InterpolationError, inst:
131 except ConfigParser.InterpolationError, inst:
132 raise util.Abort(_("Error in configuration:\n%s") % inst)
132 raise util.Abort(_("Error in configuration:\n%s") % inst)
133 x = items.items()
133 x = items.items()
134 x.sort()
134 x.sort()
135 return x
135 return x
136
136
137 def walkconfig(self, seen=None):
137 def walkconfig(self, seen=None):
138 if seen is None:
138 if seen is None:
139 seen = {}
139 seen = {}
140 for (section, name), value in self.overlay.iteritems():
140 for (section, name), value in self.overlay.iteritems():
141 yield section, name, value
141 yield section, name, value
142 seen[section, name] = 1
142 seen[section, name] = 1
143 for section in self.cdata.sections():
143 for section in self.cdata.sections():
144 for name, value in self.cdata.items(section):
144 for name, value in self.cdata.items(section):
145 if (section, name) in seen: continue
145 if (section, name) in seen: continue
146 yield section, name, value.replace('\n', '\\n')
146 yield section, name, value.replace('\n', '\\n')
147 seen[section, name] = 1
147 seen[section, name] = 1
148 if self.parentui is not None:
148 if self.parentui is not None:
149 for parent in self.parentui.walkconfig(seen):
149 for parent in self.parentui.walkconfig(seen):
150 yield parent
150 yield parent
151
151
152 def extensions(self):
152 def extensions(self):
153 result = self.configitems("extensions")
153 result = self.configitems("extensions")
154 for i, (key, value) in enumerate(result):
154 for i, (key, value) in enumerate(result):
155 if value:
155 if value:
156 result[i] = (key, os.path.expanduser(value))
156 result[i] = (key, os.path.expanduser(value))
157 return result
157 return result
158
158
159 def hgignorefiles(self):
159 def hgignorefiles(self):
160 result = []
160 result = []
161 for key, value in self.configitems("ui"):
161 for key, value in self.configitems("ui"):
162 if key == 'ignore' or key.startswith('ignore.'):
162 if key == 'ignore' or key.startswith('ignore.'):
163 result.append(os.path.expanduser(value))
163 result.append(os.path.expanduser(value))
164 return result
164 return result
165
165
166 def configrevlog(self):
166 def configrevlog(self):
167 result = {}
167 result = {}
168 for key, value in self.configitems("revlog"):
168 for key, value in self.configitems("revlog"):
169 result[key.lower()] = value
169 result[key.lower()] = value
170 return result
170 return result
171
171
172 def diffopts(self):
172 def diffopts(self):
173 if self.diffcache:
173 if self.diffcache:
174 return self.diffcache
174 return self.diffcache
175 result = {'showfunc': True, 'ignorews': False}
175 result = {'showfunc': True, 'ignorews': False}
176 for key, value in self.configitems("diff"):
176 for key, value in self.configitems("diff"):
177 if value:
177 if value:
178 result[key.lower()] = (value.lower() == 'true')
178 result[key.lower()] = (value.lower() == 'true')
179 self.diffcache = result
179 self.diffcache = result
180 return result
180 return result
181
181
182 def username(self):
182 def username(self):
183 """Return default username to be used in commits.
183 """Return default username to be used in commits.
184
184
185 Searched in this order: $HGUSER, [ui] section of hgrcs, $EMAIL
185 Searched in this order: $HGUSER, [ui] section of hgrcs, $EMAIL
186 and stop searching if one of these is set.
186 and stop searching if one of these is set.
187 Abort if found username is an empty string to force specifying
187 Abort if found username is an empty string to force specifying
188 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.
189 If not found, use ($LOGNAME or $USER or $LNAME or
189 If not found, use ($LOGNAME or $USER or $LNAME or
190 $USERNAME) +"@full.hostname".
190 $USERNAME) +"@full.hostname".
191 """
191 """
192 user = os.environ.get("HGUSER")
192 user = os.environ.get("HGUSER")
193 if user is None:
193 if user is None:
194 user = self.config("ui", "username")
194 user = self.config("ui", "username")
195 if user is None:
195 if user is None:
196 user = os.environ.get("EMAIL")
196 user = os.environ.get("EMAIL")
197 if user is None:
197 if user is None:
198 try:
198 try:
199 user = '%s@%s' % (getpass.getuser(), socket.getfqdn())
199 user = '%s@%s' % (getpass.getuser(), socket.getfqdn())
200 except KeyError:
200 except KeyError:
201 raise util.Abort(_("Please specify a username."))
201 raise util.Abort(_("Please specify a username."))
202 return user
202 return user
203
203
204 def shortuser(self, user):
204 def shortuser(self, user):
205 """Return a short representation of a user name or email address."""
205 """Return a short representation of a user name or email address."""
206 if not self.verbose: user = util.shortuser(user)
206 if not self.verbose: user = util.shortuser(user)
207 return user
207 return user
208
208
209 def expandpath(self, loc, default=None):
209 def expandpath(self, loc, default=None):
210 """Return repository location relative to cwd or from [paths]"""
210 """Return repository location relative to cwd or from [paths]"""
211 if loc.find("://") != -1 or os.path.exists(loc):
211 if loc.find("://") != -1 or os.path.exists(loc):
212 return loc
212 return loc
213
213
214 path = self.config("paths", loc)
214 path = self.config("paths", loc)
215 if not path and default is not None:
215 if not path and default is not None:
216 path = self.config("paths", default)
216 path = self.config("paths", default)
217 return path or loc
217 return path or loc
218
218
219 def write(self, *args):
219 def write(self, *args):
220 if self.header:
220 if self.header:
221 if self.header != self.prev_header:
221 if self.header != self.prev_header:
222 self.prev_header = self.header
222 self.prev_header = self.header
223 self.write(*self.header)
223 self.write(*self.header)
224 self.header = []
224 self.header = []
225 for a in args:
225 for a in args:
226 sys.stdout.write(str(a))
226 sys.stdout.write(str(a))
227
227
228 def write_header(self, *args):
228 def write_header(self, *args):
229 for a in args:
229 for a in args:
230 self.header.append(str(a))
230 self.header.append(str(a))
231
231
232 def write_err(self, *args):
232 def write_err(self, *args):
233 try:
233 try:
234 if not sys.stdout.closed: sys.stdout.flush()
234 if not sys.stdout.closed: sys.stdout.flush()
235 for a in args:
235 for a in args:
236 sys.stderr.write(str(a))
236 sys.stderr.write(str(a))
237 except IOError, inst:
237 except IOError, inst:
238 if inst.errno != errno.EPIPE:
238 if inst.errno != errno.EPIPE:
239 raise
239 raise
240
240
241 def flush(self):
241 def flush(self):
242 try: sys.stdout.flush()
242 try: sys.stdout.flush()
243 except: pass
243 except: pass
244 try: sys.stderr.flush()
244 try: sys.stderr.flush()
245 except: pass
245 except: pass
246
246
247 def readline(self):
247 def readline(self):
248 return sys.stdin.readline()[:-1]
248 return sys.stdin.readline()[:-1]
249 def prompt(self, msg, pat=None, default="y"):
249 def prompt(self, msg, pat=None, default="y"):
250 if not self.interactive: return default
250 if not self.interactive: return default
251 while 1:
251 while 1:
252 self.write(msg, " ")
252 self.write(msg, " ")
253 r = self.readline()
253 r = self.readline()
254 if not pat or re.match(pat, r):
254 if not pat or re.match(pat, r):
255 return r
255 return r
256 else:
256 else:
257 self.write(_("unrecognized response\n"))
257 self.write(_("unrecognized response\n"))
258 def getpass(self, prompt=None, default=None):
258 def getpass(self, prompt=None, default=None):
259 if not self.interactive: return default
259 if not self.interactive: return default
260 return getpass.getpass(prompt or _('password: '))
260 return getpass.getpass(prompt or _('password: '))
261 def status(self, *msg):
261 def status(self, *msg):
262 if not self.quiet: self.write(*msg)
262 if not self.quiet: self.write(*msg)
263 def warn(self, *msg):
263 def warn(self, *msg):
264 self.write_err(*msg)
264 self.write_err(*msg)
265 def note(self, *msg):
265 def note(self, *msg):
266 if self.verbose: self.write(*msg)
266 if self.verbose: self.write(*msg)
267 def debug(self, *msg):
267 def debug(self, *msg):
268 if self.debugflag: self.write(*msg)
268 if self.debugflag: self.write(*msg)
269 def edit(self, text, user):
269 def edit(self, text, user):
270 (fd, name) = tempfile.mkstemp(prefix="hg-editor-", suffix=".txt",
270 (fd, name) = tempfile.mkstemp(prefix="hg-editor-", suffix=".txt",
271 text=True)
271 text=True)
272 try:
272 try:
273 f = os.fdopen(fd, "w")
273 f = os.fdopen(fd, "w")
274 f.write(text)
274 f.write(text)
275 f.close()
275 f.close()
276
276
277 editor = (os.environ.get("HGEDITOR") or
277 editor = (os.environ.get("HGEDITOR") or
278 self.config("ui", "editor") or
278 self.config("ui", "editor") or
279 os.environ.get("EDITOR", "vi"))
279 os.environ.get("EDITOR", "vi"))
280
280
281 util.system("%s \"%s\"" % (editor, name),
281 util.system("%s \"%s\"" % (editor, name),
282 environ={'HGUSER': user},
282 environ={'HGUSER': user},
283 onerr=util.Abort, errprefix=_("edit failed"))
283 onerr=util.Abort, errprefix=_("edit failed"))
284
284
285 f = open(name)
285 f = open(name)
286 t = f.read()
286 t = f.read()
287 f.close()
287 f.close()
288 t = re.sub("(?m)^HG:.*\n", "", t)
288 t = re.sub("(?m)^HG:.*\n", "", t)
289 finally:
289 finally:
290 os.unlink(name)
290 os.unlink(name)
291
291
292 return t
292 return t
293
293
294 def sendmail(self):
294 def sendmail(self):
295 '''send mail message. object returned has one method, sendmail.
295 '''send mail message. object returned has one method, sendmail.
296 call as sendmail(sender, list-of-recipients, msg).'''
296 call as sendmail(sender, list-of-recipients, msg).'''
297
297
298 def smtp():
298 def smtp():
299 '''send mail using smtp.'''
299 '''send mail using smtp.'''
300
300
301 s = smtplib.SMTP()
301 local_hostname = self.config('smtp', 'local_hostname')
302 s = smtplib.SMTP(local_hostname=local_hostname)
302 mailhost = self.config('smtp', 'host')
303 mailhost = self.config('smtp', 'host')
303 if not mailhost:
304 if not mailhost:
304 raise util.Abort(_('no [smtp]host in hgrc - cannot send mail'))
305 raise util.Abort(_('no [smtp]host in hgrc - cannot send mail'))
305 mailport = int(self.config('smtp', 'port', 25))
306 mailport = int(self.config('smtp', 'port', 25))
306 self.note(_('sending mail: smtp host %s, port %s\n') %
307 self.note(_('sending mail: smtp host %s, port %s\n') %
307 (mailhost, mailport))
308 (mailhost, mailport))
308 s.connect(host=mailhost, port=mailport)
309 s.connect(host=mailhost, port=mailport)
309 if self.configbool('smtp', 'tls'):
310 if self.configbool('smtp', 'tls'):
310 self.note(_('(using tls)\n'))
311 self.note(_('(using tls)\n'))
311 s.ehlo()
312 s.ehlo()
312 s.starttls()
313 s.starttls()
313 s.ehlo()
314 s.ehlo()
314 username = self.config('smtp', 'username')
315 username = self.config('smtp', 'username')
315 password = self.config('smtp', 'password')
316 password = self.config('smtp', 'password')
316 if username and password:
317 if username and password:
317 self.note(_('(authenticating to mail server as %s)\n') %
318 self.note(_('(authenticating to mail server as %s)\n') %
318 (username))
319 (username))
319 s.login(username, password)
320 s.login(username, password)
320 return s
321 return s
321
322
322 class sendmail(object):
323 class sendmail(object):
323 '''send mail using sendmail.'''
324 '''send mail using sendmail.'''
324
325
325 def __init__(self, ui, program):
326 def __init__(self, ui, program):
326 self.ui = ui
327 self.ui = ui
327 self.program = program
328 self.program = program
328
329
329 def sendmail(self, sender, recipients, msg):
330 def sendmail(self, sender, recipients, msg):
330 cmdline = '%s -f %s %s' % (
331 cmdline = '%s -f %s %s' % (
331 self.program, templater.email(sender),
332 self.program, templater.email(sender),
332 ' '.join(map(templater.email, recipients)))
333 ' '.join(map(templater.email, recipients)))
333 self.ui.note(_('sending mail: %s\n') % cmdline)
334 self.ui.note(_('sending mail: %s\n') % cmdline)
334 fp = os.popen(cmdline, 'w')
335 fp = os.popen(cmdline, 'w')
335 fp.write(msg)
336 fp.write(msg)
336 ret = fp.close()
337 ret = fp.close()
337 if ret:
338 if ret:
338 raise util.Abort('%s %s' % (
339 raise util.Abort('%s %s' % (
339 os.path.basename(self.program.split(None, 1)[0]),
340 os.path.basename(self.program.split(None, 1)[0]),
340 util.explain_exit(ret)[0]))
341 util.explain_exit(ret)[0]))
341
342
342 method = self.config('email', 'method', 'smtp')
343 method = self.config('email', 'method', 'smtp')
343 if method == 'smtp':
344 if method == 'smtp':
344 mail = smtp()
345 mail = smtp()
345 else:
346 else:
346 mail = sendmail(self, method)
347 mail = sendmail(self, method)
347 return mail
348 return mail
348
349
349 def print_exc(self):
350 def print_exc(self):
350 '''print exception traceback if traceback printing enabled.
351 '''print exception traceback if traceback printing enabled.
351 only to call in exception handler. returns true if traceback
352 only to call in exception handler. returns true if traceback
352 printed.'''
353 printed.'''
353 if self.traceback:
354 if self.traceback:
354 traceback.print_exc()
355 traceback.print_exc()
355 return self.traceback
356 return self.traceback
General Comments 0
You need to be logged in to leave comments. Login now