##// END OF EJS Templates
hgweb: add web.descend configuration variable
Dirkjan Ochtman -
r9363:8635b33e default
parent child Browse files
Show More
@@ -1,934 +1,938 b''
1 ======
1 ======
2 hgrc
2 hgrc
3 ======
3 ======
4
4
5 ---------------------------------
5 ---------------------------------
6 configuration files for Mercurial
6 configuration files for Mercurial
7 ---------------------------------
7 ---------------------------------
8
8
9 :Author: Bryan O'Sullivan <bos@serpentine.com>
9 :Author: Bryan O'Sullivan <bos@serpentine.com>
10 :Organization: Mercurial
10 :Organization: Mercurial
11 :Manual section: 5
11 :Manual section: 5
12 :Manual group: Mercurial Manual
12 :Manual group: Mercurial Manual
13
13
14
14
15 SYNOPSIS
15 SYNOPSIS
16 --------
16 --------
17
17
18 The Mercurial system uses a set of configuration files to control
18 The Mercurial system uses a set of configuration files to control
19 aspects of its behavior.
19 aspects of its behavior.
20
20
21 FILES
21 FILES
22 -----
22 -----
23
23
24 Mercurial reads configuration data from several files, if they exist.
24 Mercurial reads configuration data from several files, if they exist.
25 The names of these files depend on the system on which Mercurial is
25 The names of these files depend on the system on which Mercurial is
26 installed. ``*.rc`` files from a single directory are read in
26 installed. ``*.rc`` files from a single directory are read in
27 alphabetical order, later ones overriding earlier ones. Where multiple
27 alphabetical order, later ones overriding earlier ones. Where multiple
28 paths are given below, settings from later paths override earlier
28 paths are given below, settings from later paths override earlier
29 ones.
29 ones.
30
30
31 | (Unix) ``<install-root>/etc/mercurial/hgrc.d/*.rc``
31 | (Unix) ``<install-root>/etc/mercurial/hgrc.d/*.rc``
32 | (Unix) ``<install-root>/etc/mercurial/hgrc``
32 | (Unix) ``<install-root>/etc/mercurial/hgrc``
33
33
34 Per-installation configuration files, searched for in the
34 Per-installation configuration files, searched for in the
35 directory where Mercurial is installed. ``<install-root>`` is the
35 directory where Mercurial is installed. ``<install-root>`` is the
36 parent directory of the **hg** executable (or symlink) being run. For
36 parent directory of the **hg** executable (or symlink) being run. For
37 example, if installed in ``/shared/tools/bin/hg``, Mercurial will look
37 example, if installed in ``/shared/tools/bin/hg``, Mercurial will look
38 in ``/shared/tools/etc/mercurial/hgrc``. Options in these files apply
38 in ``/shared/tools/etc/mercurial/hgrc``. Options in these files apply
39 to all Mercurial commands executed by any user in any directory.
39 to all Mercurial commands executed by any user in any directory.
40
40
41 | (Unix) ``/etc/mercurial/hgrc.d/*.rc``
41 | (Unix) ``/etc/mercurial/hgrc.d/*.rc``
42 | (Unix) ``/etc/mercurial/hgrc``
42 | (Unix) ``/etc/mercurial/hgrc``
43
43
44 Per-system configuration files, for the system on which Mercurial
44 Per-system configuration files, for the system on which Mercurial
45 is running. Options in these files apply to all Mercurial commands
45 is running. Options in these files apply to all Mercurial commands
46 executed by any user in any directory. Options in these files
46 executed by any user in any directory. Options in these files
47 override per-installation options.
47 override per-installation options.
48
48
49 | (Windows) ``<install-dir>\Mercurial.ini`` or else
49 | (Windows) ``<install-dir>\Mercurial.ini`` or else
50 | (Windows) ``HKEY_LOCAL_MACHINE\SOFTWARE\Mercurial`` or else
50 | (Windows) ``HKEY_LOCAL_MACHINE\SOFTWARE\Mercurial`` or else
51 | (Windows) ``C:\Mercurial\Mercurial.ini``
51 | (Windows) ``C:\Mercurial\Mercurial.ini``
52
52
53 Per-installation/system configuration files, for the system on
53 Per-installation/system configuration files, for the system on
54 which Mercurial is running. Options in these files apply to all
54 which Mercurial is running. Options in these files apply to all
55 Mercurial commands executed by any user in any directory. Registry
55 Mercurial commands executed by any user in any directory. Registry
56 keys contain PATH-like strings, every part of which must reference
56 keys contain PATH-like strings, every part of which must reference
57 a ``Mercurial.ini`` file or be a directory where ``*.rc`` files will
57 a ``Mercurial.ini`` file or be a directory where ``*.rc`` files will
58 be read.
58 be read.
59
59
60 | (Unix) ``$HOME/.hgrc``
60 | (Unix) ``$HOME/.hgrc``
61 | (Windows) ``%HOME%\Mercurial.ini``
61 | (Windows) ``%HOME%\Mercurial.ini``
62 | (Windows) ``%HOME%\.hgrc``
62 | (Windows) ``%HOME%\.hgrc``
63 | (Windows) ``%USERPROFILE%\Mercurial.ini``
63 | (Windows) ``%USERPROFILE%\Mercurial.ini``
64 | (Windows) ``%USERPROFILE%\.hgrc``
64 | (Windows) ``%USERPROFILE%\.hgrc``
65
65
66 Per-user configuration file(s), for the user running Mercurial. On
66 Per-user configuration file(s), for the user running Mercurial. On
67 Windows 9x, ``%HOME%`` is replaced by ``%APPDATA%``. Options in these
67 Windows 9x, ``%HOME%`` is replaced by ``%APPDATA%``. Options in these
68 files apply to all Mercurial commands executed by this user in any
68 files apply to all Mercurial commands executed by this user in any
69 directory. Options in these files override per-installation and
69 directory. Options in these files override per-installation and
70 per-system options.
70 per-system options.
71
71
72 | (Unix, Windows) ``<repo>/.hg/hgrc``
72 | (Unix, Windows) ``<repo>/.hg/hgrc``
73
73
74 Per-repository configuration options that only apply in a
74 Per-repository configuration options that only apply in a
75 particular repository. This file is not version-controlled, and
75 particular repository. This file is not version-controlled, and
76 will not get transferred during a "clone" operation. Options in
76 will not get transferred during a "clone" operation. Options in
77 this file override options in all other configuration files. On
77 this file override options in all other configuration files. On
78 Unix, most of this file will be ignored if it doesn't belong to a
78 Unix, most of this file will be ignored if it doesn't belong to a
79 trusted user or to a trusted group. See the documentation for the
79 trusted user or to a trusted group. See the documentation for the
80 trusted section below for more details.
80 trusted section below for more details.
81
81
82 SYNTAX
82 SYNTAX
83 ------
83 ------
84
84
85 A configuration file consists of sections, led by a "``[section]``" header
85 A configuration file consists of sections, led by a "``[section]``" header
86 and followed by "``name: value``" entries; "``name=value``" is also accepted.
86 and followed by "``name: value``" entries; "``name=value``" is also accepted.
87
87
88 ::
88 ::
89
89
90 [spam]
90 [spam]
91 eggs=ham
91 eggs=ham
92 green=
92 green=
93 eggs
93 eggs
94
94
95 Each line contains one entry. If the lines that follow are indented,
95 Each line contains one entry. If the lines that follow are indented,
96 they are treated as continuations of that entry.
96 they are treated as continuations of that entry.
97
97
98 Leading whitespace is removed from values. Empty lines are skipped.
98 Leading whitespace is removed from values. Empty lines are skipped.
99
99
100 Lines beginning with "``#``" or "``;``" are ignored and may be used to provide
100 Lines beginning with "``#``" or "``;``" are ignored and may be used to provide
101 comments.
101 comments.
102
102
103 SECTIONS
103 SECTIONS
104 --------
104 --------
105
105
106 This section describes the different sections that may appear in a
106 This section describes the different sections that may appear in a
107 Mercurial "hgrc" file, the purpose of each section, its possible keys,
107 Mercurial "hgrc" file, the purpose of each section, its possible keys,
108 and their possible values.
108 and their possible values.
109
109
110 ``alias``
110 ``alias``
111 """""""""
111 """""""""
112 Defines command aliases.
112 Defines command aliases.
113 Aliases allow you to define your own commands in terms of other
113 Aliases allow you to define your own commands in terms of other
114 commands (or aliases), optionally including arguments.
114 commands (or aliases), optionally including arguments.
115
115
116 Alias definitions consist of lines of the form::
116 Alias definitions consist of lines of the form::
117
117
118 <alias> = <command> [<argument]...
118 <alias> = <command> [<argument]...
119
119
120 For example, this definition::
120 For example, this definition::
121
121
122 latest = log --limit 5
122 latest = log --limit 5
123
123
124 creates a new command ``latest`` that shows only the five most recent
124 creates a new command ``latest`` that shows only the five most recent
125 changesets. You can define subsequent aliases using earlier ones::
125 changesets. You can define subsequent aliases using earlier ones::
126
126
127 stable5 = latest -b stable
127 stable5 = latest -b stable
128
128
129 NOTE: It is possible to create aliases with the same names as existing
129 NOTE: It is possible to create aliases with the same names as existing
130 commands, which will then override the original definitions. This is
130 commands, which will then override the original definitions. This is
131 almost always a bad idea!
131 almost always a bad idea!
132
132
133
133
134 ``auth``
134 ``auth``
135 """"""""
135 """"""""
136 Authentication credentials for HTTP authentication. Each line has
136 Authentication credentials for HTTP authentication. Each line has
137 the following format::
137 the following format::
138
138
139 <name>.<argument> = <value>
139 <name>.<argument> = <value>
140
140
141 where <name> is used to group arguments into authentication entries.
141 where <name> is used to group arguments into authentication entries.
142 Example::
142 Example::
143
143
144 foo.prefix = hg.intevation.org/mercurial
144 foo.prefix = hg.intevation.org/mercurial
145 foo.username = foo
145 foo.username = foo
146 foo.password = bar
146 foo.password = bar
147 foo.schemes = http https
147 foo.schemes = http https
148
148
149 bar.prefix = secure.example.org
149 bar.prefix = secure.example.org
150 bar.key = path/to/file.key
150 bar.key = path/to/file.key
151 bar.cert = path/to/file.cert
151 bar.cert = path/to/file.cert
152 bar.schemes = https
152 bar.schemes = https
153
153
154 Supported arguments:
154 Supported arguments:
155
155
156 ``prefix``
156 ``prefix``
157 Either "``*``" or a URI prefix with or without the scheme part.
157 Either "``*``" or a URI prefix with or without the scheme part.
158 The authentication entry with the longest matching prefix is used
158 The authentication entry with the longest matching prefix is used
159 (where "``*``" matches everything and counts as a match of length
159 (where "``*``" matches everything and counts as a match of length
160 1). If the prefix doesn't include a scheme, the match is performed
160 1). If the prefix doesn't include a scheme, the match is performed
161 against the URI with its scheme stripped as well, and the schemes
161 against the URI with its scheme stripped as well, and the schemes
162 argument, q.v., is then subsequently consulted.
162 argument, q.v., is then subsequently consulted.
163 ``username``
163 ``username``
164 Optional. Username to authenticate with. If not given, and the
164 Optional. Username to authenticate with. If not given, and the
165 remote site requires basic or digest authentication, the user
165 remote site requires basic or digest authentication, the user
166 will be prompted for it.
166 will be prompted for it.
167 ``password``
167 ``password``
168 Optional. Password to authenticate with. If not given, and the
168 Optional. Password to authenticate with. If not given, and the
169 remote site requires basic or digest authentication, the user
169 remote site requires basic or digest authentication, the user
170 will be prompted for it.
170 will be prompted for it.
171 ``key``
171 ``key``
172 Optional. PEM encoded client certificate key file.
172 Optional. PEM encoded client certificate key file.
173 ``cert``
173 ``cert``
174 Optional. PEM encoded client certificate chain file.
174 Optional. PEM encoded client certificate chain file.
175 ``schemes``
175 ``schemes``
176 Optional. Space separated list of URI schemes to use this
176 Optional. Space separated list of URI schemes to use this
177 authentication entry with. Only used if the prefix doesn't include
177 authentication entry with. Only used if the prefix doesn't include
178 a scheme. Supported schemes are http and https. They will match
178 a scheme. Supported schemes are http and https. They will match
179 static-http and static-https respectively, as well.
179 static-http and static-https respectively, as well.
180 Default: https.
180 Default: https.
181
181
182 If no suitable authentication entry is found, the user is prompted
182 If no suitable authentication entry is found, the user is prompted
183 for credentials as usual if required by the remote.
183 for credentials as usual if required by the remote.
184
184
185
185
186 ``decode/encode``
186 ``decode/encode``
187 """""""""""""""""
187 """""""""""""""""
188 Filters for transforming files on checkout/checkin. This would
188 Filters for transforming files on checkout/checkin. This would
189 typically be used for newline processing or other
189 typically be used for newline processing or other
190 localization/canonicalization of files.
190 localization/canonicalization of files.
191
191
192 Filters consist of a filter pattern followed by a filter command.
192 Filters consist of a filter pattern followed by a filter command.
193 Filter patterns are globs by default, rooted at the repository root.
193 Filter patterns are globs by default, rooted at the repository root.
194 For example, to match any file ending in "``.txt``" in the root
194 For example, to match any file ending in "``.txt``" in the root
195 directory only, use the pattern "``*.txt``". To match any file ending
195 directory only, use the pattern "``*.txt``". To match any file ending
196 in "``.c``" anywhere in the repository, use the pattern "``**.c``".
196 in "``.c``" anywhere in the repository, use the pattern "``**.c``".
197
197
198 The filter command can start with a specifier, either "pipe:" or
198 The filter command can start with a specifier, either "pipe:" or
199 "tempfile:". If no specifier is given, "pipe:" is used by default.
199 "tempfile:". If no specifier is given, "pipe:" is used by default.
200
200
201 A "pipe:" command must accept data on stdin and return the transformed
201 A "pipe:" command must accept data on stdin and return the transformed
202 data on stdout.
202 data on stdout.
203
203
204 Pipe example::
204 Pipe example::
205
205
206 [encode]
206 [encode]
207 # uncompress gzip files on checkin to improve delta compression
207 # uncompress gzip files on checkin to improve delta compression
208 # note: not necessarily a good idea, just an example
208 # note: not necessarily a good idea, just an example
209 *.gz = pipe: gunzip
209 *.gz = pipe: gunzip
210
210
211 [decode]
211 [decode]
212 # recompress gzip files when writing them to the working dir (we
212 # recompress gzip files when writing them to the working dir (we
213 # can safely omit "pipe:", because it's the default)
213 # can safely omit "pipe:", because it's the default)
214 *.gz = gzip
214 *.gz = gzip
215
215
216 A "tempfile:" command is a template. The string INFILE is replaced
216 A "tempfile:" command is a template. The string INFILE is replaced
217 with the name of a temporary file that contains the data to be
217 with the name of a temporary file that contains the data to be
218 filtered by the command. The string OUTFILE is replaced with the name
218 filtered by the command. The string OUTFILE is replaced with the name
219 of an empty temporary file, where the filtered data must be written by
219 of an empty temporary file, where the filtered data must be written by
220 the command.
220 the command.
221
221
222 NOTE: the tempfile mechanism is recommended for Windows systems, where
222 NOTE: the tempfile mechanism is recommended for Windows systems, where
223 the standard shell I/O redirection operators often have strange
223 the standard shell I/O redirection operators often have strange
224 effects and may corrupt the contents of your files.
224 effects and may corrupt the contents of your files.
225
225
226 The most common usage is for LF <-> CRLF translation on Windows. For
226 The most common usage is for LF <-> CRLF translation on Windows. For
227 this, use the "smart" converters which check for binary files::
227 this, use the "smart" converters which check for binary files::
228
228
229 [extensions]
229 [extensions]
230 hgext.win32text =
230 hgext.win32text =
231 [encode]
231 [encode]
232 ** = cleverencode:
232 ** = cleverencode:
233 [decode]
233 [decode]
234 ** = cleverdecode:
234 ** = cleverdecode:
235
235
236 or if you only want to translate certain files::
236 or if you only want to translate certain files::
237
237
238 [extensions]
238 [extensions]
239 hgext.win32text =
239 hgext.win32text =
240 [encode]
240 [encode]
241 **.txt = dumbencode:
241 **.txt = dumbencode:
242 [decode]
242 [decode]
243 **.txt = dumbdecode:
243 **.txt = dumbdecode:
244
244
245
245
246 ``defaults``
246 ``defaults``
247 """"""""""""
247 """"""""""""
248
248
249 Use the [defaults] section to define command defaults, i.e. the
249 Use the [defaults] section to define command defaults, i.e. the
250 default options/arguments to pass to the specified commands.
250 default options/arguments to pass to the specified commands.
251
251
252 The following example makes 'hg log' run in verbose mode, and 'hg
252 The following example makes 'hg log' run in verbose mode, and 'hg
253 status' show only the modified files, by default::
253 status' show only the modified files, by default::
254
254
255 [defaults]
255 [defaults]
256 log = -v
256 log = -v
257 status = -m
257 status = -m
258
258
259 The actual commands, instead of their aliases, must be used when
259 The actual commands, instead of their aliases, must be used when
260 defining command defaults. The command defaults will also be applied
260 defining command defaults. The command defaults will also be applied
261 to the aliases of the commands defined.
261 to the aliases of the commands defined.
262
262
263
263
264 ``diff``
264 ``diff``
265 """"""""
265 """"""""
266
266
267 Settings used when displaying diffs. They are all Boolean and
267 Settings used when displaying diffs. They are all Boolean and
268 defaults to False.
268 defaults to False.
269
269
270 ``git``
270 ``git``
271 Use git extended diff format.
271 Use git extended diff format.
272 ``nodates``
272 ``nodates``
273 Don't include dates in diff headers.
273 Don't include dates in diff headers.
274 ``showfunc``
274 ``showfunc``
275 Show which function each change is in.
275 Show which function each change is in.
276 ``ignorews``
276 ``ignorews``
277 Ignore white space when comparing lines.
277 Ignore white space when comparing lines.
278 ``ignorewsamount``
278 ``ignorewsamount``
279 Ignore changes in the amount of white space.
279 Ignore changes in the amount of white space.
280 ``ignoreblanklines``
280 ``ignoreblanklines``
281 Ignore changes whose lines are all blank.
281 Ignore changes whose lines are all blank.
282
282
283 ``email``
283 ``email``
284 """""""""
284 """""""""
285 Settings for extensions that send email messages.
285 Settings for extensions that send email messages.
286
286
287 ``from``
287 ``from``
288 Optional. Email address to use in "From" header and SMTP envelope
288 Optional. Email address to use in "From" header and SMTP envelope
289 of outgoing messages.
289 of outgoing messages.
290 ``to``
290 ``to``
291 Optional. Comma-separated list of recipients' email addresses.
291 Optional. Comma-separated list of recipients' email addresses.
292 ``cc``
292 ``cc``
293 Optional. Comma-separated list of carbon copy recipients'
293 Optional. Comma-separated list of carbon copy recipients'
294 email addresses.
294 email addresses.
295 ``bcc``
295 ``bcc``
296 Optional. Comma-separated list of blind carbon copy recipients'
296 Optional. Comma-separated list of blind carbon copy recipients'
297 email addresses. Cannot be set interactively.
297 email addresses. Cannot be set interactively.
298 ``method``
298 ``method``
299 Optional. Method to use to send email messages. If value is "smtp"
299 Optional. Method to use to send email messages. If value is "smtp"
300 (default), use SMTP (see section "[smtp]" for configuration).
300 (default), use SMTP (see section "[smtp]" for configuration).
301 Otherwise, use as name of program to run that acts like sendmail
301 Otherwise, use as name of program to run that acts like sendmail
302 (takes "-f" option for sender, list of recipients on command line,
302 (takes "-f" option for sender, list of recipients on command line,
303 message on stdin). Normally, setting this to "sendmail" or
303 message on stdin). Normally, setting this to "sendmail" or
304 "/usr/sbin/sendmail" is enough to use sendmail to send messages.
304 "/usr/sbin/sendmail" is enough to use sendmail to send messages.
305 ``charsets``
305 ``charsets``
306 Optional. Comma-separated list of character sets considered
306 Optional. Comma-separated list of character sets considered
307 convenient for recipients. Addresses, headers, and parts not
307 convenient for recipients. Addresses, headers, and parts not
308 containing patches of outgoing messages will be encoded in the
308 containing patches of outgoing messages will be encoded in the
309 first character set to which conversion from local encoding
309 first character set to which conversion from local encoding
310 (``$HGENCODING``, ``ui.fallbackencoding``) succeeds. If correct
310 (``$HGENCODING``, ``ui.fallbackencoding``) succeeds. If correct
311 conversion fails, the text in question is sent as is. Defaults to
311 conversion fails, the text in question is sent as is. Defaults to
312 empty (explicit) list.
312 empty (explicit) list.
313
313
314 Order of outgoing email character sets::
314 Order of outgoing email character sets::
315
315
316 us-ascii always first, regardless of settings
316 us-ascii always first, regardless of settings
317 email.charsets in order given by user
317 email.charsets in order given by user
318 ui.fallbackencoding if not in email.charsets
318 ui.fallbackencoding if not in email.charsets
319 $HGENCODING if not in email.charsets
319 $HGENCODING if not in email.charsets
320 utf-8 always last, regardless of settings
320 utf-8 always last, regardless of settings
321
321
322 Email example::
322 Email example::
323
323
324 [email]
324 [email]
325 from = Joseph User <joe.user@example.com>
325 from = Joseph User <joe.user@example.com>
326 method = /usr/sbin/sendmail
326 method = /usr/sbin/sendmail
327 # charsets for western Europeans
327 # charsets for western Europeans
328 # us-ascii, utf-8 omitted, as they are tried first and last
328 # us-ascii, utf-8 omitted, as they are tried first and last
329 charsets = iso-8859-1, iso-8859-15, windows-1252
329 charsets = iso-8859-1, iso-8859-15, windows-1252
330
330
331
331
332 ``extensions``
332 ``extensions``
333 """"""""""""""
333 """"""""""""""
334
334
335 Mercurial has an extension mechanism for adding new features. To
335 Mercurial has an extension mechanism for adding new features. To
336 enable an extension, create an entry for it in this section.
336 enable an extension, create an entry for it in this section.
337
337
338 If you know that the extension is already in Python's search path,
338 If you know that the extension is already in Python's search path,
339 you can give the name of the module, followed by "``=``", with nothing
339 you can give the name of the module, followed by "``=``", with nothing
340 after the "``=``".
340 after the "``=``".
341
341
342 Otherwise, give a name that you choose, followed by "``=``", followed by
342 Otherwise, give a name that you choose, followed by "``=``", followed by
343 the path to the "``.py``" file (including the file name extension) that
343 the path to the "``.py``" file (including the file name extension) that
344 defines the extension.
344 defines the extension.
345
345
346 To explicitly disable an extension that is enabled in an hgrc of
346 To explicitly disable an extension that is enabled in an hgrc of
347 broader scope, prepend its path with "``!``", as in
347 broader scope, prepend its path with "``!``", as in
348 "``hgext.foo = !/ext/path``" or "``hgext.foo = !``" when path is not
348 "``hgext.foo = !/ext/path``" or "``hgext.foo = !``" when path is not
349 supplied.
349 supplied.
350
350
351 Example for ``~/.hgrc``::
351 Example for ``~/.hgrc``::
352
352
353 [extensions]
353 [extensions]
354 # (the mq extension will get loaded from Mercurial's path)
354 # (the mq extension will get loaded from Mercurial's path)
355 hgext.mq =
355 hgext.mq =
356 # (this extension will get loaded from the file specified)
356 # (this extension will get loaded from the file specified)
357 myfeature = ~/.hgext/myfeature.py
357 myfeature = ~/.hgext/myfeature.py
358
358
359
359
360 ``format``
360 ``format``
361 """"""""""
361 """"""""""
362
362
363 ``usestore``
363 ``usestore``
364 Enable or disable the "store" repository format which improves
364 Enable or disable the "store" repository format which improves
365 compatibility with systems that fold case or otherwise mangle
365 compatibility with systems that fold case or otherwise mangle
366 filenames. Enabled by default. Disabling this option will allow
366 filenames. Enabled by default. Disabling this option will allow
367 you to store longer filenames in some situations at the expense of
367 you to store longer filenames in some situations at the expense of
368 compatibility and ensures that the on-disk format of newly created
368 compatibility and ensures that the on-disk format of newly created
369 repositories will be compatible with Mercurial before version 0.9.4.
369 repositories will be compatible with Mercurial before version 0.9.4.
370
370
371 ``usefncache``
371 ``usefncache``
372 Enable or disable the "fncache" repository format which enhances
372 Enable or disable the "fncache" repository format which enhances
373 the "store" repository format (which has to be enabled to use
373 the "store" repository format (which has to be enabled to use
374 fncache) to allow longer filenames and avoids using Windows
374 fncache) to allow longer filenames and avoids using Windows
375 reserved names, e.g. "nul". Enabled by default. Disabling this
375 reserved names, e.g. "nul". Enabled by default. Disabling this
376 option ensures that the on-disk format of newly created
376 option ensures that the on-disk format of newly created
377 repositories will be compatible with Mercurial before version 1.1.
377 repositories will be compatible with Mercurial before version 1.1.
378
378
379 ``merge-patterns``
379 ``merge-patterns``
380 """"""""""""""""""
380 """"""""""""""""""
381
381
382 This section specifies merge tools to associate with particular file
382 This section specifies merge tools to associate with particular file
383 patterns. Tools matched here will take precedence over the default
383 patterns. Tools matched here will take precedence over the default
384 merge tool. Patterns are globs by default, rooted at the repository
384 merge tool. Patterns are globs by default, rooted at the repository
385 root.
385 root.
386
386
387 Example::
387 Example::
388
388
389 [merge-patterns]
389 [merge-patterns]
390 **.c = kdiff3
390 **.c = kdiff3
391 **.jpg = myimgmerge
391 **.jpg = myimgmerge
392
392
393 ``merge-tools``
393 ``merge-tools``
394 """""""""""""""
394 """""""""""""""
395
395
396 This section configures external merge tools to use for file-level
396 This section configures external merge tools to use for file-level
397 merges.
397 merges.
398
398
399 Example ``~/.hgrc``::
399 Example ``~/.hgrc``::
400
400
401 [merge-tools]
401 [merge-tools]
402 # Override stock tool location
402 # Override stock tool location
403 kdiff3.executable = ~/bin/kdiff3
403 kdiff3.executable = ~/bin/kdiff3
404 # Specify command line
404 # Specify command line
405 kdiff3.args = $base $local $other -o $output
405 kdiff3.args = $base $local $other -o $output
406 # Give higher priority
406 # Give higher priority
407 kdiff3.priority = 1
407 kdiff3.priority = 1
408
408
409 # Define new tool
409 # Define new tool
410 myHtmlTool.args = -m $local $other $base $output
410 myHtmlTool.args = -m $local $other $base $output
411 myHtmlTool.regkey = Software\FooSoftware\HtmlMerge
411 myHtmlTool.regkey = Software\FooSoftware\HtmlMerge
412 myHtmlTool.priority = 1
412 myHtmlTool.priority = 1
413
413
414 Supported arguments:
414 Supported arguments:
415
415
416 ``priority``
416 ``priority``
417 The priority in which to evaluate this tool.
417 The priority in which to evaluate this tool.
418 Default: 0.
418 Default: 0.
419 ``executable``
419 ``executable``
420 Either just the name of the executable or its pathname.
420 Either just the name of the executable or its pathname.
421 Default: the tool name.
421 Default: the tool name.
422 ``args``
422 ``args``
423 The arguments to pass to the tool executable. You can refer to the
423 The arguments to pass to the tool executable. You can refer to the
424 files being merged as well as the output file through these
424 files being merged as well as the output file through these
425 variables: ``$base``, ``$local``, ``$other``, ``$output``.
425 variables: ``$base``, ``$local``, ``$other``, ``$output``.
426 Default: ``$local $base $other``
426 Default: ``$local $base $other``
427 ``premerge``
427 ``premerge``
428 Attempt to run internal non-interactive 3-way merge tool before
428 Attempt to run internal non-interactive 3-way merge tool before
429 launching external tool.
429 launching external tool.
430 Default: True
430 Default: True
431 ``binary``
431 ``binary``
432 This tool can merge binary files. Defaults to False, unless tool
432 This tool can merge binary files. Defaults to False, unless tool
433 was selected by file pattern match.
433 was selected by file pattern match.
434 ``symlink``
434 ``symlink``
435 This tool can merge symlinks. Defaults to False, even if tool was
435 This tool can merge symlinks. Defaults to False, even if tool was
436 selected by file pattern match.
436 selected by file pattern match.
437 ``checkconflicts``
437 ``checkconflicts``
438 Check whether there are conflicts even though the tool reported
438 Check whether there are conflicts even though the tool reported
439 success.
439 success.
440 Default: False
440 Default: False
441 ``checkchanged``
441 ``checkchanged``
442 Check whether outputs were written even though the tool reported
442 Check whether outputs were written even though the tool reported
443 success.
443 success.
444 Default: False
444 Default: False
445 ``fixeol``
445 ``fixeol``
446 Attempt to fix up EOL changes caused by the merge tool.
446 Attempt to fix up EOL changes caused by the merge tool.
447 Default: False
447 Default: False
448 ``gui``
448 ``gui``
449 This tool requires a graphical interface to run. Default: False
449 This tool requires a graphical interface to run. Default: False
450 ``regkey``
450 ``regkey``
451 Windows registry key which describes install location of this
451 Windows registry key which describes install location of this
452 tool. Mercurial will search for this key first under
452 tool. Mercurial will search for this key first under
453 ``HKEY_CURRENT_USER`` and then under ``HKEY_LOCAL_MACHINE``.
453 ``HKEY_CURRENT_USER`` and then under ``HKEY_LOCAL_MACHINE``.
454 Default: None
454 Default: None
455 ``regname``
455 ``regname``
456 Name of value to read from specified registry key. Defaults to the
456 Name of value to read from specified registry key. Defaults to the
457 unnamed (default) value.
457 unnamed (default) value.
458 ``regappend``
458 ``regappend``
459 String to append to the value read from the registry, typically
459 String to append to the value read from the registry, typically
460 the executable name of the tool.
460 the executable name of the tool.
461 Default: None
461 Default: None
462
462
463
463
464 ``hooks``
464 ``hooks``
465 """""""""
465 """""""""
466 Commands or Python functions that get automatically executed by
466 Commands or Python functions that get automatically executed by
467 various actions such as starting or finishing a commit. Multiple
467 various actions such as starting or finishing a commit. Multiple
468 hooks can be run for the same action by appending a suffix to the
468 hooks can be run for the same action by appending a suffix to the
469 action. Overriding a site-wide hook can be done by changing its
469 action. Overriding a site-wide hook can be done by changing its
470 value or setting it to an empty string.
470 value or setting it to an empty string.
471
471
472 Example ``.hg/hgrc``::
472 Example ``.hg/hgrc``::
473
473
474 [hooks]
474 [hooks]
475 # do not use the site-wide hook
475 # do not use the site-wide hook
476 incoming =
476 incoming =
477 incoming.email = /my/email/hook
477 incoming.email = /my/email/hook
478 incoming.autobuild = /my/build/hook
478 incoming.autobuild = /my/build/hook
479
479
480 Most hooks are run with environment variables set that give useful
480 Most hooks are run with environment variables set that give useful
481 additional information. For each hook below, the environment
481 additional information. For each hook below, the environment
482 variables it is passed are listed with names of the form "$HG_foo".
482 variables it is passed are listed with names of the form "$HG_foo".
483
483
484 ``changegroup``
484 ``changegroup``
485 Run after a changegroup has been added via push, pull or unbundle.
485 Run after a changegroup has been added via push, pull or unbundle.
486 ID of the first new changeset is in ``$HG_NODE``. URL from which
486 ID of the first new changeset is in ``$HG_NODE``. URL from which
487 changes came is in ``$HG_URL``.
487 changes came is in ``$HG_URL``.
488 ``commit``
488 ``commit``
489 Run after a changeset has been created in the local repository. ID
489 Run after a changeset has been created in the local repository. ID
490 of the newly created changeset is in ``$HG_NODE``. Parent changeset
490 of the newly created changeset is in ``$HG_NODE``. Parent changeset
491 IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
491 IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
492 ``incoming``
492 ``incoming``
493 Run after a changeset has been pulled, pushed, or unbundled into
493 Run after a changeset has been pulled, pushed, or unbundled into
494 the local repository. The ID of the newly arrived changeset is in
494 the local repository. The ID of the newly arrived changeset is in
495 ``$HG_NODE``. URL that was source of changes came is in ``$HG_URL``.
495 ``$HG_NODE``. URL that was source of changes came is in ``$HG_URL``.
496 ``outgoing``
496 ``outgoing``
497 Run after sending changes from local repository to another. ID of
497 Run after sending changes from local repository to another. ID of
498 first changeset sent is in ``$HG_NODE``. Source of operation is in
498 first changeset sent is in ``$HG_NODE``. Source of operation is in
499 ``$HG_SOURCE``; see "preoutgoing" hook for description.
499 ``$HG_SOURCE``; see "preoutgoing" hook for description.
500 ``post-<command>``
500 ``post-<command>``
501 Run after successful invocations of the associated command. The
501 Run after successful invocations of the associated command. The
502 contents of the command line are passed as ``$HG_ARGS`` and the result
502 contents of the command line are passed as ``$HG_ARGS`` and the result
503 code in ``$HG_RESULT``. Hook failure is ignored.
503 code in ``$HG_RESULT``. Hook failure is ignored.
504 ``pre-<command>``
504 ``pre-<command>``
505 Run before executing the associated command. The contents of the
505 Run before executing the associated command. The contents of the
506 command line are passed as ``$HG_ARGS``. If the hook returns failure,
506 command line are passed as ``$HG_ARGS``. If the hook returns failure,
507 the command doesn't execute and Mercurial returns the failure
507 the command doesn't execute and Mercurial returns the failure
508 code.
508 code.
509 ``prechangegroup``
509 ``prechangegroup``
510 Run before a changegroup is added via push, pull or unbundle. Exit
510 Run before a changegroup is added via push, pull or unbundle. Exit
511 status 0 allows the changegroup to proceed. Non-zero status will
511 status 0 allows the changegroup to proceed. Non-zero status will
512 cause the push, pull or unbundle to fail. URL from which changes
512 cause the push, pull or unbundle to fail. URL from which changes
513 will come is in ``$HG_URL``.
513 will come is in ``$HG_URL``.
514 ``precommit``
514 ``precommit``
515 Run before starting a local commit. Exit status 0 allows the
515 Run before starting a local commit. Exit status 0 allows the
516 commit to proceed. Non-zero status will cause the commit to fail.
516 commit to proceed. Non-zero status will cause the commit to fail.
517 Parent changeset IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
517 Parent changeset IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
518 ``preoutgoing``
518 ``preoutgoing``
519 Run before collecting changes to send from the local repository to
519 Run before collecting changes to send from the local repository to
520 another. Non-zero status will cause failure. This lets you prevent
520 another. Non-zero status will cause failure. This lets you prevent
521 pull over HTTP or SSH. Also prevents against local pull, push
521 pull over HTTP or SSH. Also prevents against local pull, push
522 (outbound) or bundle commands, but not effective, since you can
522 (outbound) or bundle commands, but not effective, since you can
523 just copy files instead then. Source of operation is in
523 just copy files instead then. Source of operation is in
524 ``$HG_SOURCE``. If "serve", operation is happening on behalf of remote
524 ``$HG_SOURCE``. If "serve", operation is happening on behalf of remote
525 SSH or HTTP repository. If "push", "pull" or "bundle", operation
525 SSH or HTTP repository. If "push", "pull" or "bundle", operation
526 is happening on behalf of repository on same system.
526 is happening on behalf of repository on same system.
527 ``pretag``
527 ``pretag``
528 Run before creating a tag. Exit status 0 allows the tag to be
528 Run before creating a tag. Exit status 0 allows the tag to be
529 created. Non-zero status will cause the tag to fail. ID of
529 created. Non-zero status will cause the tag to fail. ID of
530 changeset to tag is in ``$HG_NODE``. Name of tag is in ``$HG_TAG``. Tag is
530 changeset to tag is in ``$HG_NODE``. Name of tag is in ``$HG_TAG``. Tag is
531 local if ``$HG_LOCAL=1``, in repository if ``$HG_LOCAL=0``.
531 local if ``$HG_LOCAL=1``, in repository if ``$HG_LOCAL=0``.
532 ``pretxnchangegroup``
532 ``pretxnchangegroup``
533 Run after a changegroup has been added via push, pull or unbundle,
533 Run after a changegroup has been added via push, pull or unbundle,
534 but before the transaction has been committed. Changegroup is
534 but before the transaction has been committed. Changegroup is
535 visible to hook program. This lets you validate incoming changes
535 visible to hook program. This lets you validate incoming changes
536 before accepting them. Passed the ID of the first new changeset in
536 before accepting them. Passed the ID of the first new changeset in
537 ``$HG_NODE``. Exit status 0 allows the transaction to commit. Non-zero
537 ``$HG_NODE``. Exit status 0 allows the transaction to commit. Non-zero
538 status will cause the transaction to be rolled back and the push,
538 status will cause the transaction to be rolled back and the push,
539 pull or unbundle will fail. URL that was source of changes is in
539 pull or unbundle will fail. URL that was source of changes is in
540 ``$HG_URL``.
540 ``$HG_URL``.
541 ``pretxncommit``
541 ``pretxncommit``
542 Run after a changeset has been created but the transaction not yet
542 Run after a changeset has been created but the transaction not yet
543 committed. Changeset is visible to hook program. This lets you
543 committed. Changeset is visible to hook program. This lets you
544 validate commit message and changes. Exit status 0 allows the
544 validate commit message and changes. Exit status 0 allows the
545 commit to proceed. Non-zero status will cause the transaction to
545 commit to proceed. Non-zero status will cause the transaction to
546 be rolled back. ID of changeset is in ``$HG_NODE``. Parent changeset
546 be rolled back. ID of changeset is in ``$HG_NODE``. Parent changeset
547 IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
547 IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
548 ``preupdate``
548 ``preupdate``
549 Run before updating the working directory. Exit status 0 allows
549 Run before updating the working directory. Exit status 0 allows
550 the update to proceed. Non-zero status will prevent the update.
550 the update to proceed. Non-zero status will prevent the update.
551 Changeset ID of first new parent is in ``$HG_PARENT1``. If merge, ID
551 Changeset ID of first new parent is in ``$HG_PARENT1``. If merge, ID
552 of second new parent is in ``$HG_PARENT2``.
552 of second new parent is in ``$HG_PARENT2``.
553 ``tag``
553 ``tag``
554 Run after a tag is created. ID of tagged changeset is in ``$HG_NODE``.
554 Run after a tag is created. ID of tagged changeset is in ``$HG_NODE``.
555 Name of tag is in ``$HG_TAG``. Tag is local if ``$HG_LOCAL=1``, in
555 Name of tag is in ``$HG_TAG``. Tag is local if ``$HG_LOCAL=1``, in
556 repository if ``$HG_LOCAL=0``.
556 repository if ``$HG_LOCAL=0``.
557 ``update``
557 ``update``
558 Run after updating the working directory. Changeset ID of first
558 Run after updating the working directory. Changeset ID of first
559 new parent is in ``$HG_PARENT1``. If merge, ID of second new parent is
559 new parent is in ``$HG_PARENT1``. If merge, ID of second new parent is
560 in ``$HG_PARENT2``. If the update succeeded, ``$HG_ERROR=0``. If the
560 in ``$HG_PARENT2``. If the update succeeded, ``$HG_ERROR=0``. If the
561 update failed (e.g. because conflicts not resolved), ``$HG_ERROR=1``.
561 update failed (e.g. because conflicts not resolved), ``$HG_ERROR=1``.
562
562
563 NOTE: it is generally better to use standard hooks rather than the
563 NOTE: it is generally better to use standard hooks rather than the
564 generic pre- and post- command hooks as they are guaranteed to be
564 generic pre- and post- command hooks as they are guaranteed to be
565 called in the appropriate contexts for influencing transactions.
565 called in the appropriate contexts for influencing transactions.
566 Also, hooks like "commit" will be called in all contexts that
566 Also, hooks like "commit" will be called in all contexts that
567 generate a commit (e.g. tag) and not just the commit command.
567 generate a commit (e.g. tag) and not just the commit command.
568
568
569 NOTE: Environment variables with empty values may not be passed to
569 NOTE: Environment variables with empty values may not be passed to
570 hooks on platforms such as Windows. As an example, ``$HG_PARENT2`` will
570 hooks on platforms such as Windows. As an example, ``$HG_PARENT2`` will
571 have an empty value under Unix-like platforms for non-merge
571 have an empty value under Unix-like platforms for non-merge
572 changesets, while it will not be available at all under Windows.
572 changesets, while it will not be available at all under Windows.
573
573
574 The syntax for Python hooks is as follows::
574 The syntax for Python hooks is as follows::
575
575
576 hookname = python:modulename.submodule.callable
576 hookname = python:modulename.submodule.callable
577 hookname = python:/path/to/python/module.py:callable
577 hookname = python:/path/to/python/module.py:callable
578
578
579 Python hooks are run within the Mercurial process. Each hook is
579 Python hooks are run within the Mercurial process. Each hook is
580 called with at least three keyword arguments: a ui object (keyword
580 called with at least three keyword arguments: a ui object (keyword
581 "ui"), a repository object (keyword "repo"), and a "hooktype"
581 "ui"), a repository object (keyword "repo"), and a "hooktype"
582 keyword that tells what kind of hook is used. Arguments listed as
582 keyword that tells what kind of hook is used. Arguments listed as
583 environment variables above are passed as keyword arguments, with no
583 environment variables above are passed as keyword arguments, with no
584 "``HG_``" prefix, and names in lower case.
584 "``HG_``" prefix, and names in lower case.
585
585
586 If a Python hook returns a "true" value or raises an exception, this
586 If a Python hook returns a "true" value or raises an exception, this
587 is treated as a failure.
587 is treated as a failure.
588
588
589
589
590 ``http_proxy``
590 ``http_proxy``
591 """"""""""""""
591 """"""""""""""
592 Used to access web-based Mercurial repositories through a HTTP
592 Used to access web-based Mercurial repositories through a HTTP
593 proxy.
593 proxy.
594
594
595 ``host``
595 ``host``
596 Host name and (optional) port of the proxy server, for example
596 Host name and (optional) port of the proxy server, for example
597 "myproxy:8000".
597 "myproxy:8000".
598 ``no``
598 ``no``
599 Optional. Comma-separated list of host names that should bypass
599 Optional. Comma-separated list of host names that should bypass
600 the proxy.
600 the proxy.
601 ``passwd``
601 ``passwd``
602 Optional. Password to authenticate with at the proxy server.
602 Optional. Password to authenticate with at the proxy server.
603 ``user``
603 ``user``
604 Optional. User name to authenticate with at the proxy server.
604 Optional. User name to authenticate with at the proxy server.
605
605
606 ``smtp``
606 ``smtp``
607 """"""""
607 """"""""
608 Configuration for extensions that need to send email messages.
608 Configuration for extensions that need to send email messages.
609
609
610 ``host``
610 ``host``
611 Host name of mail server, e.g. "mail.example.com".
611 Host name of mail server, e.g. "mail.example.com".
612 ``port``
612 ``port``
613 Optional. Port to connect to on mail server. Default: 25.
613 Optional. Port to connect to on mail server. Default: 25.
614 ``tls``
614 ``tls``
615 Optional. Whether to connect to mail server using TLS. True or
615 Optional. Whether to connect to mail server using TLS. True or
616 False. Default: False.
616 False. Default: False.
617 ``username``
617 ``username``
618 Optional. User name to authenticate to SMTP server with. If
618 Optional. User name to authenticate to SMTP server with. If
619 username is specified, password must also be specified.
619 username is specified, password must also be specified.
620 Default: none.
620 Default: none.
621 ``password``
621 ``password``
622 Optional. Password to authenticate to SMTP server with. If
622 Optional. Password to authenticate to SMTP server with. If
623 username is specified, password must also be specified.
623 username is specified, password must also be specified.
624 Default: none.
624 Default: none.
625 ``local_hostname``
625 ``local_hostname``
626 Optional. It's the hostname that the sender can use to identify
626 Optional. It's the hostname that the sender can use to identify
627 itself to the MTA.
627 itself to the MTA.
628
628
629
629
630 ``patch``
630 ``patch``
631 """""""""
631 """""""""
632 Settings used when applying patches, for instance through the 'import'
632 Settings used when applying patches, for instance through the 'import'
633 command or with Mercurial Queues extension.
633 command or with Mercurial Queues extension.
634
634
635 ``eol``
635 ``eol``
636 When set to 'strict' patch content and patched files end of lines
636 When set to 'strict' patch content and patched files end of lines
637 are preserved. When set to 'lf' or 'crlf', both files end of lines
637 are preserved. When set to 'lf' or 'crlf', both files end of lines
638 are ignored when patching and the result line endings are
638 are ignored when patching and the result line endings are
639 normalized to either LF (Unix) or CRLF (Windows).
639 normalized to either LF (Unix) or CRLF (Windows).
640 Default: strict.
640 Default: strict.
641
641
642
642
643 ``paths``
643 ``paths``
644 """""""""
644 """""""""
645 Assigns symbolic names to repositories. The left side is the
645 Assigns symbolic names to repositories. The left side is the
646 symbolic name, and the right gives the directory or URL that is the
646 symbolic name, and the right gives the directory or URL that is the
647 location of the repository. Default paths can be declared by setting
647 location of the repository. Default paths can be declared by setting
648 the following entries.
648 the following entries.
649
649
650 ``default``
650 ``default``
651 Directory or URL to use when pulling if no source is specified.
651 Directory or URL to use when pulling if no source is specified.
652 Default is set to repository from which the current repository was
652 Default is set to repository from which the current repository was
653 cloned.
653 cloned.
654 ``default-push``
654 ``default-push``
655 Optional. Directory or URL to use when pushing if no destination
655 Optional. Directory or URL to use when pushing if no destination
656 is specified.
656 is specified.
657
657
658
658
659 ``profiling``
659 ``profiling``
660 """""""""""""
660 """""""""""""
661 Specifies profiling format and file output. In this section
661 Specifies profiling format and file output. In this section
662 description, 'profiling data' stands for the raw data collected
662 description, 'profiling data' stands for the raw data collected
663 during profiling, while 'profiling report' stands for a statistical
663 during profiling, while 'profiling report' stands for a statistical
664 text report generated from the profiling data. The profiling is done
664 text report generated from the profiling data. The profiling is done
665 using lsprof.
665 using lsprof.
666
666
667 ``format``
667 ``format``
668 Profiling format.
668 Profiling format.
669 Default: text.
669 Default: text.
670
670
671 ``text``
671 ``text``
672 Generate a profiling report. When saving to a file, it should be
672 Generate a profiling report. When saving to a file, it should be
673 noted that only the report is saved, and the profiling data is
673 noted that only the report is saved, and the profiling data is
674 not kept.
674 not kept.
675 ``kcachegrind``
675 ``kcachegrind``
676 Format profiling data for kcachegrind use: when saving to a
676 Format profiling data for kcachegrind use: when saving to a
677 file, the generated file can directly be loaded into
677 file, the generated file can directly be loaded into
678 kcachegrind.
678 kcachegrind.
679 ``output``
679 ``output``
680 File path where profiling data or report should be saved. If the
680 File path where profiling data or report should be saved. If the
681 file exists, it is replaced. Default: None, data is printed on
681 file exists, it is replaced. Default: None, data is printed on
682 stderr
682 stderr
683
683
684 ``server``
684 ``server``
685 """"""""""
685 """"""""""
686 Controls generic server settings.
686 Controls generic server settings.
687
687
688 ``uncompressed``
688 ``uncompressed``
689 Whether to allow clients to clone a repository using the
689 Whether to allow clients to clone a repository using the
690 uncompressed streaming protocol. This transfers about 40% more
690 uncompressed streaming protocol. This transfers about 40% more
691 data than a regular clone, but uses less memory and CPU on both
691 data than a regular clone, but uses less memory and CPU on both
692 server and client. Over a LAN (100 Mbps or better) or a very fast
692 server and client. Over a LAN (100 Mbps or better) or a very fast
693 WAN, an uncompressed streaming clone is a lot faster (~10x) than a
693 WAN, an uncompressed streaming clone is a lot faster (~10x) than a
694 regular clone. Over most WAN connections (anything slower than
694 regular clone. Over most WAN connections (anything slower than
695 about 6 Mbps), uncompressed streaming is slower, because of the
695 about 6 Mbps), uncompressed streaming is slower, because of the
696 extra data transfer overhead. Default is False.
696 extra data transfer overhead. Default is False.
697
697
698
698
699 ``trusted``
699 ``trusted``
700 """""""""""
700 """""""""""
701 For security reasons, Mercurial will not use the settings in the
701 For security reasons, Mercurial will not use the settings in the
702 ``.hg/hgrc`` file from a repository if it doesn't belong to a trusted
702 ``.hg/hgrc`` file from a repository if it doesn't belong to a trusted
703 user or to a trusted group. The main exception is the web interface,
703 user or to a trusted group. The main exception is the web interface,
704 which automatically uses some safe settings, since it's common to
704 which automatically uses some safe settings, since it's common to
705 serve repositories from different users.
705 serve repositories from different users.
706
706
707 This section specifies what users and groups are trusted. The
707 This section specifies what users and groups are trusted. The
708 current user is always trusted. To trust everybody, list a user or a
708 current user is always trusted. To trust everybody, list a user or a
709 group with name "``*``".
709 group with name "``*``".
710
710
711 ``users``
711 ``users``
712 Comma-separated list of trusted users.
712 Comma-separated list of trusted users.
713 ``groups``
713 ``groups``
714 Comma-separated list of trusted groups.
714 Comma-separated list of trusted groups.
715
715
716
716
717 ``ui``
717 ``ui``
718 """"""
718 """"""
719
719
720 User interface controls.
720 User interface controls.
721
721
722 ``archivemeta``
722 ``archivemeta``
723 Whether to include the .hg_archival.txt file containing meta data
723 Whether to include the .hg_archival.txt file containing meta data
724 (hashes for the repository base and for tip) in archives created
724 (hashes for the repository base and for tip) in archives created
725 by the hg archive command or downloaded via hgweb.
725 by the hg archive command or downloaded via hgweb.
726 Default is true.
726 Default is true.
727 ``askusername``
727 ``askusername``
728 Whether to prompt for a username when committing. If True, and
728 Whether to prompt for a username when committing. If True, and
729 neither ``$HGUSER`` nor ``$EMAIL`` has been specified, then the user will
729 neither ``$HGUSER`` nor ``$EMAIL`` has been specified, then the user will
730 be prompted to enter a username. If no username is entered, the
730 be prompted to enter a username. If no username is entered, the
731 default USER@HOST is used instead.
731 default USER@HOST is used instead.
732 Default is False.
732 Default is False.
733 ``debug``
733 ``debug``
734 Print debugging information. True or False. Default is False.
734 Print debugging information. True or False. Default is False.
735 ``editor``
735 ``editor``
736 The editor to use during a commit. Default is ``$EDITOR`` or "vi".
736 The editor to use during a commit. Default is ``$EDITOR`` or "vi".
737 ``fallbackencoding``
737 ``fallbackencoding``
738 Encoding to try if it's not possible to decode the changelog using
738 Encoding to try if it's not possible to decode the changelog using
739 UTF-8. Default is ISO-8859-1.
739 UTF-8. Default is ISO-8859-1.
740 ``ignore``
740 ``ignore``
741 A file to read per-user ignore patterns from. This file should be
741 A file to read per-user ignore patterns from. This file should be
742 in the same format as a repository-wide .hgignore file. This
742 in the same format as a repository-wide .hgignore file. This
743 option supports hook syntax, so if you want to specify multiple
743 option supports hook syntax, so if you want to specify multiple
744 ignore files, you can do so by setting something like
744 ignore files, you can do so by setting something like
745 "``ignore.other = ~/.hgignore2``". For details of the ignore file
745 "``ignore.other = ~/.hgignore2``". For details of the ignore file
746 format, see the |hgignore(5)|_ man page.
746 format, see the |hgignore(5)|_ man page.
747 ``interactive``
747 ``interactive``
748 Allow to prompt the user. True or False. Default is True.
748 Allow to prompt the user. True or False. Default is True.
749 ``logtemplate``
749 ``logtemplate``
750 Template string for commands that print changesets.
750 Template string for commands that print changesets.
751 ``merge``
751 ``merge``
752 The conflict resolution program to use during a manual merge.
752 The conflict resolution program to use during a manual merge.
753 There are some internal tools available:
753 There are some internal tools available:
754
754
755 ``internal:local``
755 ``internal:local``
756 keep the local version
756 keep the local version
757 ``internal:other``
757 ``internal:other``
758 use the other version
758 use the other version
759 ``internal:merge``
759 ``internal:merge``
760 use the internal non-interactive merge tool
760 use the internal non-interactive merge tool
761 ``internal:fail``
761 ``internal:fail``
762 fail to merge
762 fail to merge
763
763
764 For more information on configuring merge tools see the
764 For more information on configuring merge tools see the
765 merge-tools section.
765 merge-tools section.
766
766
767 ``patch``
767 ``patch``
768 command to use to apply patches. Look for 'gpatch' or 'patch' in
768 command to use to apply patches. Look for 'gpatch' or 'patch' in
769 PATH if unset.
769 PATH if unset.
770 ``quiet``
770 ``quiet``
771 Reduce the amount of output printed. True or False. Default is False.
771 Reduce the amount of output printed. True or False. Default is False.
772 ``remotecmd``
772 ``remotecmd``
773 remote command to use for clone/push/pull operations. Default is 'hg'.
773 remote command to use for clone/push/pull operations. Default is 'hg'.
774 ``report_untrusted``
774 ``report_untrusted``
775 Warn if a ``.hg/hgrc`` file is ignored due to not being owned by a
775 Warn if a ``.hg/hgrc`` file is ignored due to not being owned by a
776 trusted user or group. True or False. Default is True.
776 trusted user or group. True or False. Default is True.
777 ``slash``
777 ``slash``
778 Display paths using a slash ("``/``") as the path separator. This
778 Display paths using a slash ("``/``") as the path separator. This
779 only makes a difference on systems where the default path
779 only makes a difference on systems where the default path
780 separator is not the slash character (e.g. Windows uses the
780 separator is not the slash character (e.g. Windows uses the
781 backslash character ("``\``")).
781 backslash character ("``\``")).
782 Default is False.
782 Default is False.
783 ``ssh``
783 ``ssh``
784 command to use for SSH connections. Default is 'ssh'.
784 command to use for SSH connections. Default is 'ssh'.
785 ``strict``
785 ``strict``
786 Require exact command names, instead of allowing unambiguous
786 Require exact command names, instead of allowing unambiguous
787 abbreviations. True or False. Default is False.
787 abbreviations. True or False. Default is False.
788 ``style``
788 ``style``
789 Name of style to use for command output.
789 Name of style to use for command output.
790 ``timeout``
790 ``timeout``
791 The timeout used when a lock is held (in seconds), a negative value
791 The timeout used when a lock is held (in seconds), a negative value
792 means no timeout. Default is 600.
792 means no timeout. Default is 600.
793 ``username``
793 ``username``
794 The committer of a changeset created when running "commit".
794 The committer of a changeset created when running "commit".
795 Typically a person's name and email address, e.g. "Fred Widget
795 Typically a person's name and email address, e.g. "Fred Widget
796 <fred@example.com>". Default is ``$EMAIL`` or username@hostname. If
796 <fred@example.com>". Default is ``$EMAIL`` or username@hostname. If
797 the username in hgrc is empty, it has to be specified manually or
797 the username in hgrc is empty, it has to be specified manually or
798 in a different hgrc file (e.g. ``$HOME/.hgrc``, if the admin set
798 in a different hgrc file (e.g. ``$HOME/.hgrc``, if the admin set
799 "username =" in the system hgrc).
799 "username =" in the system hgrc).
800 ``verbose``
800 ``verbose``
801 Increase the amount of output printed. True or False. Default is False.
801 Increase the amount of output printed. True or False. Default is False.
802
802
803
803
804 ``web``
804 ``web``
805 """""""
805 """""""
806 Web interface configuration.
806 Web interface configuration.
807
807
808 ``accesslog``
808 ``accesslog``
809 Where to output the access log. Default is stdout.
809 Where to output the access log. Default is stdout.
810 ``address``
810 ``address``
811 Interface address to bind to. Default is all.
811 Interface address to bind to. Default is all.
812 ``allow_archive``
812 ``allow_archive``
813 List of archive format (bz2, gz, zip) allowed for downloading.
813 List of archive format (bz2, gz, zip) allowed for downloading.
814 Default is empty.
814 Default is empty.
815 ``allowbz2``
815 ``allowbz2``
816 (DEPRECATED) Whether to allow .tar.bz2 downloading of repository
816 (DEPRECATED) Whether to allow .tar.bz2 downloading of repository
817 revisions.
817 revisions.
818 Default is false.
818 Default is false.
819 ``allowgz``
819 ``allowgz``
820 (DEPRECATED) Whether to allow .tar.gz downloading of repository
820 (DEPRECATED) Whether to allow .tar.gz downloading of repository
821 revisions.
821 revisions.
822 Default is false.
822 Default is false.
823 ``allowpull``
823 ``allowpull``
824 Whether to allow pulling from the repository. Default is true.
824 Whether to allow pulling from the repository. Default is true.
825 ``allow_push``
825 ``allow_push``
826 Whether to allow pushing to the repository. If empty or not set,
826 Whether to allow pushing to the repository. If empty or not set,
827 push is not allowed. If the special value "``*``", any remote user can
827 push is not allowed. If the special value "``*``", any remote user can
828 push, including unauthenticated users. Otherwise, the remote user
828 push, including unauthenticated users. Otherwise, the remote user
829 must have been authenticated, and the authenticated user name must
829 must have been authenticated, and the authenticated user name must
830 be present in this list (separated by whitespace or ","). The
830 be present in this list (separated by whitespace or ","). The
831 contents of the allow_push list are examined after the deny_push
831 contents of the allow_push list are examined after the deny_push
832 list.
832 list.
833 ``allow_read``
833 ``allow_read``
834 If the user has not already been denied repository access due to
834 If the user has not already been denied repository access due to
835 the contents of deny_read, this list determines whether to grant
835 the contents of deny_read, this list determines whether to grant
836 repository access to the user. If this list is not empty, and the
836 repository access to the user. If this list is not empty, and the
837 user is unauthenticated or not present in the list (separated by
837 user is unauthenticated or not present in the list (separated by
838 whitespace or ","), then access is denied for the user. If the
838 whitespace or ","), then access is denied for the user. If the
839 list is empty or not set, then access is permitted to all users by
839 list is empty or not set, then access is permitted to all users by
840 default. Setting allow_read to the special value "``*``" is equivalent
840 default. Setting allow_read to the special value "``*``" is equivalent
841 to it not being set (i.e. access is permitted to all users). The
841 to it not being set (i.e. access is permitted to all users). The
842 contents of the allow_read list are examined after the deny_read
842 contents of the allow_read list are examined after the deny_read
843 list.
843 list.
844 ``allowzip``
844 ``allowzip``
845 (DEPRECATED) Whether to allow .zip downloading of repository
845 (DEPRECATED) Whether to allow .zip downloading of repository
846 revisions. Default is false. This feature creates temporary files.
846 revisions. Default is false. This feature creates temporary files.
847 ``baseurl``
847 ``baseurl``
848 Base URL to use when publishing URLs in other locations, so
848 Base URL to use when publishing URLs in other locations, so
849 third-party tools like email notification hooks can construct
849 third-party tools like email notification hooks can construct
850 URLs. Example: "http://hgserver/repos/"
850 URLs. Example: "http://hgserver/repos/"
851 ``contact``
851 ``contact``
852 Name or email address of the person in charge of the repository.
852 Name or email address of the person in charge of the repository.
853 Defaults to ui.username or ``$EMAIL`` or "unknown" if unset or empty.
853 Defaults to ui.username or ``$EMAIL`` or "unknown" if unset or empty.
854 ``deny_push``
854 ``deny_push``
855 Whether to deny pushing to the repository. If empty or not set,
855 Whether to deny pushing to the repository. If empty or not set,
856 push is not denied. If the special value "``*``", all remote users are
856 push is not denied. If the special value "``*``", all remote users are
857 denied push. Otherwise, unauthenticated users are all denied, and
857 denied push. Otherwise, unauthenticated users are all denied, and
858 any authenticated user name present in this list (separated by
858 any authenticated user name present in this list (separated by
859 whitespace or ",") is also denied. The contents of the deny_push
859 whitespace or ",") is also denied. The contents of the deny_push
860 list are examined before the allow_push list.
860 list are examined before the allow_push list.
861 ``deny_read``
861 ``deny_read``
862 Whether to deny reading/viewing of the repository. If this list is
862 Whether to deny reading/viewing of the repository. If this list is
863 not empty, unauthenticated users are all denied, and any
863 not empty, unauthenticated users are all denied, and any
864 authenticated user name present in this list (separated by
864 authenticated user name present in this list (separated by
865 whitespace or ",") is also denied access to the repository. If set
865 whitespace or ",") is also denied access to the repository. If set
866 to the special value "``*``", all remote users are denied access
866 to the special value "``*``", all remote users are denied access
867 (rarely needed ;). If deny_read is empty or not set, the
867 (rarely needed ;). If deny_read is empty or not set, the
868 determination of repository access depends on the presence and
868 determination of repository access depends on the presence and
869 content of the allow_read list (see description). If both
869 content of the allow_read list (see description). If both
870 deny_read and allow_read are empty or not set, then access is
870 deny_read and allow_read are empty or not set, then access is
871 permitted to all users by default. If the repository is being
871 permitted to all users by default. If the repository is being
872 served via hgwebdir, denied users will not be able to see it in
872 served via hgwebdir, denied users will not be able to see it in
873 the list of repositories. The contents of the deny_read list have
873 the list of repositories. The contents of the deny_read list have
874 priority over (are examined before) the contents of the allow_read
874 priority over (are examined before) the contents of the allow_read
875 list.
875 list.
876 ``descend``
877 hgwebdir indexes will not descend into subdirectories. Only repositories
878 directly in the current path will be shown (other repositories are still
879 available from the index corresponding to their containing path).
876 ``description``
880 ``description``
877 Textual description of the repository's purpose or contents.
881 Textual description of the repository's purpose or contents.
878 Default is "unknown".
882 Default is "unknown".
879 ``encoding``
883 ``encoding``
880 Character encoding name.
884 Character encoding name.
881 Example: "UTF-8"
885 Example: "UTF-8"
882 ``errorlog``
886 ``errorlog``
883 Where to output the error log. Default is stderr.
887 Where to output the error log. Default is stderr.
884 ``hidden``
888 ``hidden``
885 Whether to hide the repository in the hgwebdir index.
889 Whether to hide the repository in the hgwebdir index.
886 Default is false.
890 Default is false.
887 ``ipv6``
891 ``ipv6``
888 Whether to use IPv6. Default is false.
892 Whether to use IPv6. Default is false.
889 ``name``
893 ``name``
890 Repository name to use in the web interface. Default is current
894 Repository name to use in the web interface. Default is current
891 working directory.
895 working directory.
892 ``maxchanges``
896 ``maxchanges``
893 Maximum number of changes to list on the changelog. Default is 10.
897 Maximum number of changes to list on the changelog. Default is 10.
894 ``maxfiles``
898 ``maxfiles``
895 Maximum number of files to list per changeset. Default is 10.
899 Maximum number of files to list per changeset. Default is 10.
896 ``port``
900 ``port``
897 Port to listen on. Default is 8000.
901 Port to listen on. Default is 8000.
898 ``prefix``
902 ``prefix``
899 Prefix path to serve from. Default is '' (server root).
903 Prefix path to serve from. Default is '' (server root).
900 ``push_ssl``
904 ``push_ssl``
901 Whether to require that inbound pushes be transported over SSL to
905 Whether to require that inbound pushes be transported over SSL to
902 prevent password sniffing. Default is true.
906 prevent password sniffing. Default is true.
903 ``staticurl``
907 ``staticurl``
904 Base URL to use for static files. If unset, static files (e.g. the
908 Base URL to use for static files. If unset, static files (e.g. the
905 hgicon.png favicon) will be served by the CGI script itself. Use
909 hgicon.png favicon) will be served by the CGI script itself. Use
906 this setting to serve them directly with the HTTP server.
910 this setting to serve them directly with the HTTP server.
907 Example: "http://hgserver/static/"
911 Example: "http://hgserver/static/"
908 ``stripes``
912 ``stripes``
909 How many lines a "zebra stripe" should span in multiline output.
913 How many lines a "zebra stripe" should span in multiline output.
910 Default is 1; set to 0 to disable.
914 Default is 1; set to 0 to disable.
911 ``style``
915 ``style``
912 Which template map style to use.
916 Which template map style to use.
913 ``templates``
917 ``templates``
914 Where to find the HTML templates. Default is install path.
918 Where to find the HTML templates. Default is install path.
915
919
916
920
917 AUTHOR
921 AUTHOR
918 ------
922 ------
919 Bryan O'Sullivan <bos@serpentine.com>.
923 Bryan O'Sullivan <bos@serpentine.com>.
920
924
921 Mercurial was written by Matt Mackall <mpm@selenic.com>.
925 Mercurial was written by Matt Mackall <mpm@selenic.com>.
922
926
923 SEE ALSO
927 SEE ALSO
924 --------
928 --------
925 |hg(1)|_, |hgignore(5)|_
929 |hg(1)|_, |hgignore(5)|_
926
930
927 COPYING
931 COPYING
928 -------
932 -------
929 This manual page is copyright 2005 Bryan O'Sullivan.
933 This manual page is copyright 2005 Bryan O'Sullivan.
930 Mercurial is copyright 2005-2009 Matt Mackall.
934 Mercurial is copyright 2005-2009 Matt Mackall.
931 Free use of this software is granted under the terms of the GNU General
935 Free use of this software is granted under the terms of the GNU General
932 Public License (GPL).
936 Public License (GPL).
933
937
934 .. include:: common.txt
938 .. include:: common.txt
@@ -1,333 +1,338 b''
1 # hgweb/hgwebdir_mod.py - Web interface for a directory of repositories.
1 # hgweb/hgwebdir_mod.py - Web interface for a directory of repositories.
2 #
2 #
3 # Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net>
3 # Copyright 21 May 2005 - (c) 2005 Jake Edge <jake@edge2.net>
4 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
4 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
5 #
5 #
6 # This software may be used and distributed according to the terms of the
6 # This software may be used and distributed according to the terms of the
7 # GNU General Public License version 2, incorporated herein by reference.
7 # GNU General Public License version 2, incorporated herein by reference.
8
8
9 import os, re, time
9 import os, re, time
10 from mercurial.i18n import _
10 from mercurial.i18n import _
11 from mercurial import ui, hg, util, templater
11 from mercurial import ui, hg, util, templater
12 from mercurial import error, encoding
12 from mercurial import error, encoding
13 from common import ErrorResponse, get_mtime, staticfile, paritygen,\
13 from common import ErrorResponse, get_mtime, staticfile, paritygen,\
14 get_contact, HTTP_OK, HTTP_NOT_FOUND, HTTP_SERVER_ERROR
14 get_contact, HTTP_OK, HTTP_NOT_FOUND, HTTP_SERVER_ERROR
15 from hgweb_mod import hgweb
15 from hgweb_mod import hgweb
16 from request import wsgirequest
16 from request import wsgirequest
17 import webutil
17 import webutil
18
18
19 def cleannames(items):
19 def cleannames(items):
20 return [(util.pconvert(name).strip('/'), path) for name, path in items]
20 return [(util.pconvert(name).strip('/'), path) for name, path in items]
21
21
22 def findrepos(paths):
22 def findrepos(paths):
23 repos = {}
23 repos = {}
24 for prefix, root in cleannames(paths):
24 for prefix, root in cleannames(paths):
25 roothead, roottail = os.path.split(root)
25 roothead, roottail = os.path.split(root)
26 # "foo = /bar/*" makes every subrepo of /bar/ to be
26 # "foo = /bar/*" makes every subrepo of /bar/ to be
27 # mounted as foo/subrepo
27 # mounted as foo/subrepo
28 # and "foo = /bar/**" also recurses into the subdirectories,
28 # and "foo = /bar/**" also recurses into the subdirectories,
29 # remember to use it without working dir.
29 # remember to use it without working dir.
30 try:
30 try:
31 recurse = {'*': False, '**': True}[roottail]
31 recurse = {'*': False, '**': True}[roottail]
32 except KeyError:
32 except KeyError:
33 repos[prefix] = root
33 repos[prefix] = root
34 continue
34 continue
35 roothead = os.path.normpath(roothead)
35 roothead = os.path.normpath(roothead)
36 for path in util.walkrepos(roothead, followsym=True, recurse=recurse):
36 for path in util.walkrepos(roothead, followsym=True, recurse=recurse):
37 path = os.path.normpath(path)
37 path = os.path.normpath(path)
38 name = util.pconvert(path[len(roothead):]).strip('/')
38 name = util.pconvert(path[len(roothead):]).strip('/')
39 if prefix:
39 if prefix:
40 name = prefix + '/' + name
40 name = prefix + '/' + name
41 repos[name] = path
41 repos[name] = path
42 return repos.items()
42 return repos.items()
43
43
44 class hgwebdir(object):
44 class hgwebdir(object):
45 refreshinterval = 20
45 refreshinterval = 20
46
46
47 def __init__(self, conf, baseui=None):
47 def __init__(self, conf, baseui=None):
48 self.conf = conf
48 self.conf = conf
49 self.baseui = baseui
49 self.baseui = baseui
50 self.lastrefresh = 0
50 self.lastrefresh = 0
51 self.refresh()
51 self.refresh()
52
52
53 def refresh(self):
53 def refresh(self):
54 if self.lastrefresh + self.refreshinterval > time.time():
54 if self.lastrefresh + self.refreshinterval > time.time():
55 return
55 return
56
56
57 if self.baseui:
57 if self.baseui:
58 self.ui = self.baseui.copy()
58 self.ui = self.baseui.copy()
59 else:
59 else:
60 self.ui = ui.ui()
60 self.ui = ui.ui()
61 self.ui.setconfig('ui', 'report_untrusted', 'off')
61 self.ui.setconfig('ui', 'report_untrusted', 'off')
62 self.ui.setconfig('ui', 'interactive', 'off')
62 self.ui.setconfig('ui', 'interactive', 'off')
63
63
64 if not isinstance(self.conf, (dict, list, tuple)):
64 if not isinstance(self.conf, (dict, list, tuple)):
65 map = {'paths': 'hgweb-paths'}
65 map = {'paths': 'hgweb-paths'}
66 self.ui.readconfig(self.conf, remap=map, trust=True)
66 self.ui.readconfig(self.conf, remap=map, trust=True)
67 paths = self.ui.configitems('hgweb-paths')
67 paths = self.ui.configitems('hgweb-paths')
68 elif isinstance(self.conf, (list, tuple)):
68 elif isinstance(self.conf, (list, tuple)):
69 paths = self.conf
69 paths = self.conf
70 elif isinstance(self.conf, dict):
70 elif isinstance(self.conf, dict):
71 paths = self.conf.items()
71 paths = self.conf.items()
72
72
73 encoding.encoding = self.ui.config('web', 'encoding',
73 encoding.encoding = self.ui.config('web', 'encoding',
74 encoding.encoding)
74 encoding.encoding)
75 self.motd = self.ui.config('web', 'motd')
75 self.motd = self.ui.config('web', 'motd')
76 self.style = self.ui.config('web', 'style', 'paper')
76 self.style = self.ui.config('web', 'style', 'paper')
77 self.stripecount = self.ui.config('web', 'stripes', 1)
77 self.stripecount = self.ui.config('web', 'stripes', 1)
78 if self.stripecount:
78 if self.stripecount:
79 self.stripecount = int(self.stripecount)
79 self.stripecount = int(self.stripecount)
80 self._baseurl = self.ui.config('web', 'baseurl')
80 self._baseurl = self.ui.config('web', 'baseurl')
81
81
82 self.repos = findrepos(paths)
82 self.repos = findrepos(paths)
83 for prefix, root in self.ui.configitems('collections'):
83 for prefix, root in self.ui.configitems('collections'):
84 prefix = util.pconvert(prefix)
84 prefix = util.pconvert(prefix)
85 for path in util.walkrepos(root, followsym=True):
85 for path in util.walkrepos(root, followsym=True):
86 repo = os.path.normpath(path)
86 repo = os.path.normpath(path)
87 name = util.pconvert(repo)
87 name = util.pconvert(repo)
88 if name.startswith(prefix):
88 if name.startswith(prefix):
89 name = name[len(prefix):]
89 name = name[len(prefix):]
90 self.repos.append((name.lstrip('/'), repo))
90 self.repos.append((name.lstrip('/'), repo))
91
91
92 self.repos.sort()
92 self.repos.sort()
93 self.lastrefresh = time.time()
93 self.lastrefresh = time.time()
94
94
95 def run(self):
95 def run(self):
96 if not os.environ.get('GATEWAY_INTERFACE', '').startswith("CGI/1."):
96 if not os.environ.get('GATEWAY_INTERFACE', '').startswith("CGI/1."):
97 raise RuntimeError("This function is only intended to be "
97 raise RuntimeError("This function is only intended to be "
98 "called while running as a CGI script.")
98 "called while running as a CGI script.")
99 import mercurial.hgweb.wsgicgi as wsgicgi
99 import mercurial.hgweb.wsgicgi as wsgicgi
100 wsgicgi.launch(self)
100 wsgicgi.launch(self)
101
101
102 def __call__(self, env, respond):
102 def __call__(self, env, respond):
103 req = wsgirequest(env, respond)
103 req = wsgirequest(env, respond)
104 return self.run_wsgi(req)
104 return self.run_wsgi(req)
105
105
106 def read_allowed(self, ui, req):
106 def read_allowed(self, ui, req):
107 """Check allow_read and deny_read config options of a repo's ui object
107 """Check allow_read and deny_read config options of a repo's ui object
108 to determine user permissions. By default, with neither option set (or
108 to determine user permissions. By default, with neither option set (or
109 both empty), allow all users to read the repo. There are two ways a
109 both empty), allow all users to read the repo. There are two ways a
110 user can be denied read access: (1) deny_read is not empty, and the
110 user can be denied read access: (1) deny_read is not empty, and the
111 user is unauthenticated or deny_read contains user (or *), and (2)
111 user is unauthenticated or deny_read contains user (or *), and (2)
112 allow_read is not empty and the user is not in allow_read. Return True
112 allow_read is not empty and the user is not in allow_read. Return True
113 if user is allowed to read the repo, else return False."""
113 if user is allowed to read the repo, else return False."""
114
114
115 user = req.env.get('REMOTE_USER')
115 user = req.env.get('REMOTE_USER')
116
116
117 deny_read = ui.configlist('web', 'deny_read', untrusted=True)
117 deny_read = ui.configlist('web', 'deny_read', untrusted=True)
118 if deny_read and (not user or deny_read == ['*'] or user in deny_read):
118 if deny_read and (not user or deny_read == ['*'] or user in deny_read):
119 return False
119 return False
120
120
121 allow_read = ui.configlist('web', 'allow_read', untrusted=True)
121 allow_read = ui.configlist('web', 'allow_read', untrusted=True)
122 # by default, allow reading if no allow_read option has been set
122 # by default, allow reading if no allow_read option has been set
123 if (not allow_read) or (allow_read == ['*']) or (user in allow_read):
123 if (not allow_read) or (allow_read == ['*']) or (user in allow_read):
124 return True
124 return True
125
125
126 return False
126 return False
127
127
128 def run_wsgi(self, req):
128 def run_wsgi(self, req):
129 try:
129 try:
130 try:
130 try:
131 self.refresh()
131 self.refresh()
132
132
133 virtual = req.env.get("PATH_INFO", "").strip('/')
133 virtual = req.env.get("PATH_INFO", "").strip('/')
134 tmpl = self.templater(req)
134 tmpl = self.templater(req)
135 ctype = tmpl('mimetype', encoding=encoding.encoding)
135 ctype = tmpl('mimetype', encoding=encoding.encoding)
136 ctype = templater.stringify(ctype)
136 ctype = templater.stringify(ctype)
137
137
138 # a static file
138 # a static file
139 if virtual.startswith('static/') or 'static' in req.form:
139 if virtual.startswith('static/') or 'static' in req.form:
140 if virtual.startswith('static/'):
140 if virtual.startswith('static/'):
141 fname = virtual[7:]
141 fname = virtual[7:]
142 else:
142 else:
143 fname = req.form['static'][0]
143 fname = req.form['static'][0]
144 static = templater.templatepath('static')
144 static = templater.templatepath('static')
145 return (staticfile(static, fname, req),)
145 return (staticfile(static, fname, req),)
146
146
147 # top-level index
147 # top-level index
148 elif not virtual:
148 elif not virtual:
149 req.respond(HTTP_OK, ctype)
149 req.respond(HTTP_OK, ctype)
150 return self.makeindex(req, tmpl)
150 return self.makeindex(req, tmpl)
151
151
152 # nested indexes and hgwebs
152 # nested indexes and hgwebs
153
153
154 repos = dict(self.repos)
154 repos = dict(self.repos)
155 while virtual:
155 while virtual:
156 real = repos.get(virtual)
156 real = repos.get(virtual)
157 if real:
157 if real:
158 req.env['REPO_NAME'] = virtual
158 req.env['REPO_NAME'] = virtual
159 try:
159 try:
160 repo = hg.repository(self.ui, real)
160 repo = hg.repository(self.ui, real)
161 return hgweb(repo).run_wsgi(req)
161 return hgweb(repo).run_wsgi(req)
162 except IOError, inst:
162 except IOError, inst:
163 msg = inst.strerror
163 msg = inst.strerror
164 raise ErrorResponse(HTTP_SERVER_ERROR, msg)
164 raise ErrorResponse(HTTP_SERVER_ERROR, msg)
165 except error.RepoError, inst:
165 except error.RepoError, inst:
166 raise ErrorResponse(HTTP_SERVER_ERROR, str(inst))
166 raise ErrorResponse(HTTP_SERVER_ERROR, str(inst))
167
167
168 # browse subdirectories
168 # browse subdirectories
169 subdir = virtual + '/'
169 subdir = virtual + '/'
170 if [r for r in repos if r.startswith(subdir)]:
170 if [r for r in repos if r.startswith(subdir)]:
171 req.respond(HTTP_OK, ctype)
171 req.respond(HTTP_OK, ctype)
172 return self.makeindex(req, tmpl, subdir)
172 return self.makeindex(req, tmpl, subdir)
173
173
174 up = virtual.rfind('/')
174 up = virtual.rfind('/')
175 if up < 0:
175 if up < 0:
176 break
176 break
177 virtual = virtual[:up]
177 virtual = virtual[:up]
178
178
179 # prefixes not found
179 # prefixes not found
180 req.respond(HTTP_NOT_FOUND, ctype)
180 req.respond(HTTP_NOT_FOUND, ctype)
181 return tmpl("notfound", repo=virtual)
181 return tmpl("notfound", repo=virtual)
182
182
183 except ErrorResponse, err:
183 except ErrorResponse, err:
184 req.respond(err, ctype)
184 req.respond(err, ctype)
185 return tmpl('error', error=err.message or '')
185 return tmpl('error', error=err.message or '')
186 finally:
186 finally:
187 tmpl = None
187 tmpl = None
188
188
189 def makeindex(self, req, tmpl, subdir=""):
189 def makeindex(self, req, tmpl, subdir=""):
190
190
191 def archivelist(ui, nodeid, url):
191 def archivelist(ui, nodeid, url):
192 allowed = ui.configlist("web", "allow_archive", untrusted=True)
192 allowed = ui.configlist("web", "allow_archive", untrusted=True)
193 for i in [('zip', '.zip'), ('gz', '.tar.gz'), ('bz2', '.tar.bz2')]:
193 for i in [('zip', '.zip'), ('gz', '.tar.gz'), ('bz2', '.tar.bz2')]:
194 if i[0] in allowed or ui.configbool("web", "allow" + i[0],
194 if i[0] in allowed or ui.configbool("web", "allow" + i[0],
195 untrusted=True):
195 untrusted=True):
196 yield {"type" : i[0], "extension": i[1],
196 yield {"type" : i[0], "extension": i[1],
197 "node": nodeid, "url": url}
197 "node": nodeid, "url": url}
198
198
199 sortdefault = 'name', False
199 sortdefault = 'name', False
200 def entries(sortcolumn="", descending=False, subdir="", **map):
200 def entries(sortcolumn="", descending=False, subdir="", **map):
201
201 rows = []
202 rows = []
202 parity = paritygen(self.stripecount)
203 parity = paritygen(self.stripecount)
204 descend = self.ui.configbool('web', 'descend', True)
203 for name, path in self.repos:
205 for name, path in self.repos:
206
204 if not name.startswith(subdir):
207 if not name.startswith(subdir):
205 continue
208 continue
206 name = name[len(subdir):]
209 name = name[len(subdir):]
210 if not descend and '/' in name:
211 continue
207
212
208 u = self.ui.copy()
213 u = self.ui.copy()
209 try:
214 try:
210 u.readconfig(os.path.join(path, '.hg', 'hgrc'))
215 u.readconfig(os.path.join(path, '.hg', 'hgrc'))
211 except Exception, e:
216 except Exception, e:
212 u.warn(_('error reading %s/.hg/hgrc: %s\n') % (path, e))
217 u.warn(_('error reading %s/.hg/hgrc: %s\n') % (path, e))
213 continue
218 continue
214 def get(section, name, default=None):
219 def get(section, name, default=None):
215 return u.config(section, name, default, untrusted=True)
220 return u.config(section, name, default, untrusted=True)
216
221
217 if u.configbool("web", "hidden", untrusted=True):
222 if u.configbool("web", "hidden", untrusted=True):
218 continue
223 continue
219
224
220 if not self.read_allowed(u, req):
225 if not self.read_allowed(u, req):
221 continue
226 continue
222
227
223 parts = [name]
228 parts = [name]
224 if 'PATH_INFO' in req.env:
229 if 'PATH_INFO' in req.env:
225 parts.insert(0, req.env['PATH_INFO'].rstrip('/'))
230 parts.insert(0, req.env['PATH_INFO'].rstrip('/'))
226 if req.env['SCRIPT_NAME']:
231 if req.env['SCRIPT_NAME']:
227 parts.insert(0, req.env['SCRIPT_NAME'])
232 parts.insert(0, req.env['SCRIPT_NAME'])
228 m = re.match('((?:https?://)?)(.*)', '/'.join(parts))
233 m = re.match('((?:https?://)?)(.*)', '/'.join(parts))
229 # squish repeated slashes out of the path component
234 # squish repeated slashes out of the path component
230 url = m.group(1) + re.sub('/+', '/', m.group(2)) + '/'
235 url = m.group(1) + re.sub('/+', '/', m.group(2)) + '/'
231
236
232 # update time with local timezone
237 # update time with local timezone
233 try:
238 try:
234 d = (get_mtime(path), util.makedate()[1])
239 d = (get_mtime(path), util.makedate()[1])
235 except OSError:
240 except OSError:
236 continue
241 continue
237
242
238 contact = get_contact(get)
243 contact = get_contact(get)
239 description = get("web", "description", "")
244 description = get("web", "description", "")
240 name = get("web", "name", name)
245 name = get("web", "name", name)
241 row = dict(contact=contact or "unknown",
246 row = dict(contact=contact or "unknown",
242 contact_sort=contact.upper() or "unknown",
247 contact_sort=contact.upper() or "unknown",
243 name=name,
248 name=name,
244 name_sort=name,
249 name_sort=name,
245 url=url,
250 url=url,
246 description=description or "unknown",
251 description=description or "unknown",
247 description_sort=description.upper() or "unknown",
252 description_sort=description.upper() or "unknown",
248 lastchange=d,
253 lastchange=d,
249 lastchange_sort=d[1]-d[0],
254 lastchange_sort=d[1]-d[0],
250 archives=archivelist(u, "tip", url))
255 archives=archivelist(u, "tip", url))
251 if (not sortcolumn or (sortcolumn, descending) == sortdefault):
256 if (not sortcolumn or (sortcolumn, descending) == sortdefault):
252 # fast path for unsorted output
257 # fast path for unsorted output
253 row['parity'] = parity.next()
258 row['parity'] = parity.next()
254 yield row
259 yield row
255 else:
260 else:
256 rows.append((row["%s_sort" % sortcolumn], row))
261 rows.append((row["%s_sort" % sortcolumn], row))
257 if rows:
262 if rows:
258 rows.sort()
263 rows.sort()
259 if descending:
264 if descending:
260 rows.reverse()
265 rows.reverse()
261 for key, row in rows:
266 for key, row in rows:
262 row['parity'] = parity.next()
267 row['parity'] = parity.next()
263 yield row
268 yield row
264
269
265 self.refresh()
270 self.refresh()
266 sortable = ["name", "description", "contact", "lastchange"]
271 sortable = ["name", "description", "contact", "lastchange"]
267 sortcolumn, descending = sortdefault
272 sortcolumn, descending = sortdefault
268 if 'sort' in req.form:
273 if 'sort' in req.form:
269 sortcolumn = req.form['sort'][0]
274 sortcolumn = req.form['sort'][0]
270 descending = sortcolumn.startswith('-')
275 descending = sortcolumn.startswith('-')
271 if descending:
276 if descending:
272 sortcolumn = sortcolumn[1:]
277 sortcolumn = sortcolumn[1:]
273 if sortcolumn not in sortable:
278 if sortcolumn not in sortable:
274 sortcolumn = ""
279 sortcolumn = ""
275
280
276 sort = [("sort_%s" % column,
281 sort = [("sort_%s" % column,
277 "%s%s" % ((not descending and column == sortcolumn)
282 "%s%s" % ((not descending and column == sortcolumn)
278 and "-" or "", column))
283 and "-" or "", column))
279 for column in sortable]
284 for column in sortable]
280
285
281 self.refresh()
286 self.refresh()
282 if self._baseurl is not None:
287 if self._baseurl is not None:
283 req.env['SCRIPT_NAME'] = self._baseurl
288 req.env['SCRIPT_NAME'] = self._baseurl
284
289
285 return tmpl("index", entries=entries, subdir=subdir,
290 return tmpl("index", entries=entries, subdir=subdir,
286 sortcolumn=sortcolumn, descending=descending,
291 sortcolumn=sortcolumn, descending=descending,
287 **dict(sort))
292 **dict(sort))
288
293
289 def templater(self, req):
294 def templater(self, req):
290
295
291 def header(**map):
296 def header(**map):
292 yield tmpl('header', encoding=encoding.encoding, **map)
297 yield tmpl('header', encoding=encoding.encoding, **map)
293
298
294 def footer(**map):
299 def footer(**map):
295 yield tmpl("footer", **map)
300 yield tmpl("footer", **map)
296
301
297 def motd(**map):
302 def motd(**map):
298 if self.motd is not None:
303 if self.motd is not None:
299 yield self.motd
304 yield self.motd
300 else:
305 else:
301 yield config('web', 'motd', '')
306 yield config('web', 'motd', '')
302
307
303 def config(section, name, default=None, untrusted=True):
308 def config(section, name, default=None, untrusted=True):
304 return self.ui.config(section, name, default, untrusted)
309 return self.ui.config(section, name, default, untrusted)
305
310
306 if self._baseurl is not None:
311 if self._baseurl is not None:
307 req.env['SCRIPT_NAME'] = self._baseurl
312 req.env['SCRIPT_NAME'] = self._baseurl
308
313
309 url = req.env.get('SCRIPT_NAME', '')
314 url = req.env.get('SCRIPT_NAME', '')
310 if not url.endswith('/'):
315 if not url.endswith('/'):
311 url += '/'
316 url += '/'
312
317
313 vars = {}
318 vars = {}
314 style = self.style
319 style = self.style
315 if 'style' in req.form:
320 if 'style' in req.form:
316 vars['style'] = style = req.form['style'][0]
321 vars['style'] = style = req.form['style'][0]
317 start = url[-1] == '?' and '&' or '?'
322 start = url[-1] == '?' and '&' or '?'
318 sessionvars = webutil.sessionvars(vars, start)
323 sessionvars = webutil.sessionvars(vars, start)
319
324
320 staticurl = config('web', 'staticurl') or url + 'static/'
325 staticurl = config('web', 'staticurl') or url + 'static/'
321 if not staticurl.endswith('/'):
326 if not staticurl.endswith('/'):
322 staticurl += '/'
327 staticurl += '/'
323
328
324 style = 'style' in req.form and req.form['style'][0] or self.style
329 style = 'style' in req.form and req.form['style'][0] or self.style
325 mapfile = templater.stylemap(style)
330 mapfile = templater.stylemap(style)
326 tmpl = templater.templater(mapfile,
331 tmpl = templater.templater(mapfile,
327 defaults={"header": header,
332 defaults={"header": header,
328 "footer": footer,
333 "footer": footer,
329 "motd": motd,
334 "motd": motd,
330 "url": url,
335 "url": url,
331 "staticurl": staticurl,
336 "staticurl": staticurl,
332 "sessionvars": sessionvars})
337 "sessionvars": sessionvars})
333 return tmpl
338 return tmpl
@@ -1,107 +1,130 b''
1 #!/bin/sh
1 #!/bin/sh
2 # Tests some basic hgwebdir functionality. Tests setting up paths and
2 # Tests some basic hgwebdir functionality. Tests setting up paths and
3 # collection, different forms of 404s and the subdirectory support.
3 # collection, different forms of 404s and the subdirectory support.
4
4
5 mkdir webdir
5 mkdir webdir
6 cd webdir
6 cd webdir
7
7
8 hg init a
8 hg init a
9 echo a > a/a
9 echo a > a/a
10 hg --cwd a ci -Ama -d'1 0'
10 hg --cwd a ci -Ama -d'1 0'
11 # create a mercurial queue repository
11 # create a mercurial queue repository
12 hg --cwd a qinit --config extensions.hgext.mq= -c
12 hg --cwd a qinit --config extensions.hgext.mq= -c
13
13
14 hg init b
14 hg init b
15 echo b > b/b
15 echo b > b/b
16 hg --cwd b ci -Amb -d'2 0'
16 hg --cwd b ci -Amb -d'2 0'
17
17
18 # create a nested repository
18 # create a nested repository
19 cd b
19 cd b
20 hg init d
20 hg init d
21 echo d > d/d
21 echo d > d/d
22 hg --cwd d ci -Amd -d'3 0'
22 hg --cwd d ci -Amd -d'3 0'
23 cd ..
23 cd ..
24
24
25 hg init c
25 hg init c
26 echo c > c/c
26 echo c > c/c
27 hg --cwd c ci -Amc -d'3 0'
27 hg --cwd c ci -Amc -d'3 0'
28
28
29 root=`pwd`
29 root=`pwd`
30 cd ..
30 cd ..
31
31
32
32 cat > paths.conf <<EOF
33 cat > paths.conf <<EOF
33 [paths]
34 [paths]
34 a=$root/a
35 a=$root/a
35 b=$root/b
36 b=$root/b
36 EOF
37 EOF
37
38
38 hg serve -p $HGPORT -d --pid-file=hg.pid --webdir-conf paths.conf \
39 hg serve -p $HGPORT -d --pid-file=hg.pid --webdir-conf paths.conf \
39 -A access-paths.log -E error-paths-1.log
40 -A access-paths.log -E error-paths-1.log
40 cat hg.pid >> $DAEMON_PIDS
41 cat hg.pid >> $DAEMON_PIDS
41
42
42 echo % should give a 404 - file does not exist
43 echo % should give a 404 - file does not exist
43 "$TESTDIR/get-with-headers.py" localhost:$HGPORT '/a/file/tip/bork?style=raw'
44 "$TESTDIR/get-with-headers.py" localhost:$HGPORT '/a/file/tip/bork?style=raw'
44
45
45 echo % should succeed
46 echo % should succeed
46 "$TESTDIR/get-with-headers.py" localhost:$HGPORT '/?style=raw'
47 "$TESTDIR/get-with-headers.py" localhost:$HGPORT '/?style=raw'
47 "$TESTDIR/get-with-headers.py" localhost:$HGPORT '/a/file/tip/a?style=raw'
48 "$TESTDIR/get-with-headers.py" localhost:$HGPORT '/a/file/tip/a?style=raw'
48 "$TESTDIR/get-with-headers.py" localhost:$HGPORT '/b/file/tip/b?style=raw'
49 "$TESTDIR/get-with-headers.py" localhost:$HGPORT '/b/file/tip/b?style=raw'
49
50
50 echo % should give a 404 - repo is not published
51 echo % should give a 404 - repo is not published
51 "$TESTDIR/get-with-headers.py" localhost:$HGPORT '/c/file/tip/c?style=raw'
52 "$TESTDIR/get-with-headers.py" localhost:$HGPORT '/c/file/tip/c?style=raw'
52
53
54
53 cat > paths.conf <<EOF
55 cat > paths.conf <<EOF
54 [paths]
56 [paths]
55 t/a/=$root/a
57 t/a/=$root/a
56 b=$root/b
58 b=$root/b
57 coll=$root/*
59 coll=$root/*
58 rcoll=$root/**
60 rcoll=$root/**
59 EOF
61 EOF
60
62
61 hg serve -p $HGPORT1 -d --pid-file=hg.pid --webdir-conf paths.conf \
63 hg serve -p $HGPORT1 -d --pid-file=hg.pid --webdir-conf paths.conf \
62 -A access-paths.log -E error-paths-2.log
64 -A access-paths.log -E error-paths-2.log
63 cat hg.pid >> $DAEMON_PIDS
65 cat hg.pid >> $DAEMON_PIDS
64
66
65 echo % should succeed, slashy names
67 echo % should succeed, slashy names
66 "$TESTDIR/get-with-headers.py" localhost:$HGPORT1 '/?style=raw'
68 "$TESTDIR/get-with-headers.py" localhost:$HGPORT1 '/?style=raw'
67 "$TESTDIR/get-with-headers.py" localhost:$HGPORT1 '/?style=paper' \
69 "$TESTDIR/get-with-headers.py" localhost:$HGPORT1 '/?style=paper' \
68 | sed "s/[0-9]\{1,\} seconds\{0,1\} ago/seconds ago/"
70 | sed "s/[0-9]\{1,\} seconds\{0,1\} ago/seconds ago/"
69 "$TESTDIR/get-with-headers.py" localhost:$HGPORT1 '/t?style=raw'
71 "$TESTDIR/get-with-headers.py" localhost:$HGPORT1 '/t?style=raw'
70 "$TESTDIR/get-with-headers.py" localhost:$HGPORT1 '/t/?style=raw'
72 "$TESTDIR/get-with-headers.py" localhost:$HGPORT1 '/t/?style=raw'
71 "$TESTDIR/get-with-headers.py" localhost:$HGPORT1 '/t/?style=paper' \
73 "$TESTDIR/get-with-headers.py" localhost:$HGPORT1 '/t/?style=paper' \
72 | sed "s/[0-9]\{1,\} seconds\{0,1\} ago/seconds ago/"
74 | sed "s/[0-9]\{1,\} seconds\{0,1\} ago/seconds ago/"
73 "$TESTDIR/get-with-headers.py" localhost:$HGPORT1 '/t/a?style=atom' \
75 "$TESTDIR/get-with-headers.py" localhost:$HGPORT1 '/t/a?style=atom' \
74 | sed "s/http:\/\/[^/]*\//http:\/\/127.0.0.1\//"
76 | sed "s/http:\/\/[^/]*\//http:\/\/127.0.0.1\//"
75 "$TESTDIR/get-with-headers.py" localhost:$HGPORT1 '/t/a/?style=atom' \
77 "$TESTDIR/get-with-headers.py" localhost:$HGPORT1 '/t/a/?style=atom' \
76 | sed "s/http:\/\/[^/]*\//http:\/\/127.0.0.1\//"
78 | sed "s/http:\/\/[^/]*\//http:\/\/127.0.0.1\//"
77 "$TESTDIR/get-with-headers.py" localhost:$HGPORT1 '/t/a/file/tip/a?style=raw'
79 "$TESTDIR/get-with-headers.py" localhost:$HGPORT1 '/t/a/file/tip/a?style=raw'
78 # Test [paths] '*' extension
80 # Test [paths] '*' extension
79 "$TESTDIR/get-with-headers.py" localhost:$HGPORT1 '/coll/?style=raw'
81 "$TESTDIR/get-with-headers.py" localhost:$HGPORT1 '/coll/?style=raw'
80 "$TESTDIR/get-with-headers.py" localhost:$HGPORT1 '/coll/a/file/tip/a?style=raw'
82 "$TESTDIR/get-with-headers.py" localhost:$HGPORT1 '/coll/a/file/tip/a?style=raw'
81 #test [paths] '**' extension
83 #test [paths] '**' extension
82 "$TESTDIR/get-with-headers.py" localhost:$HGPORT1 '/rcoll/?style=raw'
84 "$TESTDIR/get-with-headers.py" localhost:$HGPORT1 '/rcoll/?style=raw'
83 "$TESTDIR/get-with-headers.py" localhost:$HGPORT1 '/rcoll/b/d/file/tip/d?style=raw'
85 "$TESTDIR/get-with-headers.py" localhost:$HGPORT1 '/rcoll/b/d/file/tip/d?style=raw'
84
86
85
87
88 "$TESTDIR/killdaemons.py"
89 cat > paths.conf <<EOF
90 [paths]
91 t/a = $root/a
92 t/b = $root/b
93 c = $root/c
94 [web]
95 descend=false
96 EOF
97
98 hg serve -p $HGPORT1 -d --pid-file=hg.pid --webdir-conf paths.conf \
99 -A access-paths.log -E error-paths-3.log
100 cat hg.pid >> $DAEMON_PIDS
101 echo % test descend = False
102 "$TESTDIR/get-with-headers.py" localhost:$HGPORT1 '/?style=raw'
103 "$TESTDIR/get-with-headers.py" localhost:$HGPORT1 '/t/?style=raw'
104
105
86 cat > collections.conf <<EOF
106 cat > collections.conf <<EOF
87 [collections]
107 [collections]
88 $root=$root
108 $root=$root
89 EOF
109 EOF
90
110
91 hg serve --config web.baseurl=http://hg.example.com:8080/ -p $HGPORT2 -d \
111 hg serve --config web.baseurl=http://hg.example.com:8080/ -p $HGPORT2 -d \
92 --pid-file=hg.pid --webdir-conf collections.conf \
112 --pid-file=hg.pid --webdir-conf collections.conf \
93 -A access-collections.log -E error-collections.log
113 -A access-collections.log -E error-collections.log
94 cat hg.pid >> $DAEMON_PIDS
114 cat hg.pid >> $DAEMON_PIDS
95
115
96 echo % collections: should succeed
116 echo % collections: should succeed
97 "$TESTDIR/get-with-headers.py" localhost:$HGPORT2 '/?style=raw'
117 "$TESTDIR/get-with-headers.py" localhost:$HGPORT2 '/?style=raw'
98 "$TESTDIR/get-with-headers.py" localhost:$HGPORT2 '/a/file/tip/a?style=raw'
118 "$TESTDIR/get-with-headers.py" localhost:$HGPORT2 '/a/file/tip/a?style=raw'
99 "$TESTDIR/get-with-headers.py" localhost:$HGPORT2 '/b/file/tip/b?style=raw'
119 "$TESTDIR/get-with-headers.py" localhost:$HGPORT2 '/b/file/tip/b?style=raw'
100 "$TESTDIR/get-with-headers.py" localhost:$HGPORT2 '/c/file/tip/c?style=raw'
120 "$TESTDIR/get-with-headers.py" localhost:$HGPORT2 '/c/file/tip/c?style=raw'
101
121
122
102 echo % paths errors 1
123 echo % paths errors 1
103 cat error-paths-1.log
124 cat error-paths-1.log
104 echo % paths errors 2
125 echo % paths errors 2
105 cat error-paths-2.log
126 cat error-paths-2.log
127 echo % paths errors 3
128 cat error-paths-3.log
106 echo % collections errors
129 echo % collections errors
107 cat error-collections.log
130 cat error-collections.log
@@ -1,330 +1,343 b''
1 adding a
1 adding a
2 adding b
2 adding b
3 adding d
3 adding d
4 adding c
4 adding c
5 % should give a 404 - file does not exist
5 % should give a 404 - file does not exist
6 404 Not Found
6 404 Not Found
7
7
8
8
9 error: bork@8580ff50825a: not found in manifest
9 error: bork@8580ff50825a: not found in manifest
10 % should succeed
10 % should succeed
11 200 Script output follows
11 200 Script output follows
12
12
13
13
14 /a/
14 /a/
15 /b/
15 /b/
16
16
17 200 Script output follows
17 200 Script output follows
18
18
19 a
19 a
20 200 Script output follows
20 200 Script output follows
21
21
22 b
22 b
23 % should give a 404 - repo is not published
23 % should give a 404 - repo is not published
24 404 Not Found
24 404 Not Found
25
25
26
26
27 error: repository c not found
27 error: repository c not found
28 % should succeed, slashy names
28 % should succeed, slashy names
29 200 Script output follows
29 200 Script output follows
30
30
31
31
32 /b/
32 /b/
33 /coll/a/
33 /coll/a/
34 /coll/a/.hg/patches/
34 /coll/a/.hg/patches/
35 /coll/b/
35 /coll/b/
36 /coll/c/
36 /coll/c/
37 /rcoll/a/
37 /rcoll/a/
38 /rcoll/a/.hg/patches/
38 /rcoll/a/.hg/patches/
39 /rcoll/b/
39 /rcoll/b/
40 /rcoll/b/d/
40 /rcoll/b/d/
41 /rcoll/c/
41 /rcoll/c/
42 /t/a/
42 /t/a/
43
43
44 200 Script output follows
44 200 Script output follows
45
45
46 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
46 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
47 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
47 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
48 <head>
48 <head>
49 <link rel="icon" href="/static/hgicon.png" type="image/png" />
49 <link rel="icon" href="/static/hgicon.png" type="image/png" />
50 <meta name="robots" content="index, nofollow" />
50 <meta name="robots" content="index, nofollow" />
51 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
51 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
52
52
53 <title>Mercurial repositories index</title>
53 <title>Mercurial repositories index</title>
54 </head>
54 </head>
55 <body>
55 <body>
56
56
57 <div class="container">
57 <div class="container">
58 <div class="menu">
58 <div class="menu">
59 <a href="http://mercurial.selenic.com/">
59 <a href="http://mercurial.selenic.com/">
60 <img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial" /></a>
60 <img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial" /></a>
61 </div>
61 </div>
62 <div class="main">
62 <div class="main">
63 <h2>Mercurial Repositories</h2>
63 <h2>Mercurial Repositories</h2>
64
64
65 <table class="bigtable">
65 <table class="bigtable">
66 <tr>
66 <tr>
67 <th><a href="?sort=-name">Name</a></th>
67 <th><a href="?sort=-name">Name</a></th>
68 <th><a href="?sort=description">Description</a></th>
68 <th><a href="?sort=description">Description</a></th>
69 <th><a href="?sort=contact">Contact</a></th>
69 <th><a href="?sort=contact">Contact</a></th>
70 <th><a href="?sort=lastchange">Last change</a></th>
70 <th><a href="?sort=lastchange">Last change</a></th>
71 <th>&nbsp;</th>
71 <th>&nbsp;</th>
72 </tr>
72 </tr>
73
73
74 <tr class="parity0">
74 <tr class="parity0">
75 <td><a href="/b/?style=paper">b</a></td>
75 <td><a href="/b/?style=paper">b</a></td>
76 <td>unknown</td>
76 <td>unknown</td>
77 <td>&#70;&#111;&#111;&#32;&#66;&#97;&#114;&#32;&#60;&#102;&#111;&#111;&#46;&#98;&#97;&#114;&#64;&#101;&#120;&#97;&#109;&#112;&#108;&#101;&#46;&#99;&#111;&#109;&#62;</td>
77 <td>&#70;&#111;&#111;&#32;&#66;&#97;&#114;&#32;&#60;&#102;&#111;&#111;&#46;&#98;&#97;&#114;&#64;&#101;&#120;&#97;&#109;&#112;&#108;&#101;&#46;&#99;&#111;&#109;&#62;</td>
78 <td class="age">seconds ago</td>
78 <td class="age">seconds ago</td>
79 <td class="indexlinks"></td>
79 <td class="indexlinks"></td>
80 </tr>
80 </tr>
81
81
82 <tr class="parity1">
82 <tr class="parity1">
83 <td><a href="/coll/a/?style=paper">coll/a</a></td>
83 <td><a href="/coll/a/?style=paper">coll/a</a></td>
84 <td>unknown</td>
84 <td>unknown</td>
85 <td>&#70;&#111;&#111;&#32;&#66;&#97;&#114;&#32;&#60;&#102;&#111;&#111;&#46;&#98;&#97;&#114;&#64;&#101;&#120;&#97;&#109;&#112;&#108;&#101;&#46;&#99;&#111;&#109;&#62;</td>
85 <td>&#70;&#111;&#111;&#32;&#66;&#97;&#114;&#32;&#60;&#102;&#111;&#111;&#46;&#98;&#97;&#114;&#64;&#101;&#120;&#97;&#109;&#112;&#108;&#101;&#46;&#99;&#111;&#109;&#62;</td>
86 <td class="age">seconds ago</td>
86 <td class="age">seconds ago</td>
87 <td class="indexlinks"></td>
87 <td class="indexlinks"></td>
88 </tr>
88 </tr>
89
89
90 <tr class="parity0">
90 <tr class="parity0">
91 <td><a href="/coll/a/.hg/patches/?style=paper">coll/a/.hg/patches</a></td>
91 <td><a href="/coll/a/.hg/patches/?style=paper">coll/a/.hg/patches</a></td>
92 <td>unknown</td>
92 <td>unknown</td>
93 <td>&#70;&#111;&#111;&#32;&#66;&#97;&#114;&#32;&#60;&#102;&#111;&#111;&#46;&#98;&#97;&#114;&#64;&#101;&#120;&#97;&#109;&#112;&#108;&#101;&#46;&#99;&#111;&#109;&#62;</td>
93 <td>&#70;&#111;&#111;&#32;&#66;&#97;&#114;&#32;&#60;&#102;&#111;&#111;&#46;&#98;&#97;&#114;&#64;&#101;&#120;&#97;&#109;&#112;&#108;&#101;&#46;&#99;&#111;&#109;&#62;</td>
94 <td class="age">seconds ago</td>
94 <td class="age">seconds ago</td>
95 <td class="indexlinks"></td>
95 <td class="indexlinks"></td>
96 </tr>
96 </tr>
97
97
98 <tr class="parity1">
98 <tr class="parity1">
99 <td><a href="/coll/b/?style=paper">coll/b</a></td>
99 <td><a href="/coll/b/?style=paper">coll/b</a></td>
100 <td>unknown</td>
100 <td>unknown</td>
101 <td>&#70;&#111;&#111;&#32;&#66;&#97;&#114;&#32;&#60;&#102;&#111;&#111;&#46;&#98;&#97;&#114;&#64;&#101;&#120;&#97;&#109;&#112;&#108;&#101;&#46;&#99;&#111;&#109;&#62;</td>
101 <td>&#70;&#111;&#111;&#32;&#66;&#97;&#114;&#32;&#60;&#102;&#111;&#111;&#46;&#98;&#97;&#114;&#64;&#101;&#120;&#97;&#109;&#112;&#108;&#101;&#46;&#99;&#111;&#109;&#62;</td>
102 <td class="age">seconds ago</td>
102 <td class="age">seconds ago</td>
103 <td class="indexlinks"></td>
103 <td class="indexlinks"></td>
104 </tr>
104 </tr>
105
105
106 <tr class="parity0">
106 <tr class="parity0">
107 <td><a href="/coll/c/?style=paper">coll/c</a></td>
107 <td><a href="/coll/c/?style=paper">coll/c</a></td>
108 <td>unknown</td>
108 <td>unknown</td>
109 <td>&#70;&#111;&#111;&#32;&#66;&#97;&#114;&#32;&#60;&#102;&#111;&#111;&#46;&#98;&#97;&#114;&#64;&#101;&#120;&#97;&#109;&#112;&#108;&#101;&#46;&#99;&#111;&#109;&#62;</td>
109 <td>&#70;&#111;&#111;&#32;&#66;&#97;&#114;&#32;&#60;&#102;&#111;&#111;&#46;&#98;&#97;&#114;&#64;&#101;&#120;&#97;&#109;&#112;&#108;&#101;&#46;&#99;&#111;&#109;&#62;</td>
110 <td class="age">seconds ago</td>
110 <td class="age">seconds ago</td>
111 <td class="indexlinks"></td>
111 <td class="indexlinks"></td>
112 </tr>
112 </tr>
113
113
114 <tr class="parity1">
114 <tr class="parity1">
115 <td><a href="/rcoll/a/?style=paper">rcoll/a</a></td>
115 <td><a href="/rcoll/a/?style=paper">rcoll/a</a></td>
116 <td>unknown</td>
116 <td>unknown</td>
117 <td>&#70;&#111;&#111;&#32;&#66;&#97;&#114;&#32;&#60;&#102;&#111;&#111;&#46;&#98;&#97;&#114;&#64;&#101;&#120;&#97;&#109;&#112;&#108;&#101;&#46;&#99;&#111;&#109;&#62;</td>
117 <td>&#70;&#111;&#111;&#32;&#66;&#97;&#114;&#32;&#60;&#102;&#111;&#111;&#46;&#98;&#97;&#114;&#64;&#101;&#120;&#97;&#109;&#112;&#108;&#101;&#46;&#99;&#111;&#109;&#62;</td>
118 <td class="age">seconds ago</td>
118 <td class="age">seconds ago</td>
119 <td class="indexlinks"></td>
119 <td class="indexlinks"></td>
120 </tr>
120 </tr>
121
121
122 <tr class="parity0">
122 <tr class="parity0">
123 <td><a href="/rcoll/a/.hg/patches/?style=paper">rcoll/a/.hg/patches</a></td>
123 <td><a href="/rcoll/a/.hg/patches/?style=paper">rcoll/a/.hg/patches</a></td>
124 <td>unknown</td>
124 <td>unknown</td>
125 <td>&#70;&#111;&#111;&#32;&#66;&#97;&#114;&#32;&#60;&#102;&#111;&#111;&#46;&#98;&#97;&#114;&#64;&#101;&#120;&#97;&#109;&#112;&#108;&#101;&#46;&#99;&#111;&#109;&#62;</td>
125 <td>&#70;&#111;&#111;&#32;&#66;&#97;&#114;&#32;&#60;&#102;&#111;&#111;&#46;&#98;&#97;&#114;&#64;&#101;&#120;&#97;&#109;&#112;&#108;&#101;&#46;&#99;&#111;&#109;&#62;</td>
126 <td class="age">seconds ago</td>
126 <td class="age">seconds ago</td>
127 <td class="indexlinks"></td>
127 <td class="indexlinks"></td>
128 </tr>
128 </tr>
129
129
130 <tr class="parity1">
130 <tr class="parity1">
131 <td><a href="/rcoll/b/?style=paper">rcoll/b</a></td>
131 <td><a href="/rcoll/b/?style=paper">rcoll/b</a></td>
132 <td>unknown</td>
132 <td>unknown</td>
133 <td>&#70;&#111;&#111;&#32;&#66;&#97;&#114;&#32;&#60;&#102;&#111;&#111;&#46;&#98;&#97;&#114;&#64;&#101;&#120;&#97;&#109;&#112;&#108;&#101;&#46;&#99;&#111;&#109;&#62;</td>
133 <td>&#70;&#111;&#111;&#32;&#66;&#97;&#114;&#32;&#60;&#102;&#111;&#111;&#46;&#98;&#97;&#114;&#64;&#101;&#120;&#97;&#109;&#112;&#108;&#101;&#46;&#99;&#111;&#109;&#62;</td>
134 <td class="age">seconds ago</td>
134 <td class="age">seconds ago</td>
135 <td class="indexlinks"></td>
135 <td class="indexlinks"></td>
136 </tr>
136 </tr>
137
137
138 <tr class="parity0">
138 <tr class="parity0">
139 <td><a href="/rcoll/b/d/?style=paper">rcoll/b/d</a></td>
139 <td><a href="/rcoll/b/d/?style=paper">rcoll/b/d</a></td>
140 <td>unknown</td>
140 <td>unknown</td>
141 <td>&#70;&#111;&#111;&#32;&#66;&#97;&#114;&#32;&#60;&#102;&#111;&#111;&#46;&#98;&#97;&#114;&#64;&#101;&#120;&#97;&#109;&#112;&#108;&#101;&#46;&#99;&#111;&#109;&#62;</td>
141 <td>&#70;&#111;&#111;&#32;&#66;&#97;&#114;&#32;&#60;&#102;&#111;&#111;&#46;&#98;&#97;&#114;&#64;&#101;&#120;&#97;&#109;&#112;&#108;&#101;&#46;&#99;&#111;&#109;&#62;</td>
142 <td class="age">seconds ago</td>
142 <td class="age">seconds ago</td>
143 <td class="indexlinks"></td>
143 <td class="indexlinks"></td>
144 </tr>
144 </tr>
145
145
146 <tr class="parity1">
146 <tr class="parity1">
147 <td><a href="/rcoll/c/?style=paper">rcoll/c</a></td>
147 <td><a href="/rcoll/c/?style=paper">rcoll/c</a></td>
148 <td>unknown</td>
148 <td>unknown</td>
149 <td>&#70;&#111;&#111;&#32;&#66;&#97;&#114;&#32;&#60;&#102;&#111;&#111;&#46;&#98;&#97;&#114;&#64;&#101;&#120;&#97;&#109;&#112;&#108;&#101;&#46;&#99;&#111;&#109;&#62;</td>
149 <td>&#70;&#111;&#111;&#32;&#66;&#97;&#114;&#32;&#60;&#102;&#111;&#111;&#46;&#98;&#97;&#114;&#64;&#101;&#120;&#97;&#109;&#112;&#108;&#101;&#46;&#99;&#111;&#109;&#62;</td>
150 <td class="age">seconds ago</td>
150 <td class="age">seconds ago</td>
151 <td class="indexlinks"></td>
151 <td class="indexlinks"></td>
152 </tr>
152 </tr>
153
153
154 <tr class="parity0">
154 <tr class="parity0">
155 <td><a href="/t/a/?style=paper">t/a</a></td>
155 <td><a href="/t/a/?style=paper">t/a</a></td>
156 <td>unknown</td>
156 <td>unknown</td>
157 <td>&#70;&#111;&#111;&#32;&#66;&#97;&#114;&#32;&#60;&#102;&#111;&#111;&#46;&#98;&#97;&#114;&#64;&#101;&#120;&#97;&#109;&#112;&#108;&#101;&#46;&#99;&#111;&#109;&#62;</td>
157 <td>&#70;&#111;&#111;&#32;&#66;&#97;&#114;&#32;&#60;&#102;&#111;&#111;&#46;&#98;&#97;&#114;&#64;&#101;&#120;&#97;&#109;&#112;&#108;&#101;&#46;&#99;&#111;&#109;&#62;</td>
158 <td class="age">seconds ago</td>
158 <td class="age">seconds ago</td>
159 <td class="indexlinks"></td>
159 <td class="indexlinks"></td>
160 </tr>
160 </tr>
161
161
162 </table>
162 </table>
163 </div>
163 </div>
164 </div>
164 </div>
165
165
166
166
167 </body>
167 </body>
168 </html>
168 </html>
169
169
170 200 Script output follows
170 200 Script output follows
171
171
172
172
173 /t/a/
173 /t/a/
174
174
175 200 Script output follows
175 200 Script output follows
176
176
177
177
178 /t/a/
178 /t/a/
179
179
180 200 Script output follows
180 200 Script output follows
181
181
182 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
182 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
183 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
183 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
184 <head>
184 <head>
185 <link rel="icon" href="/static/hgicon.png" type="image/png" />
185 <link rel="icon" href="/static/hgicon.png" type="image/png" />
186 <meta name="robots" content="index, nofollow" />
186 <meta name="robots" content="index, nofollow" />
187 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
187 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
188
188
189 <title>Mercurial repositories index</title>
189 <title>Mercurial repositories index</title>
190 </head>
190 </head>
191 <body>
191 <body>
192
192
193 <div class="container">
193 <div class="container">
194 <div class="menu">
194 <div class="menu">
195 <a href="http://mercurial.selenic.com/">
195 <a href="http://mercurial.selenic.com/">
196 <img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial" /></a>
196 <img src="/static/hglogo.png" width=75 height=90 border=0 alt="mercurial" /></a>
197 </div>
197 </div>
198 <div class="main">
198 <div class="main">
199 <h2>Mercurial Repositories</h2>
199 <h2>Mercurial Repositories</h2>
200
200
201 <table class="bigtable">
201 <table class="bigtable">
202 <tr>
202 <tr>
203 <th><a href="?sort=-name">Name</a></th>
203 <th><a href="?sort=-name">Name</a></th>
204 <th><a href="?sort=description">Description</a></th>
204 <th><a href="?sort=description">Description</a></th>
205 <th><a href="?sort=contact">Contact</a></th>
205 <th><a href="?sort=contact">Contact</a></th>
206 <th><a href="?sort=lastchange">Last change</a></th>
206 <th><a href="?sort=lastchange">Last change</a></th>
207 <th>&nbsp;</th>
207 <th>&nbsp;</th>
208 </tr>
208 </tr>
209
209
210 <tr class="parity0">
210 <tr class="parity0">
211 <td><a href="/t/a/?style=paper">a</a></td>
211 <td><a href="/t/a/?style=paper">a</a></td>
212 <td>unknown</td>
212 <td>unknown</td>
213 <td>&#70;&#111;&#111;&#32;&#66;&#97;&#114;&#32;&#60;&#102;&#111;&#111;&#46;&#98;&#97;&#114;&#64;&#101;&#120;&#97;&#109;&#112;&#108;&#101;&#46;&#99;&#111;&#109;&#62;</td>
213 <td>&#70;&#111;&#111;&#32;&#66;&#97;&#114;&#32;&#60;&#102;&#111;&#111;&#46;&#98;&#97;&#114;&#64;&#101;&#120;&#97;&#109;&#112;&#108;&#101;&#46;&#99;&#111;&#109;&#62;</td>
214 <td class="age">seconds ago</td>
214 <td class="age">seconds ago</td>
215 <td class="indexlinks"></td>
215 <td class="indexlinks"></td>
216 </tr>
216 </tr>
217
217
218 </table>
218 </table>
219 </div>
219 </div>
220 </div>
220 </div>
221
221
222
222
223 </body>
223 </body>
224 </html>
224 </html>
225
225
226 200 Script output follows
226 200 Script output follows
227
227
228 <?xml version="1.0" encoding="ascii"?>
228 <?xml version="1.0" encoding="ascii"?>
229 <feed xmlns="http://127.0.0.1/2005/Atom">
229 <feed xmlns="http://127.0.0.1/2005/Atom">
230 <!-- Changelog -->
230 <!-- Changelog -->
231 <id>http://127.0.0.1/t/a/</id>
231 <id>http://127.0.0.1/t/a/</id>
232 <link rel="self" href="http://127.0.0.1/t/a/atom-log"/>
232 <link rel="self" href="http://127.0.0.1/t/a/atom-log"/>
233 <link rel="alternate" href="http://127.0.0.1/t/a/"/>
233 <link rel="alternate" href="http://127.0.0.1/t/a/"/>
234 <title>t/a Changelog</title>
234 <title>t/a Changelog</title>
235 <updated>1970-01-01T00:00:01+00:00</updated>
235 <updated>1970-01-01T00:00:01+00:00</updated>
236
236
237 <entry>
237 <entry>
238 <title>a</title>
238 <title>a</title>
239 <id>http://127.0.0.1/t/a/#changeset-8580ff50825a50c8f716709acdf8de0deddcd6ab</id>
239 <id>http://127.0.0.1/t/a/#changeset-8580ff50825a50c8f716709acdf8de0deddcd6ab</id>
240 <link href="http://127.0.0.1/t/a/rev/8580ff50825a50c8f716709acdf8de0deddcd6ab"/>
240 <link href="http://127.0.0.1/t/a/rev/8580ff50825a50c8f716709acdf8de0deddcd6ab"/>
241 <author>
241 <author>
242 <name>test</name>
242 <name>test</name>
243 <email>&#116;&#101;&#115;&#116;</email>
243 <email>&#116;&#101;&#115;&#116;</email>
244 </author>
244 </author>
245 <updated>1970-01-01T00:00:01+00:00</updated>
245 <updated>1970-01-01T00:00:01+00:00</updated>
246 <published>1970-01-01T00:00:01+00:00</published>
246 <published>1970-01-01T00:00:01+00:00</published>
247 <content type="xhtml">
247 <content type="xhtml">
248 <div xmlns="http://127.0.0.1/1999/xhtml">
248 <div xmlns="http://127.0.0.1/1999/xhtml">
249 <pre xml:space="preserve">a</pre>
249 <pre xml:space="preserve">a</pre>
250 </div>
250 </div>
251 </content>
251 </content>
252 </entry>
252 </entry>
253
253
254 </feed>
254 </feed>
255 200 Script output follows
255 200 Script output follows
256
256
257 <?xml version="1.0" encoding="ascii"?>
257 <?xml version="1.0" encoding="ascii"?>
258 <feed xmlns="http://127.0.0.1/2005/Atom">
258 <feed xmlns="http://127.0.0.1/2005/Atom">
259 <!-- Changelog -->
259 <!-- Changelog -->
260 <id>http://127.0.0.1/t/a/</id>
260 <id>http://127.0.0.1/t/a/</id>
261 <link rel="self" href="http://127.0.0.1/t/a/atom-log"/>
261 <link rel="self" href="http://127.0.0.1/t/a/atom-log"/>
262 <link rel="alternate" href="http://127.0.0.1/t/a/"/>
262 <link rel="alternate" href="http://127.0.0.1/t/a/"/>
263 <title>t/a Changelog</title>
263 <title>t/a Changelog</title>
264 <updated>1970-01-01T00:00:01+00:00</updated>
264 <updated>1970-01-01T00:00:01+00:00</updated>
265
265
266 <entry>
266 <entry>
267 <title>a</title>
267 <title>a</title>
268 <id>http://127.0.0.1/t/a/#changeset-8580ff50825a50c8f716709acdf8de0deddcd6ab</id>
268 <id>http://127.0.0.1/t/a/#changeset-8580ff50825a50c8f716709acdf8de0deddcd6ab</id>
269 <link href="http://127.0.0.1/t/a/rev/8580ff50825a50c8f716709acdf8de0deddcd6ab"/>
269 <link href="http://127.0.0.1/t/a/rev/8580ff50825a50c8f716709acdf8de0deddcd6ab"/>
270 <author>
270 <author>
271 <name>test</name>
271 <name>test</name>
272 <email>&#116;&#101;&#115;&#116;</email>
272 <email>&#116;&#101;&#115;&#116;</email>
273 </author>
273 </author>
274 <updated>1970-01-01T00:00:01+00:00</updated>
274 <updated>1970-01-01T00:00:01+00:00</updated>
275 <published>1970-01-01T00:00:01+00:00</published>
275 <published>1970-01-01T00:00:01+00:00</published>
276 <content type="xhtml">
276 <content type="xhtml">
277 <div xmlns="http://127.0.0.1/1999/xhtml">
277 <div xmlns="http://127.0.0.1/1999/xhtml">
278 <pre xml:space="preserve">a</pre>
278 <pre xml:space="preserve">a</pre>
279 </div>
279 </div>
280 </content>
280 </content>
281 </entry>
281 </entry>
282
282
283 </feed>
283 </feed>
284 200 Script output follows
284 200 Script output follows
285
285
286 a
286 a
287 200 Script output follows
287 200 Script output follows
288
288
289
289
290 /coll/a/
290 /coll/a/
291 /coll/a/.hg/patches/
291 /coll/a/.hg/patches/
292 /coll/b/
292 /coll/b/
293 /coll/c/
293 /coll/c/
294
294
295 200 Script output follows
295 200 Script output follows
296
296
297 a
297 a
298 200 Script output follows
298 200 Script output follows
299
299
300
300
301 /rcoll/a/
301 /rcoll/a/
302 /rcoll/a/.hg/patches/
302 /rcoll/a/.hg/patches/
303 /rcoll/b/
303 /rcoll/b/
304 /rcoll/b/d/
304 /rcoll/b/d/
305 /rcoll/c/
305 /rcoll/c/
306
306
307 200 Script output follows
307 200 Script output follows
308
308
309 d
309 d
310 % test descend = False
311 200 Script output follows
312
313
314 /c/
315
316 200 Script output follows
317
318
319 /t/a/
320 /t/b/
321
310 % collections: should succeed
322 % collections: should succeed
311 200 Script output follows
323 200 Script output follows
312
324
313
325
314 http://hg.example.com:8080/a/
326 http://hg.example.com:8080/a/
315 http://hg.example.com:8080/a/.hg/patches/
327 http://hg.example.com:8080/a/.hg/patches/
316 http://hg.example.com:8080/b/
328 http://hg.example.com:8080/b/
317 http://hg.example.com:8080/c/
329 http://hg.example.com:8080/c/
318
330
319 200 Script output follows
331 200 Script output follows
320
332
321 a
333 a
322 200 Script output follows
334 200 Script output follows
323
335
324 b
336 b
325 200 Script output follows
337 200 Script output follows
326
338
327 c
339 c
328 % paths errors 1
340 % paths errors 1
329 % paths errors 2
341 % paths errors 2
342 % paths errors 3
330 % collections errors
343 % collections errors
General Comments 0
You need to be logged in to leave comments. Login now