##// END OF EJS Templates
merge with crew.
Vadim Gelfer -
r2390:8d31c71e merge default
parent child Browse files
Show More
@@ -1,420 +1,428
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,345 +1,348
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 ret = []
151 ret = []
149 for k, v in self.configitems("ui"):
152 for k, v in self.configitems("ui"):
150 if k == 'ignore' or k.startswith('ignore.'):
153 if k == 'ignore' or k.startswith('ignore.'):
151 ret.append(os.path.expanduser(v))
154 ret.append(os.path.expanduser(v))
152 return ret
155 return ret
153
156
154 def configrevlog(self):
157 def configrevlog(self):
155 ret = {}
158 ret = {}
156 for k, v in self.configitems("revlog"):
159 for k, v in self.configitems("revlog"):
157 ret[k.lower()] = v
160 ret[k.lower()] = v
158 return ret
161 return ret
159
162
160 def diffopts(self):
163 def diffopts(self):
161 if self.diffcache:
164 if self.diffcache:
162 return self.diffcache
165 return self.diffcache
163 ret = { 'showfunc' : True, 'ignorews' : False}
166 ret = { 'showfunc' : True, 'ignorews' : False}
164 for k, v in self.configitems("diff"):
167 for k, v in self.configitems("diff"):
165 if v:
168 if v:
166 v = v.lower()
169 v = v.lower()
167 if v == 'true':
170 if v == 'true':
168 v = True
171 v = True
169 else:
172 else:
170 v = False
173 v = False
171 ret[k.lower()] = v
174 ret[k.lower()] = v
172 self.diffcache = ret
175 self.diffcache = ret
173 return ret
176 return ret
174
177
175 def username(self):
178 def username(self):
176 """Return default username to be used in commits.
179 """Return default username to be used in commits.
177
180
178 Searched in this order: $HGUSER, [ui] section of hgrcs, $EMAIL
181 Searched in this order: $HGUSER, [ui] section of hgrcs, $EMAIL
179 and stop searching if one of these is set.
182 and stop searching if one of these is set.
180 Abort if found username is an empty string to force specifying
183 Abort if found username is an empty string to force specifying
181 the commit user elsewhere, e.g. with line option or repo hgrc.
184 the commit user elsewhere, e.g. with line option or repo hgrc.
182 If not found, use ($LOGNAME or $USER or $LNAME or
185 If not found, use ($LOGNAME or $USER or $LNAME or
183 $USERNAME) +"@full.hostname".
186 $USERNAME) +"@full.hostname".
184 """
187 """
185 user = os.environ.get("HGUSER")
188 user = os.environ.get("HGUSER")
186 if user is None:
189 if user is None:
187 user = self.config("ui", "username")
190 user = self.config("ui", "username")
188 if user is None:
191 if user is None:
189 user = os.environ.get("EMAIL")
192 user = os.environ.get("EMAIL")
190 if user is None:
193 if user is None:
191 try:
194 try:
192 user = '%s@%s' % (getpass.getuser(), socket.getfqdn())
195 user = '%s@%s' % (getpass.getuser(), socket.getfqdn())
193 except KeyError:
196 except KeyError:
194 raise util.Abort(_("Please specify a username."))
197 raise util.Abort(_("Please specify a username."))
195 return user
198 return user
196
199
197 def shortuser(self, user):
200 def shortuser(self, user):
198 """Return a short representation of a user name or email address."""
201 """Return a short representation of a user name or email address."""
199 if not self.verbose: user = util.shortuser(user)
202 if not self.verbose: user = util.shortuser(user)
200 return user
203 return user
201
204
202 def expandpath(self, loc):
205 def expandpath(self, loc):
203 """Return repository location relative to cwd or from [paths]"""
206 """Return repository location relative to cwd or from [paths]"""
204 if loc.find("://") != -1 or os.path.exists(loc):
207 if loc.find("://") != -1 or os.path.exists(loc):
205 return loc
208 return loc
206
209
207 return self.config("paths", loc, loc)
210 return self.config("paths", loc, loc)
208
211
209 def write(self, *args):
212 def write(self, *args):
210 if self.header:
213 if self.header:
211 if self.header != self.prev_header:
214 if self.header != self.prev_header:
212 self.prev_header = self.header
215 self.prev_header = self.header
213 self.write(*self.header)
216 self.write(*self.header)
214 self.header = []
217 self.header = []
215 for a in args:
218 for a in args:
216 sys.stdout.write(str(a))
219 sys.stdout.write(str(a))
217
220
218 def write_header(self, *args):
221 def write_header(self, *args):
219 for a in args:
222 for a in args:
220 self.header.append(str(a))
223 self.header.append(str(a))
221
224
222 def write_err(self, *args):
225 def write_err(self, *args):
223 try:
226 try:
224 if not sys.stdout.closed: sys.stdout.flush()
227 if not sys.stdout.closed: sys.stdout.flush()
225 for a in args:
228 for a in args:
226 sys.stderr.write(str(a))
229 sys.stderr.write(str(a))
227 except IOError, inst:
230 except IOError, inst:
228 if inst.errno != errno.EPIPE:
231 if inst.errno != errno.EPIPE:
229 raise
232 raise
230
233
231 def flush(self):
234 def flush(self):
232 try: sys.stdout.flush()
235 try: sys.stdout.flush()
233 except: pass
236 except: pass
234 try: sys.stderr.flush()
237 try: sys.stderr.flush()
235 except: pass
238 except: pass
236
239
237 def readline(self):
240 def readline(self):
238 return sys.stdin.readline()[:-1]
241 return sys.stdin.readline()[:-1]
239 def prompt(self, msg, pat=None, default="y"):
242 def prompt(self, msg, pat=None, default="y"):
240 if not self.interactive: return default
243 if not self.interactive: return default
241 while 1:
244 while 1:
242 self.write(msg, " ")
245 self.write(msg, " ")
243 r = self.readline()
246 r = self.readline()
244 if not pat or re.match(pat, r):
247 if not pat or re.match(pat, r):
245 return r
248 return r
246 else:
249 else:
247 self.write(_("unrecognized response\n"))
250 self.write(_("unrecognized response\n"))
248 def getpass(self, prompt=None, default=None):
251 def getpass(self, prompt=None, default=None):
249 if not self.interactive: return default
252 if not self.interactive: return default
250 return getpass.getpass(prompt or _('password: '))
253 return getpass.getpass(prompt or _('password: '))
251 def status(self, *msg):
254 def status(self, *msg):
252 if not self.quiet: self.write(*msg)
255 if not self.quiet: self.write(*msg)
253 def warn(self, *msg):
256 def warn(self, *msg):
254 self.write_err(*msg)
257 self.write_err(*msg)
255 def note(self, *msg):
258 def note(self, *msg):
256 if self.verbose: self.write(*msg)
259 if self.verbose: self.write(*msg)
257 def debug(self, *msg):
260 def debug(self, *msg):
258 if self.debugflag: self.write(*msg)
261 if self.debugflag: self.write(*msg)
259 def edit(self, text, user):
262 def edit(self, text, user):
260 (fd, name) = tempfile.mkstemp(prefix="hg-editor-", suffix=".txt",
263 (fd, name) = tempfile.mkstemp(prefix="hg-editor-", suffix=".txt",
261 text=True)
264 text=True)
262 try:
265 try:
263 f = os.fdopen(fd, "w")
266 f = os.fdopen(fd, "w")
264 f.write(text)
267 f.write(text)
265 f.close()
268 f.close()
266
269
267 editor = (os.environ.get("HGEDITOR") or
270 editor = (os.environ.get("HGEDITOR") or
268 self.config("ui", "editor") or
271 self.config("ui", "editor") or
269 os.environ.get("EDITOR", "vi"))
272 os.environ.get("EDITOR", "vi"))
270
273
271 util.system("%s \"%s\"" % (editor, name),
274 util.system("%s \"%s\"" % (editor, name),
272 environ={'HGUSER': user},
275 environ={'HGUSER': user},
273 onerr=util.Abort, errprefix=_("edit failed"))
276 onerr=util.Abort, errprefix=_("edit failed"))
274
277
275 f = open(name)
278 f = open(name)
276 t = f.read()
279 t = f.read()
277 f.close()
280 f.close()
278 t = re.sub("(?m)^HG:.*\n", "", t)
281 t = re.sub("(?m)^HG:.*\n", "", t)
279 finally:
282 finally:
280 os.unlink(name)
283 os.unlink(name)
281
284
282 return t
285 return t
283
286
284 def sendmail(self):
287 def sendmail(self):
285 '''send mail message. object returned has one method, sendmail.
288 '''send mail message. object returned has one method, sendmail.
286 call as sendmail(sender, list-of-recipients, msg).'''
289 call as sendmail(sender, list-of-recipients, msg).'''
287
290
288 def smtp():
291 def smtp():
289 '''send mail using smtp.'''
292 '''send mail using smtp.'''
290
293
291 s = smtplib.SMTP()
294 s = smtplib.SMTP()
292 mailhost = self.config('smtp', 'host')
295 mailhost = self.config('smtp', 'host')
293 if not mailhost:
296 if not mailhost:
294 raise util.Abort(_('no [smtp]host in hgrc - cannot send mail'))
297 raise util.Abort(_('no [smtp]host in hgrc - cannot send mail'))
295 mailport = int(self.config('smtp', 'port', 25))
298 mailport = int(self.config('smtp', 'port', 25))
296 self.note(_('sending mail: smtp host %s, port %s\n') %
299 self.note(_('sending mail: smtp host %s, port %s\n') %
297 (mailhost, mailport))
300 (mailhost, mailport))
298 s.connect(host=mailhost, port=mailport)
301 s.connect(host=mailhost, port=mailport)
299 if self.configbool('smtp', 'tls'):
302 if self.configbool('smtp', 'tls'):
300 self.note(_('(using tls)\n'))
303 self.note(_('(using tls)\n'))
301 s.ehlo()
304 s.ehlo()
302 s.starttls()
305 s.starttls()
303 s.ehlo()
306 s.ehlo()
304 username = self.config('smtp', 'username')
307 username = self.config('smtp', 'username')
305 password = self.config('smtp', 'password')
308 password = self.config('smtp', 'password')
306 if username and password:
309 if username and password:
307 self.note(_('(authenticating to mail server as %s)\n') %
310 self.note(_('(authenticating to mail server as %s)\n') %
308 (username))
311 (username))
309 s.login(username, password)
312 s.login(username, password)
310 return s
313 return s
311
314
312 class sendmail(object):
315 class sendmail(object):
313 '''send mail using sendmail.'''
316 '''send mail using sendmail.'''
314
317
315 def __init__(self, ui, program):
318 def __init__(self, ui, program):
316 self.ui = ui
319 self.ui = ui
317 self.program = program
320 self.program = program
318
321
319 def sendmail(self, sender, recipients, msg):
322 def sendmail(self, sender, recipients, msg):
320 cmdline = '%s -f %s %s' % (
323 cmdline = '%s -f %s %s' % (
321 self.program, templater.email(sender),
324 self.program, templater.email(sender),
322 ' '.join(map(templater.email, recipients)))
325 ' '.join(map(templater.email, recipients)))
323 self.ui.note(_('sending mail: %s\n') % cmdline)
326 self.ui.note(_('sending mail: %s\n') % cmdline)
324 fp = os.popen(cmdline, 'w')
327 fp = os.popen(cmdline, 'w')
325 fp.write(msg)
328 fp.write(msg)
326 ret = fp.close()
329 ret = fp.close()
327 if ret:
330 if ret:
328 raise util.Abort('%s %s' % (
331 raise util.Abort('%s %s' % (
329 os.path.basename(self.program.split(None, 1)[0]),
332 os.path.basename(self.program.split(None, 1)[0]),
330 util.explain_exit(ret)[0]))
333 util.explain_exit(ret)[0]))
331
334
332 method = self.config('email', 'method', 'smtp')
335 method = self.config('email', 'method', 'smtp')
333 if method == 'smtp':
336 if method == 'smtp':
334 mail = smtp()
337 mail = smtp()
335 else:
338 else:
336 mail = sendmail(self, method)
339 mail = sendmail(self, method)
337 return mail
340 return mail
338
341
339 def print_exc(self):
342 def print_exc(self):
340 '''print exception traceback if traceback printing enabled.
343 '''print exception traceback if traceback printing enabled.
341 only to call in exception handler. returns true if traceback
344 only to call in exception handler. returns true if traceback
342 printed.'''
345 printed.'''
343 if self.traceback:
346 if self.traceback:
344 traceback.print_exc()
347 traceback.print_exc()
345 return self.traceback
348 return self.traceback
General Comments 0
You need to be logged in to leave comments. Login now