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