##// END OF EJS Templates
url: 'ssh known host'-like checking of fingerprints of HTTPS certificates...
Mads Kiilerich -
r13314:8dc488df stable
parent child Browse files
Show More
@@ -1,1100 +1,1118 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 .. contents::
15 15 :backlinks: top
16 16 :class: htmlonly
17 17
18 18
19 19 Synopsis
20 20 --------
21 21
22 22 The Mercurial system uses a set of configuration files to control
23 23 aspects of its behavior.
24 24
25 25 Files
26 26 -----
27 27
28 28 Mercurial reads configuration data from several files, if they exist.
29 29 The names of these files depend on the system on which Mercurial is
30 30 installed. ``*.rc`` files from a single directory are read in
31 31 alphabetical order, later ones overriding earlier ones. Where multiple
32 32 paths are given below, settings from earlier paths override later
33 33 ones.
34 34
35 35 | (Unix, Windows) ``<repo>/.hg/hgrc``
36 36
37 37 Per-repository configuration options that only apply in a
38 38 particular repository. This file is not version-controlled, and
39 39 will not get transferred during a "clone" operation. Options in
40 40 this file override options in all other configuration files. On
41 41 Unix, most of this file will be ignored if it doesn't belong to a
42 42 trusted user or to a trusted group. See the documentation for the
43 43 trusted_ section below for more details.
44 44
45 45 | (Unix) ``$HOME/.hgrc``
46 46 | (Windows) ``%USERPROFILE%\.hgrc``
47 47 | (Windows) ``%USERPROFILE%\Mercurial.ini``
48 48 | (Windows) ``%HOME%\.hgrc``
49 49 | (Windows) ``%HOME%\Mercurial.ini``
50 50
51 51 Per-user configuration file(s), for the user running Mercurial. On
52 52 Windows 9x, ``%HOME%`` is replaced by ``%APPDATA%``. Options in these
53 53 files apply to all Mercurial commands executed by this user in any
54 54 directory. Options in these files override per-system and per-installation
55 55 options.
56 56
57 57 | (Unix) ``/etc/mercurial/hgrc``
58 58 | (Unix) ``/etc/mercurial/hgrc.d/*.rc``
59 59
60 60 Per-system configuration files, for the system on which Mercurial
61 61 is running. Options in these files apply to all Mercurial commands
62 62 executed by any user in any directory. Options in these files
63 63 override per-installation options.
64 64
65 65 | (Unix) ``<install-root>/etc/mercurial/hgrc``
66 66 | (Unix) ``<install-root>/etc/mercurial/hgrc.d/*.rc``
67 67
68 68 Per-installation configuration files, searched for in the
69 69 directory where Mercurial is installed. ``<install-root>`` is the
70 70 parent directory of the **hg** executable (or symlink) being run. For
71 71 example, if installed in ``/shared/tools/bin/hg``, Mercurial will look
72 72 in ``/shared/tools/etc/mercurial/hgrc``. Options in these files apply
73 73 to all Mercurial commands executed by any user in any directory.
74 74
75 75 | (Windows) ``<install-dir>\Mercurial.ini``
76 76 | (Windows) ``<install-dir>\hgrc.d\*.rc``
77 77 | (Windows) ``HKEY_LOCAL_MACHINE\SOFTWARE\Mercurial``
78 78
79 79 Per-installation/system configuration files, for the system on
80 80 which Mercurial is running. Options in these files apply to all
81 81 Mercurial commands executed by any user in any directory. Registry
82 82 keys contain PATH-like strings, every part of which must reference
83 83 a ``Mercurial.ini`` file or be a directory where ``*.rc`` files will
84 84 be read. Mercurial checks each of these locations in the specified
85 85 order until one or more configuration files are detected. If the
86 86 pywin32 extensions are not installed, Mercurial will only look for
87 87 site-wide configuration in ``C:\Mercurial\Mercurial.ini``.
88 88
89 89 Syntax
90 90 ------
91 91
92 92 A configuration file consists of sections, led by a ``[section]`` header
93 93 and followed by ``name = value`` entries (sometimes called
94 94 ``configuration keys``)::
95 95
96 96 [spam]
97 97 eggs=ham
98 98 green=
99 99 eggs
100 100
101 101 Each line contains one entry. If the lines that follow are indented,
102 102 they are treated as continuations of that entry. Leading whitespace is
103 103 removed from values. Empty lines are skipped. Lines beginning with
104 104 ``#`` or ``;`` are ignored and may be used to provide comments.
105 105
106 106 Configuration keys can be set multiple times, in which case mercurial
107 107 will use the value that was configured last. As an example::
108 108
109 109 [spam]
110 110 eggs=large
111 111 ham=serrano
112 112 eggs=small
113 113
114 114 This would set the configuration key named ``eggs`` to ``small``.
115 115
116 116 It is also possible to define a section multiple times. A section can
117 117 be redefined on the same and/or on different hgrc files. For example::
118 118
119 119 [foo]
120 120 eggs=large
121 121 ham=serrano
122 122 eggs=small
123 123
124 124 [bar]
125 125 eggs=ham
126 126 green=
127 127 eggs
128 128
129 129 [foo]
130 130 ham=prosciutto
131 131 eggs=medium
132 132 bread=toasted
133 133
134 134 This would set the ``eggs``, ``ham``, and ``bread`` configuration keys
135 135 of the ``foo`` section to ``medium``, ``prosciutto``, and ``toasted``,
136 136 respectively. As you can see there only thing that matters is the last
137 137 value that was set for each of the configuration keys.
138 138
139 139 If a configuration key is set multiple times in different
140 140 configuration files the final value will depend on the order in which
141 141 the different configuration files are read, with settings from earlier
142 142 paths overriding later ones as described on the ``Files`` section
143 143 above.
144 144
145 145 A line of the form ``%include file`` will include ``file`` into the
146 146 current configuration file. The inclusion is recursive, which means
147 147 that included files can include other files. Filenames are relative to
148 148 the configuration file in which the ``%include`` directive is found.
149 149 Environment variables and ``~user`` constructs are expanded in
150 150 ``file``. This lets you do something like::
151 151
152 152 %include ~/.hgrc.d/$HOST.rc
153 153
154 154 to include a different configuration file on each computer you use.
155 155
156 156 A line with ``%unset name`` will remove ``name`` from the current
157 157 section, if it has been set previously.
158 158
159 159 The values are either free-form text strings, lists of text strings,
160 160 or Boolean values. Boolean values can be set to true using any of "1",
161 161 "yes", "true", or "on" and to false using "0", "no", "false", or "off"
162 162 (all case insensitive).
163 163
164 164 List values are separated by whitespace or comma, except when values are
165 165 placed in double quotation marks::
166 166
167 167 allow_read = "John Doe, PhD", brian, betty
168 168
169 169 Quotation marks can be escaped by prefixing them with a backslash. Only
170 170 quotation marks at the beginning of a word is counted as a quotation
171 171 (e.g., ``foo"bar baz`` is the list of ``foo"bar`` and ``baz``).
172 172
173 173 Sections
174 174 --------
175 175
176 176 This section describes the different sections that may appear in a
177 177 Mercurial "hgrc" file, the purpose of each section, its possible keys,
178 178 and their possible values.
179 179
180 180 ``alias``
181 181 """""""""
182 182 Defines command aliases.
183 183 Aliases allow you to define your own commands in terms of other
184 184 commands (or aliases), optionally including arguments.
185 185
186 186 Alias definitions consist of lines of the form::
187 187
188 188 <alias> = <command> [<argument]...
189 189
190 190 For example, this definition::
191 191
192 192 latest = log --limit 5
193 193
194 194 creates a new command ``latest`` that shows only the five most recent
195 195 changesets. You can define subsequent aliases using earlier ones::
196 196
197 197 stable5 = latest -b stable
198 198
199 199 .. note:: It is possible to create aliases with the same names as
200 200 existing commands, which will then override the original
201 201 definitions. This is almost always a bad idea!
202 202
203 203
204 204 ``auth``
205 205 """"""""
206 206
207 207 Authentication credentials for HTTP authentication. This section
208 208 allows you to store usernames and passwords for use when logging
209 209 *into* HTTP servers. See the web_ configuration section if you want to
210 210 configure *who* can login to your HTTP server.
211 211
212 212 Each line has the following format::
213 213
214 214 <name>.<argument> = <value>
215 215
216 216 where ``<name>`` is used to group arguments into authentication
217 217 entries. Example::
218 218
219 219 foo.prefix = hg.intevation.org/mercurial
220 220 foo.username = foo
221 221 foo.password = bar
222 222 foo.schemes = http https
223 223
224 224 bar.prefix = secure.example.org
225 225 bar.key = path/to/file.key
226 226 bar.cert = path/to/file.cert
227 227 bar.schemes = https
228 228
229 229 Supported arguments:
230 230
231 231 ``prefix``
232 232 Either ``*`` or a URI prefix with or without the scheme part.
233 233 The authentication entry with the longest matching prefix is used
234 234 (where ``*`` matches everything and counts as a match of length
235 235 1). If the prefix doesn't include a scheme, the match is performed
236 236 against the URI with its scheme stripped as well, and the schemes
237 237 argument, q.v., is then subsequently consulted.
238 238 ``username``
239 239 Optional. Username to authenticate with. If not given, and the
240 240 remote site requires basic or digest authentication, the user will
241 241 be prompted for it. Environment variables are expanded in the
242 242 username letting you do ``foo.username = $USER``.
243 243 ``password``
244 244 Optional. Password to authenticate with. If not given, and the
245 245 remote site requires basic or digest authentication, the user
246 246 will be prompted for it.
247 247 ``key``
248 248 Optional. PEM encoded client certificate key file. Environment
249 249 variables are expanded in the filename.
250 250 ``cert``
251 251 Optional. PEM encoded client certificate chain file. Environment
252 252 variables are expanded in the filename.
253 253 ``schemes``
254 254 Optional. Space separated list of URI schemes to use this
255 255 authentication entry with. Only used if the prefix doesn't include
256 256 a scheme. Supported schemes are http and https. They will match
257 257 static-http and static-https respectively, as well.
258 258 Default: https.
259 259
260 260 If no suitable authentication entry is found, the user is prompted
261 261 for credentials as usual if required by the remote.
262 262
263 263
264 264 ``decode/encode``
265 265 """""""""""""""""
266 266 Filters for transforming files on checkout/checkin. This would
267 267 typically be used for newline processing or other
268 268 localization/canonicalization of files.
269 269
270 270 Filters consist of a filter pattern followed by a filter command.
271 271 Filter patterns are globs by default, rooted at the repository root.
272 272 For example, to match any file ending in ``.txt`` in the root
273 273 directory only, use the pattern ``*.txt``. To match any file ending
274 274 in ``.c`` anywhere in the repository, use the pattern ``**.c``.
275 275 For each file only the first matching filter applies.
276 276
277 277 The filter command can start with a specifier, either ``pipe:`` or
278 278 ``tempfile:``. If no specifier is given, ``pipe:`` is used by default.
279 279
280 280 A ``pipe:`` command must accept data on stdin and return the transformed
281 281 data on stdout.
282 282
283 283 Pipe example::
284 284
285 285 [encode]
286 286 # uncompress gzip files on checkin to improve delta compression
287 287 # note: not necessarily a good idea, just an example
288 288 *.gz = pipe: gunzip
289 289
290 290 [decode]
291 291 # recompress gzip files when writing them to the working dir (we
292 292 # can safely omit "pipe:", because it's the default)
293 293 *.gz = gzip
294 294
295 295 A ``tempfile:`` command is a template. The string ``INFILE`` is replaced
296 296 with the name of a temporary file that contains the data to be
297 297 filtered by the command. The string ``OUTFILE`` is replaced with the name
298 298 of an empty temporary file, where the filtered data must be written by
299 299 the command.
300 300
301 301 .. note:: The tempfile mechanism is recommended for Windows systems,
302 302 where the standard shell I/O redirection operators often have
303 303 strange effects and may corrupt the contents of your files.
304 304
305 305 This filter mechanism is used internally by the ``eol`` extension to
306 306 translate line ending characters between Windows (CRLF) and Unix (LF)
307 307 format. We suggest you use the ``eol`` extension for convenience.
308 308
309 309
310 310 ``defaults``
311 311 """"""""""""
312 312
313 313 (defaults are deprecated. Don't use them. Use aliases instead)
314 314
315 315 Use the ``[defaults]`` section to define command defaults, i.e. the
316 316 default options/arguments to pass to the specified commands.
317 317
318 318 The following example makes :hg:`log` run in verbose mode, and
319 319 :hg:`status` show only the modified files, by default::
320 320
321 321 [defaults]
322 322 log = -v
323 323 status = -m
324 324
325 325 The actual commands, instead of their aliases, must be used when
326 326 defining command defaults. The command defaults will also be applied
327 327 to the aliases of the commands defined.
328 328
329 329
330 330 ``diff``
331 331 """"""""
332 332
333 333 Settings used when displaying diffs. They are all Boolean and
334 334 defaults to False.
335 335
336 336 ``git``
337 337 Use git extended diff format.
338 338 ``nodates``
339 339 Don't include dates in diff headers.
340 340 ``showfunc``
341 341 Show which function each change is in.
342 342 ``ignorews``
343 343 Ignore white space when comparing lines.
344 344 ``ignorewsamount``
345 345 Ignore changes in the amount of white space.
346 346 ``ignoreblanklines``
347 347 Ignore changes whose lines are all blank.
348 348
349 349 ``email``
350 350 """""""""
351 351 Settings for extensions that send email messages.
352 352
353 353 ``from``
354 354 Optional. Email address to use in "From" header and SMTP envelope
355 355 of outgoing messages.
356 356 ``to``
357 357 Optional. Comma-separated list of recipients' email addresses.
358 358 ``cc``
359 359 Optional. Comma-separated list of carbon copy recipients'
360 360 email addresses.
361 361 ``bcc``
362 362 Optional. Comma-separated list of blind carbon copy recipients'
363 363 email addresses.
364 364 ``method``
365 365 Optional. Method to use to send email messages. If value is ``smtp``
366 366 (default), use SMTP (see the SMTP_ section for configuration).
367 367 Otherwise, use as name of program to run that acts like sendmail
368 368 (takes ``-f`` option for sender, list of recipients on command line,
369 369 message on stdin). Normally, setting this to ``sendmail`` or
370 370 ``/usr/sbin/sendmail`` is enough to use sendmail to send messages.
371 371 ``charsets``
372 372 Optional. Comma-separated list of character sets considered
373 373 convenient for recipients. Addresses, headers, and parts not
374 374 containing patches of outgoing messages will be encoded in the
375 375 first character set to which conversion from local encoding
376 376 (``$HGENCODING``, ``ui.fallbackencoding``) succeeds. If correct
377 377 conversion fails, the text in question is sent as is. Defaults to
378 378 empty (explicit) list.
379 379
380 380 Order of outgoing email character sets:
381 381
382 382 1. ``us-ascii``: always first, regardless of settings
383 383 2. ``email.charsets``: in order given by user
384 384 3. ``ui.fallbackencoding``: if not in email.charsets
385 385 4. ``$HGENCODING``: if not in email.charsets
386 386 5. ``utf-8``: always last, regardless of settings
387 387
388 388 Email example::
389 389
390 390 [email]
391 391 from = Joseph User <joe.user@example.com>
392 392 method = /usr/sbin/sendmail
393 393 # charsets for western Europeans
394 394 # us-ascii, utf-8 omitted, as they are tried first and last
395 395 charsets = iso-8859-1, iso-8859-15, windows-1252
396 396
397 397
398 398 ``extensions``
399 399 """"""""""""""
400 400
401 401 Mercurial has an extension mechanism for adding new features. To
402 402 enable an extension, create an entry for it in this section.
403 403
404 404 If you know that the extension is already in Python's search path,
405 405 you can give the name of the module, followed by ``=``, with nothing
406 406 after the ``=``.
407 407
408 408 Otherwise, give a name that you choose, followed by ``=``, followed by
409 409 the path to the ``.py`` file (including the file name extension) that
410 410 defines the extension.
411 411
412 412 To explicitly disable an extension that is enabled in an hgrc of
413 413 broader scope, prepend its path with ``!``, as in
414 414 ``hgext.foo = !/ext/path`` or ``hgext.foo = !`` when path is not
415 415 supplied.
416 416
417 417 Example for ``~/.hgrc``::
418 418
419 419 [extensions]
420 420 # (the mq extension will get loaded from Mercurial's path)
421 421 hgext.mq =
422 422 # (this extension will get loaded from the file specified)
423 423 myfeature = ~/.hgext/myfeature.py
424 424
425 425
426 ``hostfingerprints``
427 """"""""""""""""""""
428
429 Fingerprints of the certificates of known HTTPS servers.
430 A HTTPS connection to a server with a fingerprint configured here will
431 only succeed if the servers certificate matches the fingerprint.
432 This is very similar to how ssh known hosts works.
433 The fingerprint is the SHA-1 hash value of the DER encoded certificate.
434 The CA chain and web.cacerts is not used for servers with a fingerprint.
435
436 For example::
437
438 [hostfingerprints]
439 hg.intevation.org = 38:76:52:7c:87:26:9a:8f:4a:f8:d3:de:08:45:3b:ea:d6:4b:ee:cc
440
441 This feature is only supported when using Python 2.6 or later.
442
443
426 444 ``format``
427 445 """"""""""
428 446
429 447 ``usestore``
430 448 Enable or disable the "store" repository format which improves
431 449 compatibility with systems that fold case or otherwise mangle
432 450 filenames. Enabled by default. Disabling this option will allow
433 451 you to store longer filenames in some situations at the expense of
434 452 compatibility and ensures that the on-disk format of newly created
435 453 repositories will be compatible with Mercurial before version 0.9.4.
436 454
437 455 ``usefncache``
438 456 Enable or disable the "fncache" repository format which enhances
439 457 the "store" repository format (which has to be enabled to use
440 458 fncache) to allow longer filenames and avoids using Windows
441 459 reserved names, e.g. "nul". Enabled by default. Disabling this
442 460 option ensures that the on-disk format of newly created
443 461 repositories will be compatible with Mercurial before version 1.1.
444 462
445 463 ``dotencode``
446 464 Enable or disable the "dotencode" repository format which enhances
447 465 the "fncache" repository format (which has to be enabled to use
448 466 dotencode) to avoid issues with filenames starting with ._ on
449 467 Mac OS X and spaces on Windows. Enabled by default. Disabling this
450 468 option ensures that the on-disk format of newly created
451 469 repositories will be compatible with Mercurial before version 1.7.
452 470
453 471 ``merge-patterns``
454 472 """"""""""""""""""
455 473
456 474 This section specifies merge tools to associate with particular file
457 475 patterns. Tools matched here will take precedence over the default
458 476 merge tool. Patterns are globs by default, rooted at the repository
459 477 root.
460 478
461 479 Example::
462 480
463 481 [merge-patterns]
464 482 **.c = kdiff3
465 483 **.jpg = myimgmerge
466 484
467 485 ``merge-tools``
468 486 """""""""""""""
469 487
470 488 This section configures external merge tools to use for file-level
471 489 merges.
472 490
473 491 Example ``~/.hgrc``::
474 492
475 493 [merge-tools]
476 494 # Override stock tool location
477 495 kdiff3.executable = ~/bin/kdiff3
478 496 # Specify command line
479 497 kdiff3.args = $base $local $other -o $output
480 498 # Give higher priority
481 499 kdiff3.priority = 1
482 500
483 501 # Define new tool
484 502 myHtmlTool.args = -m $local $other $base $output
485 503 myHtmlTool.regkey = Software\FooSoftware\HtmlMerge
486 504 myHtmlTool.priority = 1
487 505
488 506 Supported arguments:
489 507
490 508 ``priority``
491 509 The priority in which to evaluate this tool.
492 510 Default: 0.
493 511 ``executable``
494 512 Either just the name of the executable or its pathname. On Windows,
495 513 the path can use environment variables with ${ProgramFiles} syntax.
496 514 Default: the tool name.
497 515 ``args``
498 516 The arguments to pass to the tool executable. You can refer to the
499 517 files being merged as well as the output file through these
500 518 variables: ``$base``, ``$local``, ``$other``, ``$output``.
501 519 Default: ``$local $base $other``
502 520 ``premerge``
503 521 Attempt to run internal non-interactive 3-way merge tool before
504 522 launching external tool. Options are ``true``, ``false``, or ``keep``
505 523 to leave markers in the file if the premerge fails.
506 524 Default: True
507 525 ``binary``
508 526 This tool can merge binary files. Defaults to False, unless tool
509 527 was selected by file pattern match.
510 528 ``symlink``
511 529 This tool can merge symlinks. Defaults to False, even if tool was
512 530 selected by file pattern match.
513 531 ``check``
514 532 A list of merge success-checking options:
515 533
516 534 ``changed``
517 535 Ask whether merge was successful when the merged file shows no changes.
518 536 ``conflicts``
519 537 Check whether there are conflicts even though the tool reported success.
520 538 ``prompt``
521 539 Always prompt for merge success, regardless of success reported by tool.
522 540
523 541 ``checkchanged``
524 542 True is equivalent to ``check = changed``.
525 543 Default: False
526 544 ``checkconflicts``
527 545 True is equivalent to ``check = conflicts``.
528 546 Default: False
529 547 ``fixeol``
530 548 Attempt to fix up EOL changes caused by the merge tool.
531 549 Default: False
532 550 ``gui``
533 551 This tool requires a graphical interface to run. Default: False
534 552 ``regkey``
535 553 Windows registry key which describes install location of this
536 554 tool. Mercurial will search for this key first under
537 555 ``HKEY_CURRENT_USER`` and then under ``HKEY_LOCAL_MACHINE``.
538 556 Default: None
539 557 ``regname``
540 558 Name of value to read from specified registry key. Defaults to the
541 559 unnamed (default) value.
542 560 ``regappend``
543 561 String to append to the value read from the registry, typically
544 562 the executable name of the tool.
545 563 Default: None
546 564
547 565
548 566 ``hooks``
549 567 """""""""
550 568 Commands or Python functions that get automatically executed by
551 569 various actions such as starting or finishing a commit. Multiple
552 570 hooks can be run for the same action by appending a suffix to the
553 571 action. Overriding a site-wide hook can be done by changing its
554 572 value or setting it to an empty string.
555 573
556 574 Example ``.hg/hgrc``::
557 575
558 576 [hooks]
559 577 # update working directory after adding changesets
560 578 changegroup.update = hg update
561 579 # do not use the site-wide hook
562 580 incoming =
563 581 incoming.email = /my/email/hook
564 582 incoming.autobuild = /my/build/hook
565 583
566 584 Most hooks are run with environment variables set that give useful
567 585 additional information. For each hook below, the environment
568 586 variables it is passed are listed with names of the form ``$HG_foo``.
569 587
570 588 ``changegroup``
571 589 Run after a changegroup has been added via push, pull or unbundle.
572 590 ID of the first new changeset is in ``$HG_NODE``. URL from which
573 591 changes came is in ``$HG_URL``.
574 592 ``commit``
575 593 Run after a changeset has been created in the local repository. ID
576 594 of the newly created changeset is in ``$HG_NODE``. Parent changeset
577 595 IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
578 596 ``incoming``
579 597 Run after a changeset has been pulled, pushed, or unbundled into
580 598 the local repository. The ID of the newly arrived changeset is in
581 599 ``$HG_NODE``. URL that was source of changes came is in ``$HG_URL``.
582 600 ``outgoing``
583 601 Run after sending changes from local repository to another. ID of
584 602 first changeset sent is in ``$HG_NODE``. Source of operation is in
585 603 ``$HG_SOURCE``; see "preoutgoing" hook for description.
586 604 ``post-<command>``
587 605 Run after successful invocations of the associated command. The
588 606 contents of the command line are passed as ``$HG_ARGS`` and the result
589 607 code in ``$HG_RESULT``. Parsed command line arguments are passed as
590 608 ``$HG_PATS`` and ``$HG_OPTS``. These contain string representations of
591 609 the python data internally passed to <command>. ``$HG_OPTS`` is a
592 610 dictionary of options (with unspecified options set to their defaults).
593 611 ``$HG_PATS`` is a list of arguments. Hook failure is ignored.
594 612 ``pre-<command>``
595 613 Run before executing the associated command. The contents of the
596 614 command line are passed as ``$HG_ARGS``. Parsed command line arguments
597 615 are passed as ``$HG_PATS`` and ``$HG_OPTS``. These contain string
598 616 representations of the data internally passed to <command>. ``$HG_OPTS``
599 617 is a dictionary of options (with unspecified options set to their
600 618 defaults). ``$HG_PATS`` is a list of arguments. If the hook returns
601 619 failure, the command doesn't execute and Mercurial returns the failure
602 620 code.
603 621 ``prechangegroup``
604 622 Run before a changegroup is added via push, pull or unbundle. Exit
605 623 status 0 allows the changegroup to proceed. Non-zero status will
606 624 cause the push, pull or unbundle to fail. URL from which changes
607 625 will come is in ``$HG_URL``.
608 626 ``precommit``
609 627 Run before starting a local commit. Exit status 0 allows the
610 628 commit to proceed. Non-zero status will cause the commit to fail.
611 629 Parent changeset IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
612 630 ``preoutgoing``
613 631 Run before collecting changes to send from the local repository to
614 632 another. Non-zero status will cause failure. This lets you prevent
615 633 pull over HTTP or SSH. Also prevents against local pull, push
616 634 (outbound) or bundle commands, but not effective, since you can
617 635 just copy files instead then. Source of operation is in
618 636 ``$HG_SOURCE``. If "serve", operation is happening on behalf of remote
619 637 SSH or HTTP repository. If "push", "pull" or "bundle", operation
620 638 is happening on behalf of repository on same system.
621 639 ``pretag``
622 640 Run before creating a tag. Exit status 0 allows the tag to be
623 641 created. Non-zero status will cause the tag to fail. ID of
624 642 changeset to tag is in ``$HG_NODE``. Name of tag is in ``$HG_TAG``. Tag is
625 643 local if ``$HG_LOCAL=1``, in repository if ``$HG_LOCAL=0``.
626 644 ``pretxnchangegroup``
627 645 Run after a changegroup has been added via push, pull or unbundle,
628 646 but before the transaction has been committed. Changegroup is
629 647 visible to hook program. This lets you validate incoming changes
630 648 before accepting them. Passed the ID of the first new changeset in
631 649 ``$HG_NODE``. Exit status 0 allows the transaction to commit. Non-zero
632 650 status will cause the transaction to be rolled back and the push,
633 651 pull or unbundle will fail. URL that was source of changes is in
634 652 ``$HG_URL``.
635 653 ``pretxncommit``
636 654 Run after a changeset has been created but the transaction not yet
637 655 committed. Changeset is visible to hook program. This lets you
638 656 validate commit message and changes. Exit status 0 allows the
639 657 commit to proceed. Non-zero status will cause the transaction to
640 658 be rolled back. ID of changeset is in ``$HG_NODE``. Parent changeset
641 659 IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
642 660 ``preupdate``
643 661 Run before updating the working directory. Exit status 0 allows
644 662 the update to proceed. Non-zero status will prevent the update.
645 663 Changeset ID of first new parent is in ``$HG_PARENT1``. If merge, ID
646 664 of second new parent is in ``$HG_PARENT2``.
647 665 ``tag``
648 666 Run after a tag is created. ID of tagged changeset is in ``$HG_NODE``.
649 667 Name of tag is in ``$HG_TAG``. Tag is local if ``$HG_LOCAL=1``, in
650 668 repository if ``$HG_LOCAL=0``.
651 669 ``update``
652 670 Run after updating the working directory. Changeset ID of first
653 671 new parent is in ``$HG_PARENT1``. If merge, ID of second new parent is
654 672 in ``$HG_PARENT2``. If the update succeeded, ``$HG_ERROR=0``. If the
655 673 update failed (e.g. because conflicts not resolved), ``$HG_ERROR=1``.
656 674
657 675 .. note:: It is generally better to use standard hooks rather than the
658 676 generic pre- and post- command hooks as they are guaranteed to be
659 677 called in the appropriate contexts for influencing transactions.
660 678 Also, hooks like "commit" will be called in all contexts that
661 679 generate a commit (e.g. tag) and not just the commit command.
662 680
663 681 .. note:: Environment variables with empty values may not be passed to
664 682 hooks on platforms such as Windows. As an example, ``$HG_PARENT2``
665 683 will have an empty value under Unix-like platforms for non-merge
666 684 changesets, while it will not be available at all under Windows.
667 685
668 686 The syntax for Python hooks is as follows::
669 687
670 688 hookname = python:modulename.submodule.callable
671 689 hookname = python:/path/to/python/module.py:callable
672 690
673 691 Python hooks are run within the Mercurial process. Each hook is
674 692 called with at least three keyword arguments: a ui object (keyword
675 693 ``ui``), a repository object (keyword ``repo``), and a ``hooktype``
676 694 keyword that tells what kind of hook is used. Arguments listed as
677 695 environment variables above are passed as keyword arguments, with no
678 696 ``HG_`` prefix, and names in lower case.
679 697
680 698 If a Python hook returns a "true" value or raises an exception, this
681 699 is treated as a failure.
682 700
683 701
684 702 ``http_proxy``
685 703 """"""""""""""
686 704 Used to access web-based Mercurial repositories through a HTTP
687 705 proxy.
688 706
689 707 ``host``
690 708 Host name and (optional) port of the proxy server, for example
691 709 "myproxy:8000".
692 710 ``no``
693 711 Optional. Comma-separated list of host names that should bypass
694 712 the proxy.
695 713 ``passwd``
696 714 Optional. Password to authenticate with at the proxy server.
697 715 ``user``
698 716 Optional. User name to authenticate with at the proxy server.
699 717 ``always``
700 718 Optional. Always use the proxy, even for localhost and any entries
701 719 in ``http_proxy.no``. True or False. Default: False.
702 720
703 721 ``smtp``
704 722 """"""""
705 723 Configuration for extensions that need to send email messages.
706 724
707 725 ``host``
708 726 Host name of mail server, e.g. "mail.example.com".
709 727 ``port``
710 728 Optional. Port to connect to on mail server. Default: 25.
711 729 ``tls``
712 730 Optional. Whether to connect to mail server using TLS. True or
713 731 False. Default: False.
714 732 ``username``
715 733 Optional. User name for authenticating with the SMTP server.
716 734 Default: none.
717 735 ``password``
718 736 Optional. Password for authenticating with the SMTP server. If not
719 737 specified, interactive sessions will prompt the user for a
720 738 password; non-interactive sessions will fail. Default: none.
721 739 ``local_hostname``
722 740 Optional. It's the hostname that the sender can use to identify
723 741 itself to the MTA.
724 742
725 743
726 744 ``patch``
727 745 """""""""
728 746 Settings used when applying patches, for instance through the 'import'
729 747 command or with Mercurial Queues extension.
730 748
731 749 ``eol``
732 750 When set to 'strict' patch content and patched files end of lines
733 751 are preserved. When set to ``lf`` or ``crlf``, both files end of
734 752 lines are ignored when patching and the result line endings are
735 753 normalized to either LF (Unix) or CRLF (Windows). When set to
736 754 ``auto``, end of lines are again ignored while patching but line
737 755 endings in patched files are normalized to their original setting
738 756 on a per-file basis. If target file does not exist or has no end
739 757 of line, patch line endings are preserved.
740 758 Default: strict.
741 759
742 760
743 761 ``paths``
744 762 """""""""
745 763 Assigns symbolic names to repositories. The left side is the
746 764 symbolic name, and the right gives the directory or URL that is the
747 765 location of the repository. Default paths can be declared by setting
748 766 the following entries.
749 767
750 768 ``default``
751 769 Directory or URL to use when pulling if no source is specified.
752 770 Default is set to repository from which the current repository was
753 771 cloned.
754 772 ``default-push``
755 773 Optional. Directory or URL to use when pushing if no destination
756 774 is specified.
757 775
758 776
759 777 ``profiling``
760 778 """""""""""""
761 779 Specifies profiling format and file output. In this section
762 780 description, 'profiling data' stands for the raw data collected
763 781 during profiling, while 'profiling report' stands for a statistical
764 782 text report generated from the profiling data. The profiling is done
765 783 using lsprof.
766 784
767 785 ``format``
768 786 Profiling format.
769 787 Default: text.
770 788
771 789 ``text``
772 790 Generate a profiling report. When saving to a file, it should be
773 791 noted that only the report is saved, and the profiling data is
774 792 not kept.
775 793 ``kcachegrind``
776 794 Format profiling data for kcachegrind use: when saving to a
777 795 file, the generated file can directly be loaded into
778 796 kcachegrind.
779 797 ``output``
780 798 File path where profiling data or report should be saved. If the
781 799 file exists, it is replaced. Default: None, data is printed on
782 800 stderr
783 801
784 802 ``server``
785 803 """"""""""
786 804 Controls generic server settings.
787 805
788 806 ``uncompressed``
789 807 Whether to allow clients to clone a repository using the
790 808 uncompressed streaming protocol. This transfers about 40% more
791 809 data than a regular clone, but uses less memory and CPU on both
792 810 server and client. Over a LAN (100 Mbps or better) or a very fast
793 811 WAN, an uncompressed streaming clone is a lot faster (~10x) than a
794 812 regular clone. Over most WAN connections (anything slower than
795 813 about 6 Mbps), uncompressed streaming is slower, because of the
796 814 extra data transfer overhead. This mode will also temporarily hold
797 815 the write lock while determining what data to transfer.
798 816 Default is True.
799 817
800 818 ``validate``
801 819 Whether to validate the completeness of pushed changesets by
802 820 checking that all new file revisions specified in manifests are
803 821 present. Default is False.
804 822
805 823 ``subpaths``
806 824 """"""""""""
807 825 Defines subrepositories source locations rewriting rules of the form::
808 826
809 827 <pattern> = <replacement>
810 828
811 829 Where ``pattern`` is a regular expression matching the source and
812 830 ``replacement`` is the replacement string used to rewrite it. Groups
813 831 can be matched in ``pattern`` and referenced in ``replacements``. For
814 832 instance::
815 833
816 834 http://server/(.*)-hg/ = http://hg.server/\1/
817 835
818 836 rewrites ``http://server/foo-hg/`` into ``http://hg.server/foo/``.
819 837
820 838 All patterns are applied in definition order.
821 839
822 840 ``trusted``
823 841 """""""""""
824 842
825 843 Mercurial will not use the settings in the
826 844 ``.hg/hgrc`` file from a repository if it doesn't belong to a trusted
827 845 user or to a trusted group, as various hgrc features allow arbitrary
828 846 commands to be run. This issue is often encountered when configuring
829 847 hooks or extensions for shared repositories or servers. However,
830 848 the web interface will use some safe settings from the ``[web]``
831 849 section.
832 850
833 851 This section specifies what users and groups are trusted. The
834 852 current user is always trusted. To trust everybody, list a user or a
835 853 group with name ``*``. These settings must be placed in an
836 854 *already-trusted file* to take effect, such as ``$HOME/.hgrc`` of the
837 855 user or service running Mercurial.
838 856
839 857 ``users``
840 858 Comma-separated list of trusted users.
841 859 ``groups``
842 860 Comma-separated list of trusted groups.
843 861
844 862
845 863 ``ui``
846 864 """"""
847 865
848 866 User interface controls.
849 867
850 868 ``archivemeta``
851 869 Whether to include the .hg_archival.txt file containing meta data
852 870 (hashes for the repository base and for tip) in archives created
853 871 by the :hg:`archive` command or downloaded via hgweb.
854 872 Default is True.
855 873 ``askusername``
856 874 Whether to prompt for a username when committing. If True, and
857 875 neither ``$HGUSER`` nor ``$EMAIL`` has been specified, then the user will
858 876 be prompted to enter a username. If no username is entered, the
859 877 default ``USER@HOST`` is used instead.
860 878 Default is False.
861 879 ``debug``
862 880 Print debugging information. True or False. Default is False.
863 881 ``editor``
864 882 The editor to use during a commit. Default is ``$EDITOR`` or ``vi``.
865 883 ``fallbackencoding``
866 884 Encoding to try if it's not possible to decode the changelog using
867 885 UTF-8. Default is ISO-8859-1.
868 886 ``ignore``
869 887 A file to read per-user ignore patterns from. This file should be
870 888 in the same format as a repository-wide .hgignore file. This
871 889 option supports hook syntax, so if you want to specify multiple
872 890 ignore files, you can do so by setting something like
873 891 ``ignore.other = ~/.hgignore2``. For details of the ignore file
874 892 format, see the |hgignore(5)|_ man page.
875 893 ``interactive``
876 894 Allow to prompt the user. True or False. Default is True.
877 895 ``logtemplate``
878 896 Template string for commands that print changesets.
879 897 ``merge``
880 898 The conflict resolution program to use during a manual merge.
881 899 For more information on merge tools see :hg:`help merge-tools`.
882 900 For configuring merge tools see the merge-tools_ section.
883 901 ``patch``
884 902 command to use to apply patches. Look for ``gpatch`` or ``patch`` in
885 903 PATH if unset.
886 904 ``quiet``
887 905 Reduce the amount of output printed. True or False. Default is False.
888 906 ``remotecmd``
889 907 remote command to use for clone/push/pull operations. Default is ``hg``.
890 908 ``report_untrusted``
891 909 Warn if a ``.hg/hgrc`` file is ignored due to not being owned by a
892 910 trusted user or group. True or False. Default is True.
893 911 ``slash``
894 912 Display paths using a slash (``/``) as the path separator. This
895 913 only makes a difference on systems where the default path
896 914 separator is not the slash character (e.g. Windows uses the
897 915 backslash character (``\``)).
898 916 Default is False.
899 917 ``ssh``
900 918 command to use for SSH connections. Default is ``ssh``.
901 919 ``strict``
902 920 Require exact command names, instead of allowing unambiguous
903 921 abbreviations. True or False. Default is False.
904 922 ``style``
905 923 Name of style to use for command output.
906 924 ``timeout``
907 925 The timeout used when a lock is held (in seconds), a negative value
908 926 means no timeout. Default is 600.
909 927 ``traceback``
910 928 Mercurial always prints a traceback when an unknown exception
911 929 occurs. Setting this to True will make Mercurial print a traceback
912 930 on all exceptions, even those recognized by Mercurial (such as
913 931 IOError or MemoryError). Default is False.
914 932 ``username``
915 933 The committer of a changeset created when running "commit".
916 934 Typically a person's name and email address, e.g. ``Fred Widget
917 935 <fred@example.com>``. Default is ``$EMAIL`` or ``username@hostname``. If
918 936 the username in hgrc is empty, it has to be specified manually or
919 937 in a different hgrc file (e.g. ``$HOME/.hgrc``, if the admin set
920 938 ``username =`` in the system hgrc). Environment variables in the
921 939 username are expanded.
922 940 ``verbose``
923 941 Increase the amount of output printed. True or False. Default is False.
924 942
925 943
926 944 ``web``
927 945 """""""
928 946
929 947 Web interface configuration. The settings in this section apply to
930 948 both the builtin webserver (started by :hg:`serve`) and the script you
931 949 run through a webserver (``hgweb.cgi`` and the derivatives for FastCGI
932 950 and WSGI).
933 951
934 952 The Mercurial webserver does no authentication (it does not prompt for
935 953 usernames and passwords to validate *who* users are), but it does do
936 954 authorization (it grants or denies access for *authenticated users*
937 955 based on settings in this section). You must either configure your
938 956 webserver to do authentication for you, or disable the authorization
939 957 checks.
940 958
941 959 For a quick setup in a trusted environment, e.g., a private LAN, where
942 960 you want it to accept pushes from anybody, you can use the following
943 961 command line::
944 962
945 963 $ hg --config web.allow_push=* --config web.push_ssl=False serve
946 964
947 965 Note that this will allow anybody to push anything to the server and
948 966 that this should not be used for public servers.
949 967
950 968 The full set of options is:
951 969
952 970 ``accesslog``
953 971 Where to output the access log. Default is stdout.
954 972 ``address``
955 973 Interface address to bind to. Default is all.
956 974 ``allow_archive``
957 975 List of archive format (bz2, gz, zip) allowed for downloading.
958 976 Default is empty.
959 977 ``allowbz2``
960 978 (DEPRECATED) Whether to allow .tar.bz2 downloading of repository
961 979 revisions.
962 980 Default is False.
963 981 ``allowgz``
964 982 (DEPRECATED) Whether to allow .tar.gz downloading of repository
965 983 revisions.
966 984 Default is False.
967 985 ``allowpull``
968 986 Whether to allow pulling from the repository. Default is True.
969 987 ``allow_push``
970 988 Whether to allow pushing to the repository. If empty or not set,
971 989 push is not allowed. If the special value ``*``, any remote user can
972 990 push, including unauthenticated users. Otherwise, the remote user
973 991 must have been authenticated, and the authenticated user name must
974 992 be present in this list. The contents of the allow_push list are
975 993 examined after the deny_push list.
976 994 ``allow_read``
977 995 If the user has not already been denied repository access due to
978 996 the contents of deny_read, this list determines whether to grant
979 997 repository access to the user. If this list is not empty, and the
980 998 user is unauthenticated or not present in the list, then access is
981 999 denied for the user. If the list is empty or not set, then access
982 1000 is permitted to all users by default. Setting allow_read to the
983 1001 special value ``*`` is equivalent to it not being set (i.e. access
984 1002 is permitted to all users). The contents of the allow_read list are
985 1003 examined after the deny_read list.
986 1004 ``allowzip``
987 1005 (DEPRECATED) Whether to allow .zip downloading of repository
988 1006 revisions. Default is False. This feature creates temporary files.
989 1007 ``baseurl``
990 1008 Base URL to use when publishing URLs in other locations, so
991 1009 third-party tools like email notification hooks can construct
992 1010 URLs. Example: ``http://hgserver/repos/``.
993 1011 ``cacerts``
994 1012 Path to file containing a list of PEM encoded certificate
995 1013 authority certificates. Environment variables and ``~user``
996 1014 constructs are expanded in the filename. If specified on the
997 1015 client, then it will verify the identity of remote HTTPS servers
998 1016 with these certificates. The form must be as follows::
999 1017
1000 1018 -----BEGIN CERTIFICATE-----
1001 1019 ... (certificate in base64 PEM encoding) ...
1002 1020 -----END CERTIFICATE-----
1003 1021 -----BEGIN CERTIFICATE-----
1004 1022 ... (certificate in base64 PEM encoding) ...
1005 1023 -----END CERTIFICATE-----
1006 1024
1007 1025 This feature is only supported when using Python 2.6 or later. If you wish
1008 1026 to use it with earlier versions of Python, install the backported
1009 1027 version of the ssl library that is available from
1010 1028 ``http://pypi.python.org``.
1011 1029
1012 1030 You can use OpenSSL's CA certificate file if your platform has one.
1013 1031 On most Linux systems this will be ``/etc/ssl/certs/ca-certificates.crt``.
1014 1032 Otherwise you will have to generate this file manually.
1015 1033 ``contact``
1016 1034 Name or email address of the person in charge of the repository.
1017 1035 Defaults to ui.username or ``$EMAIL`` or "unknown" if unset or empty.
1018 1036 ``deny_push``
1019 1037 Whether to deny pushing to the repository. If empty or not set,
1020 1038 push is not denied. If the special value ``*``, all remote users are
1021 1039 denied push. Otherwise, unauthenticated users are all denied, and
1022 1040 any authenticated user name present in this list is also denied. The
1023 1041 contents of the deny_push list are examined before the allow_push list.
1024 1042 ``deny_read``
1025 1043 Whether to deny reading/viewing of the repository. If this list is
1026 1044 not empty, unauthenticated users are all denied, and any
1027 1045 authenticated user name present in this list is also denied access to
1028 1046 the repository. If set to the special value ``*``, all remote users
1029 1047 are denied access (rarely needed ;). If deny_read is empty or not set,
1030 1048 the determination of repository access depends on the presence and
1031 1049 content of the allow_read list (see description). If both
1032 1050 deny_read and allow_read are empty or not set, then access is
1033 1051 permitted to all users by default. If the repository is being
1034 1052 served via hgwebdir, denied users will not be able to see it in
1035 1053 the list of repositories. The contents of the deny_read list have
1036 1054 priority over (are examined before) the contents of the allow_read
1037 1055 list.
1038 1056 ``descend``
1039 1057 hgwebdir indexes will not descend into subdirectories. Only repositories
1040 1058 directly in the current path will be shown (other repositories are still
1041 1059 available from the index corresponding to their containing path).
1042 1060 ``description``
1043 1061 Textual description of the repository's purpose or contents.
1044 1062 Default is "unknown".
1045 1063 ``encoding``
1046 1064 Character encoding name. Default is the current locale charset.
1047 1065 Example: "UTF-8"
1048 1066 ``errorlog``
1049 1067 Where to output the error log. Default is stderr.
1050 1068 ``hidden``
1051 1069 Whether to hide the repository in the hgwebdir index.
1052 1070 Default is False.
1053 1071 ``ipv6``
1054 1072 Whether to use IPv6. Default is False.
1055 1073 ``name``
1056 1074 Repository name to use in the web interface. Default is current
1057 1075 working directory.
1058 1076 ``maxchanges``
1059 1077 Maximum number of changes to list on the changelog. Default is 10.
1060 1078 ``maxfiles``
1061 1079 Maximum number of files to list per changeset. Default is 10.
1062 1080 ``port``
1063 1081 Port to listen on. Default is 8000.
1064 1082 ``prefix``
1065 1083 Prefix path to serve from. Default is '' (server root).
1066 1084 ``push_ssl``
1067 1085 Whether to require that inbound pushes be transported over SSL to
1068 1086 prevent password sniffing. Default is True.
1069 1087 ``staticurl``
1070 1088 Base URL to use for static files. If unset, static files (e.g. the
1071 1089 hgicon.png favicon) will be served by the CGI script itself. Use
1072 1090 this setting to serve them directly with the HTTP server.
1073 1091 Example: ``http://hgserver/static/``.
1074 1092 ``stripes``
1075 1093 How many lines a "zebra stripe" should span in multiline output.
1076 1094 Default is 1; set to 0 to disable.
1077 1095 ``style``
1078 1096 Which template map style to use.
1079 1097 ``templates``
1080 1098 Where to find the HTML templates. Default is install path.
1081 1099
1082 1100
1083 1101 Author
1084 1102 ------
1085 1103 Bryan O'Sullivan <bos@serpentine.com>.
1086 1104
1087 1105 Mercurial was written by Matt Mackall <mpm@selenic.com>.
1088 1106
1089 1107 See Also
1090 1108 --------
1091 1109 |hg(1)|_, |hgignore(5)|_
1092 1110
1093 1111 Copying
1094 1112 -------
1095 1113 This manual page is copyright 2005 Bryan O'Sullivan.
1096 1114 Mercurial is copyright 2005-2010 Matt Mackall.
1097 1115 Free use of this software is granted under the terms of the GNU General
1098 1116 Public License version 2 or any later version.
1099 1117
1100 1118 .. include:: common.txt
@@ -1,556 +1,556 b''
1 1 # hg.py - repository classes for mercurial
2 2 #
3 3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 4 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.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 or any later version.
8 8
9 9 from i18n import _
10 10 from lock import release
11 11 from node import hex, nullid, nullrev, short
12 12 import localrepo, bundlerepo, httprepo, sshrepo, statichttprepo
13 13 import lock, util, extensions, error, encoding, node
14 14 import cmdutil, discovery, url
15 15 import merge as mergemod
16 16 import verify as verifymod
17 17 import errno, os, shutil
18 18
19 19 def _local(path):
20 20 path = util.expandpath(util.drop_scheme('file', path))
21 21 return (os.path.isfile(path) and bundlerepo or localrepo)
22 22
23 23 def addbranchrevs(lrepo, repo, branches, revs):
24 24 hashbranch, branches = branches
25 25 if not hashbranch and not branches:
26 26 return revs or None, revs and revs[0] or None
27 27 revs = revs and list(revs) or []
28 28 if not repo.capable('branchmap'):
29 29 if branches:
30 30 raise util.Abort(_("remote branch lookup not supported"))
31 31 revs.append(hashbranch)
32 32 return revs, revs[0]
33 33 branchmap = repo.branchmap()
34 34
35 35 def primary(butf8):
36 36 if butf8 == '.':
37 37 if not lrepo or not lrepo.local():
38 38 raise util.Abort(_("dirstate branch not accessible"))
39 39 butf8 = lrepo.dirstate.branch()
40 40 if butf8 in branchmap:
41 41 revs.extend(node.hex(r) for r in reversed(branchmap[butf8]))
42 42 return True
43 43 else:
44 44 return False
45 45
46 46 for branch in branches:
47 47 butf8 = encoding.fromlocal(branch)
48 48 if not primary(butf8):
49 49 raise error.RepoLookupError(_("unknown branch '%s'") % branch)
50 50 if hashbranch:
51 51 butf8 = encoding.fromlocal(hashbranch)
52 52 if not primary(butf8):
53 53 revs.append(hashbranch)
54 54 return revs, revs[0]
55 55
56 56 def parseurl(url, branches=None):
57 57 '''parse url#branch, returning (url, (branch, branches))'''
58 58
59 59 if '#' not in url:
60 60 return url, (None, branches or [])
61 61 url, branch = url.split('#', 1)
62 62 return url, (branch, branches or [])
63 63
64 64 schemes = {
65 65 'bundle': bundlerepo,
66 66 'file': _local,
67 67 'http': httprepo,
68 68 'https': httprepo,
69 69 'ssh': sshrepo,
70 70 'static-http': statichttprepo,
71 71 }
72 72
73 73 def _lookup(path):
74 74 scheme = 'file'
75 75 if path:
76 76 c = path.find(':')
77 77 if c > 0:
78 78 scheme = path[:c]
79 79 thing = schemes.get(scheme) or schemes['file']
80 80 try:
81 81 return thing(path)
82 82 except TypeError:
83 83 return thing
84 84
85 85 def islocal(repo):
86 86 '''return true if repo or path is local'''
87 87 if isinstance(repo, str):
88 88 try:
89 89 return _lookup(repo).islocal(repo)
90 90 except AttributeError:
91 91 return False
92 92 return repo.local()
93 93
94 94 def repository(ui, path='', create=False):
95 95 """return a repository object for the specified path"""
96 96 repo = _lookup(path).instance(ui, path, create)
97 97 ui = getattr(repo, "ui", ui)
98 98 for name, module in extensions.extensions():
99 99 hook = getattr(module, 'reposetup', None)
100 100 if hook:
101 101 hook(ui, repo)
102 102 return repo
103 103
104 104 def defaultdest(source):
105 105 '''return default destination of clone if none is given'''
106 106 return os.path.basename(os.path.normpath(source))
107 107
108 108 def localpath(path):
109 109 if path.startswith('file://localhost/'):
110 110 return path[16:]
111 111 if path.startswith('file://'):
112 112 return path[7:]
113 113 if path.startswith('file:'):
114 114 return path[5:]
115 115 return path
116 116
117 117 def share(ui, source, dest=None, update=True):
118 118 '''create a shared repository'''
119 119
120 120 if not islocal(source):
121 121 raise util.Abort(_('can only share local repositories'))
122 122
123 123 if not dest:
124 124 dest = defaultdest(source)
125 125 else:
126 126 dest = ui.expandpath(dest)
127 127
128 128 if isinstance(source, str):
129 129 origsource = ui.expandpath(source)
130 130 source, branches = parseurl(origsource)
131 131 srcrepo = repository(ui, source)
132 132 rev, checkout = addbranchrevs(srcrepo, srcrepo, branches, None)
133 133 else:
134 134 srcrepo = source
135 135 origsource = source = srcrepo.url()
136 136 checkout = None
137 137
138 138 sharedpath = srcrepo.sharedpath # if our source is already sharing
139 139
140 140 root = os.path.realpath(dest)
141 141 roothg = os.path.join(root, '.hg')
142 142
143 143 if os.path.exists(roothg):
144 144 raise util.Abort(_('destination already exists'))
145 145
146 146 if not os.path.isdir(root):
147 147 os.mkdir(root)
148 148 os.mkdir(roothg)
149 149
150 150 requirements = ''
151 151 try:
152 152 requirements = srcrepo.opener('requires').read()
153 153 except IOError, inst:
154 154 if inst.errno != errno.ENOENT:
155 155 raise
156 156
157 157 requirements += 'shared\n'
158 158 file(os.path.join(roothg, 'requires'), 'w').write(requirements)
159 159 file(os.path.join(roothg, 'sharedpath'), 'w').write(sharedpath)
160 160
161 161 default = srcrepo.ui.config('paths', 'default')
162 162 if default:
163 163 f = file(os.path.join(roothg, 'hgrc'), 'w')
164 164 f.write('[paths]\ndefault = %s\n' % default)
165 165 f.close()
166 166
167 167 r = repository(ui, root)
168 168
169 169 if update:
170 170 r.ui.status(_("updating working directory\n"))
171 171 if update is not True:
172 172 checkout = update
173 173 for test in (checkout, 'default', 'tip'):
174 174 if test is None:
175 175 continue
176 176 try:
177 177 uprev = r.lookup(test)
178 178 break
179 179 except error.RepoLookupError:
180 180 continue
181 181 _update(r, uprev)
182 182
183 183 def clone(ui, source, dest=None, pull=False, rev=None, update=True,
184 184 stream=False, branch=None):
185 185 """Make a copy of an existing repository.
186 186
187 187 Create a copy of an existing repository in a new directory. The
188 188 source and destination are URLs, as passed to the repository
189 189 function. Returns a pair of repository objects, the source and
190 190 newly created destination.
191 191
192 192 The location of the source is added to the new repository's
193 193 .hg/hgrc file, as the default to be used for future pulls and
194 194 pushes.
195 195
196 196 If an exception is raised, the partly cloned/updated destination
197 197 repository will be deleted.
198 198
199 199 Arguments:
200 200
201 201 source: repository object or URL
202 202
203 203 dest: URL of destination repository to create (defaults to base
204 204 name of source repository)
205 205
206 206 pull: always pull from source repository, even in local case
207 207
208 208 stream: stream raw data uncompressed from repository (fast over
209 209 LAN, slow over WAN)
210 210
211 211 rev: revision to clone up to (implies pull=True)
212 212
213 213 update: update working directory after clone completes, if
214 214 destination is local repository (True means update to default rev,
215 215 anything else is treated as a revision)
216 216
217 217 branch: branches to clone
218 218 """
219 219
220 220 if isinstance(source, str):
221 221 origsource = ui.expandpath(source)
222 222 source, branch = parseurl(origsource, branch)
223 223 src_repo = repository(ui, source)
224 224 else:
225 225 src_repo = source
226 226 branch = (None, branch or [])
227 227 origsource = source = src_repo.url()
228 228 rev, checkout = addbranchrevs(src_repo, src_repo, branch, rev)
229 229
230 230 if dest is None:
231 231 dest = defaultdest(source)
232 232 ui.status(_("destination directory: %s\n") % dest)
233 233 else:
234 234 dest = ui.expandpath(dest)
235 235
236 236 dest = localpath(dest)
237 237 source = localpath(source)
238 238
239 239 if os.path.exists(dest):
240 240 if not os.path.isdir(dest):
241 241 raise util.Abort(_("destination '%s' already exists") % dest)
242 242 elif os.listdir(dest):
243 243 raise util.Abort(_("destination '%s' is not empty") % dest)
244 244
245 245 class DirCleanup(object):
246 246 def __init__(self, dir_):
247 247 self.rmtree = shutil.rmtree
248 248 self.dir_ = dir_
249 249 def close(self):
250 250 self.dir_ = None
251 251 def cleanup(self):
252 252 if self.dir_:
253 253 self.rmtree(self.dir_, True)
254 254
255 255 src_lock = dest_lock = dir_cleanup = None
256 256 try:
257 257 if islocal(dest):
258 258 dir_cleanup = DirCleanup(dest)
259 259
260 260 abspath = origsource
261 261 copy = False
262 262 if src_repo.cancopy() and islocal(dest):
263 263 abspath = os.path.abspath(util.drop_scheme('file', origsource))
264 264 copy = not pull and not rev
265 265
266 266 if copy:
267 267 try:
268 268 # we use a lock here because if we race with commit, we
269 269 # can end up with extra data in the cloned revlogs that's
270 270 # not pointed to by changesets, thus causing verify to
271 271 # fail
272 272 src_lock = src_repo.lock(wait=False)
273 273 except error.LockError:
274 274 copy = False
275 275
276 276 if copy:
277 277 src_repo.hook('preoutgoing', throw=True, source='clone')
278 278 hgdir = os.path.realpath(os.path.join(dest, ".hg"))
279 279 if not os.path.exists(dest):
280 280 os.mkdir(dest)
281 281 else:
282 282 # only clean up directories we create ourselves
283 283 dir_cleanup.dir_ = hgdir
284 284 try:
285 285 dest_path = hgdir
286 286 os.mkdir(dest_path)
287 287 except OSError, inst:
288 288 if inst.errno == errno.EEXIST:
289 289 dir_cleanup.close()
290 290 raise util.Abort(_("destination '%s' already exists")
291 291 % dest)
292 292 raise
293 293
294 294 hardlink = None
295 295 num = 0
296 296 for f in src_repo.store.copylist():
297 297 src = os.path.join(src_repo.sharedpath, f)
298 298 dst = os.path.join(dest_path, f)
299 299 dstbase = os.path.dirname(dst)
300 300 if dstbase and not os.path.exists(dstbase):
301 301 os.mkdir(dstbase)
302 302 if os.path.exists(src):
303 303 if dst.endswith('data'):
304 304 # lock to avoid premature writing to the target
305 305 dest_lock = lock.lock(os.path.join(dstbase, "lock"))
306 306 hardlink, n = util.copyfiles(src, dst, hardlink)
307 307 num += n
308 308 if hardlink:
309 309 ui.debug("linked %d files\n" % num)
310 310 else:
311 311 ui.debug("copied %d files\n" % num)
312 312
313 313 # we need to re-init the repo after manually copying the data
314 314 # into it
315 315 dest_repo = repository(ui, dest)
316 316 src_repo.hook('outgoing', source='clone',
317 317 node=node.hex(node.nullid))
318 318 else:
319 319 try:
320 320 dest_repo = repository(ui, dest, create=True)
321 321 except OSError, inst:
322 322 if inst.errno == errno.EEXIST:
323 323 dir_cleanup.close()
324 324 raise util.Abort(_("destination '%s' already exists")
325 325 % dest)
326 326 raise
327 327
328 328 revs = None
329 329 if rev:
330 330 if 'lookup' not in src_repo.capabilities:
331 331 raise util.Abort(_("src repository does not support "
332 332 "revision lookup and so doesn't "
333 333 "support clone by revision"))
334 334 revs = [src_repo.lookup(r) for r in rev]
335 335 checkout = revs[0]
336 336 if dest_repo.local():
337 337 dest_repo.clone(src_repo, heads=revs, stream=stream)
338 338 elif src_repo.local():
339 339 src_repo.push(dest_repo, revs=revs)
340 340 else:
341 341 raise util.Abort(_("clone from remote to remote not supported"))
342 342
343 343 if dir_cleanup:
344 344 dir_cleanup.close()
345 345
346 346 if dest_repo.local():
347 347 fp = dest_repo.opener("hgrc", "w", text=True)
348 348 fp.write("[paths]\n")
349 349 fp.write("default = %s\n" % abspath)
350 350 fp.close()
351 351
352 352 dest_repo.ui.setconfig('paths', 'default', abspath)
353 353
354 354 if update:
355 355 if update is not True:
356 356 checkout = update
357 357 if src_repo.local():
358 358 checkout = src_repo.lookup(update)
359 359 for test in (checkout, 'default', 'tip'):
360 360 if test is None:
361 361 continue
362 362 try:
363 363 uprev = dest_repo.lookup(test)
364 364 break
365 365 except error.RepoLookupError:
366 366 continue
367 367 bn = dest_repo[uprev].branch()
368 368 dest_repo.ui.status(_("updating to branch %s\n")
369 369 % encoding.tolocal(bn))
370 370 _update(dest_repo, uprev)
371 371
372 372 return src_repo, dest_repo
373 373 finally:
374 374 release(src_lock, dest_lock)
375 375 if dir_cleanup is not None:
376 376 dir_cleanup.cleanup()
377 377
378 378 def _showstats(repo, stats):
379 379 repo.ui.status(_("%d files updated, %d files merged, "
380 380 "%d files removed, %d files unresolved\n") % stats)
381 381
382 382 def update(repo, node):
383 383 """update the working directory to node, merging linear changes"""
384 384 stats = mergemod.update(repo, node, False, False, None)
385 385 _showstats(repo, stats)
386 386 if stats[3]:
387 387 repo.ui.status(_("use 'hg resolve' to retry unresolved file merges\n"))
388 388 return stats[3] > 0
389 389
390 390 # naming conflict in clone()
391 391 _update = update
392 392
393 393 def clean(repo, node, show_stats=True):
394 394 """forcibly switch the working directory to node, clobbering changes"""
395 395 stats = mergemod.update(repo, node, False, True, None)
396 396 if show_stats:
397 397 _showstats(repo, stats)
398 398 return stats[3] > 0
399 399
400 400 def merge(repo, node, force=None, remind=True):
401 401 """branch merge with node, resolving changes"""
402 402 stats = mergemod.update(repo, node, True, force, False)
403 403 _showstats(repo, stats)
404 404 if stats[3]:
405 405 repo.ui.status(_("use 'hg resolve' to retry unresolved file merges "
406 406 "or 'hg update -C .' to abandon\n"))
407 407 elif remind:
408 408 repo.ui.status(_("(branch merge, don't forget to commit)\n"))
409 409 return stats[3] > 0
410 410
411 411 def _incoming(displaychlist, subreporecurse, ui, repo, source,
412 412 opts, buffered=False):
413 413 """
414 414 Helper for incoming / gincoming.
415 415 displaychlist gets called with
416 416 (remoterepo, incomingchangesetlist, displayer) parameters,
417 417 and is supposed to contain only code that can't be unified.
418 418 """
419 419 source, branches = parseurl(ui.expandpath(source), opts.get('branch'))
420 420 other = repository(remoteui(repo, opts), source)
421 421 ui.status(_('comparing with %s\n') % url.hidepassword(source))
422 422 revs, checkout = addbranchrevs(repo, other, branches, opts.get('rev'))
423 423
424 424 if revs:
425 425 revs = [other.lookup(rev) for rev in revs]
426 426 other, incoming, bundle = bundlerepo.getremotechanges(ui, repo, other, revs,
427 427 opts["bundle"], opts["force"])
428 428 if incoming is None:
429 429 ui.status(_("no changes found\n"))
430 430 return subreporecurse()
431 431
432 432 try:
433 433 chlist = other.changelog.nodesbetween(incoming, revs)[0]
434 434 displayer = cmdutil.show_changeset(ui, other, opts, buffered)
435 435
436 436 # XXX once graphlog extension makes it into core,
437 437 # should be replaced by a if graph/else
438 438 displaychlist(other, chlist, displayer)
439 439
440 440 displayer.close()
441 441 finally:
442 442 if hasattr(other, 'close'):
443 443 other.close()
444 444 if bundle:
445 445 os.unlink(bundle)
446 446 subreporecurse()
447 447 return 0 # exit code is zero since we found incoming changes
448 448
449 449 def incoming(ui, repo, source, opts):
450 450 def subreporecurse():
451 451 ret = 1
452 452 if opts.get('subrepos'):
453 453 ctx = repo[None]
454 454 for subpath in sorted(ctx.substate):
455 455 sub = ctx.sub(subpath)
456 456 ret = min(ret, sub.incoming(ui, source, opts))
457 457 return ret
458 458
459 459 def display(other, chlist, displayer):
460 460 limit = cmdutil.loglimit(opts)
461 461 if opts.get('newest_first'):
462 462 chlist.reverse()
463 463 count = 0
464 464 for n in chlist:
465 465 if limit is not None and count >= limit:
466 466 break
467 467 parents = [p for p in other.changelog.parents(n) if p != nullid]
468 468 if opts.get('no_merges') and len(parents) == 2:
469 469 continue
470 470 count += 1
471 471 displayer.show(other[n])
472 472 return _incoming(display, subreporecurse, ui, repo, source, opts)
473 473
474 474 def _outgoing(ui, repo, dest, opts):
475 475 dest = ui.expandpath(dest or 'default-push', dest or 'default')
476 476 dest, branches = parseurl(dest, opts.get('branch'))
477 477 revs, checkout = addbranchrevs(repo, repo, branches, opts.get('rev'))
478 478 if revs:
479 479 revs = [repo.lookup(rev) for rev in revs]
480 480
481 481 other = repository(remoteui(repo, opts), dest)
482 482 ui.status(_('comparing with %s\n') % url.hidepassword(dest))
483 483 o = discovery.findoutgoing(repo, other, force=opts.get('force'))
484 484 if not o:
485 485 ui.status(_("no changes found\n"))
486 486 return None
487 487
488 488 return repo.changelog.nodesbetween(o, revs)[0]
489 489
490 490 def outgoing(ui, repo, dest, opts):
491 491 def recurse():
492 492 ret = 1
493 493 if opts.get('subrepos'):
494 494 ctx = repo[None]
495 495 for subpath in sorted(ctx.substate):
496 496 sub = ctx.sub(subpath)
497 497 ret = min(ret, sub.outgoing(ui, dest, opts))
498 498 return ret
499 499
500 500 limit = cmdutil.loglimit(opts)
501 501 o = _outgoing(ui, repo, dest, opts)
502 502 if o is None:
503 503 return recurse()
504 504
505 505 if opts.get('newest_first'):
506 506 o.reverse()
507 507 displayer = cmdutil.show_changeset(ui, repo, opts)
508 508 count = 0
509 509 for n in o:
510 510 if limit is not None and count >= limit:
511 511 break
512 512 parents = [p for p in repo.changelog.parents(n) if p != nullid]
513 513 if opts.get('no_merges') and len(parents) == 2:
514 514 continue
515 515 count += 1
516 516 displayer.show(repo[n])
517 517 displayer.close()
518 518 recurse()
519 519 return 0 # exit code is zero since we found outgoing changes
520 520
521 521 def revert(repo, node, choose):
522 522 """revert changes to revision in node without updating dirstate"""
523 523 return mergemod.update(repo, node, False, True, choose)[3] > 0
524 524
525 525 def verify(repo):
526 526 """verify the consistency of a repository"""
527 527 return verifymod.verify(repo)
528 528
529 529 def remoteui(src, opts):
530 530 'build a remote ui from ui or repo and opts'
531 531 if hasattr(src, 'baseui'): # looks like a repository
532 532 dst = src.baseui.copy() # drop repo-specific config
533 533 src = src.ui # copy target options from repo
534 534 else: # assume it's a global ui object
535 535 dst = src.copy() # keep all global options
536 536
537 537 # copy ssh-specific options
538 538 for o in 'ssh', 'remotecmd':
539 539 v = opts.get(o) or src.config('ui', o)
540 540 if v:
541 541 dst.setconfig("ui", o, v)
542 542
543 543 # copy bundle-specific options
544 544 r = src.config('bundle', 'mainreporoot')
545 545 if r:
546 546 dst.setconfig('bundle', 'mainreporoot', r)
547 547
548 548 # copy selected local settings to the remote ui
549 for sect in ('auth', 'http_proxy'):
549 for sect in ('auth', 'hostfingerprints', 'http_proxy'):
550 550 for key, val in src.configitems(sect):
551 551 dst.setconfig(sect, key, val)
552 552 v = src.config('web', 'cacerts')
553 553 if v:
554 554 dst.setconfig('web', 'cacerts', util.expandpath(v))
555 555
556 556 return dst
@@ -1,719 +1,743 b''
1 1 # url.py - HTTP handling for mercurial
2 2 #
3 3 # Copyright 2005, 2006, 2007, 2008 Matt Mackall <mpm@selenic.com>
4 4 # Copyright 2006, 2007 Alexis S. L. Carvalho <alexis@cecm.usp.br>
5 5 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
6 6 #
7 7 # This software may be used and distributed according to the terms of the
8 8 # GNU General Public License version 2 or any later version.
9 9
10 10 import urllib, urllib2, urlparse, httplib, os, re, socket, cStringIO
11 11 import __builtin__
12 12 from i18n import _
13 13 import keepalive, util
14 14
15 15 def _urlunparse(scheme, netloc, path, params, query, fragment, url):
16 16 '''Handle cases where urlunparse(urlparse(x://)) doesn't preserve the "//"'''
17 17 result = urlparse.urlunparse((scheme, netloc, path, params, query, fragment))
18 18 if (scheme and
19 19 result.startswith(scheme + ':') and
20 20 not result.startswith(scheme + '://') and
21 21 url.startswith(scheme + '://')
22 22 ):
23 23 result = scheme + '://' + result[len(scheme + ':'):]
24 24 return result
25 25
26 26 def hidepassword(url):
27 27 '''hide user credential in a url string'''
28 28 scheme, netloc, path, params, query, fragment = urlparse.urlparse(url)
29 29 netloc = re.sub('([^:]*):([^@]*)@(.*)', r'\1:***@\3', netloc)
30 30 return _urlunparse(scheme, netloc, path, params, query, fragment, url)
31 31
32 32 def removeauth(url):
33 33 '''remove all authentication information from a url string'''
34 34 scheme, netloc, path, params, query, fragment = urlparse.urlparse(url)
35 35 netloc = netloc[netloc.find('@')+1:]
36 36 return _urlunparse(scheme, netloc, path, params, query, fragment, url)
37 37
38 38 def netlocsplit(netloc):
39 39 '''split [user[:passwd]@]host[:port] into 4-tuple.'''
40 40
41 41 a = netloc.find('@')
42 42 if a == -1:
43 43 user, passwd = None, None
44 44 else:
45 45 userpass, netloc = netloc[:a], netloc[a + 1:]
46 46 c = userpass.find(':')
47 47 if c == -1:
48 48 user, passwd = urllib.unquote(userpass), None
49 49 else:
50 50 user = urllib.unquote(userpass[:c])
51 51 passwd = urllib.unquote(userpass[c + 1:])
52 52 c = netloc.find(':')
53 53 if c == -1:
54 54 host, port = netloc, None
55 55 else:
56 56 host, port = netloc[:c], netloc[c + 1:]
57 57 return host, port, user, passwd
58 58
59 59 def netlocunsplit(host, port, user=None, passwd=None):
60 60 '''turn host, port, user, passwd into [user[:passwd]@]host[:port].'''
61 61 if port:
62 62 hostport = host + ':' + port
63 63 else:
64 64 hostport = host
65 65 if user:
66 66 quote = lambda s: urllib.quote(s, safe='')
67 67 if passwd:
68 68 userpass = quote(user) + ':' + quote(passwd)
69 69 else:
70 70 userpass = quote(user)
71 71 return userpass + '@' + hostport
72 72 return hostport
73 73
74 74 _safe = ('abcdefghijklmnopqrstuvwxyz'
75 75 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
76 76 '0123456789' '_.-/')
77 77 _safeset = None
78 78 _hex = None
79 79 def quotepath(path):
80 80 '''quote the path part of a URL
81 81
82 82 This is similar to urllib.quote, but it also tries to avoid
83 83 quoting things twice (inspired by wget):
84 84
85 85 >>> quotepath('abc def')
86 86 'abc%20def'
87 87 >>> quotepath('abc%20def')
88 88 'abc%20def'
89 89 >>> quotepath('abc%20 def')
90 90 'abc%20%20def'
91 91 >>> quotepath('abc def%20')
92 92 'abc%20def%20'
93 93 >>> quotepath('abc def%2')
94 94 'abc%20def%252'
95 95 >>> quotepath('abc def%')
96 96 'abc%20def%25'
97 97 '''
98 98 global _safeset, _hex
99 99 if _safeset is None:
100 100 _safeset = set(_safe)
101 101 _hex = set('abcdefABCDEF0123456789')
102 102 l = list(path)
103 103 for i in xrange(len(l)):
104 104 c = l[i]
105 105 if (c == '%' and i + 2 < len(l) and
106 106 l[i + 1] in _hex and l[i + 2] in _hex):
107 107 pass
108 108 elif c not in _safeset:
109 109 l[i] = '%%%02X' % ord(c)
110 110 return ''.join(l)
111 111
112 112 class passwordmgr(urllib2.HTTPPasswordMgrWithDefaultRealm):
113 113 def __init__(self, ui):
114 114 urllib2.HTTPPasswordMgrWithDefaultRealm.__init__(self)
115 115 self.ui = ui
116 116
117 117 def find_user_password(self, realm, authuri):
118 118 authinfo = urllib2.HTTPPasswordMgrWithDefaultRealm.find_user_password(
119 119 self, realm, authuri)
120 120 user, passwd = authinfo
121 121 if user and passwd:
122 122 self._writedebug(user, passwd)
123 123 return (user, passwd)
124 124
125 125 if not user:
126 126 auth = self.readauthtoken(authuri)
127 127 if auth:
128 128 user, passwd = auth.get('username'), auth.get('password')
129 129 if not user or not passwd:
130 130 if not self.ui.interactive():
131 131 raise util.Abort(_('http authorization required'))
132 132
133 133 self.ui.write(_("http authorization required\n"))
134 134 self.ui.write(_("realm: %s\n") % realm)
135 135 if user:
136 136 self.ui.write(_("user: %s\n") % user)
137 137 else:
138 138 user = self.ui.prompt(_("user:"), default=None)
139 139
140 140 if not passwd:
141 141 passwd = self.ui.getpass()
142 142
143 143 self.add_password(realm, authuri, user, passwd)
144 144 self._writedebug(user, passwd)
145 145 return (user, passwd)
146 146
147 147 def _writedebug(self, user, passwd):
148 148 msg = _('http auth: user %s, password %s\n')
149 149 self.ui.debug(msg % (user, passwd and '*' * len(passwd) or 'not set'))
150 150
151 151 def readauthtoken(self, uri):
152 152 # Read configuration
153 153 config = dict()
154 154 for key, val in self.ui.configitems('auth'):
155 155 if '.' not in key:
156 156 self.ui.warn(_("ignoring invalid [auth] key '%s'\n") % key)
157 157 continue
158 158 group, setting = key.split('.', 1)
159 159 gdict = config.setdefault(group, dict())
160 160 if setting in ('username', 'cert', 'key'):
161 161 val = util.expandpath(val)
162 162 gdict[setting] = val
163 163
164 164 # Find the best match
165 165 scheme, hostpath = uri.split('://', 1)
166 166 bestlen = 0
167 167 bestauth = None
168 168 for auth in config.itervalues():
169 169 prefix = auth.get('prefix')
170 170 if not prefix:
171 171 continue
172 172 p = prefix.split('://', 1)
173 173 if len(p) > 1:
174 174 schemes, prefix = [p[0]], p[1]
175 175 else:
176 176 schemes = (auth.get('schemes') or 'https').split()
177 177 if (prefix == '*' or hostpath.startswith(prefix)) and \
178 178 len(prefix) > bestlen and scheme in schemes:
179 179 bestlen = len(prefix)
180 180 bestauth = auth
181 181 return bestauth
182 182
183 183 class proxyhandler(urllib2.ProxyHandler):
184 184 def __init__(self, ui):
185 185 proxyurl = ui.config("http_proxy", "host") or os.getenv('http_proxy')
186 186 # XXX proxyauthinfo = None
187 187
188 188 if proxyurl:
189 189 # proxy can be proper url or host[:port]
190 190 if not (proxyurl.startswith('http:') or
191 191 proxyurl.startswith('https:')):
192 192 proxyurl = 'http://' + proxyurl + '/'
193 193 snpqf = urlparse.urlsplit(proxyurl)
194 194 proxyscheme, proxynetloc, proxypath, proxyquery, proxyfrag = snpqf
195 195 hpup = netlocsplit(proxynetloc)
196 196
197 197 proxyhost, proxyport, proxyuser, proxypasswd = hpup
198 198 if not proxyuser:
199 199 proxyuser = ui.config("http_proxy", "user")
200 200 proxypasswd = ui.config("http_proxy", "passwd")
201 201
202 202 # see if we should use a proxy for this url
203 203 no_list = ["localhost", "127.0.0.1"]
204 204 no_list.extend([p.lower() for
205 205 p in ui.configlist("http_proxy", "no")])
206 206 no_list.extend([p.strip().lower() for
207 207 p in os.getenv("no_proxy", '').split(',')
208 208 if p.strip()])
209 209 # "http_proxy.always" config is for running tests on localhost
210 210 if ui.configbool("http_proxy", "always"):
211 211 self.no_list = []
212 212 else:
213 213 self.no_list = no_list
214 214
215 215 proxyurl = urlparse.urlunsplit((
216 216 proxyscheme, netlocunsplit(proxyhost, proxyport,
217 217 proxyuser, proxypasswd or ''),
218 218 proxypath, proxyquery, proxyfrag))
219 219 proxies = {'http': proxyurl, 'https': proxyurl}
220 220 ui.debug('proxying through http://%s:%s\n' %
221 221 (proxyhost, proxyport))
222 222 else:
223 223 proxies = {}
224 224
225 225 # urllib2 takes proxy values from the environment and those
226 226 # will take precedence if found, so drop them
227 227 for env in ["HTTP_PROXY", "http_proxy", "no_proxy"]:
228 228 try:
229 229 if env in os.environ:
230 230 del os.environ[env]
231 231 except OSError:
232 232 pass
233 233
234 234 urllib2.ProxyHandler.__init__(self, proxies)
235 235 self.ui = ui
236 236
237 237 def proxy_open(self, req, proxy, type_):
238 238 host = req.get_host().split(':')[0]
239 239 if host in self.no_list:
240 240 return None
241 241
242 242 # work around a bug in Python < 2.4.2
243 243 # (it leaves a "\n" at the end of Proxy-authorization headers)
244 244 baseclass = req.__class__
245 245 class _request(baseclass):
246 246 def add_header(self, key, val):
247 247 if key.lower() == 'proxy-authorization':
248 248 val = val.strip()
249 249 return baseclass.add_header(self, key, val)
250 250 req.__class__ = _request
251 251
252 252 return urllib2.ProxyHandler.proxy_open(self, req, proxy, type_)
253 253
254 254 class httpsendfile(object):
255 255 """This is a wrapper around the objects returned by python's "open".
256 256
257 257 Its purpose is to send file-like objects via HTTP and, to do so, it
258 258 defines a __len__ attribute to feed the Content-Length header.
259 259 """
260 260
261 261 def __init__(self, *args, **kwargs):
262 262 # We can't just "self._data = open(*args, **kwargs)" here because there
263 263 # is an "open" function defined in this module that shadows the global
264 264 # one
265 265 self._data = __builtin__.open(*args, **kwargs)
266 266 self.read = self._data.read
267 267 self.seek = self._data.seek
268 268 self.close = self._data.close
269 269 self.write = self._data.write
270 270
271 271 def __len__(self):
272 272 return os.fstat(self._data.fileno()).st_size
273 273
274 274 def _gen_sendfile(connection):
275 275 def _sendfile(self, data):
276 276 # send a file
277 277 if isinstance(data, httpsendfile):
278 278 # if auth required, some data sent twice, so rewind here
279 279 data.seek(0)
280 280 for chunk in util.filechunkiter(data):
281 281 connection.send(self, chunk)
282 282 else:
283 283 connection.send(self, data)
284 284 return _sendfile
285 285
286 286 has_https = hasattr(urllib2, 'HTTPSHandler')
287 287 if has_https:
288 288 try:
289 289 # avoid using deprecated/broken FakeSocket in python 2.6
290 290 import ssl
291 291 _ssl_wrap_socket = ssl.wrap_socket
292 292 CERT_REQUIRED = ssl.CERT_REQUIRED
293 293 except ImportError:
294 294 CERT_REQUIRED = 2
295 295
296 296 def _ssl_wrap_socket(sock, key_file, cert_file,
297 297 cert_reqs=CERT_REQUIRED, ca_certs=None):
298 298 if ca_certs:
299 299 raise util.Abort(_(
300 300 'certificate checking requires Python 2.6'))
301 301
302 302 ssl = socket.ssl(sock, key_file, cert_file)
303 303 return httplib.FakeSocket(sock, ssl)
304 304
305 305 try:
306 306 _create_connection = socket.create_connection
307 307 except AttributeError:
308 308 _GLOBAL_DEFAULT_TIMEOUT = object()
309 309
310 310 def _create_connection(address, timeout=_GLOBAL_DEFAULT_TIMEOUT,
311 311 source_address=None):
312 312 # lifted from Python 2.6
313 313
314 314 msg = "getaddrinfo returns an empty list"
315 315 host, port = address
316 316 for res in socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM):
317 317 af, socktype, proto, canonname, sa = res
318 318 sock = None
319 319 try:
320 320 sock = socket.socket(af, socktype, proto)
321 321 if timeout is not _GLOBAL_DEFAULT_TIMEOUT:
322 322 sock.settimeout(timeout)
323 323 if source_address:
324 324 sock.bind(source_address)
325 325 sock.connect(sa)
326 326 return sock
327 327
328 328 except socket.error, msg:
329 329 if sock is not None:
330 330 sock.close()
331 331
332 332 raise socket.error, msg
333 333
334 334 class httpconnection(keepalive.HTTPConnection):
335 335 # must be able to send big bundle as stream.
336 336 send = _gen_sendfile(keepalive.HTTPConnection)
337 337
338 338 def connect(self):
339 339 if has_https and self.realhostport: # use CONNECT proxy
340 340 self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
341 341 self.sock.connect((self.host, self.port))
342 342 if _generic_proxytunnel(self):
343 343 # we do not support client x509 certificates
344 344 self.sock = _ssl_wrap_socket(self.sock, None, None)
345 345 else:
346 346 keepalive.HTTPConnection.connect(self)
347 347
348 348 def getresponse(self):
349 349 proxyres = getattr(self, 'proxyres', None)
350 350 if proxyres:
351 351 if proxyres.will_close:
352 352 self.close()
353 353 self.proxyres = None
354 354 return proxyres
355 355 return keepalive.HTTPConnection.getresponse(self)
356 356
357 357 # general transaction handler to support different ways to handle
358 358 # HTTPS proxying before and after Python 2.6.3.
359 359 def _generic_start_transaction(handler, h, req):
360 360 if hasattr(req, '_tunnel_host') and req._tunnel_host:
361 361 tunnel_host = req._tunnel_host
362 362 if tunnel_host[:7] not in ['http://', 'https:/']:
363 363 tunnel_host = 'https://' + tunnel_host
364 364 new_tunnel = True
365 365 else:
366 366 tunnel_host = req.get_selector()
367 367 new_tunnel = False
368 368
369 369 if new_tunnel or tunnel_host == req.get_full_url(): # has proxy
370 370 urlparts = urlparse.urlparse(tunnel_host)
371 371 if new_tunnel or urlparts[0] == 'https': # only use CONNECT for HTTPS
372 372 realhostport = urlparts[1]
373 373 if realhostport[-1] == ']' or ':' not in realhostport:
374 374 realhostport += ':443'
375 375
376 376 h.realhostport = realhostport
377 377 h.headers = req.headers.copy()
378 378 h.headers.update(handler.parent.addheaders)
379 379 return
380 380
381 381 h.realhostport = None
382 382 h.headers = None
383 383
384 384 def _generic_proxytunnel(self):
385 385 proxyheaders = dict(
386 386 [(x, self.headers[x]) for x in self.headers
387 387 if x.lower().startswith('proxy-')])
388 388 self._set_hostport(self.host, self.port)
389 389 self.send('CONNECT %s HTTP/1.0\r\n' % self.realhostport)
390 390 for header in proxyheaders.iteritems():
391 391 self.send('%s: %s\r\n' % header)
392 392 self.send('\r\n')
393 393
394 394 # majority of the following code is duplicated from
395 395 # httplib.HTTPConnection as there are no adequate places to
396 396 # override functions to provide the needed functionality
397 397 res = self.response_class(self.sock,
398 398 strict=self.strict,
399 399 method=self._method)
400 400
401 401 while True:
402 402 version, status, reason = res._read_status()
403 403 if status != httplib.CONTINUE:
404 404 break
405 405 while True:
406 406 skip = res.fp.readline().strip()
407 407 if not skip:
408 408 break
409 409 res.status = status
410 410 res.reason = reason.strip()
411 411
412 412 if res.status == 200:
413 413 while True:
414 414 line = res.fp.readline()
415 415 if line == '\r\n':
416 416 break
417 417 return True
418 418
419 419 if version == 'HTTP/1.0':
420 420 res.version = 10
421 421 elif version.startswith('HTTP/1.'):
422 422 res.version = 11
423 423 elif version == 'HTTP/0.9':
424 424 res.version = 9
425 425 else:
426 426 raise httplib.UnknownProtocol(version)
427 427
428 428 if res.version == 9:
429 429 res.length = None
430 430 res.chunked = 0
431 431 res.will_close = 1
432 432 res.msg = httplib.HTTPMessage(cStringIO.StringIO())
433 433 return False
434 434
435 435 res.msg = httplib.HTTPMessage(res.fp)
436 436 res.msg.fp = None
437 437
438 438 # are we using the chunked-style of transfer encoding?
439 439 trenc = res.msg.getheader('transfer-encoding')
440 440 if trenc and trenc.lower() == "chunked":
441 441 res.chunked = 1
442 442 res.chunk_left = None
443 443 else:
444 444 res.chunked = 0
445 445
446 446 # will the connection close at the end of the response?
447 447 res.will_close = res._check_close()
448 448
449 449 # do we have a Content-Length?
450 450 # NOTE: RFC 2616, S4.4, #3 says we ignore this if tr_enc is "chunked"
451 451 length = res.msg.getheader('content-length')
452 452 if length and not res.chunked:
453 453 try:
454 454 res.length = int(length)
455 455 except ValueError:
456 456 res.length = None
457 457 else:
458 458 if res.length < 0: # ignore nonsensical negative lengths
459 459 res.length = None
460 460 else:
461 461 res.length = None
462 462
463 463 # does the body have a fixed length? (of zero)
464 464 if (status == httplib.NO_CONTENT or status == httplib.NOT_MODIFIED or
465 465 100 <= status < 200 or # 1xx codes
466 466 res._method == 'HEAD'):
467 467 res.length = 0
468 468
469 469 # if the connection remains open, and we aren't using chunked, and
470 470 # a content-length was not provided, then assume that the connection
471 471 # WILL close.
472 472 if (not res.will_close and
473 473 not res.chunked and
474 474 res.length is None):
475 475 res.will_close = 1
476 476
477 477 self.proxyres = res
478 478
479 479 return False
480 480
481 481 class httphandler(keepalive.HTTPHandler):
482 482 def http_open(self, req):
483 483 return self.do_open(httpconnection, req)
484 484
485 485 def _start_transaction(self, h, req):
486 486 _generic_start_transaction(self, h, req)
487 487 return keepalive.HTTPHandler._start_transaction(self, h, req)
488 488
489 489 def _verifycert(cert, hostname):
490 490 '''Verify that cert (in socket.getpeercert() format) matches hostname.
491 491 CRLs is not handled.
492 492
493 493 Returns error message if any problems are found and None on success.
494 494 '''
495 495 if not cert:
496 496 return _('no certificate received')
497 497 dnsname = hostname.lower()
498 498 def matchdnsname(certname):
499 499 return (certname == dnsname or
500 500 '.' in dnsname and certname == '*.' + dnsname.split('.', 1)[1])
501 501
502 502 san = cert.get('subjectAltName', [])
503 503 if san:
504 504 certnames = [value.lower() for key, value in san if key == 'DNS']
505 505 for name in certnames:
506 506 if matchdnsname(name):
507 507 return None
508 508 return _('certificate is for %s') % ', '.join(certnames)
509 509
510 510 # subject is only checked when subjectAltName is empty
511 511 for s in cert.get('subject', []):
512 512 key, value = s[0]
513 513 if key == 'commonName':
514 514 try:
515 515 # 'subject' entries are unicode
516 516 certname = value.lower().encode('ascii')
517 517 except UnicodeEncodeError:
518 518 return _('IDN in certificate not supported')
519 519 if matchdnsname(certname):
520 520 return None
521 521 return _('certificate is for %s') % certname
522 522 return _('no commonName or subjectAltName found in certificate')
523 523
524 524 if has_https:
525 525 class BetterHTTPS(httplib.HTTPSConnection):
526 526 send = keepalive.safesend
527 527
528 528 def connect(self):
529 529 if hasattr(self, 'ui'):
530 530 cacerts = self.ui.config('web', 'cacerts')
531 531 if cacerts:
532 532 cacerts = util.expandpath(cacerts)
533 533 else:
534 534 cacerts = None
535 535
536 if cacerts:
536 hostfingerprint = self.ui.config('hostfingerprints', self.host)
537 if cacerts and not hostfingerprint:
537 538 sock = _create_connection((self.host, self.port))
538 539 self.sock = _ssl_wrap_socket(sock, self.key_file,
539 540 self.cert_file, cert_reqs=CERT_REQUIRED,
540 541 ca_certs=cacerts)
541 542 msg = _verifycert(self.sock.getpeercert(), self.host)
542 543 if msg:
543 544 raise util.Abort(_('%s certificate error: %s') %
544 545 (self.host, msg))
545 546 self.ui.debug('%s certificate successfully verified\n' %
546 547 self.host)
547 548 else:
548 self.ui.warn(_("warning: %s certificate not verified "
549 "(check web.cacerts config setting)\n") %
550 self.host)
551 549 httplib.HTTPSConnection.connect(self)
550 if hasattr(self.sock, 'getpeercert'):
551 peercert = self.sock.getpeercert(True)
552 peerfingerprint = util.sha1(peercert).hexdigest()
553 nicefingerprint = ":".join([peerfingerprint[x:x + 2]
554 for x in xrange(0, len(peerfingerprint), 2)])
555 if hostfingerprint:
556 if peerfingerprint.lower() != \
557 hostfingerprint.replace(':', '').lower():
558 raise util.Abort(_('invalid certificate for %s '
559 'with fingerprint %s') %
560 (self.host, nicefingerprint))
561 self.ui.debug('%s certificate matched fingerprint %s\n' %
562 (self.host, nicefingerprint))
563 else:
564 self.ui.warn(_('warning: %s certificate '
565 'with fingerprint %s not verified '
566 '(check hostfingerprints or web.cacerts '
567 'config setting)\n') %
568 (self.host, nicefingerprint))
569 else: # python 2.5 ?
570 if hostfingerprint:
571 raise util.Abort(_('no certificate for %s '
572 'with fingerprint') % self.host)
573 self.ui.warn(_('warning: %s certificate not verified '
574 '(check web.cacerts config setting)\n') %
575 self.host)
552 576
553 577 class httpsconnection(BetterHTTPS):
554 578 response_class = keepalive.HTTPResponse
555 579 # must be able to send big bundle as stream.
556 580 send = _gen_sendfile(BetterHTTPS)
557 581 getresponse = keepalive.wrapgetresponse(httplib.HTTPSConnection)
558 582
559 583 def connect(self):
560 584 if self.realhostport: # use CONNECT proxy
561 585 self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
562 586 self.sock.connect((self.host, self.port))
563 587 if _generic_proxytunnel(self):
564 588 self.sock = _ssl_wrap_socket(self.sock, self.key_file,
565 589 self.cert_file)
566 590 else:
567 591 BetterHTTPS.connect(self)
568 592
569 593 class httpshandler(keepalive.KeepAliveHandler, urllib2.HTTPSHandler):
570 594 def __init__(self, ui):
571 595 keepalive.KeepAliveHandler.__init__(self)
572 596 urllib2.HTTPSHandler.__init__(self)
573 597 self.ui = ui
574 598 self.pwmgr = passwordmgr(self.ui)
575 599
576 600 def _start_transaction(self, h, req):
577 601 _generic_start_transaction(self, h, req)
578 602 return keepalive.KeepAliveHandler._start_transaction(self, h, req)
579 603
580 604 def https_open(self, req):
581 605 self.auth = self.pwmgr.readauthtoken(req.get_full_url())
582 606 return self.do_open(self._makeconnection, req)
583 607
584 608 def _makeconnection(self, host, port=None, *args, **kwargs):
585 609 keyfile = None
586 610 certfile = None
587 611
588 612 if len(args) >= 1: # key_file
589 613 keyfile = args[0]
590 614 if len(args) >= 2: # cert_file
591 615 certfile = args[1]
592 616 args = args[2:]
593 617
594 618 # if the user has specified different key/cert files in
595 619 # hgrc, we prefer these
596 620 if self.auth and 'key' in self.auth and 'cert' in self.auth:
597 621 keyfile = self.auth['key']
598 622 certfile = self.auth['cert']
599 623
600 624 conn = httpsconnection(host, port, keyfile, certfile, *args, **kwargs)
601 625 conn.ui = self.ui
602 626 return conn
603 627
604 628 class httpdigestauthhandler(urllib2.HTTPDigestAuthHandler):
605 629 def __init__(self, *args, **kwargs):
606 630 urllib2.HTTPDigestAuthHandler.__init__(self, *args, **kwargs)
607 631 self.retried_req = None
608 632
609 633 def reset_retry_count(self):
610 634 # Python 2.6.5 will call this on 401 or 407 errors and thus loop
611 635 # forever. We disable reset_retry_count completely and reset in
612 636 # http_error_auth_reqed instead.
613 637 pass
614 638
615 639 def http_error_auth_reqed(self, auth_header, host, req, headers):
616 640 # Reset the retry counter once for each request.
617 641 if req is not self.retried_req:
618 642 self.retried_req = req
619 643 self.retried = 0
620 644 # In python < 2.5 AbstractDigestAuthHandler raises a ValueError if
621 645 # it doesn't know about the auth type requested. This can happen if
622 646 # somebody is using BasicAuth and types a bad password.
623 647 try:
624 648 return urllib2.HTTPDigestAuthHandler.http_error_auth_reqed(
625 649 self, auth_header, host, req, headers)
626 650 except ValueError, inst:
627 651 arg = inst.args[0]
628 652 if arg.startswith("AbstractDigestAuthHandler doesn't know "):
629 653 return
630 654 raise
631 655
632 656 class httpbasicauthhandler(urllib2.HTTPBasicAuthHandler):
633 657 def __init__(self, *args, **kwargs):
634 658 urllib2.HTTPBasicAuthHandler.__init__(self, *args, **kwargs)
635 659 self.retried_req = None
636 660
637 661 def reset_retry_count(self):
638 662 # Python 2.6.5 will call this on 401 or 407 errors and thus loop
639 663 # forever. We disable reset_retry_count completely and reset in
640 664 # http_error_auth_reqed instead.
641 665 pass
642 666
643 667 def http_error_auth_reqed(self, auth_header, host, req, headers):
644 668 # Reset the retry counter once for each request.
645 669 if req is not self.retried_req:
646 670 self.retried_req = req
647 671 self.retried = 0
648 672 return urllib2.HTTPBasicAuthHandler.http_error_auth_reqed(
649 673 self, auth_header, host, req, headers)
650 674
651 675 def getauthinfo(path):
652 676 scheme, netloc, urlpath, query, frag = urlparse.urlsplit(path)
653 677 if not urlpath:
654 678 urlpath = '/'
655 679 if scheme != 'file':
656 680 # XXX: why are we quoting the path again with some smart
657 681 # heuristic here? Anyway, it cannot be done with file://
658 682 # urls since path encoding is os/fs dependent (see
659 683 # urllib.pathname2url() for details).
660 684 urlpath = quotepath(urlpath)
661 685 host, port, user, passwd = netlocsplit(netloc)
662 686
663 687 # urllib cannot handle URLs with embedded user or passwd
664 688 url = urlparse.urlunsplit((scheme, netlocunsplit(host, port),
665 689 urlpath, query, frag))
666 690 if user:
667 691 netloc = host
668 692 if port:
669 693 netloc += ':' + port
670 694 # Python < 2.4.3 uses only the netloc to search for a password
671 695 authinfo = (None, (url, netloc), user, passwd or '')
672 696 else:
673 697 authinfo = None
674 698 return url, authinfo
675 699
676 700 handlerfuncs = []
677 701
678 702 def opener(ui, authinfo=None):
679 703 '''
680 704 construct an opener suitable for urllib2
681 705 authinfo will be added to the password manager
682 706 '''
683 707 handlers = [httphandler()]
684 708 if has_https:
685 709 handlers.append(httpshandler(ui))
686 710
687 711 handlers.append(proxyhandler(ui))
688 712
689 713 passmgr = passwordmgr(ui)
690 714 if authinfo is not None:
691 715 passmgr.add_password(*authinfo)
692 716 user, passwd = authinfo[2:4]
693 717 ui.debug('http auth: user %s, password %s\n' %
694 718 (user, passwd and '*' * len(passwd) or 'not set'))
695 719
696 720 handlers.extend((httpbasicauthhandler(passmgr),
697 721 httpdigestauthhandler(passmgr)))
698 722 handlers.extend([h(ui, passmgr) for h in handlerfuncs])
699 723 opener = urllib2.build_opener(*handlers)
700 724
701 725 # 1.0 here is the _protocol_ version
702 726 opener.addheaders = [('User-agent', 'mercurial/proto-1.0')]
703 727 opener.addheaders.append(('Accept', 'application/mercurial-0.1'))
704 728 return opener
705 729
706 730 scheme_re = re.compile(r'^([a-zA-Z0-9+-.]+)://')
707 731
708 732 def open(ui, url, data=None):
709 733 scheme = None
710 734 m = scheme_re.search(url)
711 735 if m:
712 736 scheme = m.group(1).lower()
713 737 if not scheme:
714 738 path = util.normpath(os.path.abspath(url))
715 739 url = 'file://' + urllib.pathname2url(path)
716 740 authinfo = None
717 741 else:
718 742 url, authinfo = getauthinfo(url)
719 743 return opener(ui, authinfo).open(url, data)
@@ -1,190 +1,209 b''
1 1 Proper https client requires the built-in ssl from Python 2.6.
2 2
3 3 $ "$TESTDIR/hghave" ssl || exit 80
4 4
5 5 Certificates created with:
6 6 printf '.\n.\n.\n.\n.\nlocalhost\nhg@localhost\n' | \
7 7 openssl req -newkey rsa:512 -keyout priv.pem -nodes -x509 -days 9000 -out pub.pem
8 8 Can be dumped with:
9 9 openssl x509 -in pub.pem -text
10 10
11 11 $ cat << EOT > priv.pem
12 12 > -----BEGIN PRIVATE KEY-----
13 13 > MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEApjCWeYGrIa/Vo7LH
14 14 > aRF8ou0tbgHKE33Use/whCnKEUm34rDaXQd4lxxX6aDWg06n9tiVStAKTgQAHJY8
15 15 > j/xgSwIDAQABAkBxHC6+Qlf0VJXGlb6NL16yEVVTQxqDS6hA9zqu6TZjrr0YMfzc
16 16 > EGNIiZGt7HCBL0zO+cPDg/LeCZc6HQhf0KrhAiEAzlJq4hWWzvguWFIJWSoBeBUG
17 17 > MF1ACazQO7PYE8M0qfECIQDONHHP0SKZzz/ZwBZcAveC5K61f/v9hONFwbeYulzR
18 18 > +wIgc9SvbtgB/5Yzpp//4ZAEnR7oh5SClCvyB+KSx52K3nECICbhQphhoXmI10wy
19 19 > aMTellaq0bpNMHFDziqH9RsqAHhjAiEAgYGxfzkftt5IUUn/iFK89aaIpyrpuaAh
20 20 > HY8gUVkVRVs=
21 21 > -----END PRIVATE KEY-----
22 22 > EOT
23 23
24 24 $ cat << EOT > pub.pem
25 25 > -----BEGIN CERTIFICATE-----
26 26 > MIIBqzCCAVWgAwIBAgIJANAXFFyWjGnRMA0GCSqGSIb3DQEBBQUAMDExEjAQBgNV
27 27 > BAMMCWxvY2FsaG9zdDEbMBkGCSqGSIb3DQEJARYMaGdAbG9jYWxob3N0MB4XDTEw
28 28 > MTAxNDIwMzAxNFoXDTM1MDYwNTIwMzAxNFowMTESMBAGA1UEAwwJbG9jYWxob3N0
29 29 > MRswGQYJKoZIhvcNAQkBFgxoZ0Bsb2NhbGhvc3QwXDANBgkqhkiG9w0BAQEFAANL
30 30 > ADBIAkEApjCWeYGrIa/Vo7LHaRF8ou0tbgHKE33Use/whCnKEUm34rDaXQd4lxxX
31 31 > 6aDWg06n9tiVStAKTgQAHJY8j/xgSwIDAQABo1AwTjAdBgNVHQ4EFgQUE6sA+amm
32 32 > r24dGX0kpjxOgO45hzQwHwYDVR0jBBgwFoAUE6sA+ammr24dGX0kpjxOgO45hzQw
33 33 > DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAANBAFArvQFiAZJgQczRsbYlG1xl
34 34 > t+truk37w5B3m3Ick1ntRcQrqs+hf0CO1q6Squ144geYaQ8CDirSR92fICELI1c=
35 35 > -----END CERTIFICATE-----
36 36 > EOT
37 37 $ cat priv.pem pub.pem >> server.pem
38 38 $ PRIV=`pwd`/server.pem
39 39
40 40 $ cat << EOT > pub-other.pem
41 41 > -----BEGIN CERTIFICATE-----
42 42 > MIIBqzCCAVWgAwIBAgIJALwZS731c/ORMA0GCSqGSIb3DQEBBQUAMDExEjAQBgNV
43 43 > BAMMCWxvY2FsaG9zdDEbMBkGCSqGSIb3DQEJARYMaGdAbG9jYWxob3N0MB4XDTEw
44 44 > MTAxNDIwNDUxNloXDTM1MDYwNTIwNDUxNlowMTESMBAGA1UEAwwJbG9jYWxob3N0
45 45 > MRswGQYJKoZIhvcNAQkBFgxoZ0Bsb2NhbGhvc3QwXDANBgkqhkiG9w0BAQEFAANL
46 46 > ADBIAkEAsxsapLbHrqqUKuQBxdpK4G3m2LjtyrTSdpzzzFlecxd5yhNP6AyWrufo
47 47 > K4VMGo2xlu9xOo88nDSUNSKPuD09MwIDAQABo1AwTjAdBgNVHQ4EFgQUoIB1iMhN
48 48 > y868rpQ2qk9dHnU6ebswHwYDVR0jBBgwFoAUoIB1iMhNy868rpQ2qk9dHnU6ebsw
49 49 > DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAANBAJ544f125CsE7J2t55PdFaF6
50 50 > bBlNBb91FCywBgSjhBjf+GG3TNPwrPdc3yqeq+hzJiuInqbOBv9abmMyq8Wsoig=
51 51 > -----END CERTIFICATE-----
52 52 > EOT
53 53
54 54 pub.pem patched with other notBefore / notAfter:
55 55
56 56 $ cat << EOT > pub-not-yet.pem
57 57 > -----BEGIN CERTIFICATE-----
58 58 > MIIBqzCCAVWgAwIBAgIJANAXFFyWjGnRMA0GCSqGSIb3DQEBBQUAMDExEjAQBgNVBAMMCWxvY2Fs
59 59 > aG9zdDEbMBkGCSqGSIb3DQEJARYMaGdAbG9jYWxob3N0MB4XDTM1MDYwNTIwMzAxNFoXDTM1MDYw
60 60 > NTIwMzAxNFowMTESMBAGA1UEAwwJbG9jYWxob3N0MRswGQYJKoZIhvcNAQkBFgxoZ0Bsb2NhbGhv
61 61 > c3QwXDANBgkqhkiG9w0BAQEFAANLADBIAkEApjCWeYGrIa/Vo7LHaRF8ou0tbgHKE33Use/whCnK
62 62 > EUm34rDaXQd4lxxX6aDWg06n9tiVStAKTgQAHJY8j/xgSwIDAQABo1AwTjAdBgNVHQ4EFgQUE6sA
63 63 > +ammr24dGX0kpjxOgO45hzQwHwYDVR0jBBgwFoAUE6sA+ammr24dGX0kpjxOgO45hzQwDAYDVR0T
64 64 > BAUwAwEB/zANBgkqhkiG9w0BAQUFAANBAJXV41gWnkgC7jcpPpFRSUSZaxyzrXmD1CIqQf0WgVDb
65 65 > /12E0vR2DuZitgzUYtBaofM81aTtc0a2/YsrmqePGm0=
66 66 > -----END CERTIFICATE-----
67 67 > EOT
68 68 $ cat priv.pem pub-not-yet.pem > server-not-yet.pem
69 69
70 70 $ cat << EOT > pub-expired.pem
71 71 > -----BEGIN CERTIFICATE-----
72 72 > MIIBqzCCAVWgAwIBAgIJANAXFFyWjGnRMA0GCSqGSIb3DQEBBQUAMDExEjAQBgNVBAMMCWxvY2Fs
73 73 > aG9zdDEbMBkGCSqGSIb3DQEJARYMaGdAbG9jYWxob3N0MB4XDTEwMTAxNDIwMzAxNFoXDTEwMTAx
74 74 > NDIwMzAxNFowMTESMBAGA1UEAwwJbG9jYWxob3N0MRswGQYJKoZIhvcNAQkBFgxoZ0Bsb2NhbGhv
75 75 > c3QwXDANBgkqhkiG9w0BAQEFAANLADBIAkEApjCWeYGrIa/Vo7LHaRF8ou0tbgHKE33Use/whCnK
76 76 > EUm34rDaXQd4lxxX6aDWg06n9tiVStAKTgQAHJY8j/xgSwIDAQABo1AwTjAdBgNVHQ4EFgQUE6sA
77 77 > +ammr24dGX0kpjxOgO45hzQwHwYDVR0jBBgwFoAUE6sA+ammr24dGX0kpjxOgO45hzQwDAYDVR0T
78 78 > BAUwAwEB/zANBgkqhkiG9w0BAQUFAANBAJfk57DTRf2nUbYaMSlVAARxMNbFGOjQhAUtY400GhKt
79 79 > 2uiKCNGKXVXD3AHWe13yHc5KttzbHQStE5Nm/DlWBWQ=
80 80 > -----END CERTIFICATE-----
81 81 > EOT
82 82 $ cat priv.pem pub-expired.pem > server-expired.pem
83 83
84 84 $ hg init test
85 85 $ cd test
86 86 $ echo foo>foo
87 87 $ mkdir foo.d foo.d/bAr.hg.d foo.d/baR.d.hg
88 88 $ echo foo>foo.d/foo
89 89 $ echo bar>foo.d/bAr.hg.d/BaR
90 90 $ echo bar>foo.d/baR.d.hg/bAR
91 91 $ hg commit -A -m 1
92 92 adding foo
93 93 adding foo.d/bAr.hg.d/BaR
94 94 adding foo.d/baR.d.hg/bAR
95 95 adding foo.d/foo
96 96 $ hg serve -p $HGPORT -d --pid-file=../hg0.pid --certificate=$PRIV
97 97 $ cat ../hg0.pid >> $DAEMON_PIDS
98 98
99 99 Test server address cannot be reused
100 100
101 101 $ hg serve -p $HGPORT --certificate=$PRIV 2>&1
102 102 abort: cannot start server at ':$HGPORT': Address already in use
103 103 [255]
104 104 $ cd ..
105 105
106 106 clone via pull
107 107
108 108 $ hg clone https://localhost:$HGPORT/ copy-pull
109 warning: localhost certificate not verified (check web.cacerts config setting)
109 warning: localhost certificate with fingerprint 91:4f:1a:ff:87:24:9c:09:b6:85:9b:88:b1:90:6d:30:75:64:91:ca not verified (check hostfingerprints or web.cacerts config setting)
110 110 requesting all changes
111 111 adding changesets
112 112 adding manifests
113 113 adding file changes
114 114 added 1 changesets with 4 changes to 4 files
115 115 updating to branch default
116 116 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
117 117 $ hg verify -R copy-pull
118 118 checking changesets
119 119 checking manifests
120 120 crosschecking files in changesets and manifests
121 121 checking files
122 122 4 files, 1 changesets, 4 total revisions
123 123 $ cd test
124 124 $ echo bar > bar
125 125 $ hg commit -A -d '1 0' -m 2
126 126 adding bar
127 127 $ cd ..
128 128
129 129 pull without cacert
130 130
131 131 $ cd copy-pull
132 132 $ echo '[hooks]' >> .hg/hgrc
133 133 $ echo "changegroup = python '$TESTDIR'/printenv.py changegroup" >> .hg/hgrc
134 134 $ hg pull
135 warning: localhost certificate not verified (check web.cacerts config setting)
135 warning: localhost certificate with fingerprint 91:4f:1a:ff:87:24:9c:09:b6:85:9b:88:b1:90:6d:30:75:64:91:ca not verified (check hostfingerprints or web.cacerts config setting)
136 136 changegroup hook: HG_NODE=5fed3813f7f5e1824344fdc9cf8f63bb662c292d HG_SOURCE=pull HG_URL=https://localhost:$HGPORT/
137 137 pulling from https://localhost:$HGPORT/
138 138 searching for changes
139 139 adding changesets
140 140 adding manifests
141 141 adding file changes
142 142 added 1 changesets with 1 changes to 1 files
143 143 (run 'hg update' to get a working copy)
144 144 $ cd ..
145 145
146 146 cacert configured in local repo
147 147
148 148 $ cp copy-pull/.hg/hgrc copy-pull/.hg/hgrc.bu
149 149 $ echo "[web]" >> copy-pull/.hg/hgrc
150 150 $ echo "cacerts=`pwd`/pub.pem" >> copy-pull/.hg/hgrc
151 151 $ hg -R copy-pull pull --traceback
152 152 pulling from https://localhost:$HGPORT/
153 153 searching for changes
154 154 no changes found
155 155 $ mv copy-pull/.hg/hgrc.bu copy-pull/.hg/hgrc
156 156
157 157 cacert configured globally, also testing expansion of environment
158 158 variables in the filename
159 159
160 160 $ echo "[web]" >> $HGRCPATH
161 161 $ echo 'cacerts=$P/pub.pem' >> $HGRCPATH
162 162 $ P=`pwd` hg -R copy-pull pull
163 163 pulling from https://localhost:$HGPORT/
164 164 searching for changes
165 165 no changes found
166 166
167 167 cacert mismatch
168 168
169 169 $ hg -R copy-pull pull --config web.cacerts=pub.pem https://127.0.0.1:$HGPORT/
170 170 abort: 127.0.0.1 certificate error: certificate is for localhost
171 171 [255]
172 172 $ hg -R copy-pull pull --config web.cacerts=pub-other.pem
173 173 abort: error: *:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed (glob)
174 174 [255]
175 175
176 176 Test server cert which isn't valid yet
177 177
178 178 $ hg -R test serve -p $HGPORT1 -d --pid-file=hg1.pid --certificate=server-not-yet.pem
179 179 $ cat hg1.pid >> $DAEMON_PIDS
180 180 $ hg -R copy-pull pull --config web.cacerts=pub-not-yet.pem https://localhost:$HGPORT1/
181 181 abort: error: *:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed (glob)
182 182 [255]
183 183
184 184 Test server cert which no longer is valid
185 185
186 186 $ hg -R test serve -p $HGPORT2 -d --pid-file=hg2.pid --certificate=server-expired.pem
187 187 $ cat hg2.pid >> $DAEMON_PIDS
188 188 $ hg -R copy-pull pull --config web.cacerts=pub-expired.pem https://localhost:$HGPORT2/
189 189 abort: error: *:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed (glob)
190 190 [255]
191
192 Fingerprints
193
194 $ echo "[hostfingerprints]" >> copy-pull/.hg/hgrc
195 $ echo "localhost = 91:4f:1a:ff:87:24:9c:09:b6:85:9b:88:b1:90:6d:30:75:64:91:ca" >> copy-pull/.hg/hgrc
196 $ echo "127.0.0.1 = 914f1aff87249c09b6859b88b1906d30756491ca" >> copy-pull/.hg/hgrc
197
198 - works without cacerts
199 $ hg -R copy-pull id https://localhost:$HGPORT/ --config web.cacerts=
200 5fed3813f7f5
201
202 - fails when cert doesn't match hostname (port is ignored)
203 $ hg -R copy-pull id https://localhost:$HGPORT1/
204 abort: invalid certificate for localhost with fingerprint 28:ff:71:bf:65:31:14:23:ad:62:92:b4:0e:31:99:18:fc:83:e3:9b
205 [255]
206
207 - ignores that certificate doesn't match hostname
208 $ hg -R copy-pull id https://127.0.0.1:$HGPORT/
209 5fed3813f7f5
General Comments 0
You need to be logged in to leave comments. Login now