##// END OF EJS Templates
hook: add hook name information to external hook...
Pierre-Yves David -
r31747:aff7b32b default
parent child Browse files
Show More
@@ -1,2368 +1,2369
1 1 The Mercurial system uses a set of configuration files to control
2 2 aspects of its behavior.
3 3
4 4 Troubleshooting
5 5 ===============
6 6
7 7 If you're having problems with your configuration,
8 8 :hg:`config --debug` can help you understand what is introducing
9 9 a setting into your environment.
10 10
11 11 See :hg:`help config.syntax` and :hg:`help config.files`
12 12 for information about how and where to override things.
13 13
14 14 Structure
15 15 =========
16 16
17 17 The configuration files use a simple ini-file format. A configuration
18 18 file consists of sections, led by a ``[section]`` header and followed
19 19 by ``name = value`` entries::
20 20
21 21 [ui]
22 22 username = Firstname Lastname <firstname.lastname@example.net>
23 23 verbose = True
24 24
25 25 The above entries will be referred to as ``ui.username`` and
26 26 ``ui.verbose``, respectively. See :hg:`help config.syntax`.
27 27
28 28 Files
29 29 =====
30 30
31 31 Mercurial reads configuration data from several files, if they exist.
32 32 These files do not exist by default and you will have to create the
33 33 appropriate configuration files yourself:
34 34
35 35 Local configuration is put into the per-repository ``<repo>/.hg/hgrc`` file.
36 36
37 37 Global configuration like the username setting is typically put into:
38 38
39 39 .. container:: windows
40 40
41 41 - ``%USERPROFILE%\mercurial.ini`` (on Windows)
42 42
43 43 .. container:: unix.plan9
44 44
45 45 - ``$HOME/.hgrc`` (on Unix, Plan9)
46 46
47 47 The names of these files depend on the system on which Mercurial is
48 48 installed. ``*.rc`` files from a single directory are read in
49 49 alphabetical order, later ones overriding earlier ones. Where multiple
50 50 paths are given below, settings from earlier paths override later
51 51 ones.
52 52
53 53 .. container:: verbose.unix
54 54
55 55 On Unix, the following files are consulted:
56 56
57 57 - ``<repo>/.hg/hgrc`` (per-repository)
58 58 - ``$HOME/.hgrc`` (per-user)
59 59 - ``${XDG_CONFIG_HOME:-$HOME/.config}/hg/hgrc`` (per-user)
60 60 - ``<install-root>/etc/mercurial/hgrc`` (per-installation)
61 61 - ``<install-root>/etc/mercurial/hgrc.d/*.rc`` (per-installation)
62 62 - ``/etc/mercurial/hgrc`` (per-system)
63 63 - ``/etc/mercurial/hgrc.d/*.rc`` (per-system)
64 64 - ``<internal>/default.d/*.rc`` (defaults)
65 65
66 66 .. container:: verbose.windows
67 67
68 68 On Windows, the following files are consulted:
69 69
70 70 - ``<repo>/.hg/hgrc`` (per-repository)
71 71 - ``%USERPROFILE%\.hgrc`` (per-user)
72 72 - ``%USERPROFILE%\Mercurial.ini`` (per-user)
73 73 - ``%HOME%\.hgrc`` (per-user)
74 74 - ``%HOME%\Mercurial.ini`` (per-user)
75 75 - ``HKEY_LOCAL_MACHINE\SOFTWARE\Mercurial`` (per-installation)
76 76 - ``<install-dir>\hgrc.d\*.rc`` (per-installation)
77 77 - ``<install-dir>\Mercurial.ini`` (per-installation)
78 78 - ``<internal>/default.d/*.rc`` (defaults)
79 79
80 80 .. note::
81 81
82 82 The registry key ``HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Mercurial``
83 83 is used when running 32-bit Python on 64-bit Windows.
84 84
85 85 .. container:: windows
86 86
87 87 On Windows 9x, ``%HOME%`` is replaced by ``%APPDATA%``.
88 88
89 89 .. container:: verbose.plan9
90 90
91 91 On Plan9, the following files are consulted:
92 92
93 93 - ``<repo>/.hg/hgrc`` (per-repository)
94 94 - ``$home/lib/hgrc`` (per-user)
95 95 - ``<install-root>/lib/mercurial/hgrc`` (per-installation)
96 96 - ``<install-root>/lib/mercurial/hgrc.d/*.rc`` (per-installation)
97 97 - ``/lib/mercurial/hgrc`` (per-system)
98 98 - ``/lib/mercurial/hgrc.d/*.rc`` (per-system)
99 99 - ``<internal>/default.d/*.rc`` (defaults)
100 100
101 101 Per-repository configuration options only apply in a
102 102 particular repository. This file is not version-controlled, and
103 103 will not get transferred during a "clone" operation. Options in
104 104 this file override options in all other configuration files.
105 105
106 106 .. container:: unix.plan9
107 107
108 108 On Plan 9 and Unix, most of this file will be ignored if it doesn't
109 109 belong to a trusted user or to a trusted group. See
110 110 :hg:`help config.trusted` for more details.
111 111
112 112 Per-user configuration file(s) are for the user running Mercurial. Options
113 113 in these files apply to all Mercurial commands executed by this user in any
114 114 directory. Options in these files override per-system and per-installation
115 115 options.
116 116
117 117 Per-installation configuration files are searched for in the
118 118 directory where Mercurial is installed. ``<install-root>`` is the
119 119 parent directory of the **hg** executable (or symlink) being run.
120 120
121 121 .. container:: unix.plan9
122 122
123 123 For example, if installed in ``/shared/tools/bin/hg``, Mercurial
124 124 will look in ``/shared/tools/etc/mercurial/hgrc``. Options in these
125 125 files apply to all Mercurial commands executed by any user in any
126 126 directory.
127 127
128 128 Per-installation configuration files are for the system on
129 129 which Mercurial is running. Options in these files apply to all
130 130 Mercurial commands executed by any user in any directory. Registry
131 131 keys contain PATH-like strings, every part of which must reference
132 132 a ``Mercurial.ini`` file or be a directory where ``*.rc`` files will
133 133 be read. Mercurial checks each of these locations in the specified
134 134 order until one or more configuration files are detected.
135 135
136 136 Per-system configuration files are for the system on which Mercurial
137 137 is running. Options in these files apply to all Mercurial commands
138 138 executed by any user in any directory. Options in these files
139 139 override per-installation options.
140 140
141 141 Mercurial comes with some default configuration. The default configuration
142 142 files are installed with Mercurial and will be overwritten on upgrades. Default
143 143 configuration files should never be edited by users or administrators but can
144 144 be overridden in other configuration files. So far the directory only contains
145 145 merge tool configuration but packagers can also put other default configuration
146 146 there.
147 147
148 148 Syntax
149 149 ======
150 150
151 151 A configuration file consists of sections, led by a ``[section]`` header
152 152 and followed by ``name = value`` entries (sometimes called
153 153 ``configuration keys``)::
154 154
155 155 [spam]
156 156 eggs=ham
157 157 green=
158 158 eggs
159 159
160 160 Each line contains one entry. If the lines that follow are indented,
161 161 they are treated as continuations of that entry. Leading whitespace is
162 162 removed from values. Empty lines are skipped. Lines beginning with
163 163 ``#`` or ``;`` are ignored and may be used to provide comments.
164 164
165 165 Configuration keys can be set multiple times, in which case Mercurial
166 166 will use the value that was configured last. As an example::
167 167
168 168 [spam]
169 169 eggs=large
170 170 ham=serrano
171 171 eggs=small
172 172
173 173 This would set the configuration key named ``eggs`` to ``small``.
174 174
175 175 It is also possible to define a section multiple times. A section can
176 176 be redefined on the same and/or on different configuration files. For
177 177 example::
178 178
179 179 [foo]
180 180 eggs=large
181 181 ham=serrano
182 182 eggs=small
183 183
184 184 [bar]
185 185 eggs=ham
186 186 green=
187 187 eggs
188 188
189 189 [foo]
190 190 ham=prosciutto
191 191 eggs=medium
192 192 bread=toasted
193 193
194 194 This would set the ``eggs``, ``ham``, and ``bread`` configuration keys
195 195 of the ``foo`` section to ``medium``, ``prosciutto``, and ``toasted``,
196 196 respectively. As you can see there only thing that matters is the last
197 197 value that was set for each of the configuration keys.
198 198
199 199 If a configuration key is set multiple times in different
200 200 configuration files the final value will depend on the order in which
201 201 the different configuration files are read, with settings from earlier
202 202 paths overriding later ones as described on the ``Files`` section
203 203 above.
204 204
205 205 A line of the form ``%include file`` will include ``file`` into the
206 206 current configuration file. The inclusion is recursive, which means
207 207 that included files can include other files. Filenames are relative to
208 208 the configuration file in which the ``%include`` directive is found.
209 209 Environment variables and ``~user`` constructs are expanded in
210 210 ``file``. This lets you do something like::
211 211
212 212 %include ~/.hgrc.d/$HOST.rc
213 213
214 214 to include a different configuration file on each computer you use.
215 215
216 216 A line with ``%unset name`` will remove ``name`` from the current
217 217 section, if it has been set previously.
218 218
219 219 The values are either free-form text strings, lists of text strings,
220 220 or Boolean values. Boolean values can be set to true using any of "1",
221 221 "yes", "true", or "on" and to false using "0", "no", "false", or "off"
222 222 (all case insensitive).
223 223
224 224 List values are separated by whitespace or comma, except when values are
225 225 placed in double quotation marks::
226 226
227 227 allow_read = "John Doe, PhD", brian, betty
228 228
229 229 Quotation marks can be escaped by prefixing them with a backslash. Only
230 230 quotation marks at the beginning of a word is counted as a quotation
231 231 (e.g., ``foo"bar baz`` is the list of ``foo"bar`` and ``baz``).
232 232
233 233 Sections
234 234 ========
235 235
236 236 This section describes the different sections that may appear in a
237 237 Mercurial configuration file, the purpose of each section, its possible
238 238 keys, and their possible values.
239 239
240 240 ``alias``
241 241 ---------
242 242
243 243 Defines command aliases.
244 244
245 245 Aliases allow you to define your own commands in terms of other
246 246 commands (or aliases), optionally including arguments. Positional
247 247 arguments in the form of ``$1``, ``$2``, etc. in the alias definition
248 248 are expanded by Mercurial before execution. Positional arguments not
249 249 already used by ``$N`` in the definition are put at the end of the
250 250 command to be executed.
251 251
252 252 Alias definitions consist of lines of the form::
253 253
254 254 <alias> = <command> [<argument>]...
255 255
256 256 For example, this definition::
257 257
258 258 latest = log --limit 5
259 259
260 260 creates a new command ``latest`` that shows only the five most recent
261 261 changesets. You can define subsequent aliases using earlier ones::
262 262
263 263 stable5 = latest -b stable
264 264
265 265 .. note::
266 266
267 267 It is possible to create aliases with the same names as
268 268 existing commands, which will then override the original
269 269 definitions. This is almost always a bad idea!
270 270
271 271 An alias can start with an exclamation point (``!``) to make it a
272 272 shell alias. A shell alias is executed with the shell and will let you
273 273 run arbitrary commands. As an example, ::
274 274
275 275 echo = !echo $@
276 276
277 277 will let you do ``hg echo foo`` to have ``foo`` printed in your
278 278 terminal. A better example might be::
279 279
280 280 purge = !$HG status --no-status --unknown -0 re: | xargs -0 rm -f
281 281
282 282 which will make ``hg purge`` delete all unknown files in the
283 283 repository in the same manner as the purge extension.
284 284
285 285 Positional arguments like ``$1``, ``$2``, etc. in the alias definition
286 286 expand to the command arguments. Unmatched arguments are
287 287 removed. ``$0`` expands to the alias name and ``$@`` expands to all
288 288 arguments separated by a space. ``"$@"`` (with quotes) expands to all
289 289 arguments quoted individually and separated by a space. These expansions
290 290 happen before the command is passed to the shell.
291 291
292 292 Shell aliases are executed in an environment where ``$HG`` expands to
293 293 the path of the Mercurial that was used to execute the alias. This is
294 294 useful when you want to call further Mercurial commands in a shell
295 295 alias, as was done above for the purge alias. In addition,
296 296 ``$HG_ARGS`` expands to the arguments given to Mercurial. In the ``hg
297 297 echo foo`` call above, ``$HG_ARGS`` would expand to ``echo foo``.
298 298
299 299 .. note::
300 300
301 301 Some global configuration options such as ``-R`` are
302 302 processed before shell aliases and will thus not be passed to
303 303 aliases.
304 304
305 305
306 306 ``annotate``
307 307 ------------
308 308
309 309 Settings used when displaying file annotations. All values are
310 310 Booleans and default to False. See :hg:`help config.diff` for
311 311 related options for the diff command.
312 312
313 313 ``ignorews``
314 314 Ignore white space when comparing lines.
315 315
316 316 ``ignorewsamount``
317 317 Ignore changes in the amount of white space.
318 318
319 319 ``ignoreblanklines``
320 320 Ignore changes whose lines are all blank.
321 321
322 322
323 323 ``auth``
324 324 --------
325 325
326 326 Authentication credentials for HTTP authentication. This section
327 327 allows you to store usernames and passwords for use when logging
328 328 *into* HTTP servers. See :hg:`help config.web` if
329 329 you want to configure *who* can login to your HTTP server.
330 330
331 331 Each line has the following format::
332 332
333 333 <name>.<argument> = <value>
334 334
335 335 where ``<name>`` is used to group arguments into authentication
336 336 entries. Example::
337 337
338 338 foo.prefix = hg.intevation.de/mercurial
339 339 foo.username = foo
340 340 foo.password = bar
341 341 foo.schemes = http https
342 342
343 343 bar.prefix = secure.example.org
344 344 bar.key = path/to/file.key
345 345 bar.cert = path/to/file.cert
346 346 bar.schemes = https
347 347
348 348 Supported arguments:
349 349
350 350 ``prefix``
351 351 Either ``*`` or a URI prefix with or without the scheme part.
352 352 The authentication entry with the longest matching prefix is used
353 353 (where ``*`` matches everything and counts as a match of length
354 354 1). If the prefix doesn't include a scheme, the match is performed
355 355 against the URI with its scheme stripped as well, and the schemes
356 356 argument, q.v., is then subsequently consulted.
357 357
358 358 ``username``
359 359 Optional. Username to authenticate with. If not given, and the
360 360 remote site requires basic or digest authentication, the user will
361 361 be prompted for it. Environment variables are expanded in the
362 362 username letting you do ``foo.username = $USER``. If the URI
363 363 includes a username, only ``[auth]`` entries with a matching
364 364 username or without a username will be considered.
365 365
366 366 ``password``
367 367 Optional. Password to authenticate with. If not given, and the
368 368 remote site requires basic or digest authentication, the user
369 369 will be prompted for it.
370 370
371 371 ``key``
372 372 Optional. PEM encoded client certificate key file. Environment
373 373 variables are expanded in the filename.
374 374
375 375 ``cert``
376 376 Optional. PEM encoded client certificate chain file. Environment
377 377 variables are expanded in the filename.
378 378
379 379 ``schemes``
380 380 Optional. Space separated list of URI schemes to use this
381 381 authentication entry with. Only used if the prefix doesn't include
382 382 a scheme. Supported schemes are http and https. They will match
383 383 static-http and static-https respectively, as well.
384 384 (default: https)
385 385
386 386 If no suitable authentication entry is found, the user is prompted
387 387 for credentials as usual if required by the remote.
388 388
389 389 ``color``
390 390 ---------
391 391
392 392 Configure the Mercurial color mode. For details about how to define your custom
393 393 effect and style see :hg:`help color`.
394 394
395 395 ``mode``
396 396 String: control the method used to output color. One of ``auto``, ``ansi``,
397 397 ``win32``, ``terminfo`` or ``debug``. In auto mode the color extension will
398 398 use ANSI mode by default (or win32 mode on Windows) if it detects a
399 399 terminal. Any invalid value will disable color.
400 400
401 401 ``pagermode``
402 402 String: optinal override of ``color.mode`` used with pager (from the pager
403 403 extensions).
404 404
405 405 On some systems, terminfo mode may cause problems when using
406 406 color with the pager extension and less -R. less with the -R option
407 407 will only display ECMA-48 color codes, and terminfo mode may sometimes
408 408 emit codes that less doesn't understand. You can work around this by
409 409 either using ansi mode (or auto mode), or by using less -r (which will
410 410 pass through all terminal control codes, not just color control
411 411 codes).
412 412
413 413 On some systems (such as MSYS in Windows), the terminal may support
414 414 a different color mode than the pager (activated via the "pager"
415 415 extension).
416 416
417 417 ``commands``
418 418 ------------
419 419
420 420 ``status.relative``
421 421 Make paths in ``hg status`` output relative to the current directory.
422 422 (default: False)
423 423
424 424 ``update.requiredest``
425 425 Require that the user pass a destination when running ``hg update``.
426 426 For example, ``hg update .::`` will be allowed, but a plain ``hg update``
427 427 will be disallowed.
428 428 (default: False)
429 429
430 430 ``committemplate``
431 431 ------------------
432 432
433 433 ``changeset``
434 434 String: configuration in this section is used as the template to
435 435 customize the text shown in the editor when committing.
436 436
437 437 In addition to pre-defined template keywords, commit log specific one
438 438 below can be used for customization:
439 439
440 440 ``extramsg``
441 441 String: Extra message (typically 'Leave message empty to abort
442 442 commit.'). This may be changed by some commands or extensions.
443 443
444 444 For example, the template configuration below shows as same text as
445 445 one shown by default::
446 446
447 447 [committemplate]
448 448 changeset = {desc}\n\n
449 449 HG: Enter commit message. Lines beginning with 'HG:' are removed.
450 450 HG: {extramsg}
451 451 HG: --
452 452 HG: user: {author}\n{ifeq(p2rev, "-1", "",
453 453 "HG: branch merge\n")
454 454 }HG: branch '{branch}'\n{if(activebookmark,
455 455 "HG: bookmark '{activebookmark}'\n") }{subrepos %
456 456 "HG: subrepo {subrepo}\n" }{file_adds %
457 457 "HG: added {file}\n" }{file_mods %
458 458 "HG: changed {file}\n" }{file_dels %
459 459 "HG: removed {file}\n" }{if(files, "",
460 460 "HG: no files changed\n")}
461 461
462 462 ``diff()``
463 463 String: show the diff (see :hg:`help templates` for detail)
464 464
465 465 Sometimes it is helpful to show the diff of the changeset in the editor without
466 466 having to prefix 'HG: ' to each line so that highlighting works correctly. For
467 467 this, Mercurial provides a special string which will ignore everything below
468 468 it::
469 469
470 470 HG: ------------------------ >8 ------------------------
471 471
472 472 For example, the template configuration below will show the diff below the
473 473 extra message::
474 474
475 475 [committemplate]
476 476 changeset = {desc}\n\n
477 477 HG: Enter commit message. Lines beginning with 'HG:' are removed.
478 478 HG: {extramsg}
479 479 HG: ------------------------ >8 ------------------------
480 480 HG: Do not touch the line above.
481 481 HG: Everything below will be removed.
482 482 {diff()}
483 483
484 484 .. note::
485 485
486 486 For some problematic encodings (see :hg:`help win32mbcs` for
487 487 detail), this customization should be configured carefully, to
488 488 avoid showing broken characters.
489 489
490 490 For example, if a multibyte character ending with backslash (0x5c) is
491 491 followed by the ASCII character 'n' in the customized template,
492 492 the sequence of backslash and 'n' is treated as line-feed unexpectedly
493 493 (and the multibyte character is broken, too).
494 494
495 495 Customized template is used for commands below (``--edit`` may be
496 496 required):
497 497
498 498 - :hg:`backout`
499 499 - :hg:`commit`
500 500 - :hg:`fetch` (for merge commit only)
501 501 - :hg:`graft`
502 502 - :hg:`histedit`
503 503 - :hg:`import`
504 504 - :hg:`qfold`, :hg:`qnew` and :hg:`qrefresh`
505 505 - :hg:`rebase`
506 506 - :hg:`shelve`
507 507 - :hg:`sign`
508 508 - :hg:`tag`
509 509 - :hg:`transplant`
510 510
511 511 Configuring items below instead of ``changeset`` allows showing
512 512 customized message only for specific actions, or showing different
513 513 messages for each action.
514 514
515 515 - ``changeset.backout`` for :hg:`backout`
516 516 - ``changeset.commit.amend.merge`` for :hg:`commit --amend` on merges
517 517 - ``changeset.commit.amend.normal`` for :hg:`commit --amend` on other
518 518 - ``changeset.commit.normal.merge`` for :hg:`commit` on merges
519 519 - ``changeset.commit.normal.normal`` for :hg:`commit` on other
520 520 - ``changeset.fetch`` for :hg:`fetch` (impling merge commit)
521 521 - ``changeset.gpg.sign`` for :hg:`sign`
522 522 - ``changeset.graft`` for :hg:`graft`
523 523 - ``changeset.histedit.edit`` for ``edit`` of :hg:`histedit`
524 524 - ``changeset.histedit.fold`` for ``fold`` of :hg:`histedit`
525 525 - ``changeset.histedit.mess`` for ``mess`` of :hg:`histedit`
526 526 - ``changeset.histedit.pick`` for ``pick`` of :hg:`histedit`
527 527 - ``changeset.import.bypass`` for :hg:`import --bypass`
528 528 - ``changeset.import.normal.merge`` for :hg:`import` on merges
529 529 - ``changeset.import.normal.normal`` for :hg:`import` on other
530 530 - ``changeset.mq.qnew`` for :hg:`qnew`
531 531 - ``changeset.mq.qfold`` for :hg:`qfold`
532 532 - ``changeset.mq.qrefresh`` for :hg:`qrefresh`
533 533 - ``changeset.rebase.collapse`` for :hg:`rebase --collapse`
534 534 - ``changeset.rebase.merge`` for :hg:`rebase` on merges
535 535 - ``changeset.rebase.normal`` for :hg:`rebase` on other
536 536 - ``changeset.shelve.shelve`` for :hg:`shelve`
537 537 - ``changeset.tag.add`` for :hg:`tag` without ``--remove``
538 538 - ``changeset.tag.remove`` for :hg:`tag --remove`
539 539 - ``changeset.transplant.merge`` for :hg:`transplant` on merges
540 540 - ``changeset.transplant.normal`` for :hg:`transplant` on other
541 541
542 542 These dot-separated lists of names are treated as hierarchical ones.
543 543 For example, ``changeset.tag.remove`` customizes the commit message
544 544 only for :hg:`tag --remove`, but ``changeset.tag`` customizes the
545 545 commit message for :hg:`tag` regardless of ``--remove`` option.
546 546
547 547 When the external editor is invoked for a commit, the corresponding
548 548 dot-separated list of names without the ``changeset.`` prefix
549 549 (e.g. ``commit.normal.normal``) is in the ``HGEDITFORM`` environment
550 550 variable.
551 551
552 552 In this section, items other than ``changeset`` can be referred from
553 553 others. For example, the configuration to list committed files up
554 554 below can be referred as ``{listupfiles}``::
555 555
556 556 [committemplate]
557 557 listupfiles = {file_adds %
558 558 "HG: added {file}\n" }{file_mods %
559 559 "HG: changed {file}\n" }{file_dels %
560 560 "HG: removed {file}\n" }{if(files, "",
561 561 "HG: no files changed\n")}
562 562
563 563 ``decode/encode``
564 564 -----------------
565 565
566 566 Filters for transforming files on checkout/checkin. This would
567 567 typically be used for newline processing or other
568 568 localization/canonicalization of files.
569 569
570 570 Filters consist of a filter pattern followed by a filter command.
571 571 Filter patterns are globs by default, rooted at the repository root.
572 572 For example, to match any file ending in ``.txt`` in the root
573 573 directory only, use the pattern ``*.txt``. To match any file ending
574 574 in ``.c`` anywhere in the repository, use the pattern ``**.c``.
575 575 For each file only the first matching filter applies.
576 576
577 577 The filter command can start with a specifier, either ``pipe:`` or
578 578 ``tempfile:``. If no specifier is given, ``pipe:`` is used by default.
579 579
580 580 A ``pipe:`` command must accept data on stdin and return the transformed
581 581 data on stdout.
582 582
583 583 Pipe example::
584 584
585 585 [encode]
586 586 # uncompress gzip files on checkin to improve delta compression
587 587 # note: not necessarily a good idea, just an example
588 588 *.gz = pipe: gunzip
589 589
590 590 [decode]
591 591 # recompress gzip files when writing them to the working dir (we
592 592 # can safely omit "pipe:", because it's the default)
593 593 *.gz = gzip
594 594
595 595 A ``tempfile:`` command is a template. The string ``INFILE`` is replaced
596 596 with the name of a temporary file that contains the data to be
597 597 filtered by the command. The string ``OUTFILE`` is replaced with the name
598 598 of an empty temporary file, where the filtered data must be written by
599 599 the command.
600 600
601 601 .. container:: windows
602 602
603 603 .. note::
604 604
605 605 The tempfile mechanism is recommended for Windows systems,
606 606 where the standard shell I/O redirection operators often have
607 607 strange effects and may corrupt the contents of your files.
608 608
609 609 This filter mechanism is used internally by the ``eol`` extension to
610 610 translate line ending characters between Windows (CRLF) and Unix (LF)
611 611 format. We suggest you use the ``eol`` extension for convenience.
612 612
613 613
614 614 ``defaults``
615 615 ------------
616 616
617 617 (defaults are deprecated. Don't use them. Use aliases instead.)
618 618
619 619 Use the ``[defaults]`` section to define command defaults, i.e. the
620 620 default options/arguments to pass to the specified commands.
621 621
622 622 The following example makes :hg:`log` run in verbose mode, and
623 623 :hg:`status` show only the modified files, by default::
624 624
625 625 [defaults]
626 626 log = -v
627 627 status = -m
628 628
629 629 The actual commands, instead of their aliases, must be used when
630 630 defining command defaults. The command defaults will also be applied
631 631 to the aliases of the commands defined.
632 632
633 633
634 634 ``diff``
635 635 --------
636 636
637 637 Settings used when displaying diffs. Everything except for ``unified``
638 638 is a Boolean and defaults to False. See :hg:`help config.annotate`
639 639 for related options for the annotate command.
640 640
641 641 ``git``
642 642 Use git extended diff format.
643 643
644 644 ``nobinary``
645 645 Omit git binary patches.
646 646
647 647 ``nodates``
648 648 Don't include dates in diff headers.
649 649
650 650 ``noprefix``
651 651 Omit 'a/' and 'b/' prefixes from filenames. Ignored in plain mode.
652 652
653 653 ``showfunc``
654 654 Show which function each change is in.
655 655
656 656 ``ignorews``
657 657 Ignore white space when comparing lines.
658 658
659 659 ``ignorewsamount``
660 660 Ignore changes in the amount of white space.
661 661
662 662 ``ignoreblanklines``
663 663 Ignore changes whose lines are all blank.
664 664
665 665 ``unified``
666 666 Number of lines of context to show.
667 667
668 668 ``email``
669 669 ---------
670 670
671 671 Settings for extensions that send email messages.
672 672
673 673 ``from``
674 674 Optional. Email address to use in "From" header and SMTP envelope
675 675 of outgoing messages.
676 676
677 677 ``to``
678 678 Optional. Comma-separated list of recipients' email addresses.
679 679
680 680 ``cc``
681 681 Optional. Comma-separated list of carbon copy recipients'
682 682 email addresses.
683 683
684 684 ``bcc``
685 685 Optional. Comma-separated list of blind carbon copy recipients'
686 686 email addresses.
687 687
688 688 ``method``
689 689 Optional. Method to use to send email messages. If value is ``smtp``
690 690 (default), use SMTP (see the ``[smtp]`` section for configuration).
691 691 Otherwise, use as name of program to run that acts like sendmail
692 692 (takes ``-f`` option for sender, list of recipients on command line,
693 693 message on stdin). Normally, setting this to ``sendmail`` or
694 694 ``/usr/sbin/sendmail`` is enough to use sendmail to send messages.
695 695
696 696 ``charsets``
697 697 Optional. Comma-separated list of character sets considered
698 698 convenient for recipients. Addresses, headers, and parts not
699 699 containing patches of outgoing messages will be encoded in the
700 700 first character set to which conversion from local encoding
701 701 (``$HGENCODING``, ``ui.fallbackencoding``) succeeds. If correct
702 702 conversion fails, the text in question is sent as is.
703 703 (default: '')
704 704
705 705 Order of outgoing email character sets:
706 706
707 707 1. ``us-ascii``: always first, regardless of settings
708 708 2. ``email.charsets``: in order given by user
709 709 3. ``ui.fallbackencoding``: if not in email.charsets
710 710 4. ``$HGENCODING``: if not in email.charsets
711 711 5. ``utf-8``: always last, regardless of settings
712 712
713 713 Email example::
714 714
715 715 [email]
716 716 from = Joseph User <joe.user@example.com>
717 717 method = /usr/sbin/sendmail
718 718 # charsets for western Europeans
719 719 # us-ascii, utf-8 omitted, as they are tried first and last
720 720 charsets = iso-8859-1, iso-8859-15, windows-1252
721 721
722 722
723 723 ``extensions``
724 724 --------------
725 725
726 726 Mercurial has an extension mechanism for adding new features. To
727 727 enable an extension, create an entry for it in this section.
728 728
729 729 If you know that the extension is already in Python's search path,
730 730 you can give the name of the module, followed by ``=``, with nothing
731 731 after the ``=``.
732 732
733 733 Otherwise, give a name that you choose, followed by ``=``, followed by
734 734 the path to the ``.py`` file (including the file name extension) that
735 735 defines the extension.
736 736
737 737 To explicitly disable an extension that is enabled in an hgrc of
738 738 broader scope, prepend its path with ``!``, as in ``foo = !/ext/path``
739 739 or ``foo = !`` when path is not supplied.
740 740
741 741 Example for ``~/.hgrc``::
742 742
743 743 [extensions]
744 744 # (the churn extension will get loaded from Mercurial's path)
745 745 churn =
746 746 # (this extension will get loaded from the file specified)
747 747 myfeature = ~/.hgext/myfeature.py
748 748
749 749
750 750 ``format``
751 751 ----------
752 752
753 753 ``usegeneraldelta``
754 754 Enable or disable the "generaldelta" repository format which improves
755 755 repository compression by allowing "revlog" to store delta against arbitrary
756 756 revision instead of the previous stored one. This provides significant
757 757 improvement for repositories with branches.
758 758
759 759 Repositories with this on-disk format require Mercurial version 1.9.
760 760
761 761 Enabled by default.
762 762
763 763 ``dotencode``
764 764 Enable or disable the "dotencode" repository format which enhances
765 765 the "fncache" repository format (which has to be enabled to use
766 766 dotencode) to avoid issues with filenames starting with ._ on
767 767 Mac OS X and spaces on Windows.
768 768
769 769 Repositories with this on-disk format require Mercurial version 1.7.
770 770
771 771 Enabled by default.
772 772
773 773 ``usefncache``
774 774 Enable or disable the "fncache" repository format which enhances
775 775 the "store" repository format (which has to be enabled to use
776 776 fncache) to allow longer filenames and avoids using Windows
777 777 reserved names, e.g. "nul".
778 778
779 779 Repositories with this on-disk format require Mercurial version 1.1.
780 780
781 781 Enabled by default.
782 782
783 783 ``usestore``
784 784 Enable or disable the "store" repository format which improves
785 785 compatibility with systems that fold case or otherwise mangle
786 786 filenames. Disabling this option will allow you to store longer filenames
787 787 in some situations at the expense of compatibility.
788 788
789 789 Repositories with this on-disk format require Mercurial version 0.9.4.
790 790
791 791 Enabled by default.
792 792
793 793 ``graph``
794 794 ---------
795 795
796 796 Web graph view configuration. This section let you change graph
797 797 elements display properties by branches, for instance to make the
798 798 ``default`` branch stand out.
799 799
800 800 Each line has the following format::
801 801
802 802 <branch>.<argument> = <value>
803 803
804 804 where ``<branch>`` is the name of the branch being
805 805 customized. Example::
806 806
807 807 [graph]
808 808 # 2px width
809 809 default.width = 2
810 810 # red color
811 811 default.color = FF0000
812 812
813 813 Supported arguments:
814 814
815 815 ``width``
816 816 Set branch edges width in pixels.
817 817
818 818 ``color``
819 819 Set branch edges color in hexadecimal RGB notation.
820 820
821 821 ``hooks``
822 822 ---------
823 823
824 824 Commands or Python functions that get automatically executed by
825 825 various actions such as starting or finishing a commit. Multiple
826 826 hooks can be run for the same action by appending a suffix to the
827 827 action. Overriding a site-wide hook can be done by changing its
828 828 value or setting it to an empty string. Hooks can be prioritized
829 829 by adding a prefix of ``priority.`` to the hook name on a new line
830 830 and setting the priority. The default priority is 0.
831 831
832 832 Example ``.hg/hgrc``::
833 833
834 834 [hooks]
835 835 # update working directory after adding changesets
836 836 changegroup.update = hg update
837 837 # do not use the site-wide hook
838 838 incoming =
839 839 incoming.email = /my/email/hook
840 840 incoming.autobuild = /my/build/hook
841 841 # force autobuild hook to run before other incoming hooks
842 842 priority.incoming.autobuild = 1
843 843
844 844 Most hooks are run with environment variables set that give useful
845 845 additional information. For each hook below, the environment variables
846 846 it is passed are listed with names of the form ``$HG_foo``. The
847 ``$HG_HOOKTYPE`` variable is set for all hooks. It contains the type of
848 hook which triggered the run. In the example about this will be
849 ``$HG_HOOKTYPE=incoming``.
847 ``$HG_HOOKTYPE`` and ``$HG_HOOKNAME`` variables are set for all hooks.
848 their respectively contains the type of hook which triggered the run and
849 the full name of the hooks in the config. In the example about this will
850 be ``$HG_HOOKTYPE=incoming`` and ``$HG_HOOKNAME=incoming.email``.
850 851
851 852 ``changegroup``
852 853 Run after a changegroup has been added via push, pull or unbundle. ID of the
853 854 first new changeset is in ``$HG_NODE`` and last in ``$HG_NODE_LAST``. URL
854 855 from which changes came is in ``$HG_URL``.
855 856
856 857 ``commit``
857 858 Run after a changeset has been created in the local repository. ID
858 859 of the newly created changeset is in ``$HG_NODE``. Parent changeset
859 860 IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
860 861
861 862 ``incoming``
862 863 Run after a changeset has been pulled, pushed, or unbundled into
863 864 the local repository. The ID of the newly arrived changeset is in
864 865 ``$HG_NODE``. URL that was source of changes came is in ``$HG_URL``.
865 866
866 867 ``outgoing``
867 868 Run after sending changes from local repository to another. ID of
868 869 first changeset sent is in ``$HG_NODE``. Source of operation is in
869 870 ``$HG_SOURCE``; Also see :hg:`help config.hooks.preoutgoing` hook.
870 871
871 872 ``post-<command>``
872 873 Run after successful invocations of the associated command. The
873 874 contents of the command line are passed as ``$HG_ARGS`` and the result
874 875 code in ``$HG_RESULT``. Parsed command line arguments are passed as
875 876 ``$HG_PATS`` and ``$HG_OPTS``. These contain string representations of
876 877 the python data internally passed to <command>. ``$HG_OPTS`` is a
877 878 dictionary of options (with unspecified options set to their defaults).
878 879 ``$HG_PATS`` is a list of arguments. Hook failure is ignored.
879 880
880 881 ``fail-<command>``
881 882 Run after a failed invocation of an associated command. The contents
882 883 of the command line are passed as ``$HG_ARGS``. Parsed command line
883 884 arguments are passed as ``$HG_PATS`` and ``$HG_OPTS``. These contain
884 885 string representations of the python data internally passed to
885 886 <command>. ``$HG_OPTS`` is a dictionary of options (with unspecified
886 887 options set to their defaults). ``$HG_PATS`` is a list of arguments.
887 888 Hook failure is ignored.
888 889
889 890 ``pre-<command>``
890 891 Run before executing the associated command. The contents of the
891 892 command line are passed as ``$HG_ARGS``. Parsed command line arguments
892 893 are passed as ``$HG_PATS`` and ``$HG_OPTS``. These contain string
893 894 representations of the data internally passed to <command>. ``$HG_OPTS``
894 895 is a dictionary of options (with unspecified options set to their
895 896 defaults). ``$HG_PATS`` is a list of arguments. If the hook returns
896 897 failure, the command doesn't execute and Mercurial returns the failure
897 898 code.
898 899
899 900 ``prechangegroup``
900 901 Run before a changegroup is added via push, pull or unbundle. Exit
901 902 status 0 allows the changegroup to proceed. Non-zero status will
902 903 cause the push, pull or unbundle to fail. URL from which changes
903 904 will come is in ``$HG_URL``.
904 905
905 906 ``precommit``
906 907 Run before starting a local commit. Exit status 0 allows the
907 908 commit to proceed. Non-zero status will cause the commit to fail.
908 909 Parent changeset IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
909 910
910 911 ``prelistkeys``
911 912 Run before listing pushkeys (like bookmarks) in the
912 913 repository. Non-zero status will cause failure. The key namespace is
913 914 in ``$HG_NAMESPACE``.
914 915
915 916 ``preoutgoing``
916 917 Run before collecting changes to send from the local repository to
917 918 another. Non-zero status will cause failure. This lets you prevent
918 919 pull over HTTP or SSH. Also prevents against local pull, push
919 920 (outbound) or bundle commands, but not effective, since you can
920 921 just copy files instead then. Source of operation is in
921 922 ``$HG_SOURCE``. If "serve", operation is happening on behalf of remote
922 923 SSH or HTTP repository. If "push", "pull" or "bundle", operation
923 924 is happening on behalf of repository on same system.
924 925
925 926 ``prepushkey``
926 927 Run before a pushkey (like a bookmark) is added to the
927 928 repository. Non-zero status will cause the key to be rejected. The
928 929 key namespace is in ``$HG_NAMESPACE``, the key is in ``$HG_KEY``,
929 930 the old value (if any) is in ``$HG_OLD``, and the new value is in
930 931 ``$HG_NEW``.
931 932
932 933 ``pretag``
933 934 Run before creating a tag. Exit status 0 allows the tag to be
934 935 created. Non-zero status will cause the tag to fail. ID of
935 936 changeset to tag is in ``$HG_NODE``. Name of tag is in ``$HG_TAG``. Tag is
936 937 local if ``$HG_LOCAL=1``, in repository if ``$HG_LOCAL=0``.
937 938
938 939 ``pretxnopen``
939 940 Run before any new repository transaction is open. The reason for the
940 941 transaction will be in ``$HG_TXNNAME`` and a unique identifier for the
941 942 transaction will be in ``HG_TXNID``. A non-zero status will prevent the
942 943 transaction from being opened.
943 944
944 945 ``pretxnclose``
945 946 Run right before the transaction is actually finalized. Any repository change
946 947 will be visible to the hook program. This lets you validate the transaction
947 948 content or change it. Exit status 0 allows the commit to proceed. Non-zero
948 949 status will cause the transaction to be rolled back. The reason for the
949 950 transaction opening will be in ``$HG_TXNNAME`` and a unique identifier for
950 951 the transaction will be in ``HG_TXNID``. The rest of the available data will
951 952 vary according the transaction type. New changesets will add ``$HG_NODE`` (id
952 953 of the first added changeset), ``$HG_NODE_LAST`` (id of the last added
953 954 changeset), ``$HG_URL`` and ``$HG_SOURCE`` variables, bookmarks and phases
954 955 changes will set ``HG_BOOKMARK_MOVED`` and ``HG_PHASES_MOVED`` to ``1``, etc.
955 956
956 957 ``txnclose``
957 958 Run after any repository transaction has been committed. At this
958 959 point, the transaction can no longer be rolled back. The hook will run
959 960 after the lock is released. See :hg:`help config.hooks.pretxnclose` docs for
960 961 details about available variables.
961 962
962 963 ``txnabort``
963 964 Run when a transaction is aborted. See :hg:`help config.hooks.pretxnclose`
964 965 docs for details about available variables.
965 966
966 967 ``pretxnchangegroup``
967 968 Run after a changegroup has been added via push, pull or unbundle, but before
968 969 the transaction has been committed. Changegroup is visible to hook program.
969 970 This lets you validate incoming changes before accepting them. Passed the ID
970 971 of the first new changeset in ``$HG_NODE`` and last in ``$HG_NODE_LAST``.
971 972 Exit status 0 allows the transaction to commit. Non-zero status will cause
972 973 the transaction to be rolled back and the push, pull or unbundle will fail.
973 974 URL that was source of changes is in ``$HG_URL``.
974 975
975 976 ``pretxncommit``
976 977 Run after a changeset has been created but the transaction not yet
977 978 committed. Changeset is visible to hook program. This lets you
978 979 validate commit message and changes. Exit status 0 allows the
979 980 commit to proceed. Non-zero status will cause the transaction to
980 981 be rolled back. ID of changeset is in ``$HG_NODE``. Parent changeset
981 982 IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
982 983
983 984 ``preupdate``
984 985 Run before updating the working directory. Exit status 0 allows
985 986 the update to proceed. Non-zero status will prevent the update.
986 987 Changeset ID of first new parent is in ``$HG_PARENT1``. If merge, ID
987 988 of second new parent is in ``$HG_PARENT2``.
988 989
989 990 ``listkeys``
990 991 Run after listing pushkeys (like bookmarks) in the repository. The
991 992 key namespace is in ``$HG_NAMESPACE``. ``$HG_VALUES`` is a
992 993 dictionary containing the keys and values.
993 994
994 995 ``pushkey``
995 996 Run after a pushkey (like a bookmark) is added to the
996 997 repository. The key namespace is in ``$HG_NAMESPACE``, the key is in
997 998 ``$HG_KEY``, the old value (if any) is in ``$HG_OLD``, and the new
998 999 value is in ``$HG_NEW``.
999 1000
1000 1001 ``tag``
1001 1002 Run after a tag is created. ID of tagged changeset is in ``$HG_NODE``.
1002 1003 Name of tag is in ``$HG_TAG``. Tag is local if ``$HG_LOCAL=1``, in
1003 1004 repository if ``$HG_LOCAL=0``.
1004 1005
1005 1006 ``update``
1006 1007 Run after updating the working directory. Changeset ID of first
1007 1008 new parent is in ``$HG_PARENT1``. If merge, ID of second new parent is
1008 1009 in ``$HG_PARENT2``. If the update succeeded, ``$HG_ERROR=0``. If the
1009 1010 update failed (e.g. because conflicts not resolved), ``$HG_ERROR=1``.
1010 1011
1011 1012 .. note::
1012 1013
1013 1014 It is generally better to use standard hooks rather than the
1014 1015 generic pre- and post- command hooks as they are guaranteed to be
1015 1016 called in the appropriate contexts for influencing transactions.
1016 1017 Also, hooks like "commit" will be called in all contexts that
1017 1018 generate a commit (e.g. tag) and not just the commit command.
1018 1019
1019 1020 .. note::
1020 1021
1021 1022 Environment variables with empty values may not be passed to
1022 1023 hooks on platforms such as Windows. As an example, ``$HG_PARENT2``
1023 1024 will have an empty value under Unix-like platforms for non-merge
1024 1025 changesets, while it will not be available at all under Windows.
1025 1026
1026 1027 The syntax for Python hooks is as follows::
1027 1028
1028 1029 hookname = python:modulename.submodule.callable
1029 1030 hookname = python:/path/to/python/module.py:callable
1030 1031
1031 1032 Python hooks are run within the Mercurial process. Each hook is
1032 1033 called with at least three keyword arguments: a ui object (keyword
1033 1034 ``ui``), a repository object (keyword ``repo``), and a ``hooktype``
1034 1035 keyword that tells what kind of hook is used. Arguments listed as
1035 1036 environment variables above are passed as keyword arguments, with no
1036 1037 ``HG_`` prefix, and names in lower case.
1037 1038
1038 1039 If a Python hook returns a "true" value or raises an exception, this
1039 1040 is treated as a failure.
1040 1041
1041 1042
1042 1043 ``hostfingerprints``
1043 1044 --------------------
1044 1045
1045 1046 (Deprecated. Use ``[hostsecurity]``'s ``fingerprints`` options instead.)
1046 1047
1047 1048 Fingerprints of the certificates of known HTTPS servers.
1048 1049
1049 1050 A HTTPS connection to a server with a fingerprint configured here will
1050 1051 only succeed if the servers certificate matches the fingerprint.
1051 1052 This is very similar to how ssh known hosts works.
1052 1053
1053 1054 The fingerprint is the SHA-1 hash value of the DER encoded certificate.
1054 1055 Multiple values can be specified (separated by spaces or commas). This can
1055 1056 be used to define both old and new fingerprints while a host transitions
1056 1057 to a new certificate.
1057 1058
1058 1059 The CA chain and web.cacerts is not used for servers with a fingerprint.
1059 1060
1060 1061 For example::
1061 1062
1062 1063 [hostfingerprints]
1063 1064 hg.intevation.de = fc:e2:8d:d9:51:cd:cb:c1:4d:18:6b:b7:44:8d:49:72:57:e6:cd:33
1064 1065 hg.intevation.org = fc:e2:8d:d9:51:cd:cb:c1:4d:18:6b:b7:44:8d:49:72:57:e6:cd:33
1065 1066
1066 1067 ``hostsecurity``
1067 1068 ----------------
1068 1069
1069 1070 Used to specify global and per-host security settings for connecting to
1070 1071 other machines.
1071 1072
1072 1073 The following options control default behavior for all hosts.
1073 1074
1074 1075 ``ciphers``
1075 1076 Defines the cryptographic ciphers to use for connections.
1076 1077
1077 1078 Value must be a valid OpenSSL Cipher List Format as documented at
1078 1079 https://www.openssl.org/docs/manmaster/apps/ciphers.html#CIPHER-LIST-FORMAT.
1079 1080
1080 1081 This setting is for advanced users only. Setting to incorrect values
1081 1082 can significantly lower connection security or decrease performance.
1082 1083 You have been warned.
1083 1084
1084 1085 This option requires Python 2.7.
1085 1086
1086 1087 ``minimumprotocol``
1087 1088 Defines the minimum channel encryption protocol to use.
1088 1089
1089 1090 By default, the highest version of TLS supported by both client and server
1090 1091 is used.
1091 1092
1092 1093 Allowed values are: ``tls1.0``, ``tls1.1``, ``tls1.2``.
1093 1094
1094 1095 When running on an old Python version, only ``tls1.0`` is allowed since
1095 1096 old versions of Python only support up to TLS 1.0.
1096 1097
1097 1098 When running a Python that supports modern TLS versions, the default is
1098 1099 ``tls1.1``. ``tls1.0`` can still be used to allow TLS 1.0. However, this
1099 1100 weakens security and should only be used as a feature of last resort if
1100 1101 a server does not support TLS 1.1+.
1101 1102
1102 1103 Options in the ``[hostsecurity]`` section can have the form
1103 1104 ``hostname``:``setting``. This allows multiple settings to be defined on a
1104 1105 per-host basis.
1105 1106
1106 1107 The following per-host settings can be defined.
1107 1108
1108 1109 ``ciphers``
1109 1110 This behaves like ``ciphers`` as described above except it only applies
1110 1111 to the host on which it is defined.
1111 1112
1112 1113 ``fingerprints``
1113 1114 A list of hashes of the DER encoded peer/remote certificate. Values have
1114 1115 the form ``algorithm``:``fingerprint``. e.g.
1115 1116 ``sha256:c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2``.
1116 1117
1117 1118 The following algorithms/prefixes are supported: ``sha1``, ``sha256``,
1118 1119 ``sha512``.
1119 1120
1120 1121 Use of ``sha256`` or ``sha512`` is preferred.
1121 1122
1122 1123 If a fingerprint is specified, the CA chain is not validated for this
1123 1124 host and Mercurial will require the remote certificate to match one
1124 1125 of the fingerprints specified. This means if the server updates its
1125 1126 certificate, Mercurial will abort until a new fingerprint is defined.
1126 1127 This can provide stronger security than traditional CA-based validation
1127 1128 at the expense of convenience.
1128 1129
1129 1130 This option takes precedence over ``verifycertsfile``.
1130 1131
1131 1132 ``minimumprotocol``
1132 1133 This behaves like ``minimumprotocol`` as described above except it
1133 1134 only applies to the host on which it is defined.
1134 1135
1135 1136 ``verifycertsfile``
1136 1137 Path to file a containing a list of PEM encoded certificates used to
1137 1138 verify the server certificate. Environment variables and ``~user``
1138 1139 constructs are expanded in the filename.
1139 1140
1140 1141 The server certificate or the certificate's certificate authority (CA)
1141 1142 must match a certificate from this file or certificate verification
1142 1143 will fail and connections to the server will be refused.
1143 1144
1144 1145 If defined, only certificates provided by this file will be used:
1145 1146 ``web.cacerts`` and any system/default certificates will not be
1146 1147 used.
1147 1148
1148 1149 This option has no effect if the per-host ``fingerprints`` option
1149 1150 is set.
1150 1151
1151 1152 The format of the file is as follows::
1152 1153
1153 1154 -----BEGIN CERTIFICATE-----
1154 1155 ... (certificate in base64 PEM encoding) ...
1155 1156 -----END CERTIFICATE-----
1156 1157 -----BEGIN CERTIFICATE-----
1157 1158 ... (certificate in base64 PEM encoding) ...
1158 1159 -----END CERTIFICATE-----
1159 1160
1160 1161 For example::
1161 1162
1162 1163 [hostsecurity]
1163 1164 hg.example.com:fingerprints = sha256:c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2
1164 1165 hg2.example.com:fingerprints = sha1:914f1aff87249c09b6859b88b1906d30756491ca, sha1:fc:e2:8d:d9:51:cd:cb:c1:4d:18:6b:b7:44:8d:49:72:57:e6:cd:33
1165 1166 foo.example.com:verifycertsfile = /etc/ssl/trusted-ca-certs.pem
1166 1167
1167 1168 To change the default minimum protocol version to TLS 1.2 but to allow TLS 1.1
1168 1169 when connecting to ``hg.example.com``::
1169 1170
1170 1171 [hostsecurity]
1171 1172 minimumprotocol = tls1.2
1172 1173 hg.example.com:minimumprotocol = tls1.1
1173 1174
1174 1175 ``http_proxy``
1175 1176 --------------
1176 1177
1177 1178 Used to access web-based Mercurial repositories through a HTTP
1178 1179 proxy.
1179 1180
1180 1181 ``host``
1181 1182 Host name and (optional) port of the proxy server, for example
1182 1183 "myproxy:8000".
1183 1184
1184 1185 ``no``
1185 1186 Optional. Comma-separated list of host names that should bypass
1186 1187 the proxy.
1187 1188
1188 1189 ``passwd``
1189 1190 Optional. Password to authenticate with at the proxy server.
1190 1191
1191 1192 ``user``
1192 1193 Optional. User name to authenticate with at the proxy server.
1193 1194
1194 1195 ``always``
1195 1196 Optional. Always use the proxy, even for localhost and any entries
1196 1197 in ``http_proxy.no``. (default: False)
1197 1198
1198 1199 ``merge``
1199 1200 ---------
1200 1201
1201 1202 This section specifies behavior during merges and updates.
1202 1203
1203 1204 ``checkignored``
1204 1205 Controls behavior when an ignored file on disk has the same name as a tracked
1205 1206 file in the changeset being merged or updated to, and has different
1206 1207 contents. Options are ``abort``, ``warn`` and ``ignore``. With ``abort``,
1207 1208 abort on such files. With ``warn``, warn on such files and back them up as
1208 1209 ``.orig``. With ``ignore``, don't print a warning and back them up as
1209 1210 ``.orig``. (default: ``abort``)
1210 1211
1211 1212 ``checkunknown``
1212 1213 Controls behavior when an unknown file that isn't ignored has the same name
1213 1214 as a tracked file in the changeset being merged or updated to, and has
1214 1215 different contents. Similar to ``merge.checkignored``, except for files that
1215 1216 are not ignored. (default: ``abort``)
1216 1217
1217 1218 ``merge-patterns``
1218 1219 ------------------
1219 1220
1220 1221 This section specifies merge tools to associate with particular file
1221 1222 patterns. Tools matched here will take precedence over the default
1222 1223 merge tool. Patterns are globs by default, rooted at the repository
1223 1224 root.
1224 1225
1225 1226 Example::
1226 1227
1227 1228 [merge-patterns]
1228 1229 **.c = kdiff3
1229 1230 **.jpg = myimgmerge
1230 1231
1231 1232 ``merge-tools``
1232 1233 ---------------
1233 1234
1234 1235 This section configures external merge tools to use for file-level
1235 1236 merges. This section has likely been preconfigured at install time.
1236 1237 Use :hg:`config merge-tools` to check the existing configuration.
1237 1238 Also see :hg:`help merge-tools` for more details.
1238 1239
1239 1240 Example ``~/.hgrc``::
1240 1241
1241 1242 [merge-tools]
1242 1243 # Override stock tool location
1243 1244 kdiff3.executable = ~/bin/kdiff3
1244 1245 # Specify command line
1245 1246 kdiff3.args = $base $local $other -o $output
1246 1247 # Give higher priority
1247 1248 kdiff3.priority = 1
1248 1249
1249 1250 # Changing the priority of preconfigured tool
1250 1251 meld.priority = 0
1251 1252
1252 1253 # Disable a preconfigured tool
1253 1254 vimdiff.disabled = yes
1254 1255
1255 1256 # Define new tool
1256 1257 myHtmlTool.args = -m $local $other $base $output
1257 1258 myHtmlTool.regkey = Software\FooSoftware\HtmlMerge
1258 1259 myHtmlTool.priority = 1
1259 1260
1260 1261 Supported arguments:
1261 1262
1262 1263 ``priority``
1263 1264 The priority in which to evaluate this tool.
1264 1265 (default: 0)
1265 1266
1266 1267 ``executable``
1267 1268 Either just the name of the executable or its pathname.
1268 1269
1269 1270 .. container:: windows
1270 1271
1271 1272 On Windows, the path can use environment variables with ${ProgramFiles}
1272 1273 syntax.
1273 1274
1274 1275 (default: the tool name)
1275 1276
1276 1277 ``args``
1277 1278 The arguments to pass to the tool executable. You can refer to the
1278 1279 files being merged as well as the output file through these
1279 1280 variables: ``$base``, ``$local``, ``$other``, ``$output``. The meaning
1280 1281 of ``$local`` and ``$other`` can vary depending on which action is being
1281 1282 performed. During and update or merge, ``$local`` represents the original
1282 1283 state of the file, while ``$other`` represents the commit you are updating
1283 1284 to or the commit you are merging with. During a rebase ``$local``
1284 1285 represents the destination of the rebase, and ``$other`` represents the
1285 1286 commit being rebased.
1286 1287 (default: ``$local $base $other``)
1287 1288
1288 1289 ``premerge``
1289 1290 Attempt to run internal non-interactive 3-way merge tool before
1290 1291 launching external tool. Options are ``true``, ``false``, ``keep`` or
1291 1292 ``keep-merge3``. The ``keep`` option will leave markers in the file if the
1292 1293 premerge fails. The ``keep-merge3`` will do the same but include information
1293 1294 about the base of the merge in the marker (see internal :merge3 in
1294 1295 :hg:`help merge-tools`).
1295 1296 (default: True)
1296 1297
1297 1298 ``binary``
1298 1299 This tool can merge binary files. (default: False, unless tool
1299 1300 was selected by file pattern match)
1300 1301
1301 1302 ``symlink``
1302 1303 This tool can merge symlinks. (default: False)
1303 1304
1304 1305 ``check``
1305 1306 A list of merge success-checking options:
1306 1307
1307 1308 ``changed``
1308 1309 Ask whether merge was successful when the merged file shows no changes.
1309 1310 ``conflicts``
1310 1311 Check whether there are conflicts even though the tool reported success.
1311 1312 ``prompt``
1312 1313 Always prompt for merge success, regardless of success reported by tool.
1313 1314
1314 1315 ``fixeol``
1315 1316 Attempt to fix up EOL changes caused by the merge tool.
1316 1317 (default: False)
1317 1318
1318 1319 ``gui``
1319 1320 This tool requires a graphical interface to run. (default: False)
1320 1321
1321 1322 .. container:: windows
1322 1323
1323 1324 ``regkey``
1324 1325 Windows registry key which describes install location of this
1325 1326 tool. Mercurial will search for this key first under
1326 1327 ``HKEY_CURRENT_USER`` and then under ``HKEY_LOCAL_MACHINE``.
1327 1328 (default: None)
1328 1329
1329 1330 ``regkeyalt``
1330 1331 An alternate Windows registry key to try if the first key is not
1331 1332 found. The alternate key uses the same ``regname`` and ``regappend``
1332 1333 semantics of the primary key. The most common use for this key
1333 1334 is to search for 32bit applications on 64bit operating systems.
1334 1335 (default: None)
1335 1336
1336 1337 ``regname``
1337 1338 Name of value to read from specified registry key.
1338 1339 (default: the unnamed (default) value)
1339 1340
1340 1341 ``regappend``
1341 1342 String to append to the value read from the registry, typically
1342 1343 the executable name of the tool.
1343 1344 (default: None)
1344 1345
1345 1346
1346 1347 ``patch``
1347 1348 ---------
1348 1349
1349 1350 Settings used when applying patches, for instance through the 'import'
1350 1351 command or with Mercurial Queues extension.
1351 1352
1352 1353 ``eol``
1353 1354 When set to 'strict' patch content and patched files end of lines
1354 1355 are preserved. When set to ``lf`` or ``crlf``, both files end of
1355 1356 lines are ignored when patching and the result line endings are
1356 1357 normalized to either LF (Unix) or CRLF (Windows). When set to
1357 1358 ``auto``, end of lines are again ignored while patching but line
1358 1359 endings in patched files are normalized to their original setting
1359 1360 on a per-file basis. If target file does not exist or has no end
1360 1361 of line, patch line endings are preserved.
1361 1362 (default: strict)
1362 1363
1363 1364 ``fuzz``
1364 1365 The number of lines of 'fuzz' to allow when applying patches. This
1365 1366 controls how much context the patcher is allowed to ignore when
1366 1367 trying to apply a patch.
1367 1368 (default: 2)
1368 1369
1369 1370 ``paths``
1370 1371 ---------
1371 1372
1372 1373 Assigns symbolic names and behavior to repositories.
1373 1374
1374 1375 Options are symbolic names defining the URL or directory that is the
1375 1376 location of the repository. Example::
1376 1377
1377 1378 [paths]
1378 1379 my_server = https://example.com/my_repo
1379 1380 local_path = /home/me/repo
1380 1381
1381 1382 These symbolic names can be used from the command line. To pull
1382 1383 from ``my_server``: :hg:`pull my_server`. To push to ``local_path``:
1383 1384 :hg:`push local_path`.
1384 1385
1385 1386 Options containing colons (``:``) denote sub-options that can influence
1386 1387 behavior for that specific path. Example::
1387 1388
1388 1389 [paths]
1389 1390 my_server = https://example.com/my_path
1390 1391 my_server:pushurl = ssh://example.com/my_path
1391 1392
1392 1393 The following sub-options can be defined:
1393 1394
1394 1395 ``pushurl``
1395 1396 The URL to use for push operations. If not defined, the location
1396 1397 defined by the path's main entry is used.
1397 1398
1398 1399 ``pushrev``
1399 1400 A revset defining which revisions to push by default.
1400 1401
1401 1402 When :hg:`push` is executed without a ``-r`` argument, the revset
1402 1403 defined by this sub-option is evaluated to determine what to push.
1403 1404
1404 1405 For example, a value of ``.`` will push the working directory's
1405 1406 revision by default.
1406 1407
1407 1408 Revsets specifying bookmarks will not result in the bookmark being
1408 1409 pushed.
1409 1410
1410 1411 The following special named paths exist:
1411 1412
1412 1413 ``default``
1413 1414 The URL or directory to use when no source or remote is specified.
1414 1415
1415 1416 :hg:`clone` will automatically define this path to the location the
1416 1417 repository was cloned from.
1417 1418
1418 1419 ``default-push``
1419 1420 (deprecated) The URL or directory for the default :hg:`push` location.
1420 1421 ``default:pushurl`` should be used instead.
1421 1422
1422 1423 ``phases``
1423 1424 ----------
1424 1425
1425 1426 Specifies default handling of phases. See :hg:`help phases` for more
1426 1427 information about working with phases.
1427 1428
1428 1429 ``publish``
1429 1430 Controls draft phase behavior when working as a server. When true,
1430 1431 pushed changesets are set to public in both client and server and
1431 1432 pulled or cloned changesets are set to public in the client.
1432 1433 (default: True)
1433 1434
1434 1435 ``new-commit``
1435 1436 Phase of newly-created commits.
1436 1437 (default: draft)
1437 1438
1438 1439 ``checksubrepos``
1439 1440 Check the phase of the current revision of each subrepository. Allowed
1440 1441 values are "ignore", "follow" and "abort". For settings other than
1441 1442 "ignore", the phase of the current revision of each subrepository is
1442 1443 checked before committing the parent repository. If any of those phases is
1443 1444 greater than the phase of the parent repository (e.g. if a subrepo is in a
1444 1445 "secret" phase while the parent repo is in "draft" phase), the commit is
1445 1446 either aborted (if checksubrepos is set to "abort") or the higher phase is
1446 1447 used for the parent repository commit (if set to "follow").
1447 1448 (default: follow)
1448 1449
1449 1450
1450 1451 ``profiling``
1451 1452 -------------
1452 1453
1453 1454 Specifies profiling type, format, and file output. Two profilers are
1454 1455 supported: an instrumenting profiler (named ``ls``), and a sampling
1455 1456 profiler (named ``stat``).
1456 1457
1457 1458 In this section description, 'profiling data' stands for the raw data
1458 1459 collected during profiling, while 'profiling report' stands for a
1459 1460 statistical text report generated from the profiling data. The
1460 1461 profiling is done using lsprof.
1461 1462
1462 1463 ``enabled``
1463 1464 Enable the profiler.
1464 1465 (default: false)
1465 1466
1466 1467 This is equivalent to passing ``--profile`` on the command line.
1467 1468
1468 1469 ``type``
1469 1470 The type of profiler to use.
1470 1471 (default: stat)
1471 1472
1472 1473 ``ls``
1473 1474 Use Python's built-in instrumenting profiler. This profiler
1474 1475 works on all platforms, but each line number it reports is the
1475 1476 first line of a function. This restriction makes it difficult to
1476 1477 identify the expensive parts of a non-trivial function.
1477 1478 ``stat``
1478 1479 Use a statistical profiler, statprof. This profiler is most
1479 1480 useful for profiling commands that run for longer than about 0.1
1480 1481 seconds.
1481 1482
1482 1483 ``format``
1483 1484 Profiling format. Specific to the ``ls`` instrumenting profiler.
1484 1485 (default: text)
1485 1486
1486 1487 ``text``
1487 1488 Generate a profiling report. When saving to a file, it should be
1488 1489 noted that only the report is saved, and the profiling data is
1489 1490 not kept.
1490 1491 ``kcachegrind``
1491 1492 Format profiling data for kcachegrind use: when saving to a
1492 1493 file, the generated file can directly be loaded into
1493 1494 kcachegrind.
1494 1495
1495 1496 ``statformat``
1496 1497 Profiling format for the ``stat`` profiler.
1497 1498 (default: hotpath)
1498 1499
1499 1500 ``hotpath``
1500 1501 Show a tree-based display containing the hot path of execution (where
1501 1502 most time was spent).
1502 1503 ``bymethod``
1503 1504 Show a table of methods ordered by how frequently they are active.
1504 1505 ``byline``
1505 1506 Show a table of lines in files ordered by how frequently they are active.
1506 1507 ``json``
1507 1508 Render profiling data as JSON.
1508 1509
1509 1510 ``frequency``
1510 1511 Sampling frequency. Specific to the ``stat`` sampling profiler.
1511 1512 (default: 1000)
1512 1513
1513 1514 ``output``
1514 1515 File path where profiling data or report should be saved. If the
1515 1516 file exists, it is replaced. (default: None, data is printed on
1516 1517 stderr)
1517 1518
1518 1519 ``sort``
1519 1520 Sort field. Specific to the ``ls`` instrumenting profiler.
1520 1521 One of ``callcount``, ``reccallcount``, ``totaltime`` and
1521 1522 ``inlinetime``.
1522 1523 (default: inlinetime)
1523 1524
1524 1525 ``limit``
1525 1526 Number of lines to show. Specific to the ``ls`` instrumenting profiler.
1526 1527 (default: 30)
1527 1528
1528 1529 ``nested``
1529 1530 Show at most this number of lines of drill-down info after each main entry.
1530 1531 This can help explain the difference between Total and Inline.
1531 1532 Specific to the ``ls`` instrumenting profiler.
1532 1533 (default: 5)
1533 1534
1534 1535 ``progress``
1535 1536 ------------
1536 1537
1537 1538 Mercurial commands can draw progress bars that are as informative as
1538 1539 possible. Some progress bars only offer indeterminate information, while others
1539 1540 have a definite end point.
1540 1541
1541 1542 ``delay``
1542 1543 Number of seconds (float) before showing the progress bar. (default: 3)
1543 1544
1544 1545 ``changedelay``
1545 1546 Minimum delay before showing a new topic. When set to less than 3 * refresh,
1546 1547 that value will be used instead. (default: 1)
1547 1548
1548 1549 ``refresh``
1549 1550 Time in seconds between refreshes of the progress bar. (default: 0.1)
1550 1551
1551 1552 ``format``
1552 1553 Format of the progress bar.
1553 1554
1554 1555 Valid entries for the format field are ``topic``, ``bar``, ``number``,
1555 1556 ``unit``, ``estimate``, ``speed``, and ``item``. ``item`` defaults to the
1556 1557 last 20 characters of the item, but this can be changed by adding either
1557 1558 ``-<num>`` which would take the last num characters, or ``+<num>`` for the
1558 1559 first num characters.
1559 1560
1560 1561 (default: topic bar number estimate)
1561 1562
1562 1563 ``width``
1563 1564 If set, the maximum width of the progress information (that is, min(width,
1564 1565 term width) will be used).
1565 1566
1566 1567 ``clear-complete``
1567 1568 Clear the progress bar after it's done. (default: True)
1568 1569
1569 1570 ``disable``
1570 1571 If true, don't show a progress bar.
1571 1572
1572 1573 ``assume-tty``
1573 1574 If true, ALWAYS show a progress bar, unless disable is given.
1574 1575
1575 1576 ``rebase``
1576 1577 ----------
1577 1578
1578 1579 ``allowdivergence``
1579 1580 Default to False, when True allow creating divergence when performing
1580 1581 rebase of obsolete changesets.
1581 1582
1582 1583 ``revsetalias``
1583 1584 ---------------
1584 1585
1585 1586 Alias definitions for revsets. See :hg:`help revsets` for details.
1586 1587
1587 1588 ``server``
1588 1589 ----------
1589 1590
1590 1591 Controls generic server settings.
1591 1592
1592 1593 ``compressionengines``
1593 1594 List of compression engines and their relative priority to advertise
1594 1595 to clients.
1595 1596
1596 1597 The order of compression engines determines their priority, the first
1597 1598 having the highest priority. If a compression engine is not listed
1598 1599 here, it won't be advertised to clients.
1599 1600
1600 1601 If not set (the default), built-in defaults are used. Run
1601 1602 :hg:`debuginstall` to list available compression engines and their
1602 1603 default wire protocol priority.
1603 1604
1604 1605 Older Mercurial clients only support zlib compression and this setting
1605 1606 has no effect for legacy clients.
1606 1607
1607 1608 ``uncompressed``
1608 1609 Whether to allow clients to clone a repository using the
1609 1610 uncompressed streaming protocol. This transfers about 40% more
1610 1611 data than a regular clone, but uses less memory and CPU on both
1611 1612 server and client. Over a LAN (100 Mbps or better) or a very fast
1612 1613 WAN, an uncompressed streaming clone is a lot faster (~10x) than a
1613 1614 regular clone. Over most WAN connections (anything slower than
1614 1615 about 6 Mbps), uncompressed streaming is slower, because of the
1615 1616 extra data transfer overhead. This mode will also temporarily hold
1616 1617 the write lock while determining what data to transfer.
1617 1618 (default: True)
1618 1619
1619 1620 ``preferuncompressed``
1620 1621 When set, clients will try to use the uncompressed streaming
1621 1622 protocol. (default: False)
1622 1623
1623 1624 ``validate``
1624 1625 Whether to validate the completeness of pushed changesets by
1625 1626 checking that all new file revisions specified in manifests are
1626 1627 present. (default: False)
1627 1628
1628 1629 ``maxhttpheaderlen``
1629 1630 Instruct HTTP clients not to send request headers longer than this
1630 1631 many bytes. (default: 1024)
1631 1632
1632 1633 ``bundle1``
1633 1634 Whether to allow clients to push and pull using the legacy bundle1
1634 1635 exchange format. (default: True)
1635 1636
1636 1637 ``bundle1gd``
1637 1638 Like ``bundle1`` but only used if the repository is using the
1638 1639 *generaldelta* storage format. (default: True)
1639 1640
1640 1641 ``bundle1.push``
1641 1642 Whether to allow clients to push using the legacy bundle1 exchange
1642 1643 format. (default: True)
1643 1644
1644 1645 ``bundle1gd.push``
1645 1646 Like ``bundle1.push`` but only used if the repository is using the
1646 1647 *generaldelta* storage format. (default: True)
1647 1648
1648 1649 ``bundle1.pull``
1649 1650 Whether to allow clients to pull using the legacy bundle1 exchange
1650 1651 format. (default: True)
1651 1652
1652 1653 ``bundle1gd.pull``
1653 1654 Like ``bundle1.pull`` but only used if the repository is using the
1654 1655 *generaldelta* storage format. (default: True)
1655 1656
1656 1657 Large repositories using the *generaldelta* storage format should
1657 1658 consider setting this option because converting *generaldelta*
1658 1659 repositories to the exchange format required by the bundle1 data
1659 1660 format can consume a lot of CPU.
1660 1661
1661 1662 ``zliblevel``
1662 1663 Integer between ``-1`` and ``9`` that controls the zlib compression level
1663 1664 for wire protocol commands that send zlib compressed output (notably the
1664 1665 commands that send repository history data).
1665 1666
1666 1667 The default (``-1``) uses the default zlib compression level, which is
1667 1668 likely equivalent to ``6``. ``0`` means no compression. ``9`` means
1668 1669 maximum compression.
1669 1670
1670 1671 Setting this option allows server operators to make trade-offs between
1671 1672 bandwidth and CPU used. Lowering the compression lowers CPU utilization
1672 1673 but sends more bytes to clients.
1673 1674
1674 1675 This option only impacts the HTTP server.
1675 1676
1676 1677 ``zstdlevel``
1677 1678 Integer between ``1`` and ``22`` that controls the zstd compression level
1678 1679 for wire protocol commands. ``1`` is the minimal amount of compression and
1679 1680 ``22`` is the highest amount of compression.
1680 1681
1681 1682 The default (``3``) should be significantly faster than zlib while likely
1682 1683 delivering better compression ratios.
1683 1684
1684 1685 This option only impacts the HTTP server.
1685 1686
1686 1687 See also ``server.zliblevel``.
1687 1688
1688 1689 ``smtp``
1689 1690 --------
1690 1691
1691 1692 Configuration for extensions that need to send email messages.
1692 1693
1693 1694 ``host``
1694 1695 Host name of mail server, e.g. "mail.example.com".
1695 1696
1696 1697 ``port``
1697 1698 Optional. Port to connect to on mail server. (default: 465 if
1698 1699 ``tls`` is smtps; 25 otherwise)
1699 1700
1700 1701 ``tls``
1701 1702 Optional. Method to enable TLS when connecting to mail server: starttls,
1702 1703 smtps or none. (default: none)
1703 1704
1704 1705 ``username``
1705 1706 Optional. User name for authenticating with the SMTP server.
1706 1707 (default: None)
1707 1708
1708 1709 ``password``
1709 1710 Optional. Password for authenticating with the SMTP server. If not
1710 1711 specified, interactive sessions will prompt the user for a
1711 1712 password; non-interactive sessions will fail. (default: None)
1712 1713
1713 1714 ``local_hostname``
1714 1715 Optional. The hostname that the sender can use to identify
1715 1716 itself to the MTA.
1716 1717
1717 1718
1718 1719 ``subpaths``
1719 1720 ------------
1720 1721
1721 1722 Subrepository source URLs can go stale if a remote server changes name
1722 1723 or becomes temporarily unavailable. This section lets you define
1723 1724 rewrite rules of the form::
1724 1725
1725 1726 <pattern> = <replacement>
1726 1727
1727 1728 where ``pattern`` is a regular expression matching a subrepository
1728 1729 source URL and ``replacement`` is the replacement string used to
1729 1730 rewrite it. Groups can be matched in ``pattern`` and referenced in
1730 1731 ``replacements``. For instance::
1731 1732
1732 1733 http://server/(.*)-hg/ = http://hg.server/\1/
1733 1734
1734 1735 rewrites ``http://server/foo-hg/`` into ``http://hg.server/foo/``.
1735 1736
1736 1737 Relative subrepository paths are first made absolute, and the
1737 1738 rewrite rules are then applied on the full (absolute) path. If ``pattern``
1738 1739 doesn't match the full path, an attempt is made to apply it on the
1739 1740 relative path alone. The rules are applied in definition order.
1740 1741
1741 1742 ``templatealias``
1742 1743 -----------------
1743 1744
1744 1745 Alias definitions for templates. See :hg:`help templates` for details.
1745 1746
1746 1747 ``templates``
1747 1748 -------------
1748 1749
1749 1750 Use the ``[templates]`` section to define template strings.
1750 1751 See :hg:`help templates` for details.
1751 1752
1752 1753 ``trusted``
1753 1754 -----------
1754 1755
1755 1756 Mercurial will not use the settings in the
1756 1757 ``.hg/hgrc`` file from a repository if it doesn't belong to a trusted
1757 1758 user or to a trusted group, as various hgrc features allow arbitrary
1758 1759 commands to be run. This issue is often encountered when configuring
1759 1760 hooks or extensions for shared repositories or servers. However,
1760 1761 the web interface will use some safe settings from the ``[web]``
1761 1762 section.
1762 1763
1763 1764 This section specifies what users and groups are trusted. The
1764 1765 current user is always trusted. To trust everybody, list a user or a
1765 1766 group with name ``*``. These settings must be placed in an
1766 1767 *already-trusted file* to take effect, such as ``$HOME/.hgrc`` of the
1767 1768 user or service running Mercurial.
1768 1769
1769 1770 ``users``
1770 1771 Comma-separated list of trusted users.
1771 1772
1772 1773 ``groups``
1773 1774 Comma-separated list of trusted groups.
1774 1775
1775 1776
1776 1777 ``ui``
1777 1778 ------
1778 1779
1779 1780 User interface controls.
1780 1781
1781 1782 ``archivemeta``
1782 1783 Whether to include the .hg_archival.txt file containing meta data
1783 1784 (hashes for the repository base and for tip) in archives created
1784 1785 by the :hg:`archive` command or downloaded via hgweb.
1785 1786 (default: True)
1786 1787
1787 1788 ``askusername``
1788 1789 Whether to prompt for a username when committing. If True, and
1789 1790 neither ``$HGUSER`` nor ``$EMAIL`` has been specified, then the user will
1790 1791 be prompted to enter a username. If no username is entered, the
1791 1792 default ``USER@HOST`` is used instead.
1792 1793 (default: False)
1793 1794
1794 1795 ``clonebundles``
1795 1796 Whether the "clone bundles" feature is enabled.
1796 1797
1797 1798 When enabled, :hg:`clone` may download and apply a server-advertised
1798 1799 bundle file from a URL instead of using the normal exchange mechanism.
1799 1800
1800 1801 This can likely result in faster and more reliable clones.
1801 1802
1802 1803 (default: True)
1803 1804
1804 1805 ``clonebundlefallback``
1805 1806 Whether failure to apply an advertised "clone bundle" from a server
1806 1807 should result in fallback to a regular clone.
1807 1808
1808 1809 This is disabled by default because servers advertising "clone
1809 1810 bundles" often do so to reduce server load. If advertised bundles
1810 1811 start mass failing and clients automatically fall back to a regular
1811 1812 clone, this would add significant and unexpected load to the server
1812 1813 since the server is expecting clone operations to be offloaded to
1813 1814 pre-generated bundles. Failing fast (the default behavior) ensures
1814 1815 clients don't overwhelm the server when "clone bundle" application
1815 1816 fails.
1816 1817
1817 1818 (default: False)
1818 1819
1819 1820 ``clonebundleprefers``
1820 1821 Defines preferences for which "clone bundles" to use.
1821 1822
1822 1823 Servers advertising "clone bundles" may advertise multiple available
1823 1824 bundles. Each bundle may have different attributes, such as the bundle
1824 1825 type and compression format. This option is used to prefer a particular
1825 1826 bundle over another.
1826 1827
1827 1828 The following keys are defined by Mercurial:
1828 1829
1829 1830 BUNDLESPEC
1830 1831 A bundle type specifier. These are strings passed to :hg:`bundle -t`.
1831 1832 e.g. ``gzip-v2`` or ``bzip2-v1``.
1832 1833
1833 1834 COMPRESSION
1834 1835 The compression format of the bundle. e.g. ``gzip`` and ``bzip2``.
1835 1836
1836 1837 Server operators may define custom keys.
1837 1838
1838 1839 Example values: ``COMPRESSION=bzip2``,
1839 1840 ``BUNDLESPEC=gzip-v2, COMPRESSION=gzip``.
1840 1841
1841 1842 By default, the first bundle advertised by the server is used.
1842 1843
1843 1844 ``color``
1844 1845 String: when to use to colorize output. possible value are auto, always,
1845 1846 never, or debug (default: never). 'auto' will use color whenever it seems
1846 1847 possible. See :hg:`help color` for details.
1847 1848
1848 1849 (in addition a boolean can be used in place always/never)
1849 1850
1850 1851 ``commitsubrepos``
1851 1852 Whether to commit modified subrepositories when committing the
1852 1853 parent repository. If False and one subrepository has uncommitted
1853 1854 changes, abort the commit.
1854 1855 (default: False)
1855 1856
1856 1857 ``debug``
1857 1858 Print debugging information. (default: False)
1858 1859
1859 1860 ``editor``
1860 1861 The editor to use during a commit. (default: ``$EDITOR`` or ``vi``)
1861 1862
1862 1863 ``fallbackencoding``
1863 1864 Encoding to try if it's not possible to decode the changelog using
1864 1865 UTF-8. (default: ISO-8859-1)
1865 1866
1866 1867 ``graphnodetemplate``
1867 1868 The template used to print changeset nodes in an ASCII revision graph.
1868 1869 (default: ``{graphnode}``)
1869 1870
1870 1871 ``ignore``
1871 1872 A file to read per-user ignore patterns from. This file should be
1872 1873 in the same format as a repository-wide .hgignore file. Filenames
1873 1874 are relative to the repository root. This option supports hook syntax,
1874 1875 so if you want to specify multiple ignore files, you can do so by
1875 1876 setting something like ``ignore.other = ~/.hgignore2``. For details
1876 1877 of the ignore file format, see the ``hgignore(5)`` man page.
1877 1878
1878 1879 ``interactive``
1879 1880 Allow to prompt the user. (default: True)
1880 1881
1881 1882 ``interface``
1882 1883 Select the default interface for interactive features (default: text).
1883 1884 Possible values are 'text' and 'curses'.
1884 1885
1885 1886 ``interface.chunkselector``
1886 1887 Select the interface for change recording (e.g. :hg:`commit -i`).
1887 1888 Possible values are 'text' and 'curses'.
1888 1889 This config overrides the interface specified by ui.interface.
1889 1890
1890 1891 ``logtemplate``
1891 1892 Template string for commands that print changesets.
1892 1893
1893 1894 ``merge``
1894 1895 The conflict resolution program to use during a manual merge.
1895 1896 For more information on merge tools see :hg:`help merge-tools`.
1896 1897 For configuring merge tools see the ``[merge-tools]`` section.
1897 1898
1898 1899 ``mergemarkers``
1899 1900 Sets the merge conflict marker label styling. The ``detailed``
1900 1901 style uses the ``mergemarkertemplate`` setting to style the labels.
1901 1902 The ``basic`` style just uses 'local' and 'other' as the marker label.
1902 1903 One of ``basic`` or ``detailed``.
1903 1904 (default: ``basic``)
1904 1905
1905 1906 ``mergemarkertemplate``
1906 1907 The template used to print the commit description next to each conflict
1907 1908 marker during merge conflicts. See :hg:`help templates` for the template
1908 1909 format.
1909 1910
1910 1911 Defaults to showing the hash, tags, branches, bookmarks, author, and
1911 1912 the first line of the commit description.
1912 1913
1913 1914 If you use non-ASCII characters in names for tags, branches, bookmarks,
1914 1915 authors, and/or commit descriptions, you must pay attention to encodings of
1915 1916 managed files. At template expansion, non-ASCII characters use the encoding
1916 1917 specified by the ``--encoding`` global option, ``HGENCODING`` or other
1917 1918 environment variables that govern your locale. If the encoding of the merge
1918 1919 markers is different from the encoding of the merged files,
1919 1920 serious problems may occur.
1920 1921
1921 1922 ``origbackuppath``
1922 1923 The path to a directory used to store generated .orig files. If the path is
1923 1924 not a directory, one will be created.
1924 1925
1925 1926 ``patch``
1926 1927 An optional external tool that ``hg import`` and some extensions
1927 1928 will use for applying patches. By default Mercurial uses an
1928 1929 internal patch utility. The external tool must work as the common
1929 1930 Unix ``patch`` program. In particular, it must accept a ``-p``
1930 1931 argument to strip patch headers, a ``-d`` argument to specify the
1931 1932 current directory, a file name to patch, and a patch file to take
1932 1933 from stdin.
1933 1934
1934 1935 It is possible to specify a patch tool together with extra
1935 1936 arguments. For example, setting this option to ``patch --merge``
1936 1937 will use the ``patch`` program with its 2-way merge option.
1937 1938
1938 1939 ``portablefilenames``
1939 1940 Check for portable filenames. Can be ``warn``, ``ignore`` or ``abort``.
1940 1941 (default: ``warn``)
1941 1942
1942 1943 ``warn``
1943 1944 Print a warning message on POSIX platforms, if a file with a non-portable
1944 1945 filename is added (e.g. a file with a name that can't be created on
1945 1946 Windows because it contains reserved parts like ``AUX``, reserved
1946 1947 characters like ``:``, or would cause a case collision with an existing
1947 1948 file).
1948 1949
1949 1950 ``ignore``
1950 1951 Don't print a warning.
1951 1952
1952 1953 ``abort``
1953 1954 The command is aborted.
1954 1955
1955 1956 ``true``
1956 1957 Alias for ``warn``.
1957 1958
1958 1959 ``false``
1959 1960 Alias for ``ignore``.
1960 1961
1961 1962 .. container:: windows
1962 1963
1963 1964 On Windows, this configuration option is ignored and the command aborted.
1964 1965
1965 1966 ``quiet``
1966 1967 Reduce the amount of output printed.
1967 1968 (default: False)
1968 1969
1969 1970 ``remotecmd``
1970 1971 Remote command to use for clone/push/pull operations.
1971 1972 (default: ``hg``)
1972 1973
1973 1974 ``report_untrusted``
1974 1975 Warn if a ``.hg/hgrc`` file is ignored due to not being owned by a
1975 1976 trusted user or group.
1976 1977 (default: True)
1977 1978
1978 1979 ``slash``
1979 1980 Display paths using a slash (``/``) as the path separator. This
1980 1981 only makes a difference on systems where the default path
1981 1982 separator is not the slash character (e.g. Windows uses the
1982 1983 backslash character (``\``)).
1983 1984 (default: False)
1984 1985
1985 1986 ``statuscopies``
1986 1987 Display copies in the status command.
1987 1988
1988 1989 ``ssh``
1989 1990 Command to use for SSH connections. (default: ``ssh``)
1990 1991
1991 1992 ``strict``
1992 1993 Require exact command names, instead of allowing unambiguous
1993 1994 abbreviations. (default: False)
1994 1995
1995 1996 ``style``
1996 1997 Name of style to use for command output.
1997 1998
1998 1999 ``supportcontact``
1999 2000 A URL where users should report a Mercurial traceback. Use this if you are a
2000 2001 large organisation with its own Mercurial deployment process and crash
2001 2002 reports should be addressed to your internal support.
2002 2003
2003 2004 ``textwidth``
2004 2005 Maximum width of help text. A longer line generated by ``hg help`` or
2005 2006 ``hg subcommand --help`` will be broken after white space to get this
2006 2007 width or the terminal width, whichever comes first.
2007 2008 A non-positive value will disable this and the terminal width will be
2008 2009 used. (default: 78)
2009 2010
2010 2011 ``timeout``
2011 2012 The timeout used when a lock is held (in seconds), a negative value
2012 2013 means no timeout. (default: 600)
2013 2014
2014 2015 ``traceback``
2015 2016 Mercurial always prints a traceback when an unknown exception
2016 2017 occurs. Setting this to True will make Mercurial print a traceback
2017 2018 on all exceptions, even those recognized by Mercurial (such as
2018 2019 IOError or MemoryError). (default: False)
2019 2020
2020 2021 ``username``
2021 2022 The committer of a changeset created when running "commit".
2022 2023 Typically a person's name and email address, e.g. ``Fred Widget
2023 2024 <fred@example.com>``. Environment variables in the
2024 2025 username are expanded.
2025 2026
2026 2027 (default: ``$EMAIL`` or ``username@hostname``. If the username in
2027 2028 hgrc is empty, e.g. if the system admin set ``username =`` in the
2028 2029 system hgrc, it has to be specified manually or in a different
2029 2030 hgrc file)
2030 2031
2031 2032 ``verbose``
2032 2033 Increase the amount of output printed. (default: False)
2033 2034
2034 2035
2035 2036 ``web``
2036 2037 -------
2037 2038
2038 2039 Web interface configuration. The settings in this section apply to
2039 2040 both the builtin webserver (started by :hg:`serve`) and the script you
2040 2041 run through a webserver (``hgweb.cgi`` and the derivatives for FastCGI
2041 2042 and WSGI).
2042 2043
2043 2044 The Mercurial webserver does no authentication (it does not prompt for
2044 2045 usernames and passwords to validate *who* users are), but it does do
2045 2046 authorization (it grants or denies access for *authenticated users*
2046 2047 based on settings in this section). You must either configure your
2047 2048 webserver to do authentication for you, or disable the authorization
2048 2049 checks.
2049 2050
2050 2051 For a quick setup in a trusted environment, e.g., a private LAN, where
2051 2052 you want it to accept pushes from anybody, you can use the following
2052 2053 command line::
2053 2054
2054 2055 $ hg --config web.allow_push=* --config web.push_ssl=False serve
2055 2056
2056 2057 Note that this will allow anybody to push anything to the server and
2057 2058 that this should not be used for public servers.
2058 2059
2059 2060 The full set of options is:
2060 2061
2061 2062 ``accesslog``
2062 2063 Where to output the access log. (default: stdout)
2063 2064
2064 2065 ``address``
2065 2066 Interface address to bind to. (default: all)
2066 2067
2067 2068 ``allow_archive``
2068 2069 List of archive format (bz2, gz, zip) allowed for downloading.
2069 2070 (default: empty)
2070 2071
2071 2072 ``allowbz2``
2072 2073 (DEPRECATED) Whether to allow .tar.bz2 downloading of repository
2073 2074 revisions.
2074 2075 (default: False)
2075 2076
2076 2077 ``allowgz``
2077 2078 (DEPRECATED) Whether to allow .tar.gz downloading of repository
2078 2079 revisions.
2079 2080 (default: False)
2080 2081
2081 2082 ``allowpull``
2082 2083 Whether to allow pulling from the repository. (default: True)
2083 2084
2084 2085 ``allow_push``
2085 2086 Whether to allow pushing to the repository. If empty or not set,
2086 2087 pushing is not allowed. If the special value ``*``, any remote
2087 2088 user can push, including unauthenticated users. Otherwise, the
2088 2089 remote user must have been authenticated, and the authenticated
2089 2090 user name must be present in this list. The contents of the
2090 2091 allow_push list are examined after the deny_push list.
2091 2092
2092 2093 ``allow_read``
2093 2094 If the user has not already been denied repository access due to
2094 2095 the contents of deny_read, this list determines whether to grant
2095 2096 repository access to the user. If this list is not empty, and the
2096 2097 user is unauthenticated or not present in the list, then access is
2097 2098 denied for the user. If the list is empty or not set, then access
2098 2099 is permitted to all users by default. Setting allow_read to the
2099 2100 special value ``*`` is equivalent to it not being set (i.e. access
2100 2101 is permitted to all users). The contents of the allow_read list are
2101 2102 examined after the deny_read list.
2102 2103
2103 2104 ``allowzip``
2104 2105 (DEPRECATED) Whether to allow .zip downloading of repository
2105 2106 revisions. This feature creates temporary files.
2106 2107 (default: False)
2107 2108
2108 2109 ``archivesubrepos``
2109 2110 Whether to recurse into subrepositories when archiving.
2110 2111 (default: False)
2111 2112
2112 2113 ``baseurl``
2113 2114 Base URL to use when publishing URLs in other locations, so
2114 2115 third-party tools like email notification hooks can construct
2115 2116 URLs. Example: ``http://hgserver/repos/``.
2116 2117
2117 2118 ``cacerts``
2118 2119 Path to file containing a list of PEM encoded certificate
2119 2120 authority certificates. Environment variables and ``~user``
2120 2121 constructs are expanded in the filename. If specified on the
2121 2122 client, then it will verify the identity of remote HTTPS servers
2122 2123 with these certificates.
2123 2124
2124 2125 To disable SSL verification temporarily, specify ``--insecure`` from
2125 2126 command line.
2126 2127
2127 2128 You can use OpenSSL's CA certificate file if your platform has
2128 2129 one. On most Linux systems this will be
2129 2130 ``/etc/ssl/certs/ca-certificates.crt``. Otherwise you will have to
2130 2131 generate this file manually. The form must be as follows::
2131 2132
2132 2133 -----BEGIN CERTIFICATE-----
2133 2134 ... (certificate in base64 PEM encoding) ...
2134 2135 -----END CERTIFICATE-----
2135 2136 -----BEGIN CERTIFICATE-----
2136 2137 ... (certificate in base64 PEM encoding) ...
2137 2138 -----END CERTIFICATE-----
2138 2139
2139 2140 ``cache``
2140 2141 Whether to support caching in hgweb. (default: True)
2141 2142
2142 2143 ``certificate``
2143 2144 Certificate to use when running :hg:`serve`.
2144 2145
2145 2146 ``collapse``
2146 2147 With ``descend`` enabled, repositories in subdirectories are shown at
2147 2148 a single level alongside repositories in the current path. With
2148 2149 ``collapse`` also enabled, repositories residing at a deeper level than
2149 2150 the current path are grouped behind navigable directory entries that
2150 2151 lead to the locations of these repositories. In effect, this setting
2151 2152 collapses each collection of repositories found within a subdirectory
2152 2153 into a single entry for that subdirectory. (default: False)
2153 2154
2154 2155 ``comparisoncontext``
2155 2156 Number of lines of context to show in side-by-side file comparison. If
2156 2157 negative or the value ``full``, whole files are shown. (default: 5)
2157 2158
2158 2159 This setting can be overridden by a ``context`` request parameter to the
2159 2160 ``comparison`` command, taking the same values.
2160 2161
2161 2162 ``contact``
2162 2163 Name or email address of the person in charge of the repository.
2163 2164 (default: ui.username or ``$EMAIL`` or "unknown" if unset or empty)
2164 2165
2165 2166 ``csp``
2166 2167 Send a ``Content-Security-Policy`` HTTP header with this value.
2167 2168
2168 2169 The value may contain a special string ``%nonce%``, which will be replaced
2169 2170 by a randomly-generated one-time use value. If the value contains
2170 2171 ``%nonce%``, ``web.cache`` will be disabled, as caching undermines the
2171 2172 one-time property of the nonce. This nonce will also be inserted into
2172 2173 ``<script>`` elements containing inline JavaScript.
2173 2174
2174 2175 Note: lots of HTML content sent by the server is derived from repository
2175 2176 data. Please consider the potential for malicious repository data to
2176 2177 "inject" itself into generated HTML content as part of your security
2177 2178 threat model.
2178 2179
2179 2180 ``deny_push``
2180 2181 Whether to deny pushing to the repository. If empty or not set,
2181 2182 push is not denied. If the special value ``*``, all remote users are
2182 2183 denied push. Otherwise, unauthenticated users are all denied, and
2183 2184 any authenticated user name present in this list is also denied. The
2184 2185 contents of the deny_push list are examined before the allow_push list.
2185 2186
2186 2187 ``deny_read``
2187 2188 Whether to deny reading/viewing of the repository. If this list is
2188 2189 not empty, unauthenticated users are all denied, and any
2189 2190 authenticated user name present in this list is also denied access to
2190 2191 the repository. If set to the special value ``*``, all remote users
2191 2192 are denied access (rarely needed ;). If deny_read is empty or not set,
2192 2193 the determination of repository access depends on the presence and
2193 2194 content of the allow_read list (see description). If both
2194 2195 deny_read and allow_read are empty or not set, then access is
2195 2196 permitted to all users by default. If the repository is being
2196 2197 served via hgwebdir, denied users will not be able to see it in
2197 2198 the list of repositories. The contents of the deny_read list have
2198 2199 priority over (are examined before) the contents of the allow_read
2199 2200 list.
2200 2201
2201 2202 ``descend``
2202 2203 hgwebdir indexes will not descend into subdirectories. Only repositories
2203 2204 directly in the current path will be shown (other repositories are still
2204 2205 available from the index corresponding to their containing path).
2205 2206
2206 2207 ``description``
2207 2208 Textual description of the repository's purpose or contents.
2208 2209 (default: "unknown")
2209 2210
2210 2211 ``encoding``
2211 2212 Character encoding name. (default: the current locale charset)
2212 2213 Example: "UTF-8".
2213 2214
2214 2215 ``errorlog``
2215 2216 Where to output the error log. (default: stderr)
2216 2217
2217 2218 ``guessmime``
2218 2219 Control MIME types for raw download of file content.
2219 2220 Set to True to let hgweb guess the content type from the file
2220 2221 extension. This will serve HTML files as ``text/html`` and might
2221 2222 allow cross-site scripting attacks when serving untrusted
2222 2223 repositories. (default: False)
2223 2224
2224 2225 ``hidden``
2225 2226 Whether to hide the repository in the hgwebdir index.
2226 2227 (default: False)
2227 2228
2228 2229 ``ipv6``
2229 2230 Whether to use IPv6. (default: False)
2230 2231
2231 2232 ``labels``
2232 2233 List of string *labels* associated with the repository.
2233 2234
2234 2235 Labels are exposed as a template keyword and can be used to customize
2235 2236 output. e.g. the ``index`` template can group or filter repositories
2236 2237 by labels and the ``summary`` template can display additional content
2237 2238 if a specific label is present.
2238 2239
2239 2240 ``logoimg``
2240 2241 File name of the logo image that some templates display on each page.
2241 2242 The file name is relative to ``staticurl``. That is, the full path to
2242 2243 the logo image is "staticurl/logoimg".
2243 2244 If unset, ``hglogo.png`` will be used.
2244 2245
2245 2246 ``logourl``
2246 2247 Base URL to use for logos. If unset, ``https://mercurial-scm.org/``
2247 2248 will be used.
2248 2249
2249 2250 ``maxchanges``
2250 2251 Maximum number of changes to list on the changelog. (default: 10)
2251 2252
2252 2253 ``maxfiles``
2253 2254 Maximum number of files to list per changeset. (default: 10)
2254 2255
2255 2256 ``maxshortchanges``
2256 2257 Maximum number of changes to list on the shortlog, graph or filelog
2257 2258 pages. (default: 60)
2258 2259
2259 2260 ``name``
2260 2261 Repository name to use in the web interface.
2261 2262 (default: current working directory)
2262 2263
2263 2264 ``port``
2264 2265 Port to listen on. (default: 8000)
2265 2266
2266 2267 ``prefix``
2267 2268 Prefix path to serve from. (default: '' (server root))
2268 2269
2269 2270 ``push_ssl``
2270 2271 Whether to require that inbound pushes be transported over SSL to
2271 2272 prevent password sniffing. (default: True)
2272 2273
2273 2274 ``refreshinterval``
2274 2275 How frequently directory listings re-scan the filesystem for new
2275 2276 repositories, in seconds. This is relevant when wildcards are used
2276 2277 to define paths. Depending on how much filesystem traversal is
2277 2278 required, refreshing may negatively impact performance.
2278 2279
2279 2280 Values less than or equal to 0 always refresh.
2280 2281 (default: 20)
2281 2282
2282 2283 ``staticurl``
2283 2284 Base URL to use for static files. If unset, static files (e.g. the
2284 2285 hgicon.png favicon) will be served by the CGI script itself. Use
2285 2286 this setting to serve them directly with the HTTP server.
2286 2287 Example: ``http://hgserver/static/``.
2287 2288
2288 2289 ``stripes``
2289 2290 How many lines a "zebra stripe" should span in multi-line output.
2290 2291 Set to 0 to disable. (default: 1)
2291 2292
2292 2293 ``style``
2293 2294 Which template map style to use. The available options are the names of
2294 2295 subdirectories in the HTML templates path. (default: ``paper``)
2295 2296 Example: ``monoblue``.
2296 2297
2297 2298 ``templates``
2298 2299 Where to find the HTML templates. The default path to the HTML templates
2299 2300 can be obtained from ``hg debuginstall``.
2300 2301
2301 2302 ``websub``
2302 2303 ----------
2303 2304
2304 2305 Web substitution filter definition. You can use this section to
2305 2306 define a set of regular expression substitution patterns which
2306 2307 let you automatically modify the hgweb server output.
2307 2308
2308 2309 The default hgweb templates only apply these substitution patterns
2309 2310 on the revision description fields. You can apply them anywhere
2310 2311 you want when you create your own templates by adding calls to the
2311 2312 "websub" filter (usually after calling the "escape" filter).
2312 2313
2313 2314 This can be used, for example, to convert issue references to links
2314 2315 to your issue tracker, or to convert "markdown-like" syntax into
2315 2316 HTML (see the examples below).
2316 2317
2317 2318 Each entry in this section names a substitution filter.
2318 2319 The value of each entry defines the substitution expression itself.
2319 2320 The websub expressions follow the old interhg extension syntax,
2320 2321 which in turn imitates the Unix sed replacement syntax::
2321 2322
2322 2323 patternname = s/SEARCH_REGEX/REPLACE_EXPRESSION/[i]
2323 2324
2324 2325 You can use any separator other than "/". The final "i" is optional
2325 2326 and indicates that the search must be case insensitive.
2326 2327
2327 2328 Examples::
2328 2329
2329 2330 [websub]
2330 2331 issues = s|issue(\d+)|<a href="http://bts.example.org/issue\1">issue\1</a>|i
2331 2332 italic = s/\b_(\S+)_\b/<i>\1<\/i>/
2332 2333 bold = s/\*\b(\S+)\b\*/<b>\1<\/b>/
2333 2334
2334 2335 ``worker``
2335 2336 ----------
2336 2337
2337 2338 Parallel master/worker configuration. We currently perform working
2338 2339 directory updates in parallel on Unix-like systems, which greatly
2339 2340 helps performance.
2340 2341
2341 2342 ``numcpus``
2342 2343 Number of CPUs to use for parallel operations. A zero or
2343 2344 negative value is treated as ``use the default``.
2344 2345 (default: 4 or the number of CPUs on the system, whichever is larger)
2345 2346
2346 2347 ``backgroundclose``
2347 2348 Whether to enable closing file handles on background threads during certain
2348 2349 operations. Some platforms aren't very efficient at closing file
2349 2350 handles that have been written or appended to. By performing file closing
2350 2351 on background threads, file write rate can increase substantially.
2351 2352 (default: true on Windows, false elsewhere)
2352 2353
2353 2354 ``backgroundcloseminfilecount``
2354 2355 Minimum number of files required to trigger background file closing.
2355 2356 Operations not writing this many files won't start background close
2356 2357 threads.
2357 2358 (default: 2048)
2358 2359
2359 2360 ``backgroundclosemaxqueue``
2360 2361 The maximum number of opened file handles waiting to be closed in the
2361 2362 background. This option only has an effect if ``backgroundclose`` is
2362 2363 enabled.
2363 2364 (default: 384)
2364 2365
2365 2366 ``backgroundclosethreadcount``
2366 2367 Number of threads to process background file closes. Only relevant if
2367 2368 ``backgroundclose`` is enabled.
2368 2369 (default: 4)
@@ -1,267 +1,268
1 1 # hook.py - hook support for mercurial
2 2 #
3 3 # Copyright 2007 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from __future__ import absolute_import
9 9
10 10 import os
11 11 import sys
12 12
13 13 from .i18n import _
14 14 from . import (
15 15 demandimport,
16 16 error,
17 17 extensions,
18 18 pycompat,
19 19 util,
20 20 )
21 21
22 22 def _pythonhook(ui, repo, htype, hname, funcname, args, throw):
23 23 '''call python hook. hook is callable object, looked up as
24 24 name in python module. if callable returns "true", hook
25 25 fails, else passes. if hook raises exception, treated as
26 26 hook failure. exception propagates if throw is "true".
27 27
28 28 reason for "true" meaning "hook failed" is so that
29 29 unmodified commands (e.g. mercurial.commands.update) can
30 30 be run as hooks without wrappers to convert return values.'''
31 31
32 32 if callable(funcname):
33 33 obj = funcname
34 34 funcname = obj.__module__ + "." + obj.__name__
35 35 else:
36 36 d = funcname.rfind('.')
37 37 if d == -1:
38 38 raise error.HookLoadError(
39 39 _('%s hook is invalid: "%s" not in a module')
40 40 % (hname, funcname))
41 41 modname = funcname[:d]
42 42 oldpaths = sys.path
43 43 if util.mainfrozen():
44 44 # binary installs require sys.path manipulation
45 45 modpath, modfile = os.path.split(modname)
46 46 if modpath and modfile:
47 47 sys.path = sys.path[:] + [modpath]
48 48 modname = modfile
49 49 with demandimport.deactivated():
50 50 try:
51 51 obj = __import__(modname)
52 52 except (ImportError, SyntaxError):
53 53 e1 = sys.exc_info()
54 54 try:
55 55 # extensions are loaded with hgext_ prefix
56 56 obj = __import__("hgext_%s" % modname)
57 57 except (ImportError, SyntaxError):
58 58 e2 = sys.exc_info()
59 59 if ui.tracebackflag:
60 60 ui.warn(_('exception from first failed import '
61 61 'attempt:\n'))
62 62 ui.traceback(e1)
63 63 if ui.tracebackflag:
64 64 ui.warn(_('exception from second failed import '
65 65 'attempt:\n'))
66 66 ui.traceback(e2)
67 67
68 68 if not ui.tracebackflag:
69 69 tracebackhint = _(
70 70 'run with --traceback for stack trace')
71 71 else:
72 72 tracebackhint = None
73 73 raise error.HookLoadError(
74 74 _('%s hook is invalid: import of "%s" failed') %
75 75 (hname, modname), hint=tracebackhint)
76 76 sys.path = oldpaths
77 77 try:
78 78 for p in funcname.split('.')[1:]:
79 79 obj = getattr(obj, p)
80 80 except AttributeError:
81 81 raise error.HookLoadError(
82 82 _('%s hook is invalid: "%s" is not defined')
83 83 % (hname, funcname))
84 84 if not callable(obj):
85 85 raise error.HookLoadError(
86 86 _('%s hook is invalid: "%s" is not callable')
87 87 % (hname, funcname))
88 88
89 89 ui.note(_("calling hook %s: %s\n") % (hname, funcname))
90 90 starttime = util.timer()
91 91
92 92 try:
93 93 r = obj(ui=ui, repo=repo, hooktype=htype, **args)
94 94 except Exception as exc:
95 95 if isinstance(exc, error.Abort):
96 96 ui.warn(_('error: %s hook failed: %s\n') %
97 97 (hname, exc.args[0]))
98 98 else:
99 99 ui.warn(_('error: %s hook raised an exception: '
100 100 '%s\n') % (hname, exc))
101 101 if throw:
102 102 raise
103 103 if not ui.tracebackflag:
104 104 ui.warn(_('(run with --traceback for stack trace)\n'))
105 105 ui.traceback()
106 106 return True, True
107 107 finally:
108 108 duration = util.timer() - starttime
109 109 ui.log('pythonhook', 'pythonhook-%s: %s finished in %0.2f seconds\n',
110 110 htype, funcname, duration)
111 111 if r:
112 112 if throw:
113 113 raise error.HookAbort(_('%s hook failed') % hname)
114 114 ui.warn(_('warning: %s hook failed\n') % hname)
115 115 return r, False
116 116
117 117 def _exthook(ui, repo, htype, name, cmd, args, throw):
118 118 ui.note(_("running hook %s: %s\n") % (name, cmd))
119 119
120 120 starttime = util.timer()
121 121 env = {}
122 122
123 123 # make in-memory changes visible to external process
124 124 if repo is not None:
125 125 tr = repo.currenttransaction()
126 126 repo.dirstate.write(tr)
127 127 if tr and tr.writepending():
128 128 env['HG_PENDING'] = repo.root
129 129 env['HG_HOOKTYPE'] = htype
130 env['HG_HOOKNAME'] = name
130 131
131 132 for k, v in args.iteritems():
132 133 if callable(v):
133 134 v = v()
134 135 if isinstance(v, dict):
135 136 # make the dictionary element order stable across Python
136 137 # implementations
137 138 v = ('{' +
138 139 ', '.join('%r: %r' % i for i in sorted(v.iteritems())) +
139 140 '}')
140 141 env['HG_' + k.upper()] = v
141 142
142 143 if repo:
143 144 cwd = repo.root
144 145 else:
145 146 cwd = pycompat.getcwd()
146 147 r = ui.system(cmd, environ=env, cwd=cwd, blockedtag='exthook-%s' % (name,))
147 148
148 149 duration = util.timer() - starttime
149 150 ui.log('exthook', 'exthook-%s: %s finished in %0.2f seconds\n',
150 151 name, cmd, duration)
151 152 if r:
152 153 desc, r = util.explainexit(r)
153 154 if throw:
154 155 raise error.HookAbort(_('%s hook %s') % (name, desc))
155 156 ui.warn(_('warning: %s hook %s\n') % (name, desc))
156 157 return r
157 158
158 159 # represent an untrusted hook command
159 160 _fromuntrusted = object()
160 161
161 162 def _allhooks(ui):
162 163 """return a list of (hook-id, cmd) pairs sorted by priority"""
163 164 hooks = _hookitems(ui)
164 165 # Be careful in this section, propagating the real commands from untrusted
165 166 # sources would create a security vulnerability, make sure anything altered
166 167 # in that section uses "_fromuntrusted" as its command.
167 168 untrustedhooks = _hookitems(ui, _untrusted=True)
168 169 for name, value in untrustedhooks.items():
169 170 trustedvalue = hooks.get(name, (None, None, name, _fromuntrusted))
170 171 if value != trustedvalue:
171 172 (lp, lo, lk, lv) = trustedvalue
172 173 hooks[name] = (lp, lo, lk, _fromuntrusted)
173 174 # (end of the security sensitive section)
174 175 return [(k, v) for p, o, k, v in sorted(hooks.values())]
175 176
176 177 def _hookitems(ui, _untrusted=False):
177 178 """return all hooks items ready to be sorted"""
178 179 hooks = {}
179 180 for name, cmd in ui.configitems('hooks', untrusted=_untrusted):
180 181 if not name.startswith('priority'):
181 182 priority = ui.configint('hooks', 'priority.%s' % name, 0)
182 183 hooks[name] = (-priority, len(hooks), name, cmd)
183 184 return hooks
184 185
185 186 _redirect = False
186 187 def redirect(state):
187 188 global _redirect
188 189 _redirect = state
189 190
190 191 def hook(ui, repo, htype, throw=False, **args):
191 192 if not ui.callhooks:
192 193 return False
193 194
194 195 hooks = []
195 196 for hname, cmd in _allhooks(ui):
196 197 if hname.split('.')[0] == htype and cmd:
197 198 hooks.append((hname, cmd))
198 199
199 200 res = runhooks(ui, repo, htype, hooks, throw=throw, **args)
200 201 r = False
201 202 for hname, cmd in hooks:
202 203 r = res[hname][0] or r
203 204 return r
204 205
205 206 def runhooks(ui, repo, htype, hooks, throw=False, **args):
206 207 res = {}
207 208 oldstdout = -1
208 209
209 210 try:
210 211 for hname, cmd in hooks:
211 212 if oldstdout == -1 and _redirect:
212 213 try:
213 214 stdoutno = util.stdout.fileno()
214 215 stderrno = util.stderr.fileno()
215 216 # temporarily redirect stdout to stderr, if possible
216 217 if stdoutno >= 0 and stderrno >= 0:
217 218 util.stdout.flush()
218 219 oldstdout = os.dup(stdoutno)
219 220 os.dup2(stderrno, stdoutno)
220 221 except (OSError, AttributeError):
221 222 # files seem to be bogus, give up on redirecting (WSGI, etc)
222 223 pass
223 224
224 225 if cmd is _fromuntrusted:
225 226 if throw:
226 227 raise error.HookAbort(
227 228 _('untrusted hook %s not executed') % hname,
228 229 hint = _("see 'hg help config.trusted'"))
229 230 ui.warn(_('warning: untrusted hook %s not executed\n') % hname)
230 231 r = 1
231 232 raised = False
232 233 elif callable(cmd):
233 234 r, raised = _pythonhook(ui, repo, htype, hname, cmd, args,
234 235 throw)
235 236 elif cmd.startswith('python:'):
236 237 if cmd.count(':') >= 2:
237 238 path, cmd = cmd[7:].rsplit(':', 1)
238 239 path = util.expandpath(path)
239 240 if repo:
240 241 path = os.path.join(repo.root, path)
241 242 try:
242 243 mod = extensions.loadpath(path, 'hghook.%s' % hname)
243 244 except Exception:
244 245 ui.write(_("loading %s hook failed:\n") % hname)
245 246 raise
246 247 hookfn = getattr(mod, cmd)
247 248 else:
248 249 hookfn = cmd[7:].strip()
249 250 r, raised = _pythonhook(ui, repo, htype, hname, hookfn, args,
250 251 throw)
251 252 else:
252 253 r = _exthook(ui, repo, htype, hname, cmd, args, throw)
253 254 raised = False
254 255
255 256 res[hname] = r, raised
256 257
257 258 # The stderr is fully buffered on Windows when connected to a pipe.
258 259 # A forcible flush is required to make small stderr data in the
259 260 # remote side available to the client immediately.
260 261 util.stderr.flush()
261 262 finally:
262 263 if _redirect and oldstdout >= 0:
263 264 util.stdout.flush() # write hook output to stderr fd
264 265 os.dup2(oldstdout, stdoutno)
265 266 os.close(oldstdout)
266 267
267 268 return res
@@ -1,853 +1,853
1 1
2 2 $ cat << EOF >> $HGRCPATH
3 3 > [format]
4 4 > usegeneraldelta=yes
5 5 > EOF
6 6
7 7 Setting up test
8 8
9 9 $ hg init test
10 10 $ cd test
11 11 $ echo 0 > afile
12 12 $ hg add afile
13 13 $ hg commit -m "0.0"
14 14 $ echo 1 >> afile
15 15 $ hg commit -m "0.1"
16 16 $ echo 2 >> afile
17 17 $ hg commit -m "0.2"
18 18 $ echo 3 >> afile
19 19 $ hg commit -m "0.3"
20 20 $ hg update -C 0
21 21 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
22 22 $ echo 1 >> afile
23 23 $ hg commit -m "1.1"
24 24 created new head
25 25 $ echo 2 >> afile
26 26 $ hg commit -m "1.2"
27 27 $ echo "a line" > fred
28 28 $ echo 3 >> afile
29 29 $ hg add fred
30 30 $ hg commit -m "1.3"
31 31 $ hg mv afile adifferentfile
32 32 $ hg commit -m "1.3m"
33 33 $ hg update -C 3
34 34 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
35 35 $ hg mv afile anotherfile
36 36 $ hg commit -m "0.3m"
37 37 $ hg verify
38 38 checking changesets
39 39 checking manifests
40 40 crosschecking files in changesets and manifests
41 41 checking files
42 42 4 files, 9 changesets, 7 total revisions
43 43 $ cd ..
44 44 $ hg init empty
45 45
46 46 Bundle and phase
47 47
48 48 $ hg -R test phase --force --secret 0
49 49 $ hg -R test bundle phase.hg empty
50 50 searching for changes
51 51 no changes found (ignored 9 secret changesets)
52 52 [1]
53 53 $ hg -R test phase --draft -r 'head()'
54 54
55 55 Bundle --all
56 56
57 57 $ hg -R test bundle --all all.hg
58 58 9 changesets found
59 59
60 60 Bundle test to full.hg
61 61
62 62 $ hg -R test bundle full.hg empty
63 63 searching for changes
64 64 9 changesets found
65 65
66 66 Unbundle full.hg in test
67 67
68 68 $ hg -R test unbundle full.hg
69 69 adding changesets
70 70 adding manifests
71 71 adding file changes
72 72 added 0 changesets with 0 changes to 4 files
73 73 (run 'hg update' to get a working copy)
74 74
75 75 Verify empty
76 76
77 77 $ hg -R empty heads
78 78 [1]
79 79 $ hg -R empty verify
80 80 checking changesets
81 81 checking manifests
82 82 crosschecking files in changesets and manifests
83 83 checking files
84 84 0 files, 0 changesets, 0 total revisions
85 85
86 86 Pull full.hg into test (using --cwd)
87 87
88 88 $ hg --cwd test pull ../full.hg
89 89 pulling from ../full.hg
90 90 searching for changes
91 91 no changes found
92 92
93 93 Verify that there are no leaked temporary files after pull (issue2797)
94 94
95 95 $ ls test/.hg | grep .hg10un
96 96 [1]
97 97
98 98 Pull full.hg into empty (using --cwd)
99 99
100 100 $ hg --cwd empty pull ../full.hg
101 101 pulling from ../full.hg
102 102 requesting all changes
103 103 adding changesets
104 104 adding manifests
105 105 adding file changes
106 106 added 9 changesets with 7 changes to 4 files (+1 heads)
107 107 (run 'hg heads' to see heads, 'hg merge' to merge)
108 108
109 109 Rollback empty
110 110
111 111 $ hg -R empty rollback
112 112 repository tip rolled back to revision -1 (undo pull)
113 113
114 114 Pull full.hg into empty again (using --cwd)
115 115
116 116 $ hg --cwd empty pull ../full.hg
117 117 pulling from ../full.hg
118 118 requesting all changes
119 119 adding changesets
120 120 adding manifests
121 121 adding file changes
122 122 added 9 changesets with 7 changes to 4 files (+1 heads)
123 123 (run 'hg heads' to see heads, 'hg merge' to merge)
124 124
125 125 Pull full.hg into test (using -R)
126 126
127 127 $ hg -R test pull full.hg
128 128 pulling from full.hg
129 129 searching for changes
130 130 no changes found
131 131
132 132 Pull full.hg into empty (using -R)
133 133
134 134 $ hg -R empty pull full.hg
135 135 pulling from full.hg
136 136 searching for changes
137 137 no changes found
138 138
139 139 Rollback empty
140 140
141 141 $ hg -R empty rollback
142 142 repository tip rolled back to revision -1 (undo pull)
143 143
144 144 Pull full.hg into empty again (using -R)
145 145
146 146 $ hg -R empty pull full.hg
147 147 pulling from full.hg
148 148 requesting all changes
149 149 adding changesets
150 150 adding manifests
151 151 adding file changes
152 152 added 9 changesets with 7 changes to 4 files (+1 heads)
153 153 (run 'hg heads' to see heads, 'hg merge' to merge)
154 154
155 155 Log -R full.hg in fresh empty
156 156
157 157 $ rm -r empty
158 158 $ hg init empty
159 159 $ cd empty
160 160 $ hg -R bundle://../full.hg log
161 161 changeset: 8:aa35859c02ea
162 162 tag: tip
163 163 parent: 3:eebf5a27f8ca
164 164 user: test
165 165 date: Thu Jan 01 00:00:00 1970 +0000
166 166 summary: 0.3m
167 167
168 168 changeset: 7:a6a34bfa0076
169 169 user: test
170 170 date: Thu Jan 01 00:00:00 1970 +0000
171 171 summary: 1.3m
172 172
173 173 changeset: 6:7373c1169842
174 174 user: test
175 175 date: Thu Jan 01 00:00:00 1970 +0000
176 176 summary: 1.3
177 177
178 178 changeset: 5:1bb50a9436a7
179 179 user: test
180 180 date: Thu Jan 01 00:00:00 1970 +0000
181 181 summary: 1.2
182 182
183 183 changeset: 4:095197eb4973
184 184 parent: 0:f9ee2f85a263
185 185 user: test
186 186 date: Thu Jan 01 00:00:00 1970 +0000
187 187 summary: 1.1
188 188
189 189 changeset: 3:eebf5a27f8ca
190 190 user: test
191 191 date: Thu Jan 01 00:00:00 1970 +0000
192 192 summary: 0.3
193 193
194 194 changeset: 2:e38ba6f5b7e0
195 195 user: test
196 196 date: Thu Jan 01 00:00:00 1970 +0000
197 197 summary: 0.2
198 198
199 199 changeset: 1:34c2bf6b0626
200 200 user: test
201 201 date: Thu Jan 01 00:00:00 1970 +0000
202 202 summary: 0.1
203 203
204 204 changeset: 0:f9ee2f85a263
205 205 user: test
206 206 date: Thu Jan 01 00:00:00 1970 +0000
207 207 summary: 0.0
208 208
209 209 Make sure bundlerepo doesn't leak tempfiles (issue2491)
210 210
211 211 $ ls .hg
212 212 00changelog.i
213 213 cache
214 214 requires
215 215 store
216 216
217 217 Pull ../full.hg into empty (with hook)
218 218
219 219 $ cat >> .hg/hgrc <<EOF
220 220 > [hooks]
221 221 > changegroup = sh -c "printenv.py changegroup"
222 222 > EOF
223 223
224 224 doesn't work (yet ?)
225 225
226 226 hg -R bundle://../full.hg verify
227 227
228 228 $ hg pull bundle://../full.hg
229 229 pulling from bundle:../full.hg
230 230 requesting all changes
231 231 adding changesets
232 232 adding manifests
233 233 adding file changes
234 234 added 9 changesets with 7 changes to 4 files (+1 heads)
235 changegroup hook: HG_HOOKTYPE=changegroup HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735 HG_NODE_LAST=aa35859c02ea8bd48da5da68cd2740ac71afcbaf HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=bundle:../full.hg
235 changegroup hook: HG_HOOKNAME=changegroup HG_HOOKTYPE=changegroup HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735 HG_NODE_LAST=aa35859c02ea8bd48da5da68cd2740ac71afcbaf HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=bundle:../full.hg
236 236 (run 'hg heads' to see heads, 'hg merge' to merge)
237 237
238 238 Rollback empty
239 239
240 240 $ hg rollback
241 241 repository tip rolled back to revision -1 (undo pull)
242 242 $ cd ..
243 243
244 244 Log -R bundle:empty+full.hg
245 245
246 246 $ hg -R bundle:empty+full.hg log --template="{rev} "; echo ""
247 247 8 7 6 5 4 3 2 1 0
248 248
249 249 Pull full.hg into empty again (using -R; with hook)
250 250
251 251 $ hg -R empty pull full.hg
252 252 pulling from full.hg
253 253 requesting all changes
254 254 adding changesets
255 255 adding manifests
256 256 adding file changes
257 257 added 9 changesets with 7 changes to 4 files (+1 heads)
258 changegroup hook: HG_HOOKTYPE=changegroup HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735 HG_NODE_LAST=aa35859c02ea8bd48da5da68cd2740ac71afcbaf HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=bundle:empty+full.hg
258 changegroup hook: HG_HOOKNAME=changegroup HG_HOOKTYPE=changegroup HG_NODE=f9ee2f85a263049e9ae6d37a0e67e96194ffb735 HG_NODE_LAST=aa35859c02ea8bd48da5da68cd2740ac71afcbaf HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=bundle:empty+full.hg
259 259 (run 'hg heads' to see heads, 'hg merge' to merge)
260 260
261 261 Cannot produce streaming clone bundles with "hg bundle"
262 262
263 263 $ hg -R test bundle -t packed1 packed.hg
264 264 abort: packed bundles cannot be produced by "hg bundle"
265 265 (use 'hg debugcreatestreamclonebundle')
266 266 [255]
267 267
268 268 packed1 is produced properly
269 269
270 270 $ hg -R test debugcreatestreamclonebundle packed.hg
271 271 writing 2664 bytes for 6 files
272 272 bundle requirements: generaldelta, revlogv1
273 273
274 274 $ f -B 64 --size --sha1 --hexdump packed.hg
275 275 packed.hg: size=2827, sha1=9d14cb90c66a21462d915ab33656f38b9deed686
276 276 0000: 48 47 53 31 55 4e 00 00 00 00 00 00 00 06 00 00 |HGS1UN..........|
277 277 0010: 00 00 00 00 0a 68 00 16 67 65 6e 65 72 61 6c 64 |.....h..generald|
278 278 0020: 65 6c 74 61 2c 72 65 76 6c 6f 67 76 31 00 64 61 |elta,revlogv1.da|
279 279 0030: 74 61 2f 61 64 69 66 66 65 72 65 6e 74 66 69 6c |ta/adifferentfil|
280 280
281 281 $ hg debugbundle --spec packed.hg
282 282 none-packed1;requirements%3Dgeneraldelta%2Crevlogv1
283 283
284 284 generaldelta requirement is not listed in stream clone bundles unless used
285 285
286 286 $ hg --config format.usegeneraldelta=false init testnongd
287 287 $ cd testnongd
288 288 $ touch foo
289 289 $ hg -q commit -A -m initial
290 290 $ cd ..
291 291 $ hg -R testnongd debugcreatestreamclonebundle packednongd.hg
292 292 writing 301 bytes for 3 files
293 293 bundle requirements: revlogv1
294 294
295 295 $ f -B 64 --size --sha1 --hexdump packednongd.hg
296 296 packednongd.hg: size=383, sha1=1d9c230238edd5d38907100b729ba72b1831fe6f
297 297 0000: 48 47 53 31 55 4e 00 00 00 00 00 00 00 03 00 00 |HGS1UN..........|
298 298 0010: 00 00 00 00 01 2d 00 09 72 65 76 6c 6f 67 76 31 |.....-..revlogv1|
299 299 0020: 00 64 61 74 61 2f 66 6f 6f 2e 69 00 36 34 0a 00 |.data/foo.i.64..|
300 300 0030: 01 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
301 301
302 302 $ hg debugbundle --spec packednongd.hg
303 303 none-packed1;requirements%3Drevlogv1
304 304
305 305 Unpacking packed1 bundles with "hg unbundle" isn't allowed
306 306
307 307 $ hg init packed
308 308 $ hg -R packed unbundle packed.hg
309 309 abort: packed bundles cannot be applied with "hg unbundle"
310 310 (use "hg debugapplystreamclonebundle")
311 311 [255]
312 312
313 313 packed1 can be consumed from debug command
314 314
315 315 (this also confirms that streamclone-ed changes are visible via
316 316 @filecache properties to in-process procedures before closing
317 317 transaction)
318 318
319 319 $ cat > $TESTTMP/showtip.py <<EOF
320 320 > from __future__ import absolute_import
321 321 >
322 322 > def showtip(ui, repo, hooktype, **kwargs):
323 323 > ui.warn('%s: %s\n' % (hooktype, repo['tip'].hex()[:12]))
324 324 >
325 325 > def reposetup(ui, repo):
326 326 > # this confirms (and ensures) that (empty) 00changelog.i
327 327 > # before streamclone is already cached as repo.changelog
328 328 > ui.setconfig('hooks', 'pretxnopen.showtip', showtip)
329 329 >
330 330 > # this confirms that streamclone-ed changes are visible to
331 331 > # in-process procedures before closing transaction
332 332 > ui.setconfig('hooks', 'pretxnclose.showtip', showtip)
333 333 >
334 334 > # this confirms that streamclone-ed changes are still visible
335 335 > # after closing transaction
336 336 > ui.setconfig('hooks', 'txnclose.showtip', showtip)
337 337 > EOF
338 338 $ cat >> $HGRCPATH <<EOF
339 339 > [extensions]
340 340 > showtip = $TESTTMP/showtip.py
341 341 > EOF
342 342
343 343 $ hg -R packed debugapplystreamclonebundle packed.hg
344 344 6 files to transfer, 2.60 KB of data
345 345 pretxnopen: 000000000000
346 346 pretxnclose: aa35859c02ea
347 347 transferred 2.60 KB in *.* seconds (* */sec) (glob)
348 348 txnclose: aa35859c02ea
349 349
350 350 (for safety, confirm visibility of streamclone-ed changes by another
351 351 process, too)
352 352
353 353 $ hg -R packed tip -T "{node|short}\n"
354 354 aa35859c02ea
355 355
356 356 $ cat >> $HGRCPATH <<EOF
357 357 > [extensions]
358 358 > showtip = !
359 359 > EOF
360 360
361 361 Does not work on non-empty repo
362 362
363 363 $ hg -R packed debugapplystreamclonebundle packed.hg
364 364 abort: cannot apply stream clone bundle on non-empty repo
365 365 [255]
366 366
367 367 Create partial clones
368 368
369 369 $ rm -r empty
370 370 $ hg init empty
371 371 $ hg clone -r 3 test partial
372 372 adding changesets
373 373 adding manifests
374 374 adding file changes
375 375 added 4 changesets with 4 changes to 1 files
376 376 updating to branch default
377 377 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
378 378 $ hg clone partial partial2
379 379 updating to branch default
380 380 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
381 381 $ cd partial
382 382
383 383 Log -R full.hg in partial
384 384
385 385 $ hg -R bundle://../full.hg log -T phases
386 386 changeset: 8:aa35859c02ea
387 387 tag: tip
388 388 phase: draft
389 389 parent: 3:eebf5a27f8ca
390 390 user: test
391 391 date: Thu Jan 01 00:00:00 1970 +0000
392 392 summary: 0.3m
393 393
394 394 changeset: 7:a6a34bfa0076
395 395 phase: draft
396 396 user: test
397 397 date: Thu Jan 01 00:00:00 1970 +0000
398 398 summary: 1.3m
399 399
400 400 changeset: 6:7373c1169842
401 401 phase: draft
402 402 user: test
403 403 date: Thu Jan 01 00:00:00 1970 +0000
404 404 summary: 1.3
405 405
406 406 changeset: 5:1bb50a9436a7
407 407 phase: draft
408 408 user: test
409 409 date: Thu Jan 01 00:00:00 1970 +0000
410 410 summary: 1.2
411 411
412 412 changeset: 4:095197eb4973
413 413 phase: draft
414 414 parent: 0:f9ee2f85a263
415 415 user: test
416 416 date: Thu Jan 01 00:00:00 1970 +0000
417 417 summary: 1.1
418 418
419 419 changeset: 3:eebf5a27f8ca
420 420 phase: public
421 421 user: test
422 422 date: Thu Jan 01 00:00:00 1970 +0000
423 423 summary: 0.3
424 424
425 425 changeset: 2:e38ba6f5b7e0
426 426 phase: public
427 427 user: test
428 428 date: Thu Jan 01 00:00:00 1970 +0000
429 429 summary: 0.2
430 430
431 431 changeset: 1:34c2bf6b0626
432 432 phase: public
433 433 user: test
434 434 date: Thu Jan 01 00:00:00 1970 +0000
435 435 summary: 0.1
436 436
437 437 changeset: 0:f9ee2f85a263
438 438 phase: public
439 439 user: test
440 440 date: Thu Jan 01 00:00:00 1970 +0000
441 441 summary: 0.0
442 442
443 443
444 444 Incoming full.hg in partial
445 445
446 446 $ hg incoming bundle://../full.hg
447 447 comparing with bundle:../full.hg
448 448 searching for changes
449 449 changeset: 4:095197eb4973
450 450 parent: 0:f9ee2f85a263
451 451 user: test
452 452 date: Thu Jan 01 00:00:00 1970 +0000
453 453 summary: 1.1
454 454
455 455 changeset: 5:1bb50a9436a7
456 456 user: test
457 457 date: Thu Jan 01 00:00:00 1970 +0000
458 458 summary: 1.2
459 459
460 460 changeset: 6:7373c1169842
461 461 user: test
462 462 date: Thu Jan 01 00:00:00 1970 +0000
463 463 summary: 1.3
464 464
465 465 changeset: 7:a6a34bfa0076
466 466 user: test
467 467 date: Thu Jan 01 00:00:00 1970 +0000
468 468 summary: 1.3m
469 469
470 470 changeset: 8:aa35859c02ea
471 471 tag: tip
472 472 parent: 3:eebf5a27f8ca
473 473 user: test
474 474 date: Thu Jan 01 00:00:00 1970 +0000
475 475 summary: 0.3m
476 476
477 477
478 478 Outgoing -R full.hg vs partial2 in partial
479 479
480 480 $ hg -R bundle://../full.hg outgoing ../partial2
481 481 comparing with ../partial2
482 482 searching for changes
483 483 changeset: 4:095197eb4973
484 484 parent: 0:f9ee2f85a263
485 485 user: test
486 486 date: Thu Jan 01 00:00:00 1970 +0000
487 487 summary: 1.1
488 488
489 489 changeset: 5:1bb50a9436a7
490 490 user: test
491 491 date: Thu Jan 01 00:00:00 1970 +0000
492 492 summary: 1.2
493 493
494 494 changeset: 6:7373c1169842
495 495 user: test
496 496 date: Thu Jan 01 00:00:00 1970 +0000
497 497 summary: 1.3
498 498
499 499 changeset: 7:a6a34bfa0076
500 500 user: test
501 501 date: Thu Jan 01 00:00:00 1970 +0000
502 502 summary: 1.3m
503 503
504 504 changeset: 8:aa35859c02ea
505 505 tag: tip
506 506 parent: 3:eebf5a27f8ca
507 507 user: test
508 508 date: Thu Jan 01 00:00:00 1970 +0000
509 509 summary: 0.3m
510 510
511 511
512 512 Outgoing -R does-not-exist.hg vs partial2 in partial
513 513
514 514 $ hg -R bundle://../does-not-exist.hg outgoing ../partial2
515 515 abort: *../does-not-exist.hg* (glob)
516 516 [255]
517 517 $ cd ..
518 518
519 519 hide outer repo
520 520 $ hg init
521 521
522 522 Direct clone from bundle (all-history)
523 523
524 524 $ hg clone full.hg full-clone
525 525 requesting all changes
526 526 adding changesets
527 527 adding manifests
528 528 adding file changes
529 529 added 9 changesets with 7 changes to 4 files (+1 heads)
530 530 updating to branch default
531 531 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
532 532 $ hg -R full-clone heads
533 533 changeset: 8:aa35859c02ea
534 534 tag: tip
535 535 parent: 3:eebf5a27f8ca
536 536 user: test
537 537 date: Thu Jan 01 00:00:00 1970 +0000
538 538 summary: 0.3m
539 539
540 540 changeset: 7:a6a34bfa0076
541 541 user: test
542 542 date: Thu Jan 01 00:00:00 1970 +0000
543 543 summary: 1.3m
544 544
545 545 $ rm -r full-clone
546 546
547 547 When cloning from a non-copiable repository into '', do not
548 548 recurse infinitely (issue2528)
549 549
550 550 $ hg clone full.hg ''
551 551 abort: empty destination path is not valid
552 552 [255]
553 553
554 554 test for https://bz.mercurial-scm.org/216
555 555
556 556 Unbundle incremental bundles into fresh empty in one go
557 557
558 558 $ rm -r empty
559 559 $ hg init empty
560 560 $ hg -R test bundle --base null -r 0 ../0.hg
561 561 1 changesets found
562 562 $ hg -R test bundle --base 0 -r 1 ../1.hg
563 563 1 changesets found
564 564 $ hg -R empty unbundle -u ../0.hg ../1.hg
565 565 adding changesets
566 566 adding manifests
567 567 adding file changes
568 568 added 1 changesets with 1 changes to 1 files
569 569 adding changesets
570 570 adding manifests
571 571 adding file changes
572 572 added 1 changesets with 1 changes to 1 files
573 573 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
574 574
575 575 View full contents of the bundle
576 576 $ hg -R test bundle --base null -r 3 ../partial.hg
577 577 4 changesets found
578 578 $ cd test
579 579 $ hg -R ../../partial.hg log -r "bundle()"
580 580 changeset: 0:f9ee2f85a263
581 581 user: test
582 582 date: Thu Jan 01 00:00:00 1970 +0000
583 583 summary: 0.0
584 584
585 585 changeset: 1:34c2bf6b0626
586 586 user: test
587 587 date: Thu Jan 01 00:00:00 1970 +0000
588 588 summary: 0.1
589 589
590 590 changeset: 2:e38ba6f5b7e0
591 591 user: test
592 592 date: Thu Jan 01 00:00:00 1970 +0000
593 593 summary: 0.2
594 594
595 595 changeset: 3:eebf5a27f8ca
596 596 user: test
597 597 date: Thu Jan 01 00:00:00 1970 +0000
598 598 summary: 0.3
599 599
600 600 $ cd ..
601 601
602 602 test for 540d1059c802
603 603
604 604 test for 540d1059c802
605 605
606 606 $ hg init orig
607 607 $ cd orig
608 608 $ echo foo > foo
609 609 $ hg add foo
610 610 $ hg ci -m 'add foo'
611 611
612 612 $ hg clone . ../copy
613 613 updating to branch default
614 614 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
615 615 $ hg tag foo
616 616
617 617 $ cd ../copy
618 618 $ echo >> foo
619 619 $ hg ci -m 'change foo'
620 620 $ hg bundle ../bundle.hg ../orig
621 621 searching for changes
622 622 1 changesets found
623 623
624 624 $ cd ../orig
625 625 $ hg incoming ../bundle.hg
626 626 comparing with ../bundle.hg
627 627 searching for changes
628 628 changeset: 2:ed1b79f46b9a
629 629 tag: tip
630 630 parent: 0:bbd179dfa0a7
631 631 user: test
632 632 date: Thu Jan 01 00:00:00 1970 +0000
633 633 summary: change foo
634 634
635 635 $ cd ..
636 636
637 637 test bundle with # in the filename (issue2154):
638 638
639 639 $ cp bundle.hg 'test#bundle.hg'
640 640 $ cd orig
641 641 $ hg incoming '../test#bundle.hg'
642 642 comparing with ../test
643 643 abort: unknown revision 'bundle.hg'!
644 644 [255]
645 645
646 646 note that percent encoding is not handled:
647 647
648 648 $ hg incoming ../test%23bundle.hg
649 649 abort: repository ../test%23bundle.hg not found!
650 650 [255]
651 651 $ cd ..
652 652
653 653 test to bundle revisions on the newly created branch (issue3828):
654 654
655 655 $ hg -q clone -U test test-clone
656 656 $ cd test
657 657
658 658 $ hg -q branch foo
659 659 $ hg commit -m "create foo branch"
660 660 $ hg -q outgoing ../test-clone
661 661 9:b4f5acb1ee27
662 662 $ hg -q bundle --branch foo foo.hg ../test-clone
663 663 $ hg -R foo.hg -q log -r "bundle()"
664 664 9:b4f5acb1ee27
665 665
666 666 $ cd ..
667 667
668 668 test for https://bz.mercurial-scm.org/1144
669 669
670 670 test that verify bundle does not traceback
671 671
672 672 partial history bundle, fails w/ unknown parent
673 673
674 674 $ hg -R bundle.hg verify
675 675 abort: 00changelog.i@bbd179dfa0a7: unknown parent!
676 676 [255]
677 677
678 678 full history bundle, refuses to verify non-local repo
679 679
680 680 $ hg -R all.hg verify
681 681 abort: cannot verify bundle or remote repos
682 682 [255]
683 683
684 684 but, regular verify must continue to work
685 685
686 686 $ hg -R orig verify
687 687 checking changesets
688 688 checking manifests
689 689 crosschecking files in changesets and manifests
690 690 checking files
691 691 2 files, 2 changesets, 2 total revisions
692 692
693 693 diff against bundle
694 694
695 695 $ hg init b
696 696 $ cd b
697 697 $ hg -R ../all.hg diff -r tip
698 698 diff -r aa35859c02ea anotherfile
699 699 --- a/anotherfile Thu Jan 01 00:00:00 1970 +0000
700 700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
701 701 @@ -1,4 +0,0 @@
702 702 -0
703 703 -1
704 704 -2
705 705 -3
706 706 $ cd ..
707 707
708 708 bundle single branch
709 709
710 710 $ hg init branchy
711 711 $ cd branchy
712 712 $ echo a >a
713 713 $ echo x >x
714 714 $ hg ci -Ama
715 715 adding a
716 716 adding x
717 717 $ echo c >c
718 718 $ echo xx >x
719 719 $ hg ci -Amc
720 720 adding c
721 721 $ echo c1 >c1
722 722 $ hg ci -Amc1
723 723 adding c1
724 724 $ hg up 0
725 725 1 files updated, 0 files merged, 2 files removed, 0 files unresolved
726 726 $ echo b >b
727 727 $ hg ci -Amb
728 728 adding b
729 729 created new head
730 730 $ echo b1 >b1
731 731 $ echo xx >x
732 732 $ hg ci -Amb1
733 733 adding b1
734 734 $ hg clone -q -r2 . part
735 735
736 736 == bundling via incoming
737 737
738 738 $ hg in -R part --bundle incoming.hg --template "{node}\n" .
739 739 comparing with .
740 740 searching for changes
741 741 1a38c1b849e8b70c756d2d80b0b9a3ac0b7ea11a
742 742 057f4db07f61970e1c11e83be79e9d08adc4dc31
743 743
744 744 == bundling
745 745
746 746 $ hg bundle bundle.hg part --debug --config progress.debug=true
747 747 query 1; heads
748 748 searching for changes
749 749 all remote heads known locally
750 750 2 changesets found
751 751 list of changesets:
752 752 1a38c1b849e8b70c756d2d80b0b9a3ac0b7ea11a
753 753 057f4db07f61970e1c11e83be79e9d08adc4dc31
754 754 bundle2-output-bundle: "HG20", (1 params) 1 parts total
755 755 bundle2-output-part: "changegroup" (params: 1 mandatory 1 advisory) streamed payload
756 756 bundling: 1/2 changesets (50.00%)
757 757 bundling: 2/2 changesets (100.00%)
758 758 bundling: 1/2 manifests (50.00%)
759 759 bundling: 2/2 manifests (100.00%)
760 760 bundling: b 1/3 files (33.33%)
761 761 bundling: b1 2/3 files (66.67%)
762 762 bundling: x 3/3 files (100.00%)
763 763
764 764 == Test for issue3441
765 765
766 766 $ hg clone -q -r0 . part2
767 767 $ hg -q -R part2 pull bundle.hg
768 768 $ hg -R part2 verify
769 769 checking changesets
770 770 checking manifests
771 771 crosschecking files in changesets and manifests
772 772 checking files
773 773 4 files, 3 changesets, 5 total revisions
774 774
775 775 == Test bundling no commits
776 776
777 777 $ hg bundle -r 'public()' no-output.hg
778 778 abort: no commits to bundle
779 779 [255]
780 780
781 781 $ cd ..
782 782
783 783 When user merges to the revision existing only in the bundle,
784 784 it should show warning that second parent of the working
785 785 directory does not exist
786 786
787 787 $ hg init update2bundled
788 788 $ cd update2bundled
789 789 $ cat <<EOF >> .hg/hgrc
790 790 > [extensions]
791 791 > strip =
792 792 > EOF
793 793 $ echo "aaa" >> a
794 794 $ hg commit -A -m 0
795 795 adding a
796 796 $ echo "bbb" >> b
797 797 $ hg commit -A -m 1
798 798 adding b
799 799 $ echo "ccc" >> c
800 800 $ hg commit -A -m 2
801 801 adding c
802 802 $ hg update -r 1
803 803 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
804 804 $ echo "ddd" >> d
805 805 $ hg commit -A -m 3
806 806 adding d
807 807 created new head
808 808 $ hg update -r 2
809 809 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
810 810 $ hg log -G
811 811 o changeset: 3:8bd3e1f196af
812 812 | tag: tip
813 813 | parent: 1:a01eca7af26d
814 814 | user: test
815 815 | date: Thu Jan 01 00:00:00 1970 +0000
816 816 | summary: 3
817 817 |
818 818 | @ changeset: 2:4652c276ac4f
819 819 |/ user: test
820 820 | date: Thu Jan 01 00:00:00 1970 +0000
821 821 | summary: 2
822 822 |
823 823 o changeset: 1:a01eca7af26d
824 824 | user: test
825 825 | date: Thu Jan 01 00:00:00 1970 +0000
826 826 | summary: 1
827 827 |
828 828 o changeset: 0:4fe08cd4693e
829 829 user: test
830 830 date: Thu Jan 01 00:00:00 1970 +0000
831 831 summary: 0
832 832
833 833 $ hg bundle --base 1 -r 3 ../update2bundled.hg
834 834 1 changesets found
835 835 $ hg strip -r 3
836 836 saved backup bundle to $TESTTMP/update2bundled/.hg/strip-backup/8bd3e1f196af-017e56d8-backup.hg (glob)
837 837 $ hg merge -R ../update2bundled.hg -r 3
838 838 setting parent to node 8bd3e1f196af289b2b121be08031e76d7ae92098 that only exists in the bundle
839 839 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
840 840 (branch merge, don't forget to commit)
841 841
842 842 When user updates to the revision existing only in the bundle,
843 843 it should show warning
844 844
845 845 $ hg update -R ../update2bundled.hg --clean -r 3
846 846 setting parent to node 8bd3e1f196af289b2b121be08031e76d7ae92098 that only exists in the bundle
847 847 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
848 848
849 849 When user updates to the revision existing in the local repository
850 850 the warning shouldn't be emitted
851 851
852 852 $ hg update -R ../update2bundled.hg -r 0
853 853 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
@@ -1,1136 +1,1136
1 1 Test exchange of common information using bundle2
2 2
3 3
4 4 $ getmainid() {
5 5 > hg -R main log --template '{node}\n' --rev "$1"
6 6 > }
7 7
8 8 enable obsolescence
9 9
10 10 $ cp $HGRCPATH $TESTTMP/hgrc.orig
11 11 $ cat > $TESTTMP/bundle2-pushkey-hook.sh << EOF
12 12 > echo pushkey: lock state after \"\$HG_NAMESPACE\"
13 13 > hg debuglock
14 14 > EOF
15 15
16 16 $ cat >> $HGRCPATH << EOF
17 17 > [experimental]
18 18 > evolution=createmarkers,exchange
19 19 > bundle2-output-capture=True
20 20 > [ui]
21 21 > ssh=python "$TESTDIR/dummyssh"
22 22 > logtemplate={rev}:{node|short} {phase} {author} {bookmarks} {desc|firstline}
23 23 > [web]
24 24 > push_ssl = false
25 25 > allow_push = *
26 26 > [phases]
27 27 > publish=False
28 28 > [hooks]
29 29 > pretxnclose.tip = hg log -r tip -T "pre-close-tip:{node|short} {phase} {bookmarks}\n"
30 30 > txnclose.tip = hg log -r tip -T "postclose-tip:{node|short} {phase} {bookmarks}\n"
31 31 > txnclose.env = sh -c "HG_LOCAL= printenv.py txnclose"
32 32 > pushkey= sh "$TESTTMP/bundle2-pushkey-hook.sh"
33 33 > EOF
34 34
35 35 The extension requires a repo (currently unused)
36 36
37 37 $ hg init main
38 38 $ cd main
39 39 $ touch a
40 40 $ hg add a
41 41 $ hg commit -m 'a'
42 42 pre-close-tip:3903775176ed draft
43 43 postclose-tip:3903775176ed draft
44 txnclose hook: HG_HOOKTYPE=txnclose HG_PHASES_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=commit
44 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_PHASES_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=commit
45 45
46 46 $ hg unbundle $TESTDIR/bundles/rebase.hg
47 47 adding changesets
48 48 adding manifests
49 49 adding file changes
50 50 added 8 changesets with 7 changes to 7 files (+3 heads)
51 51 pre-close-tip:02de42196ebe draft
52 52 postclose-tip:02de42196ebe draft
53 txnclose hook: HG_HOOKTYPE=txnclose HG_NODE=cd010b8cd998f3981a5a8115f94f8da4ab506089 HG_NODE_LAST=02de42196ebee42ef284b6780a87cdc96e8eaab6 HG_PHASES_MOVED=1 HG_SOURCE=unbundle HG_TXNID=TXN:$ID$ HG_TXNNAME=unbundle
53 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NODE=cd010b8cd998f3981a5a8115f94f8da4ab506089 HG_NODE_LAST=02de42196ebee42ef284b6780a87cdc96e8eaab6 HG_PHASES_MOVED=1 HG_SOURCE=unbundle HG_TXNID=TXN:$ID$ HG_TXNNAME=unbundle
54 54 bundle:*/tests/bundles/rebase.hg HG_URL=bundle:*/tests/bundles/rebase.hg (glob)
55 55 (run 'hg heads' to see heads, 'hg merge' to merge)
56 56
57 57 $ cd ..
58 58
59 59 Real world exchange
60 60 =====================
61 61
62 62 Add more obsolescence information
63 63
64 64 $ hg -R main debugobsolete -d '0 0' 1111111111111111111111111111111111111111 `getmainid 9520eea781bc`
65 65 pre-close-tip:02de42196ebe draft
66 66 postclose-tip:02de42196ebe draft
67 txnclose hook: HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=debugobsolete
67 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=debugobsolete
68 68 $ hg -R main debugobsolete -d '0 0' 2222222222222222222222222222222222222222 `getmainid 24b6387c8c8c`
69 69 pre-close-tip:02de42196ebe draft
70 70 postclose-tip:02de42196ebe draft
71 txnclose hook: HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=debugobsolete
71 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=debugobsolete
72 72
73 73 clone --pull
74 74
75 75 $ hg -R main phase --public cd010b8cd998
76 76 pre-close-tip:02de42196ebe draft
77 77 postclose-tip:02de42196ebe draft
78 txnclose hook: HG_HOOKTYPE=txnclose HG_PHASES_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=phase
78 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_PHASES_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=phase
79 79 $ hg clone main other --pull --rev 9520eea781bc
80 80 adding changesets
81 81 adding manifests
82 82 adding file changes
83 83 added 2 changesets with 2 changes to 2 files
84 84 1 new obsolescence markers
85 85 pre-close-tip:9520eea781bc draft
86 86 postclose-tip:9520eea781bc draft
87 txnclose hook: HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_NODE=cd010b8cd998f3981a5a8115f94f8da4ab506089 HG_NODE_LAST=9520eea781bcca16c1e15acc0ba14335a0e8e5ba HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_TXNNAME=pull
87 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_NODE=cd010b8cd998f3981a5a8115f94f8da4ab506089 HG_NODE_LAST=9520eea781bcca16c1e15acc0ba14335a0e8e5ba HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_TXNNAME=pull
88 88 file:/*/$TESTTMP/main HG_URL=file:$TESTTMP/main (glob)
89 89 updating to branch default
90 90 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
91 91 $ hg -R other log -G
92 92 @ 1:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E
93 93 |
94 94 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A
95 95
96 96 $ hg -R other debugobsolete
97 97 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
98 98
99 99 pull
100 100
101 101 $ hg -R main phase --public 9520eea781bc
102 102 pre-close-tip:02de42196ebe draft
103 103 postclose-tip:02de42196ebe draft
104 txnclose hook: HG_HOOKTYPE=txnclose HG_PHASES_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=phase
104 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_PHASES_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=phase
105 105 $ hg -R other pull -r 24b6387c8c8c
106 106 pulling from $TESTTMP/main (glob)
107 107 searching for changes
108 108 adding changesets
109 109 adding manifests
110 110 adding file changes
111 111 added 1 changesets with 1 changes to 1 files (+1 heads)
112 112 1 new obsolescence markers
113 113 pre-close-tip:24b6387c8c8c draft
114 114 postclose-tip:24b6387c8c8c draft
115 txnclose hook: HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_NODE=24b6387c8c8cae37178880f3fa95ded3cb1cf785 HG_NODE_LAST=24b6387c8c8cae37178880f3fa95ded3cb1cf785 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_TXNNAME=pull
115 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_NODE=24b6387c8c8cae37178880f3fa95ded3cb1cf785 HG_NODE_LAST=24b6387c8c8cae37178880f3fa95ded3cb1cf785 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_TXNNAME=pull
116 116 file:/*/$TESTTMP/main HG_URL=file:$TESTTMP/main (glob)
117 117 (run 'hg heads' to see heads, 'hg merge' to merge)
118 118 $ hg -R other log -G
119 119 o 2:24b6387c8c8c draft Nicolas Dumazet <nicdumz.commits@gmail.com> F
120 120 |
121 121 | @ 1:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E
122 122 |/
123 123 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A
124 124
125 125 $ hg -R other debugobsolete
126 126 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
127 127 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
128 128
129 129 pull empty (with phase movement)
130 130
131 131 $ hg -R main phase --public 24b6387c8c8c
132 132 pre-close-tip:02de42196ebe draft
133 133 postclose-tip:02de42196ebe draft
134 txnclose hook: HG_HOOKTYPE=txnclose HG_PHASES_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=phase
134 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_PHASES_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=phase
135 135 $ hg -R other pull -r 24b6387c8c8c
136 136 pulling from $TESTTMP/main (glob)
137 137 no changes found
138 138 pre-close-tip:24b6387c8c8c public
139 139 postclose-tip:24b6387c8c8c public
140 txnclose hook: HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=0 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_TXNNAME=pull
140 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=0 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_TXNNAME=pull
141 141 file:/*/$TESTTMP/main HG_URL=file:$TESTTMP/main (glob)
142 142 $ hg -R other log -G
143 143 o 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F
144 144 |
145 145 | @ 1:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E
146 146 |/
147 147 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A
148 148
149 149 $ hg -R other debugobsolete
150 150 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
151 151 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
152 152
153 153 pull empty
154 154
155 155 $ hg -R other pull -r 24b6387c8c8c
156 156 pulling from $TESTTMP/main (glob)
157 157 no changes found
158 158 pre-close-tip:24b6387c8c8c public
159 159 postclose-tip:24b6387c8c8c public
160 txnclose hook: HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=0 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_TXNNAME=pull
160 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=0 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_TXNNAME=pull
161 161 file:/*/$TESTTMP/main HG_URL=file:$TESTTMP/main (glob)
162 162 $ hg -R other log -G
163 163 o 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F
164 164 |
165 165 | @ 1:9520eea781bc draft Nicolas Dumazet <nicdumz.commits@gmail.com> E
166 166 |/
167 167 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A
168 168
169 169 $ hg -R other debugobsolete
170 170 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
171 171 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
172 172
173 173 add extra data to test their exchange during push
174 174
175 175 $ hg -R main bookmark --rev eea13746799a book_eea1
176 176 pre-close-tip:02de42196ebe draft
177 177 postclose-tip:02de42196ebe draft
178 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
178 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
179 179 $ hg -R main debugobsolete -d '0 0' 3333333333333333333333333333333333333333 `getmainid eea13746799a`
180 180 pre-close-tip:02de42196ebe draft
181 181 postclose-tip:02de42196ebe draft
182 txnclose hook: HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=debugobsolete
182 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=debugobsolete
183 183 $ hg -R main bookmark --rev 02de42196ebe book_02de
184 184 pre-close-tip:02de42196ebe draft book_02de
185 185 postclose-tip:02de42196ebe draft book_02de
186 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
186 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
187 187 $ hg -R main debugobsolete -d '0 0' 4444444444444444444444444444444444444444 `getmainid 02de42196ebe`
188 188 pre-close-tip:02de42196ebe draft book_02de
189 189 postclose-tip:02de42196ebe draft book_02de
190 txnclose hook: HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=debugobsolete
190 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=debugobsolete
191 191 $ hg -R main bookmark --rev 42ccdea3bb16 book_42cc
192 192 pre-close-tip:02de42196ebe draft book_02de
193 193 postclose-tip:02de42196ebe draft book_02de
194 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
194 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
195 195 $ hg -R main debugobsolete -d '0 0' 5555555555555555555555555555555555555555 `getmainid 42ccdea3bb16`
196 196 pre-close-tip:02de42196ebe draft book_02de
197 197 postclose-tip:02de42196ebe draft book_02de
198 txnclose hook: HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=debugobsolete
198 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=debugobsolete
199 199 $ hg -R main bookmark --rev 5fddd98957c8 book_5fdd
200 200 pre-close-tip:02de42196ebe draft book_02de
201 201 postclose-tip:02de42196ebe draft book_02de
202 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
202 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
203 203 $ hg -R main debugobsolete -d '0 0' 6666666666666666666666666666666666666666 `getmainid 5fddd98957c8`
204 204 pre-close-tip:02de42196ebe draft book_02de
205 205 postclose-tip:02de42196ebe draft book_02de
206 txnclose hook: HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=debugobsolete
206 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=debugobsolete
207 207 $ hg -R main bookmark --rev 32af7686d403 book_32af
208 208 pre-close-tip:02de42196ebe draft book_02de
209 209 postclose-tip:02de42196ebe draft book_02de
210 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
210 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
211 211 $ hg -R main debugobsolete -d '0 0' 7777777777777777777777777777777777777777 `getmainid 32af7686d403`
212 212 pre-close-tip:02de42196ebe draft book_02de
213 213 postclose-tip:02de42196ebe draft book_02de
214 txnclose hook: HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=debugobsolete
214 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=debugobsolete
215 215
216 216 $ hg -R other bookmark --rev cd010b8cd998 book_eea1
217 217 pre-close-tip:24b6387c8c8c public
218 218 postclose-tip:24b6387c8c8c public
219 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
219 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
220 220 $ hg -R other bookmark --rev cd010b8cd998 book_02de
221 221 pre-close-tip:24b6387c8c8c public
222 222 postclose-tip:24b6387c8c8c public
223 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
223 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
224 224 $ hg -R other bookmark --rev cd010b8cd998 book_42cc
225 225 pre-close-tip:24b6387c8c8c public
226 226 postclose-tip:24b6387c8c8c public
227 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
227 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
228 228 $ hg -R other bookmark --rev cd010b8cd998 book_5fdd
229 229 pre-close-tip:24b6387c8c8c public
230 230 postclose-tip:24b6387c8c8c public
231 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
231 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
232 232 $ hg -R other bookmark --rev cd010b8cd998 book_32af
233 233 pre-close-tip:24b6387c8c8c public
234 234 postclose-tip:24b6387c8c8c public
235 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
235 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
236 236
237 237 $ hg -R main phase --public eea13746799a
238 238 pre-close-tip:02de42196ebe draft book_02de
239 239 postclose-tip:02de42196ebe draft book_02de
240 txnclose hook: HG_HOOKTYPE=txnclose HG_PHASES_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=phase
240 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_PHASES_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=phase
241 241
242 242 push
243 243 $ hg -R main push other --rev eea13746799a --bookmark book_eea1
244 244 pushing to other
245 245 searching for changes
246 246 remote: adding changesets
247 247 remote: adding manifests
248 248 remote: adding file changes
249 249 remote: added 1 changesets with 0 changes to 0 files (-1 heads)
250 250 remote: 1 new obsolescence markers
251 251 remote: pre-close-tip:eea13746799a public book_eea1
252 252 remote: pushkey: lock state after "phases"
253 253 remote: lock: free
254 254 remote: wlock: free
255 255 remote: pushkey: lock state after "bookmarks"
256 256 remote: lock: free
257 257 remote: wlock: free
258 258 remote: postclose-tip:eea13746799a public book_eea1
259 remote: txnclose hook: HG_BOOKMARK_MOVED=1 HG_BUNDLE2=1 HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_NODE=eea13746799a9e0bfd88f29d3c2e9dc9389f524f HG_NODE_LAST=eea13746799a9e0bfd88f29d3c2e9dc9389f524f HG_PHASES_MOVED=1 HG_SOURCE=push HG_TXNID=TXN:$ID$ HG_TXNNAME=push HG_URL=file:$TESTTMP/other
259 remote: txnclose hook: HG_BOOKMARK_MOVED=1 HG_BUNDLE2=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_NODE=eea13746799a9e0bfd88f29d3c2e9dc9389f524f HG_NODE_LAST=eea13746799a9e0bfd88f29d3c2e9dc9389f524f HG_PHASES_MOVED=1 HG_SOURCE=push HG_TXNID=TXN:$ID$ HG_TXNNAME=push HG_URL=file:$TESTTMP/other
260 260 updating bookmark book_eea1
261 261 pre-close-tip:02de42196ebe draft book_02de
262 262 postclose-tip:02de42196ebe draft book_02de
263 txnclose hook: HG_HOOKTYPE=txnclose HG_SOURCE=push-response HG_TXNID=TXN:$ID$ HG_TXNNAME=push-response
263 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_SOURCE=push-response HG_TXNID=TXN:$ID$ HG_TXNNAME=push-response
264 264 file:/*/$TESTTMP/other HG_URL=file:$TESTTMP/other (glob)
265 265 $ hg -R other log -G
266 266 o 3:eea13746799a public Nicolas Dumazet <nicdumz.commits@gmail.com> book_eea1 G
267 267 |\
268 268 | o 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F
269 269 | |
270 270 @ | 1:9520eea781bc public Nicolas Dumazet <nicdumz.commits@gmail.com> E
271 271 |/
272 272 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_02de book_32af book_42cc book_5fdd A
273 273
274 274 $ hg -R other debugobsolete
275 275 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
276 276 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
277 277 3333333333333333333333333333333333333333 eea13746799a9e0bfd88f29d3c2e9dc9389f524f 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
278 278
279 279 pull over ssh
280 280
281 281 $ hg -R other pull ssh://user@dummy/main -r 02de42196ebe --bookmark book_02de
282 282 pulling from ssh://user@dummy/main
283 283 searching for changes
284 284 adding changesets
285 285 adding manifests
286 286 adding file changes
287 287 added 1 changesets with 1 changes to 1 files (+1 heads)
288 288 1 new obsolescence markers
289 289 updating bookmark book_02de
290 290 pre-close-tip:02de42196ebe draft book_02de
291 291 postclose-tip:02de42196ebe draft book_02de
292 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_NODE=02de42196ebee42ef284b6780a87cdc96e8eaab6 HG_NODE_LAST=02de42196ebee42ef284b6780a87cdc96e8eaab6 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_TXNNAME=pull
292 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_NODE=02de42196ebee42ef284b6780a87cdc96e8eaab6 HG_NODE_LAST=02de42196ebee42ef284b6780a87cdc96e8eaab6 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_TXNNAME=pull
293 293 ssh://user@dummy/main HG_URL=ssh://user@dummy/main
294 294 (run 'hg heads' to see heads, 'hg merge' to merge)
295 295 $ hg -R other debugobsolete
296 296 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
297 297 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
298 298 3333333333333333333333333333333333333333 eea13746799a9e0bfd88f29d3c2e9dc9389f524f 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
299 299 4444444444444444444444444444444444444444 02de42196ebee42ef284b6780a87cdc96e8eaab6 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
300 300
301 301 pull over http
302 302
303 303 $ hg serve -R main -p $HGPORT -d --pid-file=main.pid -E main-error.log
304 304 $ cat main.pid >> $DAEMON_PIDS
305 305
306 306 $ hg -R other pull http://localhost:$HGPORT/ -r 42ccdea3bb16 --bookmark book_42cc
307 307 pulling from http://localhost:$HGPORT/
308 308 searching for changes
309 309 adding changesets
310 310 adding manifests
311 311 adding file changes
312 312 added 1 changesets with 1 changes to 1 files (+1 heads)
313 313 1 new obsolescence markers
314 314 updating bookmark book_42cc
315 315 pre-close-tip:42ccdea3bb16 draft book_42cc
316 316 postclose-tip:42ccdea3bb16 draft book_42cc
317 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_NODE=42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 HG_NODE_LAST=42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_TXNNAME=pull
317 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_NODE=42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 HG_NODE_LAST=42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_TXNNAME=pull
318 318 http://localhost:$HGPORT/ HG_URL=http://localhost:$HGPORT/
319 319 (run 'hg heads .' to see heads, 'hg merge' to merge)
320 320 $ cat main-error.log
321 321 $ hg -R other debugobsolete
322 322 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
323 323 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
324 324 3333333333333333333333333333333333333333 eea13746799a9e0bfd88f29d3c2e9dc9389f524f 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
325 325 4444444444444444444444444444444444444444 02de42196ebee42ef284b6780a87cdc96e8eaab6 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
326 326 5555555555555555555555555555555555555555 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
327 327
328 328 push over ssh
329 329
330 330 $ hg -R main push ssh://user@dummy/other -r 5fddd98957c8 --bookmark book_5fdd
331 331 pushing to ssh://user@dummy/other
332 332 searching for changes
333 333 remote: adding changesets
334 334 remote: adding manifests
335 335 remote: adding file changes
336 336 remote: added 1 changesets with 1 changes to 1 files
337 337 remote: 1 new obsolescence markers
338 338 remote: pre-close-tip:5fddd98957c8 draft book_5fdd
339 339 remote: pushkey: lock state after "bookmarks"
340 340 remote: lock: free
341 341 remote: wlock: free
342 342 remote: postclose-tip:5fddd98957c8 draft book_5fdd
343 remote: txnclose hook: HG_BOOKMARK_MOVED=1 HG_BUNDLE2=1 HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_NODE=5fddd98957c8a54a4d436dfe1da9d87f21a1b97b HG_NODE_LAST=5fddd98957c8a54a4d436dfe1da9d87f21a1b97b HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_TXNNAME=serve HG_URL=remote:ssh:$LOCALIP
343 remote: txnclose hook: HG_BOOKMARK_MOVED=1 HG_BUNDLE2=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_NODE=5fddd98957c8a54a4d436dfe1da9d87f21a1b97b HG_NODE_LAST=5fddd98957c8a54a4d436dfe1da9d87f21a1b97b HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_TXNNAME=serve HG_URL=remote:ssh:$LOCALIP
344 344 updating bookmark book_5fdd
345 345 pre-close-tip:02de42196ebe draft book_02de
346 346 postclose-tip:02de42196ebe draft book_02de
347 txnclose hook: HG_HOOKTYPE=txnclose HG_SOURCE=push-response HG_TXNID=TXN:$ID$ HG_TXNNAME=push-response
347 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_SOURCE=push-response HG_TXNID=TXN:$ID$ HG_TXNNAME=push-response
348 348 ssh://user@dummy/other HG_URL=ssh://user@dummy/other
349 349 $ hg -R other log -G
350 350 o 6:5fddd98957c8 draft Nicolas Dumazet <nicdumz.commits@gmail.com> book_5fdd C
351 351 |
352 352 o 5:42ccdea3bb16 draft Nicolas Dumazet <nicdumz.commits@gmail.com> book_42cc B
353 353 |
354 354 | o 4:02de42196ebe draft Nicolas Dumazet <nicdumz.commits@gmail.com> book_02de H
355 355 | |
356 356 | | o 3:eea13746799a public Nicolas Dumazet <nicdumz.commits@gmail.com> book_eea1 G
357 357 | |/|
358 358 | o | 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F
359 359 |/ /
360 360 | @ 1:9520eea781bc public Nicolas Dumazet <nicdumz.commits@gmail.com> E
361 361 |/
362 362 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_32af A
363 363
364 364 $ hg -R other debugobsolete
365 365 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
366 366 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
367 367 3333333333333333333333333333333333333333 eea13746799a9e0bfd88f29d3c2e9dc9389f524f 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
368 368 4444444444444444444444444444444444444444 02de42196ebee42ef284b6780a87cdc96e8eaab6 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
369 369 5555555555555555555555555555555555555555 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
370 370 6666666666666666666666666666666666666666 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
371 371
372 372 push over http
373 373
374 374 $ hg serve -R other -p $HGPORT2 -d --pid-file=other.pid -E other-error.log
375 375 $ cat other.pid >> $DAEMON_PIDS
376 376
377 377 $ hg -R main phase --public 32af7686d403
378 378 pre-close-tip:02de42196ebe draft book_02de
379 379 postclose-tip:02de42196ebe draft book_02de
380 txnclose hook: HG_HOOKTYPE=txnclose HG_PHASES_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=phase
380 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_PHASES_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=phase
381 381 $ hg -R main push http://localhost:$HGPORT2/ -r 32af7686d403 --bookmark book_32af
382 382 pushing to http://localhost:$HGPORT2/
383 383 searching for changes
384 384 remote: adding changesets
385 385 remote: adding manifests
386 386 remote: adding file changes
387 387 remote: added 1 changesets with 1 changes to 1 files
388 388 remote: 1 new obsolescence markers
389 389 remote: pre-close-tip:32af7686d403 public book_32af
390 390 remote: pushkey: lock state after "phases"
391 391 remote: lock: free
392 392 remote: wlock: free
393 393 remote: pushkey: lock state after "bookmarks"
394 394 remote: lock: free
395 395 remote: wlock: free
396 396 remote: postclose-tip:32af7686d403 public book_32af
397 remote: txnclose hook: HG_BOOKMARK_MOVED=1 HG_BUNDLE2=1 HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_NODE=32af7686d403cf45b5d95f2d70cebea587ac806a HG_NODE_LAST=32af7686d403cf45b5d95f2d70cebea587ac806a HG_PHASES_MOVED=1 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_TXNNAME=serve HG_URL=remote:http:$LOCALIP:
397 remote: txnclose hook: HG_BOOKMARK_MOVED=1 HG_BUNDLE2=1 HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_NEW_OBSMARKERS=1 HG_NODE=32af7686d403cf45b5d95f2d70cebea587ac806a HG_NODE_LAST=32af7686d403cf45b5d95f2d70cebea587ac806a HG_PHASES_MOVED=1 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_TXNNAME=serve HG_URL=remote:http:$LOCALIP:
398 398 updating bookmark book_32af
399 399 pre-close-tip:02de42196ebe draft book_02de
400 400 postclose-tip:02de42196ebe draft book_02de
401 txnclose hook: HG_HOOKTYPE=txnclose HG_SOURCE=push-response HG_TXNID=TXN:$ID$ HG_TXNNAME=push-response
401 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_SOURCE=push-response HG_TXNID=TXN:$ID$ HG_TXNNAME=push-response
402 402 http://localhost:$HGPORT2/ HG_URL=http://localhost:$HGPORT2/
403 403 $ cat other-error.log
404 404
405 405 Check final content.
406 406
407 407 $ hg -R other log -G
408 408 o 7:32af7686d403 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_32af D
409 409 |
410 410 o 6:5fddd98957c8 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_5fdd C
411 411 |
412 412 o 5:42ccdea3bb16 public Nicolas Dumazet <nicdumz.commits@gmail.com> book_42cc B
413 413 |
414 414 | o 4:02de42196ebe draft Nicolas Dumazet <nicdumz.commits@gmail.com> book_02de H
415 415 | |
416 416 | | o 3:eea13746799a public Nicolas Dumazet <nicdumz.commits@gmail.com> book_eea1 G
417 417 | |/|
418 418 | o | 2:24b6387c8c8c public Nicolas Dumazet <nicdumz.commits@gmail.com> F
419 419 |/ /
420 420 | @ 1:9520eea781bc public Nicolas Dumazet <nicdumz.commits@gmail.com> E
421 421 |/
422 422 o 0:cd010b8cd998 public Nicolas Dumazet <nicdumz.commits@gmail.com> A
423 423
424 424 $ hg -R other debugobsolete
425 425 1111111111111111111111111111111111111111 9520eea781bcca16c1e15acc0ba14335a0e8e5ba 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
426 426 2222222222222222222222222222222222222222 24b6387c8c8cae37178880f3fa95ded3cb1cf785 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
427 427 3333333333333333333333333333333333333333 eea13746799a9e0bfd88f29d3c2e9dc9389f524f 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
428 428 4444444444444444444444444444444444444444 02de42196ebee42ef284b6780a87cdc96e8eaab6 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
429 429 5555555555555555555555555555555555555555 42ccdea3bb16d28e1848c95fe2e44c000f3f21b1 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
430 430 6666666666666666666666666666666666666666 5fddd98957c8a54a4d436dfe1da9d87f21a1b97b 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
431 431 7777777777777777777777777777777777777777 32af7686d403cf45b5d95f2d70cebea587ac806a 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
432 432
433 433 (check that no 'pending' files remain)
434 434
435 435 $ ls -1 other/.hg/bookmarks*
436 436 other/.hg/bookmarks
437 437 $ ls -1 other/.hg/store/phaseroots*
438 438 other/.hg/store/phaseroots
439 439 $ ls -1 other/.hg/store/00changelog.i*
440 440 other/.hg/store/00changelog.i
441 441
442 442 Error Handling
443 443 ==============
444 444
445 445 Check that errors are properly returned to the client during push.
446 446
447 447 Setting up
448 448
449 449 $ cat > failpush.py << EOF
450 450 > """A small extension that makes push fails when using bundle2
451 451 >
452 452 > used to test error handling in bundle2
453 453 > """
454 454 >
455 455 > from mercurial import error
456 456 > from mercurial import bundle2
457 457 > from mercurial import exchange
458 458 > from mercurial import extensions
459 459 >
460 460 > def _pushbundle2failpart(pushop, bundler):
461 461 > reason = pushop.ui.config('failpush', 'reason', None)
462 462 > part = None
463 463 > if reason == 'abort':
464 464 > bundler.newpart('test:abort')
465 465 > if reason == 'unknown':
466 466 > bundler.newpart('test:unknown')
467 467 > if reason == 'race':
468 468 > # 20 Bytes of crap
469 469 > bundler.newpart('check:heads', data='01234567890123456789')
470 470 >
471 471 > @bundle2.parthandler("test:abort")
472 472 > def handleabort(op, part):
473 473 > raise error.Abort('Abandon ship!', hint="don't panic")
474 474 >
475 475 > def uisetup(ui):
476 476 > exchange.b2partsgenmapping['failpart'] = _pushbundle2failpart
477 477 > exchange.b2partsgenorder.insert(0, 'failpart')
478 478 >
479 479 > EOF
480 480
481 481 $ cd main
482 482 $ hg up tip
483 483 3 files updated, 0 files merged, 1 files removed, 0 files unresolved
484 484 $ echo 'I' > I
485 485 $ hg add I
486 486 $ hg ci -m 'I'
487 487 pre-close-tip:e7ec4e813ba6 draft
488 488 postclose-tip:e7ec4e813ba6 draft
489 txnclose hook: HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=commit
489 txnclose hook: HG_HOOKNAME=txnclose.env HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=commit
490 490 $ hg id
491 491 e7ec4e813ba6 tip
492 492 $ cd ..
493 493
494 494 $ cat << EOF >> $HGRCPATH
495 495 > [extensions]
496 496 > failpush=$TESTTMP/failpush.py
497 497 > EOF
498 498
499 499 $ killdaemons.py
500 500 $ hg serve -R other -p $HGPORT2 -d --pid-file=other.pid -E other-error.log
501 501 $ cat other.pid >> $DAEMON_PIDS
502 502
503 503 Doing the actual push: Abort error
504 504
505 505 $ cat << EOF >> $HGRCPATH
506 506 > [failpush]
507 507 > reason = abort
508 508 > EOF
509 509
510 510 $ hg -R main push other -r e7ec4e813ba6
511 511 pushing to other
512 512 searching for changes
513 513 abort: Abandon ship!
514 514 (don't panic)
515 515 [255]
516 516
517 517 $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6
518 518 pushing to ssh://user@dummy/other
519 519 searching for changes
520 520 remote: Abandon ship!
521 521 remote: (don't panic)
522 522 abort: push failed on remote
523 523 [255]
524 524
525 525 $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6
526 526 pushing to http://localhost:$HGPORT2/
527 527 searching for changes
528 528 remote: Abandon ship!
529 529 remote: (don't panic)
530 530 abort: push failed on remote
531 531 [255]
532 532
533 533
534 534 Doing the actual push: unknown mandatory parts
535 535
536 536 $ cat << EOF >> $HGRCPATH
537 537 > [failpush]
538 538 > reason = unknown
539 539 > EOF
540 540
541 541 $ hg -R main push other -r e7ec4e813ba6
542 542 pushing to other
543 543 searching for changes
544 544 abort: missing support for test:unknown
545 545 [255]
546 546
547 547 $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6
548 548 pushing to ssh://user@dummy/other
549 549 searching for changes
550 550 abort: missing support for test:unknown
551 551 [255]
552 552
553 553 $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6
554 554 pushing to http://localhost:$HGPORT2/
555 555 searching for changes
556 556 abort: missing support for test:unknown
557 557 [255]
558 558
559 559 Doing the actual push: race
560 560
561 561 $ cat << EOF >> $HGRCPATH
562 562 > [failpush]
563 563 > reason = race
564 564 > EOF
565 565
566 566 $ hg -R main push other -r e7ec4e813ba6
567 567 pushing to other
568 568 searching for changes
569 569 abort: push failed:
570 570 'repository changed while pushing - please try again'
571 571 [255]
572 572
573 573 $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6
574 574 pushing to ssh://user@dummy/other
575 575 searching for changes
576 576 abort: push failed:
577 577 'repository changed while pushing - please try again'
578 578 [255]
579 579
580 580 $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6
581 581 pushing to http://localhost:$HGPORT2/
582 582 searching for changes
583 583 abort: push failed:
584 584 'repository changed while pushing - please try again'
585 585 [255]
586 586
587 587 Doing the actual push: hook abort
588 588
589 589 $ cat << EOF >> $HGRCPATH
590 590 > [failpush]
591 591 > reason =
592 592 > [hooks]
593 593 > pretxnclose.failpush = sh -c "echo 'You shall not pass!'; false"
594 594 > txnabort.failpush = sh -c "echo 'Cleaning up the mess...'"
595 595 > EOF
596 596
597 597 $ killdaemons.py
598 598 $ hg serve -R other -p $HGPORT2 -d --pid-file=other.pid -E other-error.log
599 599 $ cat other.pid >> $DAEMON_PIDS
600 600
601 601 $ hg -R main push other -r e7ec4e813ba6
602 602 pushing to other
603 603 searching for changes
604 604 remote: adding changesets
605 605 remote: adding manifests
606 606 remote: adding file changes
607 607 remote: added 1 changesets with 1 changes to 1 files
608 608 remote: pre-close-tip:e7ec4e813ba6 draft
609 609 remote: You shall not pass!
610 610 remote: transaction abort!
611 611 remote: Cleaning up the mess...
612 612 remote: rollback completed
613 613 abort: pretxnclose.failpush hook exited with status 1
614 614 [255]
615 615
616 616 $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6
617 617 pushing to ssh://user@dummy/other
618 618 searching for changes
619 619 remote: adding changesets
620 620 remote: adding manifests
621 621 remote: adding file changes
622 622 remote: added 1 changesets with 1 changes to 1 files
623 623 remote: pre-close-tip:e7ec4e813ba6 draft
624 624 remote: You shall not pass!
625 625 remote: transaction abort!
626 626 remote: Cleaning up the mess...
627 627 remote: rollback completed
628 628 remote: pretxnclose.failpush hook exited with status 1
629 629 abort: push failed on remote
630 630 [255]
631 631
632 632 $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6
633 633 pushing to http://localhost:$HGPORT2/
634 634 searching for changes
635 635 remote: adding changesets
636 636 remote: adding manifests
637 637 remote: adding file changes
638 638 remote: added 1 changesets with 1 changes to 1 files
639 639 remote: pre-close-tip:e7ec4e813ba6 draft
640 640 remote: You shall not pass!
641 641 remote: transaction abort!
642 642 remote: Cleaning up the mess...
643 643 remote: rollback completed
644 644 remote: pretxnclose.failpush hook exited with status 1
645 645 abort: push failed on remote
646 646 [255]
647 647
648 648 (check that no 'pending' files remain)
649 649
650 650 $ ls -1 other/.hg/bookmarks*
651 651 other/.hg/bookmarks
652 652 $ ls -1 other/.hg/store/phaseroots*
653 653 other/.hg/store/phaseroots
654 654 $ ls -1 other/.hg/store/00changelog.i*
655 655 other/.hg/store/00changelog.i
656 656
657 657 Check error from hook during the unbundling process itself
658 658
659 659 $ cat << EOF >> $HGRCPATH
660 660 > pretxnchangegroup = sh -c "echo 'Fail early!'; false"
661 661 > EOF
662 662 $ killdaemons.py # reload http config
663 663 $ hg serve -R other -p $HGPORT2 -d --pid-file=other.pid -E other-error.log
664 664 $ cat other.pid >> $DAEMON_PIDS
665 665
666 666 $ hg -R main push other -r e7ec4e813ba6
667 667 pushing to other
668 668 searching for changes
669 669 remote: adding changesets
670 670 remote: adding manifests
671 671 remote: adding file changes
672 672 remote: added 1 changesets with 1 changes to 1 files
673 673 remote: Fail early!
674 674 remote: transaction abort!
675 675 remote: Cleaning up the mess...
676 676 remote: rollback completed
677 677 abort: pretxnchangegroup hook exited with status 1
678 678 [255]
679 679 $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6
680 680 pushing to ssh://user@dummy/other
681 681 searching for changes
682 682 remote: adding changesets
683 683 remote: adding manifests
684 684 remote: adding file changes
685 685 remote: added 1 changesets with 1 changes to 1 files
686 686 remote: Fail early!
687 687 remote: transaction abort!
688 688 remote: Cleaning up the mess...
689 689 remote: rollback completed
690 690 remote: pretxnchangegroup hook exited with status 1
691 691 abort: push failed on remote
692 692 [255]
693 693 $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6
694 694 pushing to http://localhost:$HGPORT2/
695 695 searching for changes
696 696 remote: adding changesets
697 697 remote: adding manifests
698 698 remote: adding file changes
699 699 remote: added 1 changesets with 1 changes to 1 files
700 700 remote: Fail early!
701 701 remote: transaction abort!
702 702 remote: Cleaning up the mess...
703 703 remote: rollback completed
704 704 remote: pretxnchangegroup hook exited with status 1
705 705 abort: push failed on remote
706 706 [255]
707 707
708 708 Check output capture control.
709 709
710 710 (should be still forced for http, disabled for local and ssh)
711 711
712 712 $ cat >> $HGRCPATH << EOF
713 713 > [experimental]
714 714 > bundle2-output-capture=False
715 715 > EOF
716 716
717 717 $ hg -R main push other -r e7ec4e813ba6
718 718 pushing to other
719 719 searching for changes
720 720 adding changesets
721 721 adding manifests
722 722 adding file changes
723 723 added 1 changesets with 1 changes to 1 files
724 724 Fail early!
725 725 transaction abort!
726 726 Cleaning up the mess...
727 727 rollback completed
728 728 abort: pretxnchangegroup hook exited with status 1
729 729 [255]
730 730 $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6
731 731 pushing to ssh://user@dummy/other
732 732 searching for changes
733 733 remote: adding changesets
734 734 remote: adding manifests
735 735 remote: adding file changes
736 736 remote: added 1 changesets with 1 changes to 1 files
737 737 remote: Fail early!
738 738 remote: transaction abort!
739 739 remote: Cleaning up the mess...
740 740 remote: rollback completed
741 741 remote: pretxnchangegroup hook exited with status 1
742 742 abort: push failed on remote
743 743 [255]
744 744 $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6
745 745 pushing to http://localhost:$HGPORT2/
746 746 searching for changes
747 747 remote: adding changesets
748 748 remote: adding manifests
749 749 remote: adding file changes
750 750 remote: added 1 changesets with 1 changes to 1 files
751 751 remote: Fail early!
752 752 remote: transaction abort!
753 753 remote: Cleaning up the mess...
754 754 remote: rollback completed
755 755 remote: pretxnchangegroup hook exited with status 1
756 756 abort: push failed on remote
757 757 [255]
758 758
759 759 Check abort from mandatory pushkey
760 760
761 761 $ cat > mandatorypart.py << EOF
762 762 > from mercurial import exchange
763 763 > from mercurial import pushkey
764 764 > from mercurial import node
765 765 > from mercurial import error
766 766 > @exchange.b2partsgenerator('failingpuskey')
767 767 > def addfailingpushey(pushop, bundler):
768 768 > enc = pushkey.encode
769 769 > part = bundler.newpart('pushkey')
770 770 > part.addparam('namespace', enc('phases'))
771 771 > part.addparam('key', enc(pushop.repo['cd010b8cd998'].hex()))
772 772 > part.addparam('old', enc(str(0))) # successful update
773 773 > part.addparam('new', enc(str(0)))
774 774 > def fail(pushop, exc):
775 775 > raise error.Abort('Correct phase push failed (because hooks)')
776 776 > pushop.pkfailcb[part.id] = fail
777 777 > EOF
778 778 $ cat >> $HGRCPATH << EOF
779 779 > [hooks]
780 780 > pretxnchangegroup=
781 781 > pretxnclose.failpush=
782 782 > prepushkey.failpush = sh -c "echo 'do not push the key !'; false"
783 783 > [extensions]
784 784 > mandatorypart=$TESTTMP/mandatorypart.py
785 785 > EOF
786 786 $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS # reload http config
787 787 $ hg serve -R other -p $HGPORT2 -d --pid-file=other.pid -E other-error.log
788 788 $ cat other.pid >> $DAEMON_PIDS
789 789
790 790 (Failure from a hook)
791 791
792 792 $ hg -R main push other -r e7ec4e813ba6
793 793 pushing to other
794 794 searching for changes
795 795 adding changesets
796 796 adding manifests
797 797 adding file changes
798 798 added 1 changesets with 1 changes to 1 files
799 799 do not push the key !
800 800 pushkey-abort: prepushkey.failpush hook exited with status 1
801 801 transaction abort!
802 802 Cleaning up the mess...
803 803 rollback completed
804 804 abort: Correct phase push failed (because hooks)
805 805 [255]
806 806 $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6
807 807 pushing to ssh://user@dummy/other
808 808 searching for changes
809 809 remote: adding changesets
810 810 remote: adding manifests
811 811 remote: adding file changes
812 812 remote: added 1 changesets with 1 changes to 1 files
813 813 remote: do not push the key !
814 814 remote: pushkey-abort: prepushkey.failpush hook exited with status 1
815 815 remote: transaction abort!
816 816 remote: Cleaning up the mess...
817 817 remote: rollback completed
818 818 abort: Correct phase push failed (because hooks)
819 819 [255]
820 820 $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6
821 821 pushing to http://localhost:$HGPORT2/
822 822 searching for changes
823 823 remote: adding changesets
824 824 remote: adding manifests
825 825 remote: adding file changes
826 826 remote: added 1 changesets with 1 changes to 1 files
827 827 remote: do not push the key !
828 828 remote: pushkey-abort: prepushkey.failpush hook exited with status 1
829 829 remote: transaction abort!
830 830 remote: Cleaning up the mess...
831 831 remote: rollback completed
832 832 abort: Correct phase push failed (because hooks)
833 833 [255]
834 834
835 835 (Failure from a the pushkey)
836 836
837 837 $ cat > mandatorypart.py << EOF
838 838 > from mercurial import exchange
839 839 > from mercurial import pushkey
840 840 > from mercurial import node
841 841 > from mercurial import error
842 842 > @exchange.b2partsgenerator('failingpuskey')
843 843 > def addfailingpushey(pushop, bundler):
844 844 > enc = pushkey.encode
845 845 > part = bundler.newpart('pushkey')
846 846 > part.addparam('namespace', enc('phases'))
847 847 > part.addparam('key', enc(pushop.repo['cd010b8cd998'].hex()))
848 848 > part.addparam('old', enc(str(4))) # will fail
849 849 > part.addparam('new', enc(str(3)))
850 850 > def fail(pushop, exc):
851 851 > raise error.Abort('Clown phase push failed')
852 852 > pushop.pkfailcb[part.id] = fail
853 853 > EOF
854 854 $ cat >> $HGRCPATH << EOF
855 855 > [hooks]
856 856 > prepushkey.failpush =
857 857 > EOF
858 858 $ "$TESTDIR/killdaemons.py" $DAEMON_PIDS # reload http config
859 859 $ hg serve -R other -p $HGPORT2 -d --pid-file=other.pid -E other-error.log
860 860 $ cat other.pid >> $DAEMON_PIDS
861 861
862 862 $ hg -R main push other -r e7ec4e813ba6
863 863 pushing to other
864 864 searching for changes
865 865 adding changesets
866 866 adding manifests
867 867 adding file changes
868 868 added 1 changesets with 1 changes to 1 files
869 869 transaction abort!
870 870 Cleaning up the mess...
871 871 rollback completed
872 872 pushkey: lock state after "phases"
873 873 lock: free
874 874 wlock: free
875 875 abort: Clown phase push failed
876 876 [255]
877 877 $ hg -R main push ssh://user@dummy/other -r e7ec4e813ba6
878 878 pushing to ssh://user@dummy/other
879 879 searching for changes
880 880 remote: adding changesets
881 881 remote: adding manifests
882 882 remote: adding file changes
883 883 remote: added 1 changesets with 1 changes to 1 files
884 884 remote: transaction abort!
885 885 remote: Cleaning up the mess...
886 886 remote: rollback completed
887 887 remote: pushkey: lock state after "phases"
888 888 remote: lock: free
889 889 remote: wlock: free
890 890 abort: Clown phase push failed
891 891 [255]
892 892 $ hg -R main push http://localhost:$HGPORT2/ -r e7ec4e813ba6
893 893 pushing to http://localhost:$HGPORT2/
894 894 searching for changes
895 895 remote: adding changesets
896 896 remote: adding manifests
897 897 remote: adding file changes
898 898 remote: added 1 changesets with 1 changes to 1 files
899 899 remote: transaction abort!
900 900 remote: Cleaning up the mess...
901 901 remote: rollback completed
902 902 remote: pushkey: lock state after "phases"
903 903 remote: lock: free
904 904 remote: wlock: free
905 905 abort: Clown phase push failed
906 906 [255]
907 907
908 908 Test lazily acquiring the lock during unbundle
909 909 $ cp $TESTTMP/hgrc.orig $HGRCPATH
910 910 $ cat >> $HGRCPATH <<EOF
911 911 > [ui]
912 912 > ssh=python "$TESTDIR/dummyssh"
913 913 > EOF
914 914
915 915 $ cat >> $TESTTMP/locktester.py <<EOF
916 916 > import os
917 917 > from mercurial import extensions, bundle2, util
918 918 > def checklock(orig, repo, *args, **kwargs):
919 919 > if repo.svfs.lexists("lock"):
920 920 > raise util.Abort("Lock should not be taken")
921 921 > return orig(repo, *args, **kwargs)
922 922 > def extsetup(ui):
923 923 > extensions.wrapfunction(bundle2, 'processbundle', checklock)
924 924 > EOF
925 925
926 926 $ hg init lazylock
927 927 $ cat >> lazylock/.hg/hgrc <<EOF
928 928 > [extensions]
929 929 > locktester=$TESTTMP/locktester.py
930 930 > EOF
931 931
932 932 $ hg clone -q ssh://user@dummy/lazylock lazylockclient
933 933 $ cd lazylockclient
934 934 $ touch a && hg ci -Aqm a
935 935 $ hg push
936 936 pushing to ssh://user@dummy/lazylock
937 937 searching for changes
938 938 remote: Lock should not be taken
939 939 abort: push failed on remote
940 940 [255]
941 941
942 942 $ cat >> ../lazylock/.hg/hgrc <<EOF
943 943 > [experimental]
944 944 > bundle2lazylocking=True
945 945 > EOF
946 946 $ hg push
947 947 pushing to ssh://user@dummy/lazylock
948 948 searching for changes
949 949 remote: adding changesets
950 950 remote: adding manifests
951 951 remote: adding file changes
952 952 remote: added 1 changesets with 1 changes to 1 files
953 953
954 954 $ cd ..
955 955
956 956 Servers can disable bundle1 for clone/pull operations
957 957
958 958 $ killdaemons.py
959 959 $ hg init bundle2onlyserver
960 960 $ cd bundle2onlyserver
961 961 $ cat > .hg/hgrc << EOF
962 962 > [server]
963 963 > bundle1.pull = false
964 964 > EOF
965 965
966 966 $ touch foo
967 967 $ hg -q commit -A -m initial
968 968
969 969 $ hg serve -p $HGPORT -d --pid-file=hg.pid
970 970 $ cat hg.pid >> $DAEMON_PIDS
971 971
972 972 $ hg --config devel.legacy.exchange=bundle1 clone http://localhost:$HGPORT/ not-bundle2
973 973 requesting all changes
974 974 abort: remote error:
975 975 incompatible Mercurial client; bundle2 required
976 976 (see https://www.mercurial-scm.org/wiki/IncompatibleClient)
977 977 [255]
978 978 $ killdaemons.py
979 979 $ cd ..
980 980
981 981 bundle1 can still pull non-generaldelta repos when generaldelta bundle1 disabled
982 982
983 983 $ hg --config format.usegeneraldelta=false init notgdserver
984 984 $ cd notgdserver
985 985 $ cat > .hg/hgrc << EOF
986 986 > [server]
987 987 > bundle1gd.pull = false
988 988 > EOF
989 989
990 990 $ touch foo
991 991 $ hg -q commit -A -m initial
992 992 $ hg serve -p $HGPORT -d --pid-file=hg.pid
993 993 $ cat hg.pid >> $DAEMON_PIDS
994 994
995 995 $ hg --config devel.legacy.exchange=bundle1 clone http://localhost:$HGPORT/ not-bundle2-1
996 996 requesting all changes
997 997 adding changesets
998 998 adding manifests
999 999 adding file changes
1000 1000 added 1 changesets with 1 changes to 1 files
1001 1001 updating to branch default
1002 1002 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1003 1003
1004 1004 $ killdaemons.py
1005 1005 $ cd ../bundle2onlyserver
1006 1006
1007 1007 bundle1 pull can be disabled for generaldelta repos only
1008 1008
1009 1009 $ cat > .hg/hgrc << EOF
1010 1010 > [server]
1011 1011 > bundle1gd.pull = false
1012 1012 > EOF
1013 1013
1014 1014 $ hg serve -p $HGPORT -d --pid-file=hg.pid
1015 1015 $ cat hg.pid >> $DAEMON_PIDS
1016 1016 $ hg --config devel.legacy.exchange=bundle1 clone http://localhost:$HGPORT/ not-bundle2
1017 1017 requesting all changes
1018 1018 abort: remote error:
1019 1019 incompatible Mercurial client; bundle2 required
1020 1020 (see https://www.mercurial-scm.org/wiki/IncompatibleClient)
1021 1021 [255]
1022 1022
1023 1023 $ killdaemons.py
1024 1024
1025 1025 Verify the global server.bundle1 option works
1026 1026
1027 1027 $ cd ..
1028 1028 $ cat > bundle2onlyserver/.hg/hgrc << EOF
1029 1029 > [server]
1030 1030 > bundle1 = false
1031 1031 > EOF
1032 1032 $ hg -R bundle2onlyserver serve -p $HGPORT -d --pid-file=hg.pid
1033 1033 $ cat hg.pid >> $DAEMON_PIDS
1034 1034 $ hg --config devel.legacy.exchange=bundle1 clone http://localhost:$HGPORT not-bundle2
1035 1035 requesting all changes
1036 1036 abort: remote error:
1037 1037 incompatible Mercurial client; bundle2 required
1038 1038 (see https://www.mercurial-scm.org/wiki/IncompatibleClient)
1039 1039 [255]
1040 1040 $ killdaemons.py
1041 1041
1042 1042 $ hg --config devel.legacy.exchange=bundle1 clone ssh://user@dummy/bundle2onlyserver not-bundle2-ssh
1043 1043 requesting all changes
1044 1044 adding changesets
1045 1045 remote: abort: incompatible Mercurial client; bundle2 required
1046 1046 remote: (see https://www.mercurial-scm.org/wiki/IncompatibleClient)
1047 1047 transaction abort!
1048 1048 rollback completed
1049 1049 abort: stream ended unexpectedly (got 0 bytes, expected 4)
1050 1050 [255]
1051 1051
1052 1052 $ cat > bundle2onlyserver/.hg/hgrc << EOF
1053 1053 > [server]
1054 1054 > bundle1gd = false
1055 1055 > EOF
1056 1056 $ hg -R bundle2onlyserver serve -p $HGPORT -d --pid-file=hg.pid
1057 1057 $ cat hg.pid >> $DAEMON_PIDS
1058 1058
1059 1059 $ hg --config devel.legacy.exchange=bundle1 clone http://localhost:$HGPORT/ not-bundle2
1060 1060 requesting all changes
1061 1061 abort: remote error:
1062 1062 incompatible Mercurial client; bundle2 required
1063 1063 (see https://www.mercurial-scm.org/wiki/IncompatibleClient)
1064 1064 [255]
1065 1065
1066 1066 $ killdaemons.py
1067 1067
1068 1068 $ cd notgdserver
1069 1069 $ cat > .hg/hgrc << EOF
1070 1070 > [server]
1071 1071 > bundle1gd = false
1072 1072 > EOF
1073 1073 $ hg serve -p $HGPORT -d --pid-file=hg.pid
1074 1074 $ cat hg.pid >> $DAEMON_PIDS
1075 1075
1076 1076 $ hg --config devel.legacy.exchange=bundle1 clone http://localhost:$HGPORT/ not-bundle2-2
1077 1077 requesting all changes
1078 1078 adding changesets
1079 1079 adding manifests
1080 1080 adding file changes
1081 1081 added 1 changesets with 1 changes to 1 files
1082 1082 updating to branch default
1083 1083 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1084 1084
1085 1085 $ killdaemons.py
1086 1086 $ cd ../bundle2onlyserver
1087 1087
1088 1088 Verify bundle1 pushes can be disabled
1089 1089
1090 1090 $ cat > .hg/hgrc << EOF
1091 1091 > [server]
1092 1092 > bundle1.push = false
1093 1093 > [web]
1094 1094 > allow_push = *
1095 1095 > push_ssl = false
1096 1096 > EOF
1097 1097
1098 1098 $ hg serve -p $HGPORT -d --pid-file=hg.pid -E error.log
1099 1099 $ cat hg.pid >> $DAEMON_PIDS
1100 1100 $ cd ..
1101 1101
1102 1102 $ hg clone http://localhost:$HGPORT bundle2-only
1103 1103 requesting all changes
1104 1104 adding changesets
1105 1105 adding manifests
1106 1106 adding file changes
1107 1107 added 1 changesets with 1 changes to 1 files
1108 1108 updating to branch default
1109 1109 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1110 1110 $ cd bundle2-only
1111 1111 $ echo commit > foo
1112 1112 $ hg commit -m commit
1113 1113 $ hg --config devel.legacy.exchange=bundle1 push
1114 1114 pushing to http://localhost:$HGPORT/
1115 1115 searching for changes
1116 1116 abort: remote error:
1117 1117 incompatible Mercurial client; bundle2 required
1118 1118 (see https://www.mercurial-scm.org/wiki/IncompatibleClient)
1119 1119 [255]
1120 1120
1121 1121 (also check with ssh)
1122 1122
1123 1123 $ hg --config devel.legacy.exchange=bundle1 push ssh://user@dummy/bundle2onlyserver
1124 1124 pushing to ssh://user@dummy/bundle2onlyserver
1125 1125 searching for changes
1126 1126 remote: abort: incompatible Mercurial client; bundle2 required
1127 1127 remote: (see https://www.mercurial-scm.org/wiki/IncompatibleClient)
1128 1128 [1]
1129 1129
1130 1130 $ hg push
1131 1131 pushing to http://localhost:$HGPORT/
1132 1132 searching for changes
1133 1133 remote: adding changesets
1134 1134 remote: adding manifests
1135 1135 remote: adding file changes
1136 1136 remote: added 1 changesets with 1 changes to 1 files
@@ -1,260 +1,260
1 1 Create an extension to test bundle2 with multiple changegroups
2 2
3 3 $ cat > bundle2.py <<EOF
4 4 > """
5 5 > """
6 6 > from mercurial import changegroup, discovery, exchange
7 7 >
8 8 > def _getbundlechangegrouppart(bundler, repo, source, bundlecaps=None,
9 9 > b2caps=None, heads=None, common=None,
10 10 > **kwargs):
11 11 > # Create two changegroups given the common changesets and heads for the
12 12 > # changegroup part we are being requested. Use the parent of each head
13 13 > # in 'heads' as intermediate heads for the first changegroup.
14 14 > intermediates = [repo[r].p1().node() for r in heads]
15 15 > outgoing = discovery.outgoing(repo, common, intermediates)
16 16 > cg = changegroup.getchangegroup(repo, source, outgoing,
17 17 > bundlecaps=bundlecaps)
18 18 > bundler.newpart('output', data='changegroup1')
19 19 > bundler.newpart('changegroup', data=cg.getchunks())
20 20 > outgoing = discovery.outgoing(repo, common + intermediates, heads)
21 21 > cg = changegroup.getchangegroup(repo, source, outgoing,
22 22 > bundlecaps=bundlecaps)
23 23 > bundler.newpart('output', data='changegroup2')
24 24 > bundler.newpart('changegroup', data=cg.getchunks())
25 25 >
26 26 > def _pull(repo, *args, **kwargs):
27 27 > pullop = _orig_pull(repo, *args, **kwargs)
28 28 > repo.ui.write('pullop.cgresult is %d\n' % pullop.cgresult)
29 29 > return pullop
30 30 >
31 31 > _orig_pull = exchange.pull
32 32 > exchange.pull = _pull
33 33 > exchange.getbundle2partsmapping['changegroup'] = _getbundlechangegrouppart
34 34 > EOF
35 35
36 36 $ cat >> $HGRCPATH << EOF
37 37 > [ui]
38 38 > logtemplate={rev}:{node|short} {phase} {author} {bookmarks} {desc|firstline}
39 39 > EOF
40 40
41 41 Start with a simple repository with a single commit
42 42
43 43 $ hg init repo
44 44 $ cd repo
45 45 $ cat > .hg/hgrc << EOF
46 46 > [extensions]
47 47 > bundle2=$TESTTMP/bundle2.py
48 48 > EOF
49 49
50 50 $ echo A > A
51 51 $ hg commit -A -m A -q
52 52 $ cd ..
53 53
54 54 Clone
55 55
56 56 $ hg clone -q repo clone
57 57
58 58 Add two linear commits
59 59
60 60 $ cd repo
61 61 $ echo B > B
62 62 $ hg commit -A -m B -q
63 63 $ echo C > C
64 64 $ hg commit -A -m C -q
65 65
66 66 $ cd ../clone
67 67 $ cat >> .hg/hgrc <<EOF
68 68 > [hooks]
69 69 > pretxnchangegroup = sh -c "printenv.py pretxnchangegroup"
70 70 > changegroup = sh -c "printenv.py changegroup"
71 71 > incoming = sh -c "printenv.py incoming"
72 72 > EOF
73 73
74 74 Pull the new commits in the clone
75 75
76 76 $ hg pull
77 77 pulling from $TESTTMP/repo (glob)
78 78 searching for changes
79 79 remote: changegroup1
80 80 adding changesets
81 81 adding manifests
82 82 adding file changes
83 83 added 1 changesets with 1 changes to 1 files
84 pretxnchangegroup hook: HG_HOOKTYPE=pretxnchangegroup HG_NODE=27547f69f25460a52fff66ad004e58da7ad3fb56 HG_NODE_LAST=27547f69f25460a52fff66ad004e58da7ad3fb56 HG_PENDING=$TESTTMP/clone HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo
84 pretxnchangegroup hook: HG_HOOKNAME=pretxnchangegroup HG_HOOKTYPE=pretxnchangegroup HG_NODE=27547f69f25460a52fff66ad004e58da7ad3fb56 HG_NODE_LAST=27547f69f25460a52fff66ad004e58da7ad3fb56 HG_PENDING=$TESTTMP/clone HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo
85 85 remote: changegroup2
86 86 adding changesets
87 87 adding manifests
88 88 adding file changes
89 89 added 1 changesets with 1 changes to 1 files
90 pretxnchangegroup hook: HG_HOOKTYPE=pretxnchangegroup HG_NODE=f838bfaca5c7226600ebcfd84f3c3c13a28d3757 HG_NODE_LAST=f838bfaca5c7226600ebcfd84f3c3c13a28d3757 HG_PENDING=$TESTTMP/clone HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo
91 changegroup hook: HG_HOOKTYPE=changegroup HG_NODE=27547f69f25460a52fff66ad004e58da7ad3fb56 HG_NODE_LAST=27547f69f25460a52fff66ad004e58da7ad3fb56 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo
92 incoming hook: HG_HOOKTYPE=incoming HG_NODE=27547f69f25460a52fff66ad004e58da7ad3fb56 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo
93 changegroup hook: HG_HOOKTYPE=changegroup HG_NODE=f838bfaca5c7226600ebcfd84f3c3c13a28d3757 HG_NODE_LAST=f838bfaca5c7226600ebcfd84f3c3c13a28d3757 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo
94 incoming hook: HG_HOOKTYPE=incoming HG_NODE=f838bfaca5c7226600ebcfd84f3c3c13a28d3757 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo
90 pretxnchangegroup hook: HG_HOOKNAME=pretxnchangegroup HG_HOOKTYPE=pretxnchangegroup HG_NODE=f838bfaca5c7226600ebcfd84f3c3c13a28d3757 HG_NODE_LAST=f838bfaca5c7226600ebcfd84f3c3c13a28d3757 HG_PENDING=$TESTTMP/clone HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo
91 changegroup hook: HG_HOOKNAME=changegroup HG_HOOKTYPE=changegroup HG_NODE=27547f69f25460a52fff66ad004e58da7ad3fb56 HG_NODE_LAST=27547f69f25460a52fff66ad004e58da7ad3fb56 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo
92 incoming hook: HG_HOOKNAME=incoming HG_HOOKTYPE=incoming HG_NODE=27547f69f25460a52fff66ad004e58da7ad3fb56 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo
93 changegroup hook: HG_HOOKNAME=changegroup HG_HOOKTYPE=changegroup HG_NODE=f838bfaca5c7226600ebcfd84f3c3c13a28d3757 HG_NODE_LAST=f838bfaca5c7226600ebcfd84f3c3c13a28d3757 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo
94 incoming hook: HG_HOOKNAME=incoming HG_HOOKTYPE=incoming HG_NODE=f838bfaca5c7226600ebcfd84f3c3c13a28d3757 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo
95 95 pullop.cgresult is 1
96 96 (run 'hg update' to get a working copy)
97 97 $ hg update
98 98 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
99 99 $ hg log -G
100 100 @ 2:f838bfaca5c7 public test C
101 101 |
102 102 o 1:27547f69f254 public test B
103 103 |
104 104 o 0:4a2df7238c3b public test A
105 105
106 106 Add more changesets with multiple heads to the original repository
107 107
108 108 $ cd ../repo
109 109 $ echo D > D
110 110 $ hg commit -A -m D -q
111 111 $ hg up -r 1
112 112 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
113 113 $ echo E > E
114 114 $ hg commit -A -m E -q
115 115 $ echo F > F
116 116 $ hg commit -A -m F -q
117 117 $ hg up -r 1
118 118 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
119 119 $ echo G > G
120 120 $ hg commit -A -m G -q
121 121 $ hg up -r 3
122 122 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
123 123 $ echo H > H
124 124 $ hg commit -A -m H -q
125 125 $ hg log -G
126 126 @ 7:5cd59d311f65 draft test H
127 127 |
128 128 | o 6:1d14c3ce6ac0 draft test G
129 129 | |
130 130 | | o 5:7f219660301f draft test F
131 131 | | |
132 132 | | o 4:8a5212ebc852 draft test E
133 133 | |/
134 134 o | 3:b3325c91a4d9 draft test D
135 135 | |
136 136 o | 2:f838bfaca5c7 draft test C
137 137 |/
138 138 o 1:27547f69f254 draft test B
139 139 |
140 140 o 0:4a2df7238c3b draft test A
141 141
142 142 New heads are reported during transfer and properly accounted for in
143 143 pullop.cgresult
144 144
145 145 $ cd ../clone
146 146 $ hg pull
147 147 pulling from $TESTTMP/repo (glob)
148 148 searching for changes
149 149 remote: changegroup1
150 150 adding changesets
151 151 adding manifests
152 152 adding file changes
153 153 added 2 changesets with 2 changes to 2 files (+1 heads)
154 pretxnchangegroup hook: HG_HOOKTYPE=pretxnchangegroup HG_NODE=b3325c91a4d916bcc4cdc83ea3fe4ece46a42f6e HG_NODE_LAST=8a5212ebc8527f9fb821601504794e3eb11a1ed3 HG_PENDING=$TESTTMP/clone HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo
154 pretxnchangegroup hook: HG_HOOKNAME=pretxnchangegroup HG_HOOKTYPE=pretxnchangegroup HG_NODE=b3325c91a4d916bcc4cdc83ea3fe4ece46a42f6e HG_NODE_LAST=8a5212ebc8527f9fb821601504794e3eb11a1ed3 HG_PENDING=$TESTTMP/clone HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo
155 155 remote: changegroup2
156 156 adding changesets
157 157 adding manifests
158 158 adding file changes
159 159 added 3 changesets with 3 changes to 3 files (+1 heads)
160 pretxnchangegroup hook: HG_HOOKTYPE=pretxnchangegroup HG_NODE=7f219660301fe4c8a116f714df5e769695cc2b46 HG_NODE_LAST=5cd59d311f6508b8e0ed28a266756c859419c9f1 HG_PENDING=$TESTTMP/clone HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo
161 changegroup hook: HG_HOOKTYPE=changegroup HG_NODE=b3325c91a4d916bcc4cdc83ea3fe4ece46a42f6e HG_NODE_LAST=8a5212ebc8527f9fb821601504794e3eb11a1ed3 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo
162 incoming hook: HG_HOOKTYPE=incoming HG_NODE=b3325c91a4d916bcc4cdc83ea3fe4ece46a42f6e HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo
163 incoming hook: HG_HOOKTYPE=incoming HG_NODE=8a5212ebc8527f9fb821601504794e3eb11a1ed3 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo
164 changegroup hook: HG_HOOKTYPE=changegroup HG_NODE=7f219660301fe4c8a116f714df5e769695cc2b46 HG_NODE_LAST=5cd59d311f6508b8e0ed28a266756c859419c9f1 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo
165 incoming hook: HG_HOOKTYPE=incoming HG_NODE=7f219660301fe4c8a116f714df5e769695cc2b46 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo
166 incoming hook: HG_HOOKTYPE=incoming HG_NODE=1d14c3ce6ac0582d2809220d33e8cd7a696e0156 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo
167 incoming hook: HG_HOOKTYPE=incoming HG_NODE=5cd59d311f6508b8e0ed28a266756c859419c9f1 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo
160 pretxnchangegroup hook: HG_HOOKNAME=pretxnchangegroup HG_HOOKTYPE=pretxnchangegroup HG_NODE=7f219660301fe4c8a116f714df5e769695cc2b46 HG_NODE_LAST=5cd59d311f6508b8e0ed28a266756c859419c9f1 HG_PENDING=$TESTTMP/clone HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo
161 changegroup hook: HG_HOOKNAME=changegroup HG_HOOKTYPE=changegroup HG_NODE=b3325c91a4d916bcc4cdc83ea3fe4ece46a42f6e HG_NODE_LAST=8a5212ebc8527f9fb821601504794e3eb11a1ed3 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo
162 incoming hook: HG_HOOKNAME=incoming HG_HOOKTYPE=incoming HG_NODE=b3325c91a4d916bcc4cdc83ea3fe4ece46a42f6e HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo
163 incoming hook: HG_HOOKNAME=incoming HG_HOOKTYPE=incoming HG_NODE=8a5212ebc8527f9fb821601504794e3eb11a1ed3 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo
164 changegroup hook: HG_HOOKNAME=changegroup HG_HOOKTYPE=changegroup HG_NODE=7f219660301fe4c8a116f714df5e769695cc2b46 HG_NODE_LAST=5cd59d311f6508b8e0ed28a266756c859419c9f1 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo
165 incoming hook: HG_HOOKNAME=incoming HG_HOOKTYPE=incoming HG_NODE=7f219660301fe4c8a116f714df5e769695cc2b46 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo
166 incoming hook: HG_HOOKNAME=incoming HG_HOOKTYPE=incoming HG_NODE=1d14c3ce6ac0582d2809220d33e8cd7a696e0156 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo
167 incoming hook: HG_HOOKNAME=incoming HG_HOOKTYPE=incoming HG_NODE=5cd59d311f6508b8e0ed28a266756c859419c9f1 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo
168 168 pullop.cgresult is 3
169 169 (run 'hg heads' to see heads, 'hg merge' to merge)
170 170 $ hg log -G
171 171 o 7:5cd59d311f65 public test H
172 172 |
173 173 | o 6:1d14c3ce6ac0 public test G
174 174 | |
175 175 | | o 5:7f219660301f public test F
176 176 | | |
177 177 | | o 4:8a5212ebc852 public test E
178 178 | |/
179 179 o | 3:b3325c91a4d9 public test D
180 180 | |
181 181 @ | 2:f838bfaca5c7 public test C
182 182 |/
183 183 o 1:27547f69f254 public test B
184 184 |
185 185 o 0:4a2df7238c3b public test A
186 186
187 187 Removing a head from the original repository by merging it
188 188
189 189 $ cd ../repo
190 190 $ hg merge -r 6 -q
191 191 $ hg commit -m Merge
192 192 $ echo I > I
193 193 $ hg commit -A -m H -q
194 194 $ hg log -G
195 195 @ 9:9d18e5bd9ab0 draft test H
196 196 |
197 197 o 8:71bd7b46de72 draft test Merge
198 198 |\
199 199 | o 7:5cd59d311f65 draft test H
200 200 | |
201 201 o | 6:1d14c3ce6ac0 draft test G
202 202 | |
203 203 | | o 5:7f219660301f draft test F
204 204 | | |
205 205 +---o 4:8a5212ebc852 draft test E
206 206 | |
207 207 | o 3:b3325c91a4d9 draft test D
208 208 | |
209 209 | o 2:f838bfaca5c7 draft test C
210 210 |/
211 211 o 1:27547f69f254 draft test B
212 212 |
213 213 o 0:4a2df7238c3b draft test A
214 214
215 215 Removed heads are reported during transfer and properly accounted for in
216 216 pullop.cgresult
217 217
218 218 $ cd ../clone
219 219 $ hg pull
220 220 pulling from $TESTTMP/repo (glob)
221 221 searching for changes
222 222 remote: changegroup1
223 223 adding changesets
224 224 adding manifests
225 225 adding file changes
226 226 added 1 changesets with 0 changes to 0 files (-1 heads)
227 pretxnchangegroup hook: HG_HOOKTYPE=pretxnchangegroup HG_NODE=71bd7b46de72e69a32455bf88d04757d542e6cf4 HG_NODE_LAST=71bd7b46de72e69a32455bf88d04757d542e6cf4 HG_PENDING=$TESTTMP/clone HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo
227 pretxnchangegroup hook: HG_HOOKNAME=pretxnchangegroup HG_HOOKTYPE=pretxnchangegroup HG_NODE=71bd7b46de72e69a32455bf88d04757d542e6cf4 HG_NODE_LAST=71bd7b46de72e69a32455bf88d04757d542e6cf4 HG_PENDING=$TESTTMP/clone HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo
228 228 remote: changegroup2
229 229 adding changesets
230 230 adding manifests
231 231 adding file changes
232 232 added 1 changesets with 1 changes to 1 files
233 pretxnchangegroup hook: HG_HOOKTYPE=pretxnchangegroup HG_NODE=9d18e5bd9ab09337802595d49f1dad0c98df4d84 HG_NODE_LAST=9d18e5bd9ab09337802595d49f1dad0c98df4d84 HG_PENDING=$TESTTMP/clone HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo
234 changegroup hook: HG_HOOKTYPE=changegroup HG_NODE=71bd7b46de72e69a32455bf88d04757d542e6cf4 HG_NODE_LAST=71bd7b46de72e69a32455bf88d04757d542e6cf4 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo
235 incoming hook: HG_HOOKTYPE=incoming HG_NODE=71bd7b46de72e69a32455bf88d04757d542e6cf4 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo
236 changegroup hook: HG_HOOKTYPE=changegroup HG_NODE=9d18e5bd9ab09337802595d49f1dad0c98df4d84 HG_NODE_LAST=9d18e5bd9ab09337802595d49f1dad0c98df4d84 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo
237 incoming hook: HG_HOOKTYPE=incoming HG_NODE=9d18e5bd9ab09337802595d49f1dad0c98df4d84 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo
233 pretxnchangegroup hook: HG_HOOKNAME=pretxnchangegroup HG_HOOKTYPE=pretxnchangegroup HG_NODE=9d18e5bd9ab09337802595d49f1dad0c98df4d84 HG_NODE_LAST=9d18e5bd9ab09337802595d49f1dad0c98df4d84 HG_PENDING=$TESTTMP/clone HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo
234 changegroup hook: HG_HOOKNAME=changegroup HG_HOOKTYPE=changegroup HG_NODE=71bd7b46de72e69a32455bf88d04757d542e6cf4 HG_NODE_LAST=71bd7b46de72e69a32455bf88d04757d542e6cf4 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo
235 incoming hook: HG_HOOKNAME=incoming HG_HOOKTYPE=incoming HG_NODE=71bd7b46de72e69a32455bf88d04757d542e6cf4 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo
236 changegroup hook: HG_HOOKNAME=changegroup HG_HOOKTYPE=changegroup HG_NODE=9d18e5bd9ab09337802595d49f1dad0c98df4d84 HG_NODE_LAST=9d18e5bd9ab09337802595d49f1dad0c98df4d84 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo
237 incoming hook: HG_HOOKNAME=incoming HG_HOOKTYPE=incoming HG_NODE=9d18e5bd9ab09337802595d49f1dad0c98df4d84 HG_PHASES_MOVED=1 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/repo
238 238 pullop.cgresult is -2
239 239 (run 'hg update' to get a working copy)
240 240 $ hg log -G
241 241 o 9:9d18e5bd9ab0 public test H
242 242 |
243 243 o 8:71bd7b46de72 public test Merge
244 244 |\
245 245 | o 7:5cd59d311f65 public test H
246 246 | |
247 247 o | 6:1d14c3ce6ac0 public test G
248 248 | |
249 249 | | o 5:7f219660301f public test F
250 250 | | |
251 251 +---o 4:8a5212ebc852 public test E
252 252 | |
253 253 | o 3:b3325c91a4d9 public test D
254 254 | |
255 255 | @ 2:f838bfaca5c7 public test C
256 256 |/
257 257 o 1:27547f69f254 public test B
258 258 |
259 259 o 0:4a2df7238c3b public test A
260 260
@@ -1,935 +1,935
1 1 commit hooks can see env vars
2 2 (and post-transaction one are run unlocked)
3 3
4 4
5 5 $ cat > $TESTTMP/txnabort.checkargs.py <<EOF
6 6 > def showargs(ui, repo, hooktype, **kwargs):
7 7 > ui.write('%s python hook: %s\n' % (hooktype, ','.join(sorted(kwargs))))
8 8 > EOF
9 9
10 10 $ hg init a
11 11 $ cd a
12 12 $ cat > .hg/hgrc <<EOF
13 13 > [hooks]
14 14 > commit = sh -c "HG_LOCAL= HG_TAG= printenv.py commit"
15 15 > commit.b = sh -c "HG_LOCAL= HG_TAG= printenv.py commit.b"
16 16 > precommit = sh -c "HG_LOCAL= HG_NODE= HG_TAG= printenv.py precommit"
17 17 > pretxncommit = sh -c "HG_LOCAL= HG_TAG= printenv.py pretxncommit"
18 18 > pretxncommit.tip = hg -q tip
19 19 > pre-identify = sh -c "printenv.py pre-identify 1"
20 20 > pre-cat = sh -c "printenv.py pre-cat"
21 21 > post-cat = sh -c "printenv.py post-cat"
22 22 > pretxnopen = sh -c "HG_LOCAL= HG_TAG= printenv.py pretxnopen"
23 23 > pretxnclose = sh -c "HG_LOCAL= HG_TAG= printenv.py pretxnclose"
24 24 > txnclose = sh -c "HG_LOCAL= HG_TAG= printenv.py txnclose"
25 25 > txnabort.0 = python:$TESTTMP/txnabort.checkargs.py:showargs
26 26 > txnabort.1 = sh -c "HG_LOCAL= HG_TAG= printenv.py txnabort"
27 27 > txnclose.checklock = sh -c "hg debuglock > /dev/null"
28 28 > EOF
29 29 $ echo a > a
30 30 $ hg add a
31 31 $ hg commit -m a
32 precommit hook: HG_HOOKTYPE=precommit HG_PARENT1=0000000000000000000000000000000000000000
33 pretxnopen hook: HG_HOOKTYPE=pretxnopen HG_TXNID=TXN:$ID$ HG_TXNNAME=commit
34 pretxncommit hook: HG_HOOKTYPE=pretxncommit HG_NODE=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b HG_PARENT1=0000000000000000000000000000000000000000 HG_PENDING=$TESTTMP/a
32 precommit hook: HG_HOOKNAME=precommit HG_HOOKTYPE=precommit HG_PARENT1=0000000000000000000000000000000000000000
33 pretxnopen hook: HG_HOOKNAME=pretxnopen HG_HOOKTYPE=pretxnopen HG_TXNID=TXN:$ID$ HG_TXNNAME=commit
34 pretxncommit hook: HG_HOOKNAME=pretxncommit HG_HOOKTYPE=pretxncommit HG_NODE=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b HG_PARENT1=0000000000000000000000000000000000000000 HG_PENDING=$TESTTMP/a
35 35 0:cb9a9f314b8b
36 pretxnclose hook: HG_HOOKTYPE=pretxnclose HG_PENDING=$TESTTMP/a HG_PHASES_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=commit
37 txnclose hook: HG_HOOKTYPE=txnclose HG_PHASES_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=commit
38 commit hook: HG_HOOKTYPE=commit HG_NODE=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b HG_PARENT1=0000000000000000000000000000000000000000
39 commit.b hook: HG_HOOKTYPE=commit HG_NODE=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b HG_PARENT1=0000000000000000000000000000000000000000
36 pretxnclose hook: HG_HOOKNAME=pretxnclose HG_HOOKTYPE=pretxnclose HG_PENDING=$TESTTMP/a HG_PHASES_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=commit
37 txnclose hook: HG_HOOKNAME=txnclose HG_HOOKTYPE=txnclose HG_PHASES_MOVED=1 HG_TXNID=TXN:$ID$ HG_TXNNAME=commit
38 commit hook: HG_HOOKNAME=commit HG_HOOKTYPE=commit HG_NODE=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b HG_PARENT1=0000000000000000000000000000000000000000
39 commit.b hook: HG_HOOKNAME=commit.b HG_HOOKTYPE=commit HG_NODE=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b HG_PARENT1=0000000000000000000000000000000000000000
40 40
41 41 $ hg clone . ../b
42 42 updating to branch default
43 43 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
44 44 $ cd ../b
45 45
46 46 changegroup hooks can see env vars
47 47
48 48 $ cat > .hg/hgrc <<EOF
49 49 > [hooks]
50 50 > prechangegroup = sh -c "printenv.py prechangegroup"
51 51 > changegroup = sh -c "printenv.py changegroup"
52 52 > incoming = sh -c "printenv.py incoming"
53 53 > EOF
54 54
55 55 pretxncommit and commit hooks can see both parents of merge
56 56
57 57 $ cd ../a
58 58 $ echo b >> a
59 59 $ hg commit -m a1 -d "1 0"
60 precommit hook: HG_HOOKTYPE=precommit HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b
61 pretxnopen hook: HG_HOOKTYPE=pretxnopen HG_TXNID=TXN:$ID$ HG_TXNNAME=commit
62 pretxncommit hook: HG_HOOKTYPE=pretxncommit HG_NODE=ab228980c14deea8b9555d91c9581127383e40fd HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b HG_PENDING=$TESTTMP/a
60 precommit hook: HG_HOOKNAME=precommit HG_HOOKTYPE=precommit HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b
61 pretxnopen hook: HG_HOOKNAME=pretxnopen HG_HOOKTYPE=pretxnopen HG_TXNID=TXN:$ID$ HG_TXNNAME=commit
62 pretxncommit hook: HG_HOOKNAME=pretxncommit HG_HOOKTYPE=pretxncommit HG_NODE=ab228980c14deea8b9555d91c9581127383e40fd HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b HG_PENDING=$TESTTMP/a
63 63 1:ab228980c14d
64 pretxnclose hook: HG_HOOKTYPE=pretxnclose HG_PENDING=$TESTTMP/a HG_TXNID=TXN:$ID$ HG_TXNNAME=commit
65 txnclose hook: HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=commit
66 commit hook: HG_HOOKTYPE=commit HG_NODE=ab228980c14deea8b9555d91c9581127383e40fd HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b
67 commit.b hook: HG_HOOKTYPE=commit HG_NODE=ab228980c14deea8b9555d91c9581127383e40fd HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b
64 pretxnclose hook: HG_HOOKNAME=pretxnclose HG_HOOKTYPE=pretxnclose HG_PENDING=$TESTTMP/a HG_TXNID=TXN:$ID$ HG_TXNNAME=commit
65 txnclose hook: HG_HOOKNAME=txnclose HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=commit
66 commit hook: HG_HOOKNAME=commit HG_HOOKTYPE=commit HG_NODE=ab228980c14deea8b9555d91c9581127383e40fd HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b
67 commit.b hook: HG_HOOKNAME=commit.b HG_HOOKTYPE=commit HG_NODE=ab228980c14deea8b9555d91c9581127383e40fd HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b
68 68 $ hg update -C 0
69 69 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
70 70 $ echo b > b
71 71 $ hg add b
72 72 $ hg commit -m b -d '1 0'
73 precommit hook: HG_HOOKTYPE=precommit HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b
74 pretxnopen hook: HG_HOOKTYPE=pretxnopen HG_TXNID=TXN:$ID$ HG_TXNNAME=commit
75 pretxncommit hook: HG_HOOKTYPE=pretxncommit HG_NODE=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b HG_PENDING=$TESTTMP/a
73 precommit hook: HG_HOOKNAME=precommit HG_HOOKTYPE=precommit HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b
74 pretxnopen hook: HG_HOOKNAME=pretxnopen HG_HOOKTYPE=pretxnopen HG_TXNID=TXN:$ID$ HG_TXNNAME=commit
75 pretxncommit hook: HG_HOOKNAME=pretxncommit HG_HOOKTYPE=pretxncommit HG_NODE=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b HG_PENDING=$TESTTMP/a
76 76 2:ee9deb46ab31
77 pretxnclose hook: HG_HOOKTYPE=pretxnclose HG_PENDING=$TESTTMP/a HG_TXNID=TXN:$ID$ HG_TXNNAME=commit
77 pretxnclose hook: HG_HOOKNAME=pretxnclose HG_HOOKTYPE=pretxnclose HG_PENDING=$TESTTMP/a HG_TXNID=TXN:$ID$ HG_TXNNAME=commit
78 78 created new head
79 txnclose hook: HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=commit
80 commit hook: HG_HOOKTYPE=commit HG_NODE=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b
81 commit.b hook: HG_HOOKTYPE=commit HG_NODE=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b
79 txnclose hook: HG_HOOKNAME=txnclose HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=commit
80 commit hook: HG_HOOKNAME=commit HG_HOOKTYPE=commit HG_NODE=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b
81 commit.b hook: HG_HOOKNAME=commit.b HG_HOOKTYPE=commit HG_NODE=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT1=cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b
82 82 $ hg merge 1
83 83 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
84 84 (branch merge, don't forget to commit)
85 85 $ hg commit -m merge -d '2 0'
86 precommit hook: HG_HOOKTYPE=precommit HG_PARENT1=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT2=ab228980c14deea8b9555d91c9581127383e40fd
87 pretxnopen hook: HG_HOOKTYPE=pretxnopen HG_TXNID=TXN:$ID$ HG_TXNNAME=commit
88 pretxncommit hook: HG_HOOKTYPE=pretxncommit HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 HG_PARENT1=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT2=ab228980c14deea8b9555d91c9581127383e40fd HG_PENDING=$TESTTMP/a
86 precommit hook: HG_HOOKNAME=precommit HG_HOOKTYPE=precommit HG_PARENT1=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT2=ab228980c14deea8b9555d91c9581127383e40fd
87 pretxnopen hook: HG_HOOKNAME=pretxnopen HG_HOOKTYPE=pretxnopen HG_TXNID=TXN:$ID$ HG_TXNNAME=commit
88 pretxncommit hook: HG_HOOKNAME=pretxncommit HG_HOOKTYPE=pretxncommit HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 HG_PARENT1=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT2=ab228980c14deea8b9555d91c9581127383e40fd HG_PENDING=$TESTTMP/a
89 89 3:07f3376c1e65
90 pretxnclose hook: HG_HOOKTYPE=pretxnclose HG_PENDING=$TESTTMP/a HG_TXNID=TXN:$ID$ HG_TXNNAME=commit
91 txnclose hook: HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=commit
92 commit hook: HG_HOOKTYPE=commit HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 HG_PARENT1=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT2=ab228980c14deea8b9555d91c9581127383e40fd
93 commit.b hook: HG_HOOKTYPE=commit HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 HG_PARENT1=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT2=ab228980c14deea8b9555d91c9581127383e40fd
90 pretxnclose hook: HG_HOOKNAME=pretxnclose HG_HOOKTYPE=pretxnclose HG_PENDING=$TESTTMP/a HG_TXNID=TXN:$ID$ HG_TXNNAME=commit
91 txnclose hook: HG_HOOKNAME=txnclose HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=commit
92 commit hook: HG_HOOKNAME=commit HG_HOOKTYPE=commit HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 HG_PARENT1=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT2=ab228980c14deea8b9555d91c9581127383e40fd
93 commit.b hook: HG_HOOKNAME=commit.b HG_HOOKTYPE=commit HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 HG_PARENT1=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_PARENT2=ab228980c14deea8b9555d91c9581127383e40fd
94 94
95 95 test generic hooks
96 96
97 97 $ hg id
98 pre-identify hook: HG_ARGS=id HG_HOOKTYPE=pre-identify HG_OPTS={'bookmarks': None, 'branch': None, 'id': None, 'insecure': None, 'num': None, 'remotecmd': '', 'rev': '', 'ssh': '', 'tags': None} HG_PATS=[]
98 pre-identify hook: HG_ARGS=id HG_HOOKNAME=pre-identify HG_HOOKTYPE=pre-identify HG_OPTS={'bookmarks': None, 'branch': None, 'id': None, 'insecure': None, 'num': None, 'remotecmd': '', 'rev': '', 'ssh': '', 'tags': None} HG_PATS=[]
99 99 abort: pre-identify hook exited with status 1
100 100 [255]
101 101 $ hg cat b
102 pre-cat hook: HG_ARGS=cat b HG_HOOKTYPE=pre-cat HG_OPTS={'decode': None, 'exclude': [], 'include': [], 'output': '', 'rev': ''} HG_PATS=['b']
102 pre-cat hook: HG_ARGS=cat b HG_HOOKNAME=pre-cat HG_HOOKTYPE=pre-cat HG_OPTS={'decode': None, 'exclude': [], 'include': [], 'output': '', 'rev': ''} HG_PATS=['b']
103 103 b
104 post-cat hook: HG_ARGS=cat b HG_HOOKTYPE=post-cat HG_OPTS={'decode': None, 'exclude': [], 'include': [], 'output': '', 'rev': ''} HG_PATS=['b'] HG_RESULT=0
104 post-cat hook: HG_ARGS=cat b HG_HOOKNAME=post-cat HG_HOOKTYPE=post-cat HG_OPTS={'decode': None, 'exclude': [], 'include': [], 'output': '', 'rev': ''} HG_PATS=['b'] HG_RESULT=0
105 105
106 106 $ cd ../b
107 107 $ hg pull ../a
108 108 pulling from ../a
109 109 searching for changes
110 prechangegroup hook: HG_HOOKTYPE=prechangegroup HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/a
110 prechangegroup hook: HG_HOOKNAME=prechangegroup HG_HOOKTYPE=prechangegroup HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/a
111 111 adding changesets
112 112 adding manifests
113 113 adding file changes
114 114 added 3 changesets with 2 changes to 2 files
115 changegroup hook: HG_HOOKTYPE=changegroup HG_NODE=ab228980c14deea8b9555d91c9581127383e40fd HG_NODE_LAST=07f3376c1e655977439df2a814e3cc14b27abac2 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/a
116 incoming hook: HG_HOOKTYPE=incoming HG_NODE=ab228980c14deea8b9555d91c9581127383e40fd HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/a
117 incoming hook: HG_HOOKTYPE=incoming HG_NODE=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/a
118 incoming hook: HG_HOOKTYPE=incoming HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/a
115 changegroup hook: HG_HOOKNAME=changegroup HG_HOOKTYPE=changegroup HG_NODE=ab228980c14deea8b9555d91c9581127383e40fd HG_NODE_LAST=07f3376c1e655977439df2a814e3cc14b27abac2 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/a
116 incoming hook: HG_HOOKNAME=incoming HG_HOOKTYPE=incoming HG_NODE=ab228980c14deea8b9555d91c9581127383e40fd HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/a
117 incoming hook: HG_HOOKNAME=incoming HG_HOOKTYPE=incoming HG_NODE=ee9deb46ab31e4cc3310f3cf0c3d668e4d8fffc2 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/a
118 incoming hook: HG_HOOKNAME=incoming HG_HOOKTYPE=incoming HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/a
119 119 (run 'hg update' to get a working copy)
120 120
121 121 tag hooks can see env vars
122 122
123 123 $ cd ../a
124 124 $ cat >> .hg/hgrc <<EOF
125 125 > pretag = sh -c "printenv.py pretag"
126 126 > tag = sh -c "HG_PARENT1= HG_PARENT2= printenv.py tag"
127 127 > EOF
128 128 $ hg tag -d '3 0' a
129 pretag hook: HG_HOOKTYPE=pretag HG_LOCAL=0 HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 HG_TAG=a
130 precommit hook: HG_HOOKTYPE=precommit HG_PARENT1=07f3376c1e655977439df2a814e3cc14b27abac2
131 pretxnopen hook: HG_HOOKTYPE=pretxnopen HG_TXNID=TXN:$ID$ HG_TXNNAME=commit
132 pretxncommit hook: HG_HOOKTYPE=pretxncommit HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_PARENT1=07f3376c1e655977439df2a814e3cc14b27abac2 HG_PENDING=$TESTTMP/a
129 pretag hook: HG_HOOKNAME=pretag HG_HOOKTYPE=pretag HG_LOCAL=0 HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 HG_TAG=a
130 precommit hook: HG_HOOKNAME=precommit HG_HOOKTYPE=precommit HG_PARENT1=07f3376c1e655977439df2a814e3cc14b27abac2
131 pretxnopen hook: HG_HOOKNAME=pretxnopen HG_HOOKTYPE=pretxnopen HG_TXNID=TXN:$ID$ HG_TXNNAME=commit
132 pretxncommit hook: HG_HOOKNAME=pretxncommit HG_HOOKTYPE=pretxncommit HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_PARENT1=07f3376c1e655977439df2a814e3cc14b27abac2 HG_PENDING=$TESTTMP/a
133 133 4:539e4b31b6dc
134 pretxnclose hook: HG_HOOKTYPE=pretxnclose HG_PENDING=$TESTTMP/a HG_TXNID=TXN:$ID$ HG_TXNNAME=commit
135 tag hook: HG_HOOKTYPE=tag HG_LOCAL=0 HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 HG_TAG=a
136 txnclose hook: HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=commit
137 commit hook: HG_HOOKTYPE=commit HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_PARENT1=07f3376c1e655977439df2a814e3cc14b27abac2
138 commit.b hook: HG_HOOKTYPE=commit HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_PARENT1=07f3376c1e655977439df2a814e3cc14b27abac2
134 pretxnclose hook: HG_HOOKNAME=pretxnclose HG_HOOKTYPE=pretxnclose HG_PENDING=$TESTTMP/a HG_TXNID=TXN:$ID$ HG_TXNNAME=commit
135 tag hook: HG_HOOKNAME=tag HG_HOOKTYPE=tag HG_LOCAL=0 HG_NODE=07f3376c1e655977439df2a814e3cc14b27abac2 HG_TAG=a
136 txnclose hook: HG_HOOKNAME=txnclose HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=commit
137 commit hook: HG_HOOKNAME=commit HG_HOOKTYPE=commit HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_PARENT1=07f3376c1e655977439df2a814e3cc14b27abac2
138 commit.b hook: HG_HOOKNAME=commit.b HG_HOOKTYPE=commit HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_PARENT1=07f3376c1e655977439df2a814e3cc14b27abac2
139 139 $ hg tag -l la
140 pretag hook: HG_HOOKTYPE=pretag HG_LOCAL=1 HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_TAG=la
141 tag hook: HG_HOOKTYPE=tag HG_LOCAL=1 HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_TAG=la
140 pretag hook: HG_HOOKNAME=pretag HG_HOOKTYPE=pretag HG_LOCAL=1 HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_TAG=la
141 tag hook: HG_HOOKNAME=tag HG_HOOKTYPE=tag HG_LOCAL=1 HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_TAG=la
142 142
143 143 pretag hook can forbid tagging
144 144
145 145 $ cat >> .hg/hgrc <<EOF
146 146 > pretag.forbid = sh -c "printenv.py pretag.forbid 1"
147 147 > EOF
148 148 $ hg tag -d '4 0' fa
149 pretag hook: HG_HOOKTYPE=pretag HG_LOCAL=0 HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_TAG=fa
150 pretag.forbid hook: HG_HOOKTYPE=pretag HG_LOCAL=0 HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_TAG=fa
149 pretag hook: HG_HOOKNAME=pretag HG_HOOKTYPE=pretag HG_LOCAL=0 HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_TAG=fa
150 pretag.forbid hook: HG_HOOKNAME=pretag.forbid HG_HOOKTYPE=pretag HG_LOCAL=0 HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_TAG=fa
151 151 abort: pretag.forbid hook exited with status 1
152 152 [255]
153 153 $ hg tag -l fla
154 pretag hook: HG_HOOKTYPE=pretag HG_LOCAL=1 HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_TAG=fla
155 pretag.forbid hook: HG_HOOKTYPE=pretag HG_LOCAL=1 HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_TAG=fla
154 pretag hook: HG_HOOKNAME=pretag HG_HOOKTYPE=pretag HG_LOCAL=1 HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_TAG=fla
155 pretag.forbid hook: HG_HOOKNAME=pretag.forbid HG_HOOKTYPE=pretag HG_LOCAL=1 HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_TAG=fla
156 156 abort: pretag.forbid hook exited with status 1
157 157 [255]
158 158
159 159 pretxncommit hook can see changeset, can roll back txn, changeset no
160 160 more there after
161 161
162 162 $ cat >> .hg/hgrc <<EOF
163 163 > pretxncommit.forbid0 = sh -c "hg tip -q"
164 164 > pretxncommit.forbid1 = sh -c "printenv.py pretxncommit.forbid 1"
165 165 > EOF
166 166 $ echo z > z
167 167 $ hg add z
168 168 $ hg -q tip
169 169 4:539e4b31b6dc
170 170 $ hg commit -m 'fail' -d '4 0'
171 precommit hook: HG_HOOKTYPE=precommit HG_PARENT1=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10
172 pretxnopen hook: HG_HOOKTYPE=pretxnopen HG_TXNID=TXN:$ID$ HG_TXNNAME=commit
173 pretxncommit hook: HG_HOOKTYPE=pretxncommit HG_NODE=6f611f8018c10e827fee6bd2bc807f937e761567 HG_PARENT1=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_PENDING=$TESTTMP/a
171 precommit hook: HG_HOOKNAME=precommit HG_HOOKTYPE=precommit HG_PARENT1=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10
172 pretxnopen hook: HG_HOOKNAME=pretxnopen HG_HOOKTYPE=pretxnopen HG_TXNID=TXN:$ID$ HG_TXNNAME=commit
173 pretxncommit hook: HG_HOOKNAME=pretxncommit HG_HOOKTYPE=pretxncommit HG_NODE=6f611f8018c10e827fee6bd2bc807f937e761567 HG_PARENT1=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_PENDING=$TESTTMP/a
174 174 5:6f611f8018c1
175 175 5:6f611f8018c1
176 pretxncommit.forbid hook: HG_HOOKTYPE=pretxncommit HG_NODE=6f611f8018c10e827fee6bd2bc807f937e761567 HG_PARENT1=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_PENDING=$TESTTMP/a
176 pretxncommit.forbid hook: HG_HOOKNAME=pretxncommit.forbid1 HG_HOOKTYPE=pretxncommit HG_NODE=6f611f8018c10e827fee6bd2bc807f937e761567 HG_PARENT1=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_PENDING=$TESTTMP/a
177 177 transaction abort!
178 178 txnabort python hook: txnid,txnname
179 txnabort hook: HG_HOOKTYPE=txnabort HG_TXNID=TXN:$ID$ HG_TXNNAME=commit
179 txnabort hook: HG_HOOKNAME=txnabort.1 HG_HOOKTYPE=txnabort HG_TXNID=TXN:$ID$ HG_TXNNAME=commit
180 180 rollback completed
181 181 abort: pretxncommit.forbid1 hook exited with status 1
182 182 [255]
183 183 $ hg -q tip
184 184 4:539e4b31b6dc
185 185
186 186 (Check that no 'changelog.i.a' file were left behind)
187 187
188 188 $ ls -1 .hg/store/
189 189 00changelog.i
190 190 00manifest.i
191 191 data
192 192 fncache
193 193 journal.phaseroots
194 194 phaseroots
195 195 undo
196 196 undo.backup.fncache
197 197 undo.backupfiles
198 198 undo.phaseroots
199 199
200 200
201 201 precommit hook can prevent commit
202 202
203 203 $ cat >> .hg/hgrc <<EOF
204 204 > precommit.forbid = sh -c "printenv.py precommit.forbid 1"
205 205 > EOF
206 206 $ hg commit -m 'fail' -d '4 0'
207 precommit hook: HG_HOOKTYPE=precommit HG_PARENT1=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10
208 precommit.forbid hook: HG_HOOKTYPE=precommit HG_PARENT1=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10
207 precommit hook: HG_HOOKNAME=precommit HG_HOOKTYPE=precommit HG_PARENT1=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10
208 precommit.forbid hook: HG_HOOKNAME=precommit.forbid HG_HOOKTYPE=precommit HG_PARENT1=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10
209 209 abort: precommit.forbid hook exited with status 1
210 210 [255]
211 211 $ hg -q tip
212 212 4:539e4b31b6dc
213 213
214 214 preupdate hook can prevent update
215 215
216 216 $ cat >> .hg/hgrc <<EOF
217 217 > preupdate = sh -c "printenv.py preupdate"
218 218 > EOF
219 219 $ hg update 1
220 preupdate hook: HG_HOOKTYPE=preupdate HG_PARENT1=ab228980c14d
220 preupdate hook: HG_HOOKNAME=preupdate HG_HOOKTYPE=preupdate HG_PARENT1=ab228980c14d
221 221 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
222 222
223 223 update hook
224 224
225 225 $ cat >> .hg/hgrc <<EOF
226 226 > update = sh -c "printenv.py update"
227 227 > EOF
228 228 $ hg update
229 preupdate hook: HG_HOOKTYPE=preupdate HG_PARENT1=539e4b31b6dc
230 update hook: HG_ERROR=0 HG_HOOKTYPE=update HG_PARENT1=539e4b31b6dc
229 preupdate hook: HG_HOOKNAME=preupdate HG_HOOKTYPE=preupdate HG_PARENT1=539e4b31b6dc
230 update hook: HG_ERROR=0 HG_HOOKNAME=update HG_HOOKTYPE=update HG_PARENT1=539e4b31b6dc
231 231 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
232 232
233 233 pushkey hook
234 234
235 235 $ cat >> .hg/hgrc <<EOF
236 236 > pushkey = sh -c "printenv.py pushkey"
237 237 > EOF
238 238 $ cd ../b
239 239 $ hg bookmark -r null foo
240 240 $ hg push -B foo ../a
241 241 pushing to ../a
242 242 searching for changes
243 243 no changes found
244 pretxnopen hook: HG_HOOKTYPE=pretxnopen HG_TXNID=TXN:$ID$ HG_TXNNAME=push
245 pretxnclose hook: HG_BOOKMARK_MOVED=1 HG_BUNDLE2=1 HG_HOOKTYPE=pretxnclose HG_PENDING=$TESTTMP/a HG_SOURCE=push HG_TXNID=TXN:$ID$ HG_TXNNAME=push HG_URL=file:$TESTTMP/a
246 pushkey hook: HG_HOOKTYPE=pushkey HG_KEY=foo HG_NAMESPACE=bookmarks HG_NEW=0000000000000000000000000000000000000000 HG_RET=1
247 txnclose hook: HG_BOOKMARK_MOVED=1 HG_BUNDLE2=1 HG_HOOKTYPE=txnclose HG_SOURCE=push HG_TXNID=TXN:$ID$ HG_TXNNAME=push HG_URL=file:$TESTTMP/a
244 pretxnopen hook: HG_HOOKNAME=pretxnopen HG_HOOKTYPE=pretxnopen HG_TXNID=TXN:$ID$ HG_TXNNAME=push
245 pretxnclose hook: HG_BOOKMARK_MOVED=1 HG_BUNDLE2=1 HG_HOOKNAME=pretxnclose HG_HOOKTYPE=pretxnclose HG_PENDING=$TESTTMP/a HG_SOURCE=push HG_TXNID=TXN:$ID$ HG_TXNNAME=push HG_URL=file:$TESTTMP/a
246 pushkey hook: HG_HOOKNAME=pushkey HG_HOOKTYPE=pushkey HG_KEY=foo HG_NAMESPACE=bookmarks HG_NEW=0000000000000000000000000000000000000000 HG_RET=1
247 txnclose hook: HG_BOOKMARK_MOVED=1 HG_BUNDLE2=1 HG_HOOKNAME=txnclose HG_HOOKTYPE=txnclose HG_SOURCE=push HG_TXNID=TXN:$ID$ HG_TXNNAME=push HG_URL=file:$TESTTMP/a
248 248 exporting bookmark foo
249 249 [1]
250 250 $ cd ../a
251 251
252 252 listkeys hook
253 253
254 254 $ cat >> .hg/hgrc <<EOF
255 255 > listkeys = sh -c "printenv.py listkeys"
256 256 > EOF
257 257 $ hg bookmark -r null bar
258 pretxnopen hook: HG_HOOKTYPE=pretxnopen HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
259 pretxnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKTYPE=pretxnclose HG_PENDING=$TESTTMP/a HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
260 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
258 pretxnopen hook: HG_HOOKNAME=pretxnopen HG_HOOKTYPE=pretxnopen HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
259 pretxnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKNAME=pretxnclose HG_HOOKTYPE=pretxnclose HG_PENDING=$TESTTMP/a HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
260 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKNAME=txnclose HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
261 261 $ cd ../b
262 262 $ hg pull -B bar ../a
263 263 pulling from ../a
264 listkeys hook: HG_HOOKTYPE=listkeys HG_NAMESPACE=bookmarks HG_VALUES={'bar': '0000000000000000000000000000000000000000', 'foo': '0000000000000000000000000000000000000000'}
264 listkeys hook: HG_HOOKNAME=listkeys HG_HOOKTYPE=listkeys HG_NAMESPACE=bookmarks HG_VALUES={'bar': '0000000000000000000000000000000000000000', 'foo': '0000000000000000000000000000000000000000'}
265 265 no changes found
266 listkeys hook: HG_HOOKTYPE=listkeys HG_NAMESPACE=phases HG_VALUES={'cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b': '1', 'publishing': 'True'}
266 listkeys hook: HG_HOOKNAME=listkeys HG_HOOKTYPE=listkeys HG_NAMESPACE=phases HG_VALUES={'cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b': '1', 'publishing': 'True'}
267 267 adding remote bookmark bar
268 268 $ cd ../a
269 269
270 270 test that prepushkey can prevent incoming keys
271 271
272 272 $ cat >> .hg/hgrc <<EOF
273 273 > prepushkey = sh -c "printenv.py prepushkey.forbid 1"
274 274 > EOF
275 275 $ cd ../b
276 276 $ hg bookmark -r null baz
277 277 $ hg push -B baz ../a
278 278 pushing to ../a
279 279 searching for changes
280 listkeys hook: HG_HOOKTYPE=listkeys HG_NAMESPACE=phases HG_VALUES={'cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b': '1', 'publishing': 'True'}
281 listkeys hook: HG_HOOKTYPE=listkeys HG_NAMESPACE=bookmarks HG_VALUES={'bar': '0000000000000000000000000000000000000000', 'foo': '0000000000000000000000000000000000000000'}
280 listkeys hook: HG_HOOKNAME=listkeys HG_HOOKTYPE=listkeys HG_NAMESPACE=phases HG_VALUES={'cb9a9f314b8b07ba71012fcdbc544b5a4d82ff5b': '1', 'publishing': 'True'}
281 listkeys hook: HG_HOOKNAME=listkeys HG_HOOKTYPE=listkeys HG_NAMESPACE=bookmarks HG_VALUES={'bar': '0000000000000000000000000000000000000000', 'foo': '0000000000000000000000000000000000000000'}
282 282 no changes found
283 pretxnopen hook: HG_HOOKTYPE=pretxnopen HG_TXNID=TXN:$ID$ HG_TXNNAME=push
284 prepushkey.forbid hook: HG_BUNDLE2=1 HG_HOOKTYPE=prepushkey HG_KEY=baz HG_NAMESPACE=bookmarks HG_NEW=0000000000000000000000000000000000000000 HG_SOURCE=push HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/a
283 pretxnopen hook: HG_HOOKNAME=pretxnopen HG_HOOKTYPE=pretxnopen HG_TXNID=TXN:$ID$ HG_TXNNAME=push
284 prepushkey.forbid hook: HG_BUNDLE2=1 HG_HOOKNAME=prepushkey HG_HOOKTYPE=prepushkey HG_KEY=baz HG_NAMESPACE=bookmarks HG_NEW=0000000000000000000000000000000000000000 HG_SOURCE=push HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/a
285 285 pushkey-abort: prepushkey hook exited with status 1
286 286 abort: exporting bookmark baz failed!
287 287 [255]
288 288 $ cd ../a
289 289
290 290 test that prelistkeys can prevent listing keys
291 291
292 292 $ cat >> .hg/hgrc <<EOF
293 293 > prelistkeys = sh -c "printenv.py prelistkeys.forbid 1"
294 294 > EOF
295 295 $ hg bookmark -r null quux
296 pretxnopen hook: HG_HOOKTYPE=pretxnopen HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
297 pretxnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKTYPE=pretxnclose HG_PENDING=$TESTTMP/a HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
298 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
296 pretxnopen hook: HG_HOOKNAME=pretxnopen HG_HOOKTYPE=pretxnopen HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
297 pretxnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKNAME=pretxnclose HG_HOOKTYPE=pretxnclose HG_PENDING=$TESTTMP/a HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
298 txnclose hook: HG_BOOKMARK_MOVED=1 HG_HOOKNAME=txnclose HG_HOOKTYPE=txnclose HG_TXNID=TXN:$ID$ HG_TXNNAME=bookmark
299 299 $ cd ../b
300 300 $ hg pull -B quux ../a
301 301 pulling from ../a
302 prelistkeys.forbid hook: HG_HOOKTYPE=prelistkeys HG_NAMESPACE=bookmarks
302 prelistkeys.forbid hook: HG_HOOKNAME=prelistkeys HG_HOOKTYPE=prelistkeys HG_NAMESPACE=bookmarks
303 303 abort: prelistkeys hook exited with status 1
304 304 [255]
305 305 $ cd ../a
306 306 $ rm .hg/hgrc
307 307
308 308 prechangegroup hook can prevent incoming changes
309 309
310 310 $ cd ../b
311 311 $ hg -q tip
312 312 3:07f3376c1e65
313 313 $ cat > .hg/hgrc <<EOF
314 314 > [hooks]
315 315 > prechangegroup.forbid = sh -c "printenv.py prechangegroup.forbid 1"
316 316 > EOF
317 317 $ hg pull ../a
318 318 pulling from ../a
319 319 searching for changes
320 prechangegroup.forbid hook: HG_HOOKTYPE=prechangegroup HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/a
320 prechangegroup.forbid hook: HG_HOOKNAME=prechangegroup.forbid HG_HOOKTYPE=prechangegroup HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/a
321 321 abort: prechangegroup.forbid hook exited with status 1
322 322 [255]
323 323
324 324 pretxnchangegroup hook can see incoming changes, can roll back txn,
325 325 incoming changes no longer there after
326 326
327 327 $ cat > .hg/hgrc <<EOF
328 328 > [hooks]
329 329 > pretxnchangegroup.forbid0 = hg tip -q
330 330 > pretxnchangegroup.forbid1 = sh -c "printenv.py pretxnchangegroup.forbid 1"
331 331 > EOF
332 332 $ hg pull ../a
333 333 pulling from ../a
334 334 searching for changes
335 335 adding changesets
336 336 adding manifests
337 337 adding file changes
338 338 added 1 changesets with 1 changes to 1 files
339 339 4:539e4b31b6dc
340 pretxnchangegroup.forbid hook: HG_HOOKTYPE=pretxnchangegroup HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_NODE_LAST=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_PENDING=$TESTTMP/b HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/a
340 pretxnchangegroup.forbid hook: HG_HOOKNAME=pretxnchangegroup.forbid1 HG_HOOKTYPE=pretxnchangegroup HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_NODE_LAST=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_PENDING=$TESTTMP/b HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=file:$TESTTMP/a
341 341 transaction abort!
342 342 rollback completed
343 343 abort: pretxnchangegroup.forbid1 hook exited with status 1
344 344 [255]
345 345 $ hg -q tip
346 346 3:07f3376c1e65
347 347
348 348 outgoing hooks can see env vars
349 349
350 350 $ rm .hg/hgrc
351 351 $ cat > ../a/.hg/hgrc <<EOF
352 352 > [hooks]
353 353 > preoutgoing = sh -c "printenv.py preoutgoing"
354 354 > outgoing = sh -c "printenv.py outgoing"
355 355 > EOF
356 356 $ hg pull ../a
357 357 pulling from ../a
358 358 searching for changes
359 preoutgoing hook: HG_HOOKTYPE=preoutgoing HG_SOURCE=pull
360 outgoing hook: HG_HOOKTYPE=outgoing HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_SOURCE=pull
359 preoutgoing hook: HG_HOOKNAME=preoutgoing HG_HOOKTYPE=preoutgoing HG_SOURCE=pull
360 outgoing hook: HG_HOOKNAME=outgoing HG_HOOKTYPE=outgoing HG_NODE=539e4b31b6dc99b3cfbaa6b53cbc1c1f9a1e3a10 HG_SOURCE=pull
361 361 adding changesets
362 362 adding manifests
363 363 adding file changes
364 364 added 1 changesets with 1 changes to 1 files
365 365 adding remote bookmark quux
366 366 (run 'hg update' to get a working copy)
367 367 $ hg rollback
368 368 repository tip rolled back to revision 3 (undo pull)
369 369
370 370 preoutgoing hook can prevent outgoing changes
371 371
372 372 $ cat >> ../a/.hg/hgrc <<EOF
373 373 > preoutgoing.forbid = sh -c "printenv.py preoutgoing.forbid 1"
374 374 > EOF
375 375 $ hg pull ../a
376 376 pulling from ../a
377 377 searching for changes
378 preoutgoing hook: HG_HOOKTYPE=preoutgoing HG_SOURCE=pull
379 preoutgoing.forbid hook: HG_HOOKTYPE=preoutgoing HG_SOURCE=pull
378 preoutgoing hook: HG_HOOKNAME=preoutgoing HG_HOOKTYPE=preoutgoing HG_SOURCE=pull
379 preoutgoing.forbid hook: HG_HOOKNAME=preoutgoing.forbid HG_HOOKTYPE=preoutgoing HG_SOURCE=pull
380 380 abort: preoutgoing.forbid hook exited with status 1
381 381 [255]
382 382
383 383 outgoing hooks work for local clones
384 384
385 385 $ cd ..
386 386 $ cat > a/.hg/hgrc <<EOF
387 387 > [hooks]
388 388 > preoutgoing = sh -c "printenv.py preoutgoing"
389 389 > outgoing = sh -c "printenv.py outgoing"
390 390 > EOF
391 391 $ hg clone a c
392 preoutgoing hook: HG_HOOKTYPE=preoutgoing HG_SOURCE=clone
393 outgoing hook: HG_HOOKTYPE=outgoing HG_NODE=0000000000000000000000000000000000000000 HG_SOURCE=clone
392 preoutgoing hook: HG_HOOKNAME=preoutgoing HG_HOOKTYPE=preoutgoing HG_SOURCE=clone
393 outgoing hook: HG_HOOKNAME=outgoing HG_HOOKTYPE=outgoing HG_NODE=0000000000000000000000000000000000000000 HG_SOURCE=clone
394 394 updating to branch default
395 395 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
396 396 $ rm -rf c
397 397
398 398 preoutgoing hook can prevent outgoing changes for local clones
399 399
400 400 $ cat >> a/.hg/hgrc <<EOF
401 401 > preoutgoing.forbid = sh -c "printenv.py preoutgoing.forbid 1"
402 402 > EOF
403 403 $ hg clone a zzz
404 preoutgoing hook: HG_HOOKTYPE=preoutgoing HG_SOURCE=clone
405 preoutgoing.forbid hook: HG_HOOKTYPE=preoutgoing HG_SOURCE=clone
404 preoutgoing hook: HG_HOOKNAME=preoutgoing HG_HOOKTYPE=preoutgoing HG_SOURCE=clone
405 preoutgoing.forbid hook: HG_HOOKNAME=preoutgoing.forbid HG_HOOKTYPE=preoutgoing HG_SOURCE=clone
406 406 abort: preoutgoing.forbid hook exited with status 1
407 407 [255]
408 408
409 409 $ cd "$TESTTMP/b"
410 410
411 411 $ cat > hooktests.py <<EOF
412 412 > from mercurial import error
413 413 >
414 414 > uncallable = 0
415 415 >
416 416 > def printargs(args):
417 417 > args.pop('ui', None)
418 418 > args.pop('repo', None)
419 419 > a = list(args.items())
420 420 > a.sort()
421 421 > print 'hook args:'
422 422 > for k, v in a:
423 423 > print ' ', k, v
424 424 >
425 425 > def passhook(**args):
426 426 > printargs(args)
427 427 >
428 428 > def failhook(**args):
429 429 > printargs(args)
430 430 > return True
431 431 >
432 432 > class LocalException(Exception):
433 433 > pass
434 434 >
435 435 > def raisehook(**args):
436 436 > raise LocalException('exception from hook')
437 437 >
438 438 > def aborthook(**args):
439 439 > raise error.Abort('raise abort from hook')
440 440 >
441 441 > def brokenhook(**args):
442 442 > return 1 + {}
443 443 >
444 444 > def verbosehook(ui, **args):
445 445 > ui.note('verbose output from hook\n')
446 446 >
447 447 > def printtags(ui, repo, **args):
448 448 > print sorted(repo.tags())
449 449 >
450 450 > class container:
451 451 > unreachable = 1
452 452 > EOF
453 453
454 454 $ cat > syntaxerror.py << EOF
455 455 > (foo
456 456 > EOF
457 457
458 458 test python hooks
459 459
460 460 #if windows
461 461 $ PYTHONPATH="$TESTTMP/b;$PYTHONPATH"
462 462 #else
463 463 $ PYTHONPATH="$TESTTMP/b:$PYTHONPATH"
464 464 #endif
465 465 $ export PYTHONPATH
466 466
467 467 $ echo '[hooks]' > ../a/.hg/hgrc
468 468 $ echo 'preoutgoing.broken = python:hooktests.brokenhook' >> ../a/.hg/hgrc
469 469 $ hg pull ../a 2>&1 | grep 'raised an exception'
470 470 error: preoutgoing.broken hook raised an exception: unsupported operand type(s) for +: 'int' and 'dict'
471 471
472 472 $ echo '[hooks]' > ../a/.hg/hgrc
473 473 $ echo 'preoutgoing.raise = python:hooktests.raisehook' >> ../a/.hg/hgrc
474 474 $ hg pull ../a 2>&1 | grep 'raised an exception'
475 475 error: preoutgoing.raise hook raised an exception: exception from hook
476 476
477 477 $ echo '[hooks]' > ../a/.hg/hgrc
478 478 $ echo 'preoutgoing.abort = python:hooktests.aborthook' >> ../a/.hg/hgrc
479 479 $ hg pull ../a
480 480 pulling from ../a
481 481 searching for changes
482 482 error: preoutgoing.abort hook failed: raise abort from hook
483 483 abort: raise abort from hook
484 484 [255]
485 485
486 486 $ echo '[hooks]' > ../a/.hg/hgrc
487 487 $ echo 'preoutgoing.fail = python:hooktests.failhook' >> ../a/.hg/hgrc
488 488 $ hg pull ../a
489 489 pulling from ../a
490 490 searching for changes
491 491 hook args:
492 492 hooktype preoutgoing
493 493 source pull
494 494 abort: preoutgoing.fail hook failed
495 495 [255]
496 496
497 497 $ echo '[hooks]' > ../a/.hg/hgrc
498 498 $ echo 'preoutgoing.uncallable = python:hooktests.uncallable' >> ../a/.hg/hgrc
499 499 $ hg pull ../a
500 500 pulling from ../a
501 501 searching for changes
502 502 abort: preoutgoing.uncallable hook is invalid: "hooktests.uncallable" is not callable
503 503 [255]
504 504
505 505 $ echo '[hooks]' > ../a/.hg/hgrc
506 506 $ echo 'preoutgoing.nohook = python:hooktests.nohook' >> ../a/.hg/hgrc
507 507 $ hg pull ../a
508 508 pulling from ../a
509 509 searching for changes
510 510 abort: preoutgoing.nohook hook is invalid: "hooktests.nohook" is not defined
511 511 [255]
512 512
513 513 $ echo '[hooks]' > ../a/.hg/hgrc
514 514 $ echo 'preoutgoing.nomodule = python:nomodule' >> ../a/.hg/hgrc
515 515 $ hg pull ../a
516 516 pulling from ../a
517 517 searching for changes
518 518 abort: preoutgoing.nomodule hook is invalid: "nomodule" not in a module
519 519 [255]
520 520
521 521 $ echo '[hooks]' > ../a/.hg/hgrc
522 522 $ echo 'preoutgoing.badmodule = python:nomodule.nowhere' >> ../a/.hg/hgrc
523 523 $ hg pull ../a
524 524 pulling from ../a
525 525 searching for changes
526 526 abort: preoutgoing.badmodule hook is invalid: import of "nomodule" failed
527 527 (run with --traceback for stack trace)
528 528 [255]
529 529
530 530 $ echo '[hooks]' > ../a/.hg/hgrc
531 531 $ echo 'preoutgoing.unreachable = python:hooktests.container.unreachable' >> ../a/.hg/hgrc
532 532 $ hg pull ../a
533 533 pulling from ../a
534 534 searching for changes
535 535 abort: preoutgoing.unreachable hook is invalid: import of "hooktests.container" failed
536 536 (run with --traceback for stack trace)
537 537 [255]
538 538
539 539 $ echo '[hooks]' > ../a/.hg/hgrc
540 540 $ echo 'preoutgoing.syntaxerror = python:syntaxerror.syntaxerror' >> ../a/.hg/hgrc
541 541 $ hg pull ../a
542 542 pulling from ../a
543 543 searching for changes
544 544 abort: preoutgoing.syntaxerror hook is invalid: import of "syntaxerror" failed
545 545 (run with --traceback for stack trace)
546 546 [255]
547 547
548 548 The second egrep is to filter out lines like ' ^', which are slightly
549 549 different between Python 2.6 and Python 2.7.
550 550 $ hg pull ../a --traceback 2>&1 | egrep -v '^( +File| [_a-zA-Z*(])' | egrep -v '^( )+(\^)?$'
551 551 pulling from ../a
552 552 searching for changes
553 553 exception from first failed import attempt:
554 554 Traceback (most recent call last):
555 555 SyntaxError: * (glob)
556 556 exception from second failed import attempt:
557 557 Traceback (most recent call last):
558 558 ImportError: No module named hgext_syntaxerror
559 559 Traceback (most recent call last):
560 560 HookLoadError: preoutgoing.syntaxerror hook is invalid: import of "syntaxerror" failed
561 561 abort: preoutgoing.syntaxerror hook is invalid: import of "syntaxerror" failed
562 562
563 563 $ echo '[hooks]' > ../a/.hg/hgrc
564 564 $ echo 'preoutgoing.pass = python:hooktests.passhook' >> ../a/.hg/hgrc
565 565 $ hg pull ../a
566 566 pulling from ../a
567 567 searching for changes
568 568 hook args:
569 569 hooktype preoutgoing
570 570 source pull
571 571 adding changesets
572 572 adding manifests
573 573 adding file changes
574 574 added 1 changesets with 1 changes to 1 files
575 575 adding remote bookmark quux
576 576 (run 'hg update' to get a working copy)
577 577
578 578 post- python hooks that fail to *run* don't cause an abort
579 579 $ rm ../a/.hg/hgrc
580 580 $ echo '[hooks]' > .hg/hgrc
581 581 $ echo 'post-pull.broken = python:hooktests.brokenhook' >> .hg/hgrc
582 582 $ hg pull ../a
583 583 pulling from ../a
584 584 searching for changes
585 585 no changes found
586 586 error: post-pull.broken hook raised an exception: unsupported operand type(s) for +: 'int' and 'dict'
587 587 (run with --traceback for stack trace)
588 588
589 589 but post- python hooks that fail to *load* do
590 590 $ echo '[hooks]' > .hg/hgrc
591 591 $ echo 'post-pull.nomodule = python:nomodule' >> .hg/hgrc
592 592 $ hg pull ../a
593 593 pulling from ../a
594 594 searching for changes
595 595 no changes found
596 596 abort: post-pull.nomodule hook is invalid: "nomodule" not in a module
597 597 [255]
598 598
599 599 $ echo '[hooks]' > .hg/hgrc
600 600 $ echo 'post-pull.badmodule = python:nomodule.nowhere' >> .hg/hgrc
601 601 $ hg pull ../a
602 602 pulling from ../a
603 603 searching for changes
604 604 no changes found
605 605 abort: post-pull.badmodule hook is invalid: import of "nomodule" failed
606 606 (run with --traceback for stack trace)
607 607 [255]
608 608
609 609 $ echo '[hooks]' > .hg/hgrc
610 610 $ echo 'post-pull.nohook = python:hooktests.nohook' >> .hg/hgrc
611 611 $ hg pull ../a
612 612 pulling from ../a
613 613 searching for changes
614 614 no changes found
615 615 abort: post-pull.nohook hook is invalid: "hooktests.nohook" is not defined
616 616 [255]
617 617
618 618 make sure --traceback works
619 619
620 620 $ echo '[hooks]' > .hg/hgrc
621 621 $ echo 'commit.abort = python:hooktests.aborthook' >> .hg/hgrc
622 622
623 623 $ echo aa > a
624 624 $ hg --traceback commit -d '0 0' -ma 2>&1 | grep '^Traceback'
625 625 Traceback (most recent call last):
626 626
627 627 $ cd ..
628 628 $ hg init c
629 629 $ cd c
630 630
631 631 $ cat > hookext.py <<EOF
632 632 > def autohook(**args):
633 633 > print "Automatically installed hook"
634 634 >
635 635 > def reposetup(ui, repo):
636 636 > repo.ui.setconfig("hooks", "commit.auto", autohook)
637 637 > EOF
638 638 $ echo '[extensions]' >> .hg/hgrc
639 639 $ echo 'hookext = hookext.py' >> .hg/hgrc
640 640
641 641 $ touch foo
642 642 $ hg add foo
643 643 $ hg ci -d '0 0' -m 'add foo'
644 644 Automatically installed hook
645 645 $ echo >> foo
646 646 $ hg ci --debug -d '0 0' -m 'change foo'
647 647 committing files:
648 648 foo
649 649 committing manifest
650 650 committing changelog
651 651 committed changeset 1:52998019f6252a2b893452765fcb0a47351a5708
652 652 calling hook commit.auto: hgext_hookext.autohook
653 653 Automatically installed hook
654 654
655 655 $ hg showconfig hooks
656 656 hooks.commit.auto=<function autohook at *> (glob)
657 657
658 658 test python hook configured with python:[file]:[hook] syntax
659 659
660 660 $ cd ..
661 661 $ mkdir d
662 662 $ cd d
663 663 $ hg init repo
664 664 $ mkdir hooks
665 665
666 666 $ cd hooks
667 667 $ cat > testhooks.py <<EOF
668 668 > def testhook(**args):
669 669 > print 'hook works'
670 670 > EOF
671 671 $ echo '[hooks]' > ../repo/.hg/hgrc
672 672 $ echo "pre-commit.test = python:`pwd`/testhooks.py:testhook" >> ../repo/.hg/hgrc
673 673
674 674 $ cd ../repo
675 675 $ hg commit -d '0 0'
676 676 hook works
677 677 nothing changed
678 678 [1]
679 679
680 680 $ echo '[hooks]' > .hg/hgrc
681 681 $ echo "update.ne = python:`pwd`/nonexistent.py:testhook" >> .hg/hgrc
682 682 $ echo "pre-identify.npmd = python:`pwd`/:no_python_module_dir" >> .hg/hgrc
683 683
684 684 $ hg up null
685 685 loading update.ne hook failed:
686 686 abort: No such file or directory: $TESTTMP/d/repo/nonexistent.py
687 687 [255]
688 688
689 689 $ hg id
690 690 loading pre-identify.npmd hook failed:
691 691 abort: No module named repo!
692 692 [255]
693 693
694 694 $ cd ../../b
695 695
696 696 make sure --traceback works on hook import failure
697 697
698 698 $ cat > importfail.py <<EOF
699 699 > import somebogusmodule
700 700 > # dereference something in the module to force demandimport to load it
701 701 > somebogusmodule.whatever
702 702 > EOF
703 703
704 704 $ echo '[hooks]' > .hg/hgrc
705 705 $ echo 'precommit.importfail = python:importfail.whatever' >> .hg/hgrc
706 706
707 707 $ echo a >> a
708 708 $ hg --traceback commit -ma 2>&1 | egrep -v '^( +File| [a-zA-Z(])'
709 709 exception from first failed import attempt:
710 710 Traceback (most recent call last):
711 711 ImportError: No module named somebogusmodule
712 712 exception from second failed import attempt:
713 713 Traceback (most recent call last):
714 714 ImportError: No module named hgext_importfail
715 715 Traceback (most recent call last):
716 716 HookLoadError: precommit.importfail hook is invalid: import of "importfail" failed
717 717 abort: precommit.importfail hook is invalid: import of "importfail" failed
718 718
719 719 Issue1827: Hooks Update & Commit not completely post operation
720 720
721 721 commit and update hooks should run after command completion. The largefiles
722 722 use demonstrates a recursive wlock, showing the hook doesn't run until the
723 723 final release (and dirstate flush).
724 724
725 725 $ echo '[hooks]' > .hg/hgrc
726 726 $ echo 'commit = hg id' >> .hg/hgrc
727 727 $ echo 'update = hg id' >> .hg/hgrc
728 728 $ echo bb > a
729 729 $ hg ci -ma
730 730 223eafe2750c tip
731 731 $ hg up 0 --config extensions.largefiles=
732 732 cb9a9f314b8b
733 733 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
734 734
735 735 make sure --verbose (and --quiet/--debug etc.) are propagated to the local ui
736 736 that is passed to pre/post hooks
737 737
738 738 $ echo '[hooks]' > .hg/hgrc
739 739 $ echo 'pre-identify = python:hooktests.verbosehook' >> .hg/hgrc
740 740 $ hg id
741 741 cb9a9f314b8b
742 742 $ hg id --verbose
743 743 calling hook pre-identify: hooktests.verbosehook
744 744 verbose output from hook
745 745 cb9a9f314b8b
746 746
747 747 Ensure hooks can be prioritized
748 748
749 749 $ echo '[hooks]' > .hg/hgrc
750 750 $ echo 'pre-identify.a = python:hooktests.verbosehook' >> .hg/hgrc
751 751 $ echo 'pre-identify.b = python:hooktests.verbosehook' >> .hg/hgrc
752 752 $ echo 'priority.pre-identify.b = 1' >> .hg/hgrc
753 753 $ echo 'pre-identify.c = python:hooktests.verbosehook' >> .hg/hgrc
754 754 $ hg id --verbose
755 755 calling hook pre-identify.b: hooktests.verbosehook
756 756 verbose output from hook
757 757 calling hook pre-identify.a: hooktests.verbosehook
758 758 verbose output from hook
759 759 calling hook pre-identify.c: hooktests.verbosehook
760 760 verbose output from hook
761 761 cb9a9f314b8b
762 762
763 763 new tags must be visible in pretxncommit (issue3210)
764 764
765 765 $ echo 'pretxncommit.printtags = python:hooktests.printtags' >> .hg/hgrc
766 766 $ hg tag -f foo
767 767 ['a', 'foo', 'tip']
768 768
769 769 post-init hooks must not crash (issue4983)
770 770 This also creates the `to` repo for the next test block.
771 771
772 772 $ cd ..
773 773 $ cat << EOF >> hgrc-with-post-init-hook
774 774 > [hooks]
775 775 > post-init = sh -c "printenv.py post-init"
776 776 > EOF
777 777 $ HGRCPATH=hgrc-with-post-init-hook hg init to
778 post-init hook: HG_ARGS=init to HG_HOOKTYPE=post-init HG_OPTS={'insecure': None, 'remotecmd': '', 'ssh': ''} HG_PATS=['to'] HG_RESULT=0
778 post-init hook: HG_ARGS=init to HG_HOOKNAME=post-init HG_HOOKTYPE=post-init HG_OPTS={'insecure': None, 'remotecmd': '', 'ssh': ''} HG_PATS=['to'] HG_RESULT=0
779 779
780 780 new commits must be visible in pretxnchangegroup (issue3428)
781 781
782 782 $ echo '[hooks]' >> to/.hg/hgrc
783 783 $ echo 'prechangegroup = hg --traceback tip' >> to/.hg/hgrc
784 784 $ echo 'pretxnchangegroup = hg --traceback tip' >> to/.hg/hgrc
785 785 $ echo a >> to/a
786 786 $ hg --cwd to ci -Ama
787 787 adding a
788 788 $ hg clone to from
789 789 updating to branch default
790 790 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
791 791 $ echo aa >> from/a
792 792 $ hg --cwd from ci -mb
793 793 $ hg --cwd from push
794 794 pushing to $TESTTMP/to (glob)
795 795 searching for changes
796 796 changeset: 0:cb9a9f314b8b
797 797 tag: tip
798 798 user: test
799 799 date: Thu Jan 01 00:00:00 1970 +0000
800 800 summary: a
801 801
802 802 adding changesets
803 803 adding manifests
804 804 adding file changes
805 805 added 1 changesets with 1 changes to 1 files
806 806 changeset: 1:9836a07b9b9d
807 807 tag: tip
808 808 user: test
809 809 date: Thu Jan 01 00:00:00 1970 +0000
810 810 summary: b
811 811
812 812
813 813 pretxnclose hook failure should abort the transaction
814 814
815 815 $ hg init txnfailure
816 816 $ cd txnfailure
817 817 $ touch a && hg commit -Aqm a
818 818 $ cat >> .hg/hgrc <<EOF
819 819 > [hooks]
820 820 > pretxnclose.error = exit 1
821 821 > EOF
822 822 $ hg strip -r 0 --config extensions.strip=
823 823 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
824 824 saved backup bundle to * (glob)
825 825 transaction abort!
826 826 rollback completed
827 827 strip failed, backup bundle stored in * (glob)
828 828 abort: pretxnclose.error hook exited with status 1
829 829 [255]
830 830 $ hg recover
831 831 no interrupted transaction available
832 832 [1]
833 833 $ cd ..
834 834
835 835 check whether HG_PENDING makes pending changes only in related
836 836 repositories visible to an external hook.
837 837
838 838 (emulate a transaction running concurrently by copied
839 839 .hg/store/00changelog.i.a in subsequent test)
840 840
841 841 $ cat > $TESTTMP/savepending.sh <<EOF
842 842 > cp .hg/store/00changelog.i.a .hg/store/00changelog.i.a.saved
843 843 > exit 1 # to avoid adding new revision for subsequent tests
844 844 > EOF
845 845 $ cd a
846 846 $ hg tip -q
847 847 4:539e4b31b6dc
848 848 $ hg --config hooks.pretxnclose="sh $TESTTMP/savepending.sh" commit -m "invisible"
849 849 transaction abort!
850 850 rollback completed
851 851 abort: pretxnclose hook exited with status 1
852 852 [255]
853 853 $ cp .hg/store/00changelog.i.a.saved .hg/store/00changelog.i.a
854 854
855 855 (check (in)visibility of new changeset while transaction running in
856 856 repo)
857 857
858 858 $ cat > $TESTTMP/checkpending.sh <<EOF
859 859 > echo '@a'
860 860 > hg -R $TESTTMP/a tip -q
861 861 > echo '@a/nested'
862 862 > hg -R $TESTTMP/a/nested tip -q
863 863 > exit 1 # to avoid adding new revision for subsequent tests
864 864 > EOF
865 865 $ hg init nested
866 866 $ cd nested
867 867 $ echo a > a
868 868 $ hg add a
869 869 $ hg --config hooks.pretxnclose="sh $TESTTMP/checkpending.sh" commit -m '#0'
870 870 @a
871 871 4:539e4b31b6dc
872 872 @a/nested
873 873 0:bf5e395ced2c
874 874 transaction abort!
875 875 rollback completed
876 876 abort: pretxnclose hook exited with status 1
877 877 [255]
878 878
879 879 Hook from untrusted hgrc are reported as failure
880 880 ================================================
881 881
882 882 $ cat << EOF > $TESTTMP/untrusted.py
883 883 > from mercurial import scmutil, util
884 884 > def uisetup(ui):
885 885 > class untrustedui(ui.__class__):
886 886 > def _trusted(self, fp, f):
887 887 > if util.normpath(fp.name).endswith('untrusted/.hg/hgrc'):
888 888 > return False
889 889 > return super(untrustedui, self)._trusted(fp, f)
890 890 > ui.__class__ = untrustedui
891 891 > EOF
892 892 $ cat << EOF >> $HGRCPATH
893 893 > [extensions]
894 894 > untrusted=$TESTTMP/untrusted.py
895 895 > EOF
896 896 $ hg init untrusted
897 897 $ cd untrusted
898 898
899 899 Non-blocking hook
900 900 -----------------
901 901
902 902 $ cat << EOF >> .hg/hgrc
903 903 > [hooks]
904 904 > txnclose.testing=echo txnclose hook called
905 905 > EOF
906 906 $ touch a && hg commit -Aqm a
907 907 warning: untrusted hook txnclose.testing not executed
908 908 $ hg log
909 909 changeset: 0:3903775176ed
910 910 tag: tip
911 911 user: test
912 912 date: Thu Jan 01 00:00:00 1970 +0000
913 913 summary: a
914 914
915 915
916 916 Non-blocking hook
917 917 -----------------
918 918
919 919 $ cat << EOF >> .hg/hgrc
920 920 > [hooks]
921 921 > pretxnclose.testing=echo pre-txnclose hook called
922 922 > EOF
923 923 $ touch b && hg commit -Aqm a
924 924 transaction abort!
925 925 rollback completed
926 926 abort: untrusted hook pretxnclose.testing not executed
927 927 (see 'hg help config.trusted')
928 928 [255]
929 929 $ hg log
930 930 changeset: 0:3903775176ed
931 931 tag: tip
932 932 user: test
933 933 date: Thu Jan 01 00:00:00 1970 +0000
934 934 summary: a
935 935
@@ -1,347 +1,347
1 1 #require serve
2 2
3 3 This test is a duplicate of 'test-http.t', feel free to factor out
4 4 parts that are not bundle1/bundle2 specific.
5 5
6 6 $ cat << EOF >> $HGRCPATH
7 7 > [devel]
8 8 > # This test is dedicated to interaction through old bundle
9 9 > legacy.exchange = bundle1
10 10 > EOF
11 11
12 12 $ hg init test
13 13 $ cd test
14 14 $ echo foo>foo
15 15 $ mkdir foo.d foo.d/bAr.hg.d foo.d/baR.d.hg
16 16 $ echo foo>foo.d/foo
17 17 $ echo bar>foo.d/bAr.hg.d/BaR
18 18 $ echo bar>foo.d/baR.d.hg/bAR
19 19 $ hg commit -A -m 1
20 20 adding foo
21 21 adding foo.d/bAr.hg.d/BaR
22 22 adding foo.d/baR.d.hg/bAR
23 23 adding foo.d/foo
24 24 $ hg serve -p $HGPORT -d --pid-file=../hg1.pid -E ../error.log
25 25 $ hg serve --config server.uncompressed=False -p $HGPORT1 -d --pid-file=../hg2.pid
26 26
27 27 Test server address cannot be reused
28 28
29 29 #if windows
30 30 $ hg serve -p $HGPORT1 2>&1
31 31 abort: cannot start server at 'localhost:$HGPORT1': * (glob)
32 32 [255]
33 33 #else
34 34 $ hg serve -p $HGPORT1 2>&1
35 35 abort: cannot start server at 'localhost:$HGPORT1': Address already in use
36 36 [255]
37 37 #endif
38 38 $ cd ..
39 39 $ cat hg1.pid hg2.pid >> $DAEMON_PIDS
40 40
41 41 clone via stream
42 42
43 43 $ hg clone --uncompressed http://localhost:$HGPORT/ copy 2>&1
44 44 streaming all changes
45 45 6 files to transfer, 606 bytes of data
46 46 transferred * bytes in * seconds (*/sec) (glob)
47 47 searching for changes
48 48 no changes found
49 49 updating to branch default
50 50 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
51 51 $ hg verify -R copy
52 52 checking changesets
53 53 checking manifests
54 54 crosschecking files in changesets and manifests
55 55 checking files
56 56 4 files, 1 changesets, 4 total revisions
57 57
58 58 try to clone via stream, should use pull instead
59 59
60 60 $ hg clone --uncompressed http://localhost:$HGPORT1/ copy2
61 61 requesting all changes
62 62 adding changesets
63 63 adding manifests
64 64 adding file changes
65 65 added 1 changesets with 4 changes to 4 files
66 66 updating to branch default
67 67 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
68 68
69 69 clone via pull
70 70
71 71 $ hg clone http://localhost:$HGPORT1/ copy-pull
72 72 requesting all changes
73 73 adding changesets
74 74 adding manifests
75 75 adding file changes
76 76 added 1 changesets with 4 changes to 4 files
77 77 updating to branch default
78 78 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
79 79 $ hg verify -R copy-pull
80 80 checking changesets
81 81 checking manifests
82 82 crosschecking files in changesets and manifests
83 83 checking files
84 84 4 files, 1 changesets, 4 total revisions
85 85 $ cd test
86 86 $ echo bar > bar
87 87 $ hg commit -A -d '1 0' -m 2
88 88 adding bar
89 89 $ cd ..
90 90
91 91 clone over http with --update
92 92
93 93 $ hg clone http://localhost:$HGPORT1/ updated --update 0
94 94 requesting all changes
95 95 adding changesets
96 96 adding manifests
97 97 adding file changes
98 98 added 2 changesets with 5 changes to 5 files
99 99 updating to branch default
100 100 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
101 101 $ hg log -r . -R updated
102 102 changeset: 0:8b6053c928fe
103 103 user: test
104 104 date: Thu Jan 01 00:00:00 1970 +0000
105 105 summary: 1
106 106
107 107 $ rm -rf updated
108 108
109 109 incoming via HTTP
110 110
111 111 $ hg clone http://localhost:$HGPORT1/ --rev 0 partial
112 112 adding changesets
113 113 adding manifests
114 114 adding file changes
115 115 added 1 changesets with 4 changes to 4 files
116 116 updating to branch default
117 117 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
118 118 $ cd partial
119 119 $ touch LOCAL
120 120 $ hg ci -qAm LOCAL
121 121 $ hg incoming http://localhost:$HGPORT1/ --template '{desc}\n'
122 122 comparing with http://localhost:$HGPORT1/
123 123 searching for changes
124 124 2
125 125 $ cd ..
126 126
127 127 pull
128 128
129 129 $ cd copy-pull
130 130 $ cat >> .hg/hgrc <<EOF
131 131 > [hooks]
132 132 > changegroup = sh -c "printenv.py changegroup"
133 133 > EOF
134 134 $ hg pull
135 135 pulling from http://localhost:$HGPORT1/
136 136 searching for changes
137 137 adding changesets
138 138 adding manifests
139 139 adding file changes
140 140 added 1 changesets with 1 changes to 1 files
141 changegroup hook: HG_HOOKTYPE=changegroup HG_NODE=5fed3813f7f5e1824344fdc9cf8f63bb662c292d HG_NODE_LAST=5fed3813f7f5e1824344fdc9cf8f63bb662c292d HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=http://localhost:$HGPORT1/
141 changegroup hook: HG_HOOKNAME=changegroup HG_HOOKTYPE=changegroup HG_NODE=5fed3813f7f5e1824344fdc9cf8f63bb662c292d HG_NODE_LAST=5fed3813f7f5e1824344fdc9cf8f63bb662c292d HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=http://localhost:$HGPORT1/
142 142 (run 'hg update' to get a working copy)
143 143 $ cd ..
144 144
145 145 clone from invalid URL
146 146
147 147 $ hg clone http://localhost:$HGPORT/bad
148 148 abort: HTTP Error 404: Not Found
149 149 [255]
150 150
151 151 test http authentication
152 152 + use the same server to test server side streaming preference
153 153
154 154 $ cd test
155 155 $ cat << EOT > userpass.py
156 156 > import base64
157 157 > from mercurial.hgweb import common
158 158 > def perform_authentication(hgweb, req, op):
159 159 > auth = req.env.get('HTTP_AUTHORIZATION')
160 160 > if not auth:
161 161 > raise common.ErrorResponse(common.HTTP_UNAUTHORIZED, 'who',
162 162 > [('WWW-Authenticate', 'Basic Realm="mercurial"')])
163 163 > if base64.b64decode(auth.split()[1]).split(':', 1) != ['user', 'pass']:
164 164 > raise common.ErrorResponse(common.HTTP_FORBIDDEN, 'no')
165 165 > def extsetup():
166 166 > common.permhooks.insert(0, perform_authentication)
167 167 > EOT
168 168 $ hg serve --config extensions.x=userpass.py -p $HGPORT2 -d --pid-file=pid \
169 169 > --config server.preferuncompressed=True \
170 170 > --config web.push_ssl=False --config web.allow_push=* -A ../access.log
171 171 $ cat pid >> $DAEMON_PIDS
172 172
173 173 $ cat << EOF > get_pass.py
174 174 > import getpass
175 175 > def newgetpass(arg):
176 176 > return "pass"
177 177 > getpass.getpass = newgetpass
178 178 > EOF
179 179
180 180 $ hg id http://localhost:$HGPORT2/
181 181 abort: http authorization required for http://localhost:$HGPORT2/
182 182 [255]
183 183 $ hg id http://localhost:$HGPORT2/
184 184 abort: http authorization required for http://localhost:$HGPORT2/
185 185 [255]
186 186 $ hg id --config ui.interactive=true --config extensions.getpass=get_pass.py http://user@localhost:$HGPORT2/
187 187 http authorization required for http://localhost:$HGPORT2/
188 188 realm: mercurial
189 189 user: user
190 190 password: 5fed3813f7f5
191 191 $ hg id http://user:pass@localhost:$HGPORT2/
192 192 5fed3813f7f5
193 193 $ echo '[auth]' >> .hg/hgrc
194 194 $ echo 'l.schemes=http' >> .hg/hgrc
195 195 $ echo 'l.prefix=lo' >> .hg/hgrc
196 196 $ echo 'l.username=user' >> .hg/hgrc
197 197 $ echo 'l.password=pass' >> .hg/hgrc
198 198 $ hg id http://localhost:$HGPORT2/
199 199 5fed3813f7f5
200 200 $ hg id http://localhost:$HGPORT2/
201 201 5fed3813f7f5
202 202 $ hg id http://user@localhost:$HGPORT2/
203 203 5fed3813f7f5
204 204 $ hg clone http://user:pass@localhost:$HGPORT2/ dest 2>&1
205 205 streaming all changes
206 206 7 files to transfer, 916 bytes of data
207 207 transferred * bytes in * seconds (*/sec) (glob)
208 208 searching for changes
209 209 no changes found
210 210 updating to branch default
211 211 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
212 212 --pull should override server's preferuncompressed
213 213 $ hg clone --pull http://user:pass@localhost:$HGPORT2/ dest-pull 2>&1
214 214 requesting all changes
215 215 adding changesets
216 216 adding manifests
217 217 adding file changes
218 218 added 2 changesets with 5 changes to 5 files
219 219 updating to branch default
220 220 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
221 221
222 222 $ hg id http://user2@localhost:$HGPORT2/
223 223 abort: http authorization required for http://localhost:$HGPORT2/
224 224 [255]
225 225 $ hg id http://user:pass2@localhost:$HGPORT2/
226 226 abort: HTTP Error 403: no
227 227 [255]
228 228
229 229 $ hg -R dest tag -r tip top
230 230 $ hg -R dest push http://user:pass@localhost:$HGPORT2/
231 231 pushing to http://user:***@localhost:$HGPORT2/
232 232 searching for changes
233 233 remote: adding changesets
234 234 remote: adding manifests
235 235 remote: adding file changes
236 236 remote: added 1 changesets with 1 changes to 1 files
237 237 $ hg rollback -q
238 238
239 239 $ sed 's/.*] "/"/' < ../access.log
240 240 "GET /?cmd=capabilities HTTP/1.1" 200 -
241 241 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
242 242 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
243 243 "GET /?cmd=capabilities HTTP/1.1" 200 -
244 244 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
245 245 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
246 246 "GET /?cmd=capabilities HTTP/1.1" 200 -
247 247 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
248 248 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
249 249 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
250 250 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
251 251 "GET /?cmd=capabilities HTTP/1.1" 200 -
252 252 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
253 253 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
254 254 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
255 255 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
256 256 "GET /?cmd=capabilities HTTP/1.1" 200 -
257 257 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
258 258 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
259 259 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
260 260 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
261 261 "GET /?cmd=capabilities HTTP/1.1" 200 -
262 262 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
263 263 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
264 264 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
265 265 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
266 266 "GET /?cmd=capabilities HTTP/1.1" 200 -
267 267 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
268 268 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
269 269 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
270 270 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
271 271 "GET /?cmd=capabilities HTTP/1.1" 200 -
272 272 "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
273 273 "GET /?cmd=stream_out HTTP/1.1" 401 - x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
274 274 "GET /?cmd=stream_out HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
275 275 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
276 276 "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D5fed3813f7f5e1824344fdc9cf8f63bb662c292d x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
277 277 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
278 278 "GET /?cmd=capabilities HTTP/1.1" 200 -
279 279 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
280 280 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
281 281 "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
282 282 "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:common=0000000000000000000000000000000000000000&heads=5fed3813f7f5e1824344fdc9cf8f63bb662c292d x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
283 283 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
284 284 "GET /?cmd=capabilities HTTP/1.1" 200 -
285 285 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
286 286 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
287 287 "GET /?cmd=capabilities HTTP/1.1" 200 -
288 288 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
289 289 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
290 290 "GET /?cmd=listkeys HTTP/1.1" 403 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
291 291 "GET /?cmd=capabilities HTTP/1.1" 200 -
292 292 "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D7f4e523d01f2cc3765ac8934da3d14db775ff872 x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
293 293 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
294 294 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
295 295 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
296 296 "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
297 297 "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
298 298 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
299 299 "POST /?cmd=unbundle HTTP/1.1" 200 - x-hgarg-1:heads=686173686564+5eb5abfefeea63c80dd7553bcc3783f37e0c5524* (glob)
300 300 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
301 301
302 302 $ cd ..
303 303
304 304 clone of serve with repo in root and unserved subrepo (issue2970)
305 305
306 306 $ hg --cwd test init sub
307 307 $ echo empty > test/sub/empty
308 308 $ hg --cwd test/sub add empty
309 309 $ hg --cwd test/sub commit -qm 'add empty'
310 310 $ hg --cwd test/sub tag -r 0 something
311 311 $ echo sub = sub > test/.hgsub
312 312 $ hg --cwd test add .hgsub
313 313 $ hg --cwd test commit -qm 'add subrepo'
314 314 $ hg clone http://localhost:$HGPORT noslash-clone
315 315 requesting all changes
316 316 adding changesets
317 317 adding manifests
318 318 adding file changes
319 319 added 3 changesets with 7 changes to 7 files
320 320 updating to branch default
321 321 abort: HTTP Error 404: Not Found
322 322 [255]
323 323 $ hg clone http://localhost:$HGPORT/ slash-clone
324 324 requesting all changes
325 325 adding changesets
326 326 adding manifests
327 327 adding file changes
328 328 added 3 changesets with 7 changes to 7 files
329 329 updating to branch default
330 330 abort: HTTP Error 404: Not Found
331 331 [255]
332 332
333 333 check error log
334 334
335 335 $ cat error.log
336 336
337 337 Check error reporting while pulling/cloning
338 338
339 339 $ $RUNTESTDIR/killdaemons.py
340 340 $ hg -R test serve -p $HGPORT -d --pid-file=hg3.pid -E error.log --config extensions.crash=${TESTDIR}/crashgetbundler.py
341 341 $ cat hg3.pid >> $DAEMON_PIDS
342 342 $ hg clone http://localhost:$HGPORT/ abort-clone
343 343 requesting all changes
344 344 abort: remote error:
345 345 this is an exercise
346 346 [255]
347 347 $ cat error.log
@@ -1,335 +1,335
1 1 #require serve
2 2
3 3 $ hg init test
4 4 $ cd test
5 5 $ echo foo>foo
6 6 $ mkdir foo.d foo.d/bAr.hg.d foo.d/baR.d.hg
7 7 $ echo foo>foo.d/foo
8 8 $ echo bar>foo.d/bAr.hg.d/BaR
9 9 $ echo bar>foo.d/baR.d.hg/bAR
10 10 $ hg commit -A -m 1
11 11 adding foo
12 12 adding foo.d/bAr.hg.d/BaR
13 13 adding foo.d/baR.d.hg/bAR
14 14 adding foo.d/foo
15 15 $ hg serve -p $HGPORT -d --pid-file=../hg1.pid -E ../error.log
16 16 $ hg serve --config server.uncompressed=False -p $HGPORT1 -d --pid-file=../hg2.pid
17 17
18 18 Test server address cannot be reused
19 19
20 20 #if windows
21 21 $ hg serve -p $HGPORT1 2>&1
22 22 abort: cannot start server at ':$HGPORT1': * (glob)
23 23 [255]
24 24 #else
25 25 $ hg serve -p $HGPORT1 2>&1
26 26 abort: cannot start server at 'localhost:$HGPORT1': Address already in use
27 27 [255]
28 28 #endif
29 29 $ cd ..
30 30 $ cat hg1.pid hg2.pid >> $DAEMON_PIDS
31 31
32 32 clone via stream
33 33
34 34 $ hg clone --uncompressed http://localhost:$HGPORT/ copy 2>&1
35 35 streaming all changes
36 36 6 files to transfer, 606 bytes of data
37 37 transferred * bytes in * seconds (*/sec) (glob)
38 38 searching for changes
39 39 no changes found
40 40 updating to branch default
41 41 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
42 42 $ hg verify -R copy
43 43 checking changesets
44 44 checking manifests
45 45 crosschecking files in changesets and manifests
46 46 checking files
47 47 4 files, 1 changesets, 4 total revisions
48 48
49 49 try to clone via stream, should use pull instead
50 50
51 51 $ hg clone --uncompressed http://localhost:$HGPORT1/ copy2
52 52 requesting all changes
53 53 adding changesets
54 54 adding manifests
55 55 adding file changes
56 56 added 1 changesets with 4 changes to 4 files
57 57 updating to branch default
58 58 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
59 59
60 60 clone via pull
61 61
62 62 $ hg clone http://localhost:$HGPORT1/ copy-pull
63 63 requesting all changes
64 64 adding changesets
65 65 adding manifests
66 66 adding file changes
67 67 added 1 changesets with 4 changes to 4 files
68 68 updating to branch default
69 69 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
70 70 $ hg verify -R copy-pull
71 71 checking changesets
72 72 checking manifests
73 73 crosschecking files in changesets and manifests
74 74 checking files
75 75 4 files, 1 changesets, 4 total revisions
76 76 $ cd test
77 77 $ echo bar > bar
78 78 $ hg commit -A -d '1 0' -m 2
79 79 adding bar
80 80 $ cd ..
81 81
82 82 clone over http with --update
83 83
84 84 $ hg clone http://localhost:$HGPORT1/ updated --update 0
85 85 requesting all changes
86 86 adding changesets
87 87 adding manifests
88 88 adding file changes
89 89 added 2 changesets with 5 changes to 5 files
90 90 updating to branch default
91 91 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
92 92 $ hg log -r . -R updated
93 93 changeset: 0:8b6053c928fe
94 94 user: test
95 95 date: Thu Jan 01 00:00:00 1970 +0000
96 96 summary: 1
97 97
98 98 $ rm -rf updated
99 99
100 100 incoming via HTTP
101 101
102 102 $ hg clone http://localhost:$HGPORT1/ --rev 0 partial
103 103 adding changesets
104 104 adding manifests
105 105 adding file changes
106 106 added 1 changesets with 4 changes to 4 files
107 107 updating to branch default
108 108 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
109 109 $ cd partial
110 110 $ touch LOCAL
111 111 $ hg ci -qAm LOCAL
112 112 $ hg incoming http://localhost:$HGPORT1/ --template '{desc}\n'
113 113 comparing with http://localhost:$HGPORT1/
114 114 searching for changes
115 115 2
116 116 $ cd ..
117 117
118 118 pull
119 119
120 120 $ cd copy-pull
121 121 $ cat >> .hg/hgrc <<EOF
122 122 > [hooks]
123 123 > changegroup = sh -c "printenv.py changegroup"
124 124 > EOF
125 125 $ hg pull
126 126 pulling from http://localhost:$HGPORT1/
127 127 searching for changes
128 128 adding changesets
129 129 adding manifests
130 130 adding file changes
131 131 added 1 changesets with 1 changes to 1 files
132 changegroup hook: HG_HOOKTYPE=changegroup HG_NODE=5fed3813f7f5e1824344fdc9cf8f63bb662c292d HG_NODE_LAST=5fed3813f7f5e1824344fdc9cf8f63bb662c292d HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=http://localhost:$HGPORT1/
132 changegroup hook: HG_HOOKNAME=changegroup HG_HOOKTYPE=changegroup HG_NODE=5fed3813f7f5e1824344fdc9cf8f63bb662c292d HG_NODE_LAST=5fed3813f7f5e1824344fdc9cf8f63bb662c292d HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=http://localhost:$HGPORT1/
133 133 (run 'hg update' to get a working copy)
134 134 $ cd ..
135 135
136 136 clone from invalid URL
137 137
138 138 $ hg clone http://localhost:$HGPORT/bad
139 139 abort: HTTP Error 404: Not Found
140 140 [255]
141 141
142 142 test http authentication
143 143 + use the same server to test server side streaming preference
144 144
145 145 $ cd test
146 146 $ cat << EOT > userpass.py
147 147 > import base64
148 148 > from mercurial.hgweb import common
149 149 > def perform_authentication(hgweb, req, op):
150 150 > auth = req.env.get('HTTP_AUTHORIZATION')
151 151 > if not auth:
152 152 > raise common.ErrorResponse(common.HTTP_UNAUTHORIZED, 'who',
153 153 > [('WWW-Authenticate', 'Basic Realm="mercurial"')])
154 154 > if base64.b64decode(auth.split()[1]).split(':', 1) != ['user', 'pass']:
155 155 > raise common.ErrorResponse(common.HTTP_FORBIDDEN, 'no')
156 156 > def extsetup():
157 157 > common.permhooks.insert(0, perform_authentication)
158 158 > EOT
159 159 $ hg serve --config extensions.x=userpass.py -p $HGPORT2 -d --pid-file=pid \
160 160 > --config server.preferuncompressed=True \
161 161 > --config web.push_ssl=False --config web.allow_push=* -A ../access.log
162 162 $ cat pid >> $DAEMON_PIDS
163 163
164 164 $ cat << EOF > get_pass.py
165 165 > import getpass
166 166 > def newgetpass(arg):
167 167 > return "pass"
168 168 > getpass.getpass = newgetpass
169 169 > EOF
170 170
171 171 $ hg id http://localhost:$HGPORT2/
172 172 abort: http authorization required for http://localhost:$HGPORT2/
173 173 [255]
174 174 $ hg id http://localhost:$HGPORT2/
175 175 abort: http authorization required for http://localhost:$HGPORT2/
176 176 [255]
177 177 $ hg id --config ui.interactive=true --config extensions.getpass=get_pass.py http://user@localhost:$HGPORT2/
178 178 http authorization required for http://localhost:$HGPORT2/
179 179 realm: mercurial
180 180 user: user
181 181 password: 5fed3813f7f5
182 182 $ hg id http://user:pass@localhost:$HGPORT2/
183 183 5fed3813f7f5
184 184 $ echo '[auth]' >> .hg/hgrc
185 185 $ echo 'l.schemes=http' >> .hg/hgrc
186 186 $ echo 'l.prefix=lo' >> .hg/hgrc
187 187 $ echo 'l.username=user' >> .hg/hgrc
188 188 $ echo 'l.password=pass' >> .hg/hgrc
189 189 $ hg id http://localhost:$HGPORT2/
190 190 5fed3813f7f5
191 191 $ hg id http://localhost:$HGPORT2/
192 192 5fed3813f7f5
193 193 $ hg id http://user@localhost:$HGPORT2/
194 194 5fed3813f7f5
195 195 $ hg clone http://user:pass@localhost:$HGPORT2/ dest 2>&1
196 196 streaming all changes
197 197 7 files to transfer, 916 bytes of data
198 198 transferred * bytes in * seconds (*/sec) (glob)
199 199 searching for changes
200 200 no changes found
201 201 updating to branch default
202 202 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
203 203 --pull should override server's preferuncompressed
204 204 $ hg clone --pull http://user:pass@localhost:$HGPORT2/ dest-pull 2>&1
205 205 requesting all changes
206 206 adding changesets
207 207 adding manifests
208 208 adding file changes
209 209 added 2 changesets with 5 changes to 5 files
210 210 updating to branch default
211 211 5 files updated, 0 files merged, 0 files removed, 0 files unresolved
212 212
213 213 $ hg id http://user2@localhost:$HGPORT2/
214 214 abort: http authorization required for http://localhost:$HGPORT2/
215 215 [255]
216 216 $ hg id http://user:pass2@localhost:$HGPORT2/
217 217 abort: HTTP Error 403: no
218 218 [255]
219 219
220 220 $ hg -R dest tag -r tip top
221 221 $ hg -R dest push http://user:pass@localhost:$HGPORT2/
222 222 pushing to http://user:***@localhost:$HGPORT2/
223 223 searching for changes
224 224 remote: adding changesets
225 225 remote: adding manifests
226 226 remote: adding file changes
227 227 remote: added 1 changesets with 1 changes to 1 files
228 228 $ hg rollback -q
229 229
230 230 $ sed 's/.*] "/"/' < ../access.log
231 231 "GET /?cmd=capabilities HTTP/1.1" 200 -
232 232 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
233 233 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
234 234 "GET /?cmd=capabilities HTTP/1.1" 200 -
235 235 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
236 236 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
237 237 "GET /?cmd=capabilities HTTP/1.1" 200 -
238 238 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
239 239 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
240 240 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
241 241 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
242 242 "GET /?cmd=capabilities HTTP/1.1" 200 -
243 243 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
244 244 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
245 245 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
246 246 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
247 247 "GET /?cmd=capabilities HTTP/1.1" 200 -
248 248 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
249 249 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
250 250 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
251 251 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
252 252 "GET /?cmd=capabilities HTTP/1.1" 200 -
253 253 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
254 254 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
255 255 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
256 256 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
257 257 "GET /?cmd=capabilities HTTP/1.1" 200 -
258 258 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
259 259 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
260 260 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
261 261 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
262 262 "GET /?cmd=capabilities HTTP/1.1" 200 -
263 263 "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
264 264 "GET /?cmd=stream_out HTTP/1.1" 401 - x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
265 265 "GET /?cmd=stream_out HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
266 266 "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D5fed3813f7f5e1824344fdc9cf8f63bb662c292d x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
267 267 "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bundlecaps=HG20%2Cbundle2%3DHG20%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=0&common=5fed3813f7f5e1824344fdc9cf8f63bb662c292d&heads=5fed3813f7f5e1824344fdc9cf8f63bb662c292d&listkeys=phases%2Cbookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
268 268 "GET /?cmd=capabilities HTTP/1.1" 200 -
269 269 "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
270 270 "GET /?cmd=getbundle HTTP/1.1" 401 - x-hgarg-1:bundlecaps=HG20%2Cbundle2%3DHG20%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=1&common=0000000000000000000000000000000000000000&heads=5fed3813f7f5e1824344fdc9cf8f63bb662c292d&listkeys=phases%2Cbookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
271 271 "GET /?cmd=getbundle HTTP/1.1" 200 - x-hgarg-1:bundlecaps=HG20%2Cbundle2%3DHG20%250Achangegroup%253D01%252C02%250Adigests%253Dmd5%252Csha1%252Csha512%250Aerror%253Dabort%252Cunsupportedcontent%252Cpushraced%252Cpushkey%250Ahgtagsfnodes%250Alistkeys%250Apushkey%250Aremote-changegroup%253Dhttp%252Chttps&cg=1&common=0000000000000000000000000000000000000000&heads=5fed3813f7f5e1824344fdc9cf8f63bb662c292d&listkeys=phases%2Cbookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
272 272 "GET /?cmd=capabilities HTTP/1.1" 200 -
273 273 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
274 274 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
275 275 "GET /?cmd=capabilities HTTP/1.1" 200 -
276 276 "GET /?cmd=lookup HTTP/1.1" 200 - x-hgarg-1:key=tip x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
277 277 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
278 278 "GET /?cmd=listkeys HTTP/1.1" 403 - x-hgarg-1:namespace=namespaces x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
279 279 "GET /?cmd=capabilities HTTP/1.1" 200 -
280 280 "GET /?cmd=batch HTTP/1.1" 200 - x-hgarg-1:cmds=heads+%3Bknown+nodes%3D7f4e523d01f2cc3765ac8934da3d14db775ff872 x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
281 281 "GET /?cmd=listkeys HTTP/1.1" 401 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
282 282 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
283 283 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
284 284 "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
285 285 "GET /?cmd=branchmap HTTP/1.1" 200 - x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
286 286 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=bookmarks x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
287 287 "POST /?cmd=unbundle HTTP/1.1" 200 - x-hgarg-1:heads=666f726365* (glob)
288 288 "GET /?cmd=listkeys HTTP/1.1" 200 - x-hgarg-1:namespace=phases x-hgproto-1:0.1 0.2 comp=*zlib,none,bzip2 (glob)
289 289
290 290 $ cd ..
291 291
292 292 clone of serve with repo in root and unserved subrepo (issue2970)
293 293
294 294 $ hg --cwd test init sub
295 295 $ echo empty > test/sub/empty
296 296 $ hg --cwd test/sub add empty
297 297 $ hg --cwd test/sub commit -qm 'add empty'
298 298 $ hg --cwd test/sub tag -r 0 something
299 299 $ echo sub = sub > test/.hgsub
300 300 $ hg --cwd test add .hgsub
301 301 $ hg --cwd test commit -qm 'add subrepo'
302 302 $ hg clone http://localhost:$HGPORT noslash-clone
303 303 requesting all changes
304 304 adding changesets
305 305 adding manifests
306 306 adding file changes
307 307 added 3 changesets with 7 changes to 7 files
308 308 updating to branch default
309 309 abort: HTTP Error 404: Not Found
310 310 [255]
311 311 $ hg clone http://localhost:$HGPORT/ slash-clone
312 312 requesting all changes
313 313 adding changesets
314 314 adding manifests
315 315 adding file changes
316 316 added 3 changesets with 7 changes to 7 files
317 317 updating to branch default
318 318 abort: HTTP Error 404: Not Found
319 319 [255]
320 320
321 321 check error log
322 322
323 323 $ cat error.log
324 324
325 325 check abort error reporting while pulling/cloning
326 326
327 327 $ $RUNTESTDIR/killdaemons.py
328 328 $ hg -R test serve -p $HGPORT -d --pid-file=hg3.pid -E error.log --config extensions.crash=${TESTDIR}/crashgetbundler.py
329 329 $ cat hg3.pid >> $DAEMON_PIDS
330 330 $ hg clone http://localhost:$HGPORT/ abort-clone
331 331 requesting all changes
332 332 remote: abort: this is an exercise
333 333 abort: pull failed on remote
334 334 [255]
335 335 $ cat error.log
@@ -1,644 +1,644
1 1 #require serve ssl
2 2
3 3 Proper https client requires the built-in ssl from Python 2.6.
4 4
5 5 Make server certificates:
6 6
7 7 $ CERTSDIR="$TESTDIR/sslcerts"
8 8 $ cat "$CERTSDIR/priv.pem" "$CERTSDIR/pub.pem" >> server.pem
9 9 $ PRIV=`pwd`/server.pem
10 10 $ cat "$CERTSDIR/priv.pem" "$CERTSDIR/pub-not-yet.pem" > server-not-yet.pem
11 11 $ cat "$CERTSDIR/priv.pem" "$CERTSDIR/pub-expired.pem" > server-expired.pem
12 12
13 13 $ hg init test
14 14 $ cd test
15 15 $ echo foo>foo
16 16 $ mkdir foo.d foo.d/bAr.hg.d foo.d/baR.d.hg
17 17 $ echo foo>foo.d/foo
18 18 $ echo bar>foo.d/bAr.hg.d/BaR
19 19 $ echo bar>foo.d/baR.d.hg/bAR
20 20 $ hg commit -A -m 1
21 21 adding foo
22 22 adding foo.d/bAr.hg.d/BaR
23 23 adding foo.d/baR.d.hg/bAR
24 24 adding foo.d/foo
25 25 $ hg serve -p $HGPORT -d --pid-file=../hg0.pid --certificate=$PRIV
26 26 $ cat ../hg0.pid >> $DAEMON_PIDS
27 27
28 28 cacert not found
29 29
30 30 $ hg in --config web.cacerts=no-such.pem https://localhost:$HGPORT/
31 31 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
32 32 abort: could not find web.cacerts: no-such.pem
33 33 [255]
34 34
35 35 Test server address cannot be reused
36 36
37 37 #if windows
38 38 $ hg serve -p $HGPORT --certificate=$PRIV 2>&1
39 39 abort: cannot start server at 'localhost:$HGPORT':
40 40 [255]
41 41 #else
42 42 $ hg serve -p $HGPORT --certificate=$PRIV 2>&1
43 43 abort: cannot start server at 'localhost:$HGPORT': Address already in use
44 44 [255]
45 45 #endif
46 46 $ cd ..
47 47
48 48 Our test cert is not signed by a trusted CA. It should fail to verify if
49 49 we are able to load CA certs.
50 50
51 51 #if sslcontext defaultcacerts no-defaultcacertsloaded
52 52 $ hg clone https://localhost:$HGPORT/ copy-pull
53 53 (an attempt was made to load CA certificates but none were loaded; see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this error)
54 54 abort: error: *certificate verify failed* (glob)
55 55 [255]
56 56 #endif
57 57
58 58 #if no-sslcontext defaultcacerts
59 59 $ hg clone https://localhost:$HGPORT/ copy-pull
60 60 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
61 61 (using CA certificates from *; if you see this message, your Mercurial install is not properly configured; see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this message) (glob) (?)
62 62 abort: error: *certificate verify failed* (glob)
63 63 [255]
64 64 #endif
65 65
66 66 #if no-sslcontext windows
67 67 $ hg clone https://localhost:$HGPORT/ copy-pull
68 68 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info
69 69 (unable to load Windows CA certificates; see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this message)
70 70 abort: error: *certificate verify failed* (glob)
71 71 [255]
72 72 #endif
73 73
74 74 #if no-sslcontext osx
75 75 $ hg clone https://localhost:$HGPORT/ copy-pull
76 76 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info
77 77 (unable to load CA certificates; see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this message)
78 78 abort: localhost certificate error: no certificate received
79 79 (set hostsecurity.localhost:certfingerprints=sha256:20:de:b3:ad:b4:cd:a5:42:f0:74:41:1c:a2:70:1e:da:6e:c0:5c:16:9e:e7:22:0f:f1:b7:e5:6e:e4:92:af:7e config setting or use --insecure to connect insecurely)
80 80 [255]
81 81 #endif
82 82
83 83 #if defaultcacertsloaded
84 84 $ hg clone https://localhost:$HGPORT/ copy-pull
85 85 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
86 86 (using CA certificates from *; if you see this message, your Mercurial install is not properly configured; see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this message) (glob) (?)
87 87 abort: error: *certificate verify failed* (glob)
88 88 [255]
89 89 #endif
90 90
91 91 #if no-defaultcacerts
92 92 $ hg clone https://localhost:$HGPORT/ copy-pull
93 93 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
94 94 (unable to load * certificates; see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this message) (glob) (?)
95 95 abort: localhost certificate error: no certificate received
96 96 (set hostsecurity.localhost:certfingerprints=sha256:20:de:b3:ad:b4:cd:a5:42:f0:74:41:1c:a2:70:1e:da:6e:c0:5c:16:9e:e7:22:0f:f1:b7:e5:6e:e4:92:af:7e config setting or use --insecure to connect insecurely)
97 97 [255]
98 98 #endif
99 99
100 100 Specifying a per-host certificate file that doesn't exist will abort
101 101
102 102 $ hg --config hostsecurity.localhost:verifycertsfile=/does/not/exist clone https://localhost:$HGPORT/
103 103 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
104 104 abort: path specified by hostsecurity.localhost:verifycertsfile does not exist: /does/not/exist
105 105 [255]
106 106
107 107 A malformed per-host certificate file will raise an error
108 108
109 109 $ echo baddata > badca.pem
110 110 #if sslcontext
111 111 $ hg --config hostsecurity.localhost:verifycertsfile=badca.pem clone https://localhost:$HGPORT/
112 112 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
113 113 abort: error loading CA file badca.pem: * (glob)
114 114 (file is empty or malformed?)
115 115 [255]
116 116 #else
117 117 $ hg --config hostsecurity.localhost:verifycertsfile=badca.pem clone https://localhost:$HGPORT/
118 118 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
119 119 abort: error: * (glob)
120 120 [255]
121 121 #endif
122 122
123 123 A per-host certificate mismatching the server will fail verification
124 124
125 125 (modern ssl is able to discern whether the loaded cert is a CA cert)
126 126 #if sslcontext
127 127 $ hg --config hostsecurity.localhost:verifycertsfile="$CERTSDIR/client-cert.pem" clone https://localhost:$HGPORT/
128 128 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
129 129 (an attempt was made to load CA certificates but none were loaded; see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this error)
130 130 abort: error: *certificate verify failed* (glob)
131 131 [255]
132 132 #else
133 133 $ hg --config hostsecurity.localhost:verifycertsfile="$CERTSDIR/client-cert.pem" clone https://localhost:$HGPORT/
134 134 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
135 135 abort: error: *certificate verify failed* (glob)
136 136 [255]
137 137 #endif
138 138
139 139 A per-host certificate matching the server's cert will be accepted
140 140
141 141 $ hg --config hostsecurity.localhost:verifycertsfile="$CERTSDIR/pub.pem" clone -U https://localhost:$HGPORT/ perhostgood1
142 142 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
143 143 requesting all changes
144 144 adding changesets
145 145 adding manifests
146 146 adding file changes
147 147 added 1 changesets with 4 changes to 4 files
148 148
149 149 A per-host certificate with multiple certs and one matching will be accepted
150 150
151 151 $ cat "$CERTSDIR/client-cert.pem" "$CERTSDIR/pub.pem" > perhost.pem
152 152 $ hg --config hostsecurity.localhost:verifycertsfile=perhost.pem clone -U https://localhost:$HGPORT/ perhostgood2
153 153 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
154 154 requesting all changes
155 155 adding changesets
156 156 adding manifests
157 157 adding file changes
158 158 added 1 changesets with 4 changes to 4 files
159 159
160 160 Defining both per-host certificate and a fingerprint will print a warning
161 161
162 162 $ hg --config hostsecurity.localhost:verifycertsfile="$CERTSDIR/pub.pem" --config hostsecurity.localhost:fingerprints=sha1:ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03 clone -U https://localhost:$HGPORT/ caandfingerwarning
163 163 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
164 164 (hostsecurity.localhost:verifycertsfile ignored when host fingerprints defined; using host fingerprints for verification)
165 165 requesting all changes
166 166 adding changesets
167 167 adding manifests
168 168 adding file changes
169 169 added 1 changesets with 4 changes to 4 files
170 170
171 171 $ DISABLECACERTS="--config devel.disableloaddefaultcerts=true"
172 172
173 173 Inability to verify peer certificate will result in abort
174 174
175 175 $ hg clone https://localhost:$HGPORT/ copy-pull $DISABLECACERTS
176 176 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
177 177 abort: unable to verify security of localhost (no loaded CA certificates); refusing to connect
178 178 (see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this error or set hostsecurity.localhost:fingerprints=sha256:20:de:b3:ad:b4:cd:a5:42:f0:74:41:1c:a2:70:1e:da:6e:c0:5c:16:9e:e7:22:0f:f1:b7:e5:6e:e4:92:af:7e to trust this server)
179 179 [255]
180 180
181 181 $ hg clone --insecure https://localhost:$HGPORT/ copy-pull
182 182 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
183 183 warning: connection security to localhost is disabled per current settings; communication is susceptible to eavesdropping and tampering
184 184 requesting all changes
185 185 adding changesets
186 186 adding manifests
187 187 adding file changes
188 188 added 1 changesets with 4 changes to 4 files
189 189 updating to branch default
190 190 4 files updated, 0 files merged, 0 files removed, 0 files unresolved
191 191 $ hg verify -R copy-pull
192 192 checking changesets
193 193 checking manifests
194 194 crosschecking files in changesets and manifests
195 195 checking files
196 196 4 files, 1 changesets, 4 total revisions
197 197 $ cd test
198 198 $ echo bar > bar
199 199 $ hg commit -A -d '1 0' -m 2
200 200 adding bar
201 201 $ cd ..
202 202
203 203 pull without cacert
204 204
205 205 $ cd copy-pull
206 206 $ cat >> .hg/hgrc <<EOF
207 207 > [hooks]
208 208 > changegroup = sh -c "printenv.py changegroup"
209 209 > EOF
210 210 $ hg pull $DISABLECACERTS
211 211 pulling from https://localhost:$HGPORT/
212 212 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
213 213 abort: unable to verify security of localhost (no loaded CA certificates); refusing to connect
214 214 (see https://mercurial-scm.org/wiki/SecureConnections for how to configure Mercurial to avoid this error or set hostsecurity.localhost:fingerprints=sha256:20:de:b3:ad:b4:cd:a5:42:f0:74:41:1c:a2:70:1e:da:6e:c0:5c:16:9e:e7:22:0f:f1:b7:e5:6e:e4:92:af:7e to trust this server)
215 215 [255]
216 216
217 217 $ hg pull --insecure
218 218 pulling from https://localhost:$HGPORT/
219 219 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
220 220 warning: connection security to localhost is disabled per current settings; communication is susceptible to eavesdropping and tampering
221 221 searching for changes
222 222 adding changesets
223 223 adding manifests
224 224 adding file changes
225 225 added 1 changesets with 1 changes to 1 files
226 changegroup hook: HG_HOOKTYPE=changegroup HG_NODE=5fed3813f7f5e1824344fdc9cf8f63bb662c292d HG_NODE_LAST=5fed3813f7f5e1824344fdc9cf8f63bb662c292d HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=https://localhost:$HGPORT/
226 changegroup hook: HG_HOOKNAME=changegroup HG_HOOKTYPE=changegroup HG_NODE=5fed3813f7f5e1824344fdc9cf8f63bb662c292d HG_NODE_LAST=5fed3813f7f5e1824344fdc9cf8f63bb662c292d HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=https://localhost:$HGPORT/
227 227 (run 'hg update' to get a working copy)
228 228 $ cd ..
229 229
230 230 cacert configured in local repo
231 231
232 232 $ cp copy-pull/.hg/hgrc copy-pull/.hg/hgrc.bu
233 233 $ echo "[web]" >> copy-pull/.hg/hgrc
234 234 $ echo "cacerts=$CERTSDIR/pub.pem" >> copy-pull/.hg/hgrc
235 235 $ hg -R copy-pull pull
236 236 pulling from https://localhost:$HGPORT/
237 237 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
238 238 searching for changes
239 239 no changes found
240 240 $ mv copy-pull/.hg/hgrc.bu copy-pull/.hg/hgrc
241 241
242 242 cacert configured globally, also testing expansion of environment
243 243 variables in the filename
244 244
245 245 $ echo "[web]" >> $HGRCPATH
246 246 $ echo 'cacerts=$P/pub.pem' >> $HGRCPATH
247 247 $ P="$CERTSDIR" hg -R copy-pull pull
248 248 pulling from https://localhost:$HGPORT/
249 249 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
250 250 searching for changes
251 251 no changes found
252 252 $ P="$CERTSDIR" hg -R copy-pull pull --insecure
253 253 pulling from https://localhost:$HGPORT/
254 254 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
255 255 warning: connection security to localhost is disabled per current settings; communication is susceptible to eavesdropping and tampering
256 256 searching for changes
257 257 no changes found
258 258
259 259 empty cacert file
260 260
261 261 $ touch emptycafile
262 262
263 263 #if sslcontext
264 264 $ hg --config web.cacerts=emptycafile -R copy-pull pull
265 265 pulling from https://localhost:$HGPORT/
266 266 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
267 267 abort: error loading CA file emptycafile: * (glob)
268 268 (file is empty or malformed?)
269 269 [255]
270 270 #else
271 271 $ hg --config web.cacerts=emptycafile -R copy-pull pull
272 272 pulling from https://localhost:$HGPORT/
273 273 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
274 274 abort: error: * (glob)
275 275 [255]
276 276 #endif
277 277
278 278 cacert mismatch
279 279
280 280 $ hg -R copy-pull pull --config web.cacerts="$CERTSDIR/pub.pem" \
281 281 > https://$LOCALIP:$HGPORT/
282 282 pulling from https://*:$HGPORT/ (glob)
283 283 warning: connecting to $LOCALIP using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
284 284 abort: $LOCALIP certificate error: certificate is for localhost
285 285 (set hostsecurity.$LOCALIP:certfingerprints=sha256:20:de:b3:ad:b4:cd:a5:42:f0:74:41:1c:a2:70:1e:da:6e:c0:5c:16:9e:e7:22:0f:f1:b7:e5:6e:e4:92:af:7e config setting or use --insecure to connect insecurely)
286 286 [255]
287 287 $ hg -R copy-pull pull --config web.cacerts="$CERTSDIR/pub.pem" \
288 288 > https://$LOCALIP:$HGPORT/ --insecure
289 289 pulling from https://*:$HGPORT/ (glob)
290 290 warning: connecting to $LOCALIP using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
291 291 warning: connection security to $LOCALIP is disabled per current settings; communication is susceptible to eavesdropping and tampering
292 292 searching for changes
293 293 no changes found
294 294 $ hg -R copy-pull pull --config web.cacerts="$CERTSDIR/pub-other.pem"
295 295 pulling from https://localhost:$HGPORT/
296 296 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
297 297 abort: error: *certificate verify failed* (glob)
298 298 [255]
299 299 $ hg -R copy-pull pull --config web.cacerts="$CERTSDIR/pub-other.pem" \
300 300 > --insecure
301 301 pulling from https://localhost:$HGPORT/
302 302 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
303 303 warning: connection security to localhost is disabled per current settings; communication is susceptible to eavesdropping and tampering
304 304 searching for changes
305 305 no changes found
306 306
307 307 Test server cert which isn't valid yet
308 308
309 309 $ hg serve -R test -p $HGPORT1 -d --pid-file=hg1.pid --certificate=server-not-yet.pem
310 310 $ cat hg1.pid >> $DAEMON_PIDS
311 311 $ hg -R copy-pull pull --config web.cacerts="$CERTSDIR/pub-not-yet.pem" \
312 312 > https://localhost:$HGPORT1/
313 313 pulling from https://localhost:$HGPORT1/
314 314 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
315 315 abort: error: *certificate verify failed* (glob)
316 316 [255]
317 317
318 318 Test server cert which no longer is valid
319 319
320 320 $ hg serve -R test -p $HGPORT2 -d --pid-file=hg2.pid --certificate=server-expired.pem
321 321 $ cat hg2.pid >> $DAEMON_PIDS
322 322 $ hg -R copy-pull pull --config web.cacerts="$CERTSDIR/pub-expired.pem" \
323 323 > https://localhost:$HGPORT2/
324 324 pulling from https://localhost:$HGPORT2/
325 325 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
326 326 abort: error: *certificate verify failed* (glob)
327 327 [255]
328 328
329 329 Disabling the TLS 1.0 warning works
330 330 $ hg -R copy-pull id https://localhost:$HGPORT/ \
331 331 > --config hostsecurity.localhost:fingerprints=sha1:ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03 \
332 332 > --config hostsecurity.disabletls10warning=true
333 333 5fed3813f7f5
334 334
335 335 #if no-sslcontext no-py27+
336 336 Setting ciphers doesn't work in Python 2.6
337 337 $ P="$CERTSDIR" hg --config hostsecurity.ciphers=HIGH -R copy-pull id https://localhost:$HGPORT/
338 338 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info
339 339 abort: setting ciphers in [hostsecurity] is not supported by this version of Python
340 340 (remove the config option or run Mercurial with a modern Python version (preferred))
341 341 [255]
342 342 #endif
343 343
344 344 Setting ciphers works in Python 2.7+ but the error message is different on
345 345 legacy ssl. We test legacy once and do more feature checking on modern
346 346 configs.
347 347
348 348 #if py27+ no-sslcontext
349 349 $ P="$CERTSDIR" hg --config hostsecurity.ciphers=invalid -R copy-pull id https://localhost:$HGPORT/
350 350 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info
351 351 abort: *No cipher can be selected. (glob)
352 352 [255]
353 353
354 354 $ P="$CERTSDIR" hg --config hostsecurity.ciphers=HIGH -R copy-pull id https://localhost:$HGPORT/
355 355 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info
356 356 5fed3813f7f5
357 357 #endif
358 358
359 359 #if sslcontext
360 360 Setting ciphers to an invalid value aborts
361 361 $ P="$CERTSDIR" hg --config hostsecurity.ciphers=invalid -R copy-pull id https://localhost:$HGPORT/
362 362 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
363 363 abort: could not set ciphers: No cipher can be selected.
364 364 (change cipher string (invalid) in config)
365 365 [255]
366 366
367 367 $ P="$CERTSDIR" hg --config hostsecurity.localhost:ciphers=invalid -R copy-pull id https://localhost:$HGPORT/
368 368 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
369 369 abort: could not set ciphers: No cipher can be selected.
370 370 (change cipher string (invalid) in config)
371 371 [255]
372 372
373 373 Changing the cipher string works
374 374
375 375 $ P="$CERTSDIR" hg --config hostsecurity.ciphers=HIGH -R copy-pull id https://localhost:$HGPORT/
376 376 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
377 377 5fed3813f7f5
378 378 #endif
379 379
380 380 Fingerprints
381 381
382 382 - works without cacerts (hostfingerprints)
383 383 $ hg -R copy-pull id https://localhost:$HGPORT/ --insecure --config hostfingerprints.localhost=ec:d8:7c:d6:b3:86:d0:4f:c1:b8:b4:1c:9d:8f:5e:16:8e:ef:1c:03
384 384 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
385 385 (SHA-1 fingerprint for localhost found in legacy [hostfingerprints] section; if you trust this fingerprint, set the following config value in [hostsecurity] and remove the old one from [hostfingerprints] to upgrade to a more secure SHA-256 fingerprint: localhost.fingerprints=sha256:20:de:b3:ad:b4:cd:a5:42:f0:74:41:1c:a2:70:1e:da:6e:c0:5c:16:9e:e7:22:0f:f1:b7:e5:6e:e4:92:af:7e)
386 386 5fed3813f7f5
387 387
388 388 - works without cacerts (hostsecurity)
389 389 $ hg -R copy-pull id https://localhost:$HGPORT/ --config hostsecurity.localhost:fingerprints=sha1:ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03
390 390 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
391 391 5fed3813f7f5
392 392
393 393 $ hg -R copy-pull id https://localhost:$HGPORT/ --config hostsecurity.localhost:fingerprints=sha256:20:de:b3:ad:b4:cd:a5:42:f0:74:41:1c:a2:70:1e:da:6e:c0:5c:16:9e:e7:22:0f:f1:b7:e5:6e:e4:92:af:7e
394 394 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
395 395 5fed3813f7f5
396 396
397 397 - multiple fingerprints specified and first matches
398 398 $ hg --config 'hostfingerprints.localhost=ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03, deadbeefdeadbeefdeadbeefdeadbeefdeadbeef' -R copy-pull id https://localhost:$HGPORT/ --insecure
399 399 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
400 400 (SHA-1 fingerprint for localhost found in legacy [hostfingerprints] section; if you trust this fingerprint, set the following config value in [hostsecurity] and remove the old one from [hostfingerprints] to upgrade to a more secure SHA-256 fingerprint: localhost.fingerprints=sha256:20:de:b3:ad:b4:cd:a5:42:f0:74:41:1c:a2:70:1e:da:6e:c0:5c:16:9e:e7:22:0f:f1:b7:e5:6e:e4:92:af:7e)
401 401 5fed3813f7f5
402 402
403 403 $ hg --config 'hostsecurity.localhost:fingerprints=sha1:ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03, sha1:deadbeefdeadbeefdeadbeefdeadbeefdeadbeef' -R copy-pull id https://localhost:$HGPORT/
404 404 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
405 405 5fed3813f7f5
406 406
407 407 - multiple fingerprints specified and last matches
408 408 $ hg --config 'hostfingerprints.localhost=deadbeefdeadbeefdeadbeefdeadbeefdeadbeef, ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03' -R copy-pull id https://localhost:$HGPORT/ --insecure
409 409 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
410 410 (SHA-1 fingerprint for localhost found in legacy [hostfingerprints] section; if you trust this fingerprint, set the following config value in [hostsecurity] and remove the old one from [hostfingerprints] to upgrade to a more secure SHA-256 fingerprint: localhost.fingerprints=sha256:20:de:b3:ad:b4:cd:a5:42:f0:74:41:1c:a2:70:1e:da:6e:c0:5c:16:9e:e7:22:0f:f1:b7:e5:6e:e4:92:af:7e)
411 411 5fed3813f7f5
412 412
413 413 $ hg --config 'hostsecurity.localhost:fingerprints=sha1:deadbeefdeadbeefdeadbeefdeadbeefdeadbeef, sha1:ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03' -R copy-pull id https://localhost:$HGPORT/
414 414 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
415 415 5fed3813f7f5
416 416
417 417 - multiple fingerprints specified and none match
418 418
419 419 $ hg --config 'hostfingerprints.localhost=deadbeefdeadbeefdeadbeefdeadbeefdeadbeef, aeadbeefdeadbeefdeadbeefdeadbeefdeadbeef' -R copy-pull id https://localhost:$HGPORT/ --insecure
420 420 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
421 421 abort: certificate for localhost has unexpected fingerprint ec:d8:7c:d6:b3:86:d0:4f:c1:b8:b4:1c:9d:8f:5e:16:8e:ef:1c:03
422 422 (check hostfingerprint configuration)
423 423 [255]
424 424
425 425 $ hg --config 'hostsecurity.localhost:fingerprints=sha1:deadbeefdeadbeefdeadbeefdeadbeefdeadbeef, sha1:aeadbeefdeadbeefdeadbeefdeadbeefdeadbeef' -R copy-pull id https://localhost:$HGPORT/
426 426 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
427 427 abort: certificate for localhost has unexpected fingerprint sha1:ec:d8:7c:d6:b3:86:d0:4f:c1:b8:b4:1c:9d:8f:5e:16:8e:ef:1c:03
428 428 (check hostsecurity configuration)
429 429 [255]
430 430
431 431 - fails when cert doesn't match hostname (port is ignored)
432 432 $ hg -R copy-pull id https://localhost:$HGPORT1/ --config hostfingerprints.localhost=ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03
433 433 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
434 434 abort: certificate for localhost has unexpected fingerprint f4:2f:5a:0c:3e:52:5b:db:e7:24:a8:32:1d:18:97:6d:69:b5:87:84
435 435 (check hostfingerprint configuration)
436 436 [255]
437 437
438 438
439 439 - ignores that certificate doesn't match hostname
440 440 $ hg -R copy-pull id https://$LOCALIP:$HGPORT/ --config hostfingerprints.$LOCALIP=ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03
441 441 warning: connecting to $LOCALIP using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
442 442 (SHA-1 fingerprint for $LOCALIP found in legacy [hostfingerprints] section; if you trust this fingerprint, set the following config value in [hostsecurity] and remove the old one from [hostfingerprints] to upgrade to a more secure SHA-256 fingerprint: $LOCALIP.fingerprints=sha256:20:de:b3:ad:b4:cd:a5:42:f0:74:41:1c:a2:70:1e:da:6e:c0:5c:16:9e:e7:22:0f:f1:b7:e5:6e:e4:92:af:7e)
443 443 5fed3813f7f5
444 444
445 445 Ports used by next test. Kill servers.
446 446
447 447 $ killdaemons.py hg0.pid
448 448 $ killdaemons.py hg1.pid
449 449 $ killdaemons.py hg2.pid
450 450
451 451 #if sslcontext tls1.2
452 452 Start servers running supported TLS versions
453 453
454 454 $ cd test
455 455 $ hg serve -p $HGPORT -d --pid-file=../hg0.pid --certificate=$PRIV \
456 456 > --config devel.serverexactprotocol=tls1.0
457 457 $ cat ../hg0.pid >> $DAEMON_PIDS
458 458 $ hg serve -p $HGPORT1 -d --pid-file=../hg1.pid --certificate=$PRIV \
459 459 > --config devel.serverexactprotocol=tls1.1
460 460 $ cat ../hg1.pid >> $DAEMON_PIDS
461 461 $ hg serve -p $HGPORT2 -d --pid-file=../hg2.pid --certificate=$PRIV \
462 462 > --config devel.serverexactprotocol=tls1.2
463 463 $ cat ../hg2.pid >> $DAEMON_PIDS
464 464 $ cd ..
465 465
466 466 Clients talking same TLS versions work
467 467
468 468 $ P="$CERTSDIR" hg --config hostsecurity.minimumprotocol=tls1.0 id https://localhost:$HGPORT/
469 469 5fed3813f7f5
470 470 $ P="$CERTSDIR" hg --config hostsecurity.minimumprotocol=tls1.1 id https://localhost:$HGPORT1/
471 471 5fed3813f7f5
472 472 $ P="$CERTSDIR" hg --config hostsecurity.minimumprotocol=tls1.2 id https://localhost:$HGPORT2/
473 473 5fed3813f7f5
474 474
475 475 Clients requiring newer TLS version than what server supports fail
476 476
477 477 $ P="$CERTSDIR" hg id https://localhost:$HGPORT/
478 478 (could not negotiate a common security protocol (tls1.1+) with localhost; the likely cause is Mercurial is configured to be more secure than the server can support)
479 479 (consider contacting the operator of this server and ask them to support modern TLS protocol versions; or, set hostsecurity.localhost:minimumprotocol=tls1.0 to allow use of legacy, less secure protocols when communicating with this server)
480 480 (see https://mercurial-scm.org/wiki/SecureConnections for more info)
481 481 abort: error: *unsupported protocol* (glob)
482 482 [255]
483 483
484 484 $ P="$CERTSDIR" hg --config hostsecurity.minimumprotocol=tls1.1 id https://localhost:$HGPORT/
485 485 (could not negotiate a common security protocol (tls1.1+) with localhost; the likely cause is Mercurial is configured to be more secure than the server can support)
486 486 (consider contacting the operator of this server and ask them to support modern TLS protocol versions; or, set hostsecurity.localhost:minimumprotocol=tls1.0 to allow use of legacy, less secure protocols when communicating with this server)
487 487 (see https://mercurial-scm.org/wiki/SecureConnections for more info)
488 488 abort: error: *unsupported protocol* (glob)
489 489 [255]
490 490 $ P="$CERTSDIR" hg --config hostsecurity.minimumprotocol=tls1.2 id https://localhost:$HGPORT/
491 491 (could not negotiate a common security protocol (tls1.2+) with localhost; the likely cause is Mercurial is configured to be more secure than the server can support)
492 492 (consider contacting the operator of this server and ask them to support modern TLS protocol versions; or, set hostsecurity.localhost:minimumprotocol=tls1.0 to allow use of legacy, less secure protocols when communicating with this server)
493 493 (see https://mercurial-scm.org/wiki/SecureConnections for more info)
494 494 abort: error: *unsupported protocol* (glob)
495 495 [255]
496 496 $ P="$CERTSDIR" hg --config hostsecurity.minimumprotocol=tls1.2 id https://localhost:$HGPORT1/
497 497 (could not negotiate a common security protocol (tls1.2+) with localhost; the likely cause is Mercurial is configured to be more secure than the server can support)
498 498 (consider contacting the operator of this server and ask them to support modern TLS protocol versions; or, set hostsecurity.localhost:minimumprotocol=tls1.0 to allow use of legacy, less secure protocols when communicating with this server)
499 499 (see https://mercurial-scm.org/wiki/SecureConnections for more info)
500 500 abort: error: *unsupported protocol* (glob)
501 501 [255]
502 502
503 503 --insecure will allow TLS 1.0 connections and override configs
504 504
505 505 $ hg --config hostsecurity.minimumprotocol=tls1.2 id --insecure https://localhost:$HGPORT1/
506 506 warning: connection security to localhost is disabled per current settings; communication is susceptible to eavesdropping and tampering
507 507 5fed3813f7f5
508 508
509 509 The per-host config option overrides the default
510 510
511 511 $ P="$CERTSDIR" hg id https://localhost:$HGPORT/ \
512 512 > --config hostsecurity.minimumprotocol=tls1.2 \
513 513 > --config hostsecurity.localhost:minimumprotocol=tls1.0
514 514 5fed3813f7f5
515 515
516 516 The per-host config option by itself works
517 517
518 518 $ P="$CERTSDIR" hg id https://localhost:$HGPORT/ \
519 519 > --config hostsecurity.localhost:minimumprotocol=tls1.2
520 520 (could not negotiate a common security protocol (tls1.2+) with localhost; the likely cause is Mercurial is configured to be more secure than the server can support)
521 521 (consider contacting the operator of this server and ask them to support modern TLS protocol versions; or, set hostsecurity.localhost:minimumprotocol=tls1.0 to allow use of legacy, less secure protocols when communicating with this server)
522 522 (see https://mercurial-scm.org/wiki/SecureConnections for more info)
523 523 abort: error: *unsupported protocol* (glob)
524 524 [255]
525 525
526 526 .hg/hgrc file [hostsecurity] settings are applied to remote ui instances (issue5305)
527 527
528 528 $ cat >> copy-pull/.hg/hgrc << EOF
529 529 > [hostsecurity]
530 530 > localhost:minimumprotocol=tls1.2
531 531 > EOF
532 532 $ P="$CERTSDIR" hg -R copy-pull id https://localhost:$HGPORT/
533 533 (could not negotiate a common security protocol (tls1.2+) with localhost; the likely cause is Mercurial is configured to be more secure than the server can support)
534 534 (consider contacting the operator of this server and ask them to support modern TLS protocol versions; or, set hostsecurity.localhost:minimumprotocol=tls1.0 to allow use of legacy, less secure protocols when communicating with this server)
535 535 (see https://mercurial-scm.org/wiki/SecureConnections for more info)
536 536 abort: error: *unsupported protocol* (glob)
537 537 [255]
538 538
539 539 $ killdaemons.py hg0.pid
540 540 $ killdaemons.py hg1.pid
541 541 $ killdaemons.py hg2.pid
542 542 #endif
543 543
544 544 Prepare for connecting through proxy
545 545
546 546 $ hg serve -R test -p $HGPORT -d --pid-file=hg0.pid --certificate=$PRIV
547 547 $ cat hg0.pid >> $DAEMON_PIDS
548 548 $ hg serve -R test -p $HGPORT2 -d --pid-file=hg2.pid --certificate=server-expired.pem
549 549 $ cat hg2.pid >> $DAEMON_PIDS
550 550 tinyproxy.py doesn't fully detach, so killing it may result in extra output
551 551 from the shell. So don't kill it.
552 552 $ tinyproxy.py $HGPORT1 localhost >proxy.log </dev/null 2>&1 &
553 553 $ while [ ! -f proxy.pid ]; do sleep 0; done
554 554 $ cat proxy.pid >> $DAEMON_PIDS
555 555
556 556 $ echo "[http_proxy]" >> copy-pull/.hg/hgrc
557 557 $ echo "always=True" >> copy-pull/.hg/hgrc
558 558 $ echo "[hostfingerprints]" >> copy-pull/.hg/hgrc
559 559 $ echo "localhost =" >> copy-pull/.hg/hgrc
560 560
561 561 Test unvalidated https through proxy
562 562
563 563 $ http_proxy=http://localhost:$HGPORT1/ hg -R copy-pull pull --insecure
564 564 pulling from https://localhost:$HGPORT/
565 565 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
566 566 warning: connection security to localhost is disabled per current settings; communication is susceptible to eavesdropping and tampering
567 567 searching for changes
568 568 no changes found
569 569
570 570 Test https with cacert and fingerprint through proxy
571 571
572 572 $ http_proxy=http://localhost:$HGPORT1/ hg -R copy-pull pull \
573 573 > --config web.cacerts="$CERTSDIR/pub.pem"
574 574 pulling from https://localhost:$HGPORT/
575 575 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
576 576 searching for changes
577 577 no changes found
578 578 $ http_proxy=http://localhost:$HGPORT1/ hg -R copy-pull pull https://localhost:$HGPORT/ --config hostfingerprints.localhost=ecd87cd6b386d04fc1b8b41c9d8f5e168eef1c03 --trace
579 579 pulling from https://*:$HGPORT/ (glob)
580 580 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
581 581 (SHA-1 fingerprint for localhost found in legacy [hostfingerprints] section; if you trust this fingerprint, set the following config value in [hostsecurity] and remove the old one from [hostfingerprints] to upgrade to a more secure SHA-256 fingerprint: localhost.fingerprints=sha256:20:de:b3:ad:b4:cd:a5:42:f0:74:41:1c:a2:70:1e:da:6e:c0:5c:16:9e:e7:22:0f:f1:b7:e5:6e:e4:92:af:7e)
582 582 searching for changes
583 583 no changes found
584 584
585 585 Test https with cert problems through proxy
586 586
587 587 $ http_proxy=http://localhost:$HGPORT1/ hg -R copy-pull pull \
588 588 > --config web.cacerts="$CERTSDIR/pub-other.pem"
589 589 pulling from https://localhost:$HGPORT/
590 590 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
591 591 abort: error: *certificate verify failed* (glob)
592 592 [255]
593 593 $ http_proxy=http://localhost:$HGPORT1/ hg -R copy-pull pull \
594 594 > --config web.cacerts="$CERTSDIR/pub-expired.pem" https://localhost:$HGPORT2/
595 595 pulling from https://localhost:$HGPORT2/
596 596 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
597 597 abort: error: *certificate verify failed* (glob)
598 598 [255]
599 599
600 600
601 601 $ killdaemons.py hg0.pid
602 602
603 603 #if sslcontext
604 604
605 605 Start hgweb that requires client certificates:
606 606
607 607 $ cd test
608 608 $ hg serve -p $HGPORT -d --pid-file=../hg0.pid --certificate=$PRIV \
609 609 > --config devel.servercafile=$PRIV --config devel.serverrequirecert=true
610 610 $ cat ../hg0.pid >> $DAEMON_PIDS
611 611 $ cd ..
612 612
613 613 without client certificate:
614 614
615 615 $ P="$CERTSDIR" hg id https://localhost:$HGPORT/
616 616 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
617 617 abort: error: *handshake failure* (glob)
618 618 [255]
619 619
620 620 with client certificate:
621 621
622 622 $ cat << EOT >> $HGRCPATH
623 623 > [auth]
624 624 > l.prefix = localhost
625 625 > l.cert = $CERTSDIR/client-cert.pem
626 626 > l.key = $CERTSDIR/client-key.pem
627 627 > EOT
628 628
629 629 $ P="$CERTSDIR" hg id https://localhost:$HGPORT/ \
630 630 > --config auth.l.key="$CERTSDIR/client-key-decrypted.pem"
631 631 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
632 632 5fed3813f7f5
633 633
634 634 $ printf '1234\n' | env P="$CERTSDIR" hg id https://localhost:$HGPORT/ \
635 635 > --config ui.interactive=True --config ui.nontty=True
636 636 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
637 637 passphrase for */client-key.pem: 5fed3813f7f5 (glob)
638 638
639 639 $ env P="$CERTSDIR" hg id https://localhost:$HGPORT/
640 640 warning: connecting to localhost using legacy security technology (TLS 1.0); see https://mercurial-scm.org/wiki/SecureConnections for more info (?)
641 641 abort: error: * (glob)
642 642 [255]
643 643
644 644 #endif
@@ -1,203 +1,203
1 1 #require killdaemons
2 2
3 3 This test checks behavior related to bundle1 that changed or is likely
4 4 to change with bundle2. Feel free to factor out any part of the test
5 5 which does not need to exist to keep bundle1 working.
6 6
7 7 $ cat << EOF >> $HGRCPATH
8 8 > [devel]
9 9 > # This test is dedicated to interaction through old bundle
10 10 > legacy.exchange = bundle1
11 11 > EOF
12 12
13 13 $ hg init test
14 14 $ cd test
15 15 $ echo a > a
16 16 $ hg ci -Ama
17 17 adding a
18 18 $ cd ..
19 19 $ hg clone test test2
20 20 updating to branch default
21 21 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
22 22 $ cd test2
23 23 $ echo a >> a
24 24 $ hg ci -mb
25 25 $ req() {
26 26 > hg serve -p $HGPORT -d --pid-file=hg.pid -E errors.log
27 27 > cat hg.pid >> $DAEMON_PIDS
28 28 > hg --cwd ../test2 push http://localhost:$HGPORT/
29 29 > exitstatus=$?
30 30 > killdaemons.py
31 31 > echo % serve errors
32 32 > cat errors.log
33 33 > return $exitstatus
34 34 > }
35 35 $ cd ../test
36 36
37 37 expect ssl error
38 38
39 39 $ req
40 40 pushing to http://localhost:$HGPORT/
41 41 searching for changes
42 42 abort: HTTP Error 403: ssl required
43 43 % serve errors
44 44 [255]
45 45
46 46 expect authorization error
47 47
48 48 $ echo '[web]' > .hg/hgrc
49 49 $ echo 'push_ssl = false' >> .hg/hgrc
50 50 $ req
51 51 pushing to http://localhost:$HGPORT/
52 52 searching for changes
53 53 abort: authorization failed
54 54 % serve errors
55 55 [255]
56 56
57 57 expect authorization error: must have authorized user
58 58
59 59 $ echo 'allow_push = unperson' >> .hg/hgrc
60 60 $ req
61 61 pushing to http://localhost:$HGPORT/
62 62 searching for changes
63 63 abort: authorization failed
64 64 % serve errors
65 65 [255]
66 66
67 67 expect success
68 68
69 69 $ cat >> .hg/hgrc <<EOF
70 70 > allow_push = *
71 71 > [hooks]
72 72 > changegroup = sh -c "printenv.py changegroup 0"
73 73 > pushkey = sh -c "printenv.py pushkey 0"
74 74 > EOF
75 75 $ req
76 76 pushing to http://localhost:$HGPORT/
77 77 searching for changes
78 78 remote: adding changesets
79 79 remote: adding manifests
80 80 remote: adding file changes
81 81 remote: added 1 changesets with 1 changes to 1 files
82 remote: changegroup hook: HG_HOOKTYPE=changegroup HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:http:$LOCALIP:
82 remote: changegroup hook: HG_HOOKNAME=changegroup HG_HOOKTYPE=changegroup HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:http:$LOCALIP:
83 83 % serve errors
84 84 $ hg rollback
85 85 repository tip rolled back to revision 0 (undo serve)
86 86
87 87 expect success, server lacks the httpheader capability
88 88
89 89 $ CAP=httpheader
90 90 $ . "$TESTDIR/notcapable"
91 91 $ req
92 92 pushing to http://localhost:$HGPORT/
93 93 searching for changes
94 94 remote: adding changesets
95 95 remote: adding manifests
96 96 remote: adding file changes
97 97 remote: added 1 changesets with 1 changes to 1 files
98 remote: changegroup hook: HG_HOOKTYPE=changegroup HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:http:$LOCALIP:
98 remote: changegroup hook: HG_HOOKNAME=changegroup HG_HOOKTYPE=changegroup HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:http:$LOCALIP:
99 99 % serve errors
100 100 $ hg rollback
101 101 repository tip rolled back to revision 0 (undo serve)
102 102
103 103 expect success, server lacks the unbundlehash capability
104 104
105 105 $ CAP=unbundlehash
106 106 $ . "$TESTDIR/notcapable"
107 107 $ req
108 108 pushing to http://localhost:$HGPORT/
109 109 searching for changes
110 110 remote: adding changesets
111 111 remote: adding manifests
112 112 remote: adding file changes
113 113 remote: added 1 changesets with 1 changes to 1 files
114 remote: changegroup hook: HG_HOOKTYPE=changegroup HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:http:$LOCALIP:
114 remote: changegroup hook: HG_HOOKNAME=changegroup HG_HOOKTYPE=changegroup HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:http:$LOCALIP:
115 115 % serve errors
116 116 $ hg rollback
117 117 repository tip rolled back to revision 0 (undo serve)
118 118
119 119 expect success, pre-d1b16a746db6 server supports the unbundle capability, but
120 120 has no parameter
121 121
122 122 $ cat <<EOF > notcapable-unbundleparam.py
123 123 > from mercurial import extensions, httppeer
124 124 > def capable(orig, self, name):
125 125 > if name == 'unbundle':
126 126 > return True
127 127 > return orig(self, name)
128 128 > def uisetup(ui):
129 129 > extensions.wrapfunction(httppeer.httppeer, 'capable', capable)
130 130 > EOF
131 131 $ cp $HGRCPATH $HGRCPATH.orig
132 132 $ cat <<EOF >> $HGRCPATH
133 133 > [extensions]
134 134 > notcapable-unbundleparam = `pwd`/notcapable-unbundleparam.py
135 135 > EOF
136 136 $ req
137 137 pushing to http://localhost:$HGPORT/
138 138 searching for changes
139 139 remote: adding changesets
140 140 remote: adding manifests
141 141 remote: adding file changes
142 142 remote: added 1 changesets with 1 changes to 1 files
143 143 remote: changegroup hook: * (glob)
144 144 % serve errors
145 145 $ hg rollback
146 146 repository tip rolled back to revision 0 (undo serve)
147 147 $ mv $HGRCPATH.orig $HGRCPATH
148 148
149 149 expect push success, phase change failure
150 150
151 151 $ cat > .hg/hgrc <<EOF
152 152 > [web]
153 153 > push_ssl = false
154 154 > allow_push = *
155 155 > [hooks]
156 156 > prepushkey = sh -c "printenv.py prepushkey 1"
157 157 > EOF
158 158 $ req
159 159 pushing to http://localhost:$HGPORT/
160 160 searching for changes
161 161 remote: adding changesets
162 162 remote: adding manifests
163 163 remote: adding file changes
164 164 remote: added 1 changesets with 1 changes to 1 files
165 165 % serve errors
166 166
167 167 expect phase change success
168 168
169 169 $ cat >> .hg/hgrc <<EOF
170 170 > prepushkey = sh -c "printenv.py prepushkey 0"
171 171 > EOF
172 172 $ req
173 173 pushing to http://localhost:$HGPORT/
174 174 searching for changes
175 175 no changes found
176 176 % serve errors
177 177 [1]
178 178 $ hg rollback
179 179 repository tip rolled back to revision 0 (undo serve)
180 180
181 181 expect authorization error: all users denied
182 182
183 183 $ echo '[web]' > .hg/hgrc
184 184 $ echo 'push_ssl = false' >> .hg/hgrc
185 185 $ echo 'deny_push = *' >> .hg/hgrc
186 186 $ req
187 187 pushing to http://localhost:$HGPORT/
188 188 searching for changes
189 189 abort: authorization failed
190 190 % serve errors
191 191 [255]
192 192
193 193 expect authorization error: some users denied, users must be authenticated
194 194
195 195 $ echo 'deny_push = unperson' >> .hg/hgrc
196 196 $ req
197 197 pushing to http://localhost:$HGPORT/
198 198 searching for changes
199 199 abort: authorization failed
200 200 % serve errors
201 201 [255]
202 202
203 203 $ cd ..
@@ -1,175 +1,175
1 1 #require killdaemons
2 2
3 3 $ hg init test
4 4 $ cd test
5 5 $ echo a > a
6 6 $ hg ci -Ama
7 7 adding a
8 8 $ cd ..
9 9 $ hg clone test test2
10 10 updating to branch default
11 11 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
12 12 $ cd test2
13 13 $ echo a >> a
14 14 $ hg ci -mb
15 15 $ req() {
16 16 > hg serve -p $HGPORT -d --pid-file=hg.pid -E errors.log
17 17 > cat hg.pid >> $DAEMON_PIDS
18 18 > hg --cwd ../test2 push http://localhost:$HGPORT/
19 19 > exitstatus=$?
20 20 > killdaemons.py
21 21 > echo % serve errors
22 22 > cat errors.log
23 23 > return $exitstatus
24 24 > }
25 25 $ cd ../test
26 26
27 27 expect ssl error
28 28
29 29 $ req
30 30 pushing to http://localhost:$HGPORT/
31 31 searching for changes
32 32 abort: HTTP Error 403: ssl required
33 33 % serve errors
34 34 [255]
35 35
36 36 expect authorization error
37 37
38 38 $ echo '[web]' > .hg/hgrc
39 39 $ echo 'push_ssl = false' >> .hg/hgrc
40 40 $ req
41 41 pushing to http://localhost:$HGPORT/
42 42 searching for changes
43 43 abort: authorization failed
44 44 % serve errors
45 45 [255]
46 46
47 47 expect authorization error: must have authorized user
48 48
49 49 $ echo 'allow_push = unperson' >> .hg/hgrc
50 50 $ req
51 51 pushing to http://localhost:$HGPORT/
52 52 searching for changes
53 53 abort: authorization failed
54 54 % serve errors
55 55 [255]
56 56
57 57 expect success
58 58
59 59 $ cat >> .hg/hgrc <<EOF
60 60 > allow_push = *
61 61 > [hooks]
62 62 > changegroup = sh -c "printenv.py changegroup 0"
63 63 > pushkey = sh -c "printenv.py pushkey 0"
64 64 > EOF
65 65 $ req
66 66 pushing to http://localhost:$HGPORT/
67 67 searching for changes
68 68 remote: adding changesets
69 69 remote: adding manifests
70 70 remote: adding file changes
71 71 remote: added 1 changesets with 1 changes to 1 files
72 remote: pushkey hook: HG_HOOKTYPE=pushkey HG_KEY=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NAMESPACE=phases HG_NEW=0 HG_OLD=1 HG_RET=1
73 remote: changegroup hook: HG_BUNDLE2=1 HG_HOOKTYPE=changegroup HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:http:$LOCALIP:
72 remote: pushkey hook: HG_HOOKNAME=pushkey HG_HOOKTYPE=pushkey HG_KEY=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NAMESPACE=phases HG_NEW=0 HG_OLD=1 HG_RET=1
73 remote: changegroup hook: HG_BUNDLE2=1 HG_HOOKNAME=changegroup HG_HOOKTYPE=changegroup HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:http:$LOCALIP:
74 74 % serve errors
75 75 $ hg rollback
76 76 repository tip rolled back to revision 0 (undo serve)
77 77
78 78 expect success, server lacks the httpheader capability
79 79
80 80 $ CAP=httpheader
81 81 $ . "$TESTDIR/notcapable"
82 82 $ req
83 83 pushing to http://localhost:$HGPORT/
84 84 searching for changes
85 85 remote: adding changesets
86 86 remote: adding manifests
87 87 remote: adding file changes
88 88 remote: added 1 changesets with 1 changes to 1 files
89 remote: pushkey hook: HG_HOOKTYPE=pushkey HG_KEY=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NAMESPACE=phases HG_NEW=0 HG_OLD=1 HG_RET=1
90 remote: changegroup hook: HG_BUNDLE2=1 HG_HOOKTYPE=changegroup HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:http:$LOCALIP:
89 remote: pushkey hook: HG_HOOKNAME=pushkey HG_HOOKTYPE=pushkey HG_KEY=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NAMESPACE=phases HG_NEW=0 HG_OLD=1 HG_RET=1
90 remote: changegroup hook: HG_BUNDLE2=1 HG_HOOKNAME=changegroup HG_HOOKTYPE=changegroup HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:http:$LOCALIP:
91 91 % serve errors
92 92 $ hg rollback
93 93 repository tip rolled back to revision 0 (undo serve)
94 94
95 95 expect success, server lacks the unbundlehash capability
96 96
97 97 $ CAP=unbundlehash
98 98 $ . "$TESTDIR/notcapable"
99 99 $ req
100 100 pushing to http://localhost:$HGPORT/
101 101 searching for changes
102 102 remote: adding changesets
103 103 remote: adding manifests
104 104 remote: adding file changes
105 105 remote: added 1 changesets with 1 changes to 1 files
106 remote: pushkey hook: HG_HOOKTYPE=pushkey HG_KEY=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NAMESPACE=phases HG_NEW=0 HG_OLD=1 HG_RET=1
107 remote: changegroup hook: HG_BUNDLE2=1 HG_HOOKTYPE=changegroup HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:http:$LOCALIP:
106 remote: pushkey hook: HG_HOOKNAME=pushkey HG_HOOKTYPE=pushkey HG_KEY=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NAMESPACE=phases HG_NEW=0 HG_OLD=1 HG_RET=1
107 remote: changegroup hook: HG_BUNDLE2=1 HG_HOOKNAME=changegroup HG_HOOKTYPE=changegroup HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:http:$LOCALIP:
108 108 % serve errors
109 109 $ hg rollback
110 110 repository tip rolled back to revision 0 (undo serve)
111 111
112 112 expect push success, phase change failure
113 113
114 114 $ cat > .hg/hgrc <<EOF
115 115 > [web]
116 116 > push_ssl = false
117 117 > allow_push = *
118 118 > [hooks]
119 119 > prepushkey = sh -c "printenv.py prepushkey 1"
120 120 > EOF
121 121 $ req
122 122 pushing to http://localhost:$HGPORT/
123 123 searching for changes
124 124 remote: adding changesets
125 125 remote: adding manifests
126 126 remote: adding file changes
127 127 remote: added 1 changesets with 1 changes to 1 files
128 remote: prepushkey hook: HG_BUNDLE2=1 HG_HOOKTYPE=prepushkey HG_KEY=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NAMESPACE=phases HG_NEW=0 HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_OLD=1 HG_PENDING=$TESTTMP/test HG_PHASES_MOVED=1 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:http:$LOCALIP:
128 remote: prepushkey hook: HG_BUNDLE2=1 HG_HOOKNAME=prepushkey HG_HOOKTYPE=prepushkey HG_KEY=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NAMESPACE=phases HG_NEW=0 HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_OLD=1 HG_PENDING=$TESTTMP/test HG_PHASES_MOVED=1 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:http:$LOCALIP:
129 129 remote: pushkey-abort: prepushkey hook exited with status 1
130 130 remote: transaction abort!
131 131 remote: rollback completed
132 132 abort: updating ba677d0156c1 to public failed
133 133 % serve errors
134 134 [255]
135 135
136 136 expect phase change success
137 137
138 138 $ cat >> .hg/hgrc <<EOF
139 139 > prepushkey = sh -c "printenv.py prepushkey 0"
140 140 > EOF
141 141 $ req
142 142 pushing to http://localhost:$HGPORT/
143 143 searching for changes
144 144 remote: adding changesets
145 145 remote: adding manifests
146 146 remote: adding file changes
147 147 remote: added 1 changesets with 1 changes to 1 files
148 remote: prepushkey hook: HG_BUNDLE2=1 HG_HOOKTYPE=prepushkey HG_KEY=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NAMESPACE=phases HG_NEW=0 HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_OLD=1 HG_PENDING=$TESTTMP/test HG_PHASES_MOVED=1 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:http:$LOCALIP:
148 remote: prepushkey hook: HG_BUNDLE2=1 HG_HOOKNAME=prepushkey HG_HOOKTYPE=prepushkey HG_KEY=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NAMESPACE=phases HG_NEW=0 HG_NODE=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_NODE_LAST=ba677d0156c1196c1a699fa53f390dcfc3ce3872 HG_OLD=1 HG_PENDING=$TESTTMP/test HG_PHASES_MOVED=1 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:http:$LOCALIP:
149 149 % serve errors
150 150 $ hg rollback
151 151 repository tip rolled back to revision 0 (undo serve)
152 152
153 153 expect authorization error: all users denied
154 154
155 155 $ echo '[web]' > .hg/hgrc
156 156 $ echo 'push_ssl = false' >> .hg/hgrc
157 157 $ echo 'deny_push = *' >> .hg/hgrc
158 158 $ req
159 159 pushing to http://localhost:$HGPORT/
160 160 searching for changes
161 161 abort: authorization failed
162 162 % serve errors
163 163 [255]
164 164
165 165 expect authorization error: some users denied, users must be authenticated
166 166
167 167 $ echo 'deny_push = unperson' >> .hg/hgrc
168 168 $ req
169 169 pushing to http://localhost:$HGPORT/
170 170 searching for changes
171 171 abort: authorization failed
172 172 % serve errors
173 173 [255]
174 174
175 175 $ cd ..
@@ -1,562 +1,562
1 1 This test is a duplicate of 'test-http.t' feel free to factor out
2 2 parts that are not bundle1/bundle2 specific.
3 3
4 4 $ cat << EOF >> $HGRCPATH
5 5 > [devel]
6 6 > # This test is dedicated to interaction through old bundle
7 7 > legacy.exchange = bundle1
8 8 > [format] # temporary settings
9 9 > usegeneraldelta=yes
10 10 > EOF
11 11
12 12
13 13 This test tries to exercise the ssh functionality with a dummy script
14 14
15 15 creating 'remote' repo
16 16
17 17 $ hg init remote
18 18 $ cd remote
19 19 $ echo this > foo
20 20 $ echo this > fooO
21 21 $ hg ci -A -m "init" foo fooO
22 22
23 23 insert a closed branch (issue4428)
24 24
25 25 $ hg up null
26 26 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
27 27 $ hg branch closed
28 28 marked working directory as branch closed
29 29 (branches are permanent and global, did you want a bookmark?)
30 30 $ hg ci -mc0
31 31 $ hg ci --close-branch -mc1
32 32 $ hg up -q default
33 33
34 34 configure for serving
35 35
36 36 $ cat <<EOF > .hg/hgrc
37 37 > [server]
38 38 > uncompressed = True
39 39 >
40 40 > [hooks]
41 41 > changegroup = sh -c "printenv.py changegroup-in-remote 0 ../dummylog"
42 42 > EOF
43 43 $ cd ..
44 44
45 45 repo not found error
46 46
47 47 $ hg clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/nonexistent local
48 48 remote: abort: repository nonexistent not found!
49 49 abort: no suitable response from remote hg!
50 50 [255]
51 51
52 52 non-existent absolute path
53 53
54 54 $ hg clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy//`pwd`/nonexistent local
55 55 remote: abort: repository /$TESTTMP/nonexistent not found!
56 56 abort: no suitable response from remote hg!
57 57 [255]
58 58
59 59 clone remote via stream
60 60
61 61 $ hg clone -e "python \"$TESTDIR/dummyssh\"" --uncompressed ssh://user@dummy/remote local-stream
62 62 streaming all changes
63 63 4 files to transfer, 602 bytes of data
64 64 transferred 602 bytes in * seconds (*) (glob)
65 65 searching for changes
66 66 no changes found
67 67 updating to branch default
68 68 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
69 69 $ cd local-stream
70 70 $ hg verify
71 71 checking changesets
72 72 checking manifests
73 73 crosschecking files in changesets and manifests
74 74 checking files
75 75 2 files, 3 changesets, 2 total revisions
76 76 $ hg branches
77 77 default 0:1160648e36ce
78 78 $ cd ..
79 79
80 80 clone bookmarks via stream
81 81
82 82 $ hg -R local-stream book mybook
83 83 $ hg clone -e "python \"$TESTDIR/dummyssh\"" --uncompressed ssh://user@dummy/local-stream stream2
84 84 streaming all changes
85 85 4 files to transfer, 602 bytes of data
86 86 transferred 602 bytes in * seconds (*) (glob)
87 87 searching for changes
88 88 no changes found
89 89 updating to branch default
90 90 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
91 91 $ cd stream2
92 92 $ hg book
93 93 mybook 0:1160648e36ce
94 94 $ cd ..
95 95 $ rm -rf local-stream stream2
96 96
97 97 clone remote via pull
98 98
99 99 $ hg clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/remote local
100 100 requesting all changes
101 101 adding changesets
102 102 adding manifests
103 103 adding file changes
104 104 added 3 changesets with 2 changes to 2 files
105 105 updating to branch default
106 106 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
107 107
108 108 verify
109 109
110 110 $ cd local
111 111 $ hg verify
112 112 checking changesets
113 113 checking manifests
114 114 crosschecking files in changesets and manifests
115 115 checking files
116 116 2 files, 3 changesets, 2 total revisions
117 117 $ cat >> .hg/hgrc <<EOF
118 118 > [hooks]
119 119 > changegroup = sh -c "printenv.py changegroup-in-local 0 ../dummylog"
120 120 > EOF
121 121
122 122 empty default pull
123 123
124 124 $ hg paths
125 125 default = ssh://user@dummy/remote
126 126 $ hg pull -e "python \"$TESTDIR/dummyssh\""
127 127 pulling from ssh://user@dummy/remote
128 128 searching for changes
129 129 no changes found
130 130
131 131 pull from wrong ssh URL
132 132
133 133 $ hg pull -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/doesnotexist
134 134 pulling from ssh://user@dummy/doesnotexist
135 135 remote: abort: repository doesnotexist not found!
136 136 abort: no suitable response from remote hg!
137 137 [255]
138 138
139 139 local change
140 140
141 141 $ echo bleah > foo
142 142 $ hg ci -m "add"
143 143
144 144 updating rc
145 145
146 146 $ echo "default-push = ssh://user@dummy/remote" >> .hg/hgrc
147 147 $ echo "[ui]" >> .hg/hgrc
148 148 $ echo "ssh = python \"$TESTDIR/dummyssh\"" >> .hg/hgrc
149 149
150 150 find outgoing
151 151
152 152 $ hg out ssh://user@dummy/remote
153 153 comparing with ssh://user@dummy/remote
154 154 searching for changes
155 155 changeset: 3:a28a9d1a809c
156 156 tag: tip
157 157 parent: 0:1160648e36ce
158 158 user: test
159 159 date: Thu Jan 01 00:00:00 1970 +0000
160 160 summary: add
161 161
162 162
163 163 find incoming on the remote side
164 164
165 165 $ hg incoming -R ../remote -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/local
166 166 comparing with ssh://user@dummy/local
167 167 searching for changes
168 168 changeset: 3:a28a9d1a809c
169 169 tag: tip
170 170 parent: 0:1160648e36ce
171 171 user: test
172 172 date: Thu Jan 01 00:00:00 1970 +0000
173 173 summary: add
174 174
175 175
176 176 find incoming on the remote side (using absolute path)
177 177
178 178 $ hg incoming -R ../remote -e "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/`pwd`"
179 179 comparing with ssh://user@dummy/$TESTTMP/local
180 180 searching for changes
181 181 changeset: 3:a28a9d1a809c
182 182 tag: tip
183 183 parent: 0:1160648e36ce
184 184 user: test
185 185 date: Thu Jan 01 00:00:00 1970 +0000
186 186 summary: add
187 187
188 188
189 189 push
190 190
191 191 $ hg push
192 192 pushing to ssh://user@dummy/remote
193 193 searching for changes
194 194 remote: adding changesets
195 195 remote: adding manifests
196 196 remote: adding file changes
197 197 remote: added 1 changesets with 1 changes to 1 files
198 198 $ cd ../remote
199 199
200 200 check remote tip
201 201
202 202 $ hg tip
203 203 changeset: 3:a28a9d1a809c
204 204 tag: tip
205 205 parent: 0:1160648e36ce
206 206 user: test
207 207 date: Thu Jan 01 00:00:00 1970 +0000
208 208 summary: add
209 209
210 210 $ hg verify
211 211 checking changesets
212 212 checking manifests
213 213 crosschecking files in changesets and manifests
214 214 checking files
215 215 2 files, 4 changesets, 3 total revisions
216 216 $ hg cat -r tip foo
217 217 bleah
218 218 $ echo z > z
219 219 $ hg ci -A -m z z
220 220 created new head
221 221
222 222 test pushkeys and bookmarks
223 223
224 224 $ cd ../local
225 225 $ hg debugpushkey --config ui.ssh="python \"$TESTDIR/dummyssh\"" ssh://user@dummy/remote namespaces
226 226 bookmarks
227 227 namespaces
228 228 phases
229 229 $ hg book foo -r 0
230 230 $ hg out -B
231 231 comparing with ssh://user@dummy/remote
232 232 searching for changed bookmarks
233 233 foo 1160648e36ce
234 234 $ hg push -B foo
235 235 pushing to ssh://user@dummy/remote
236 236 searching for changes
237 237 no changes found
238 238 exporting bookmark foo
239 239 [1]
240 240 $ hg debugpushkey --config ui.ssh="python \"$TESTDIR/dummyssh\"" ssh://user@dummy/remote bookmarks
241 241 foo 1160648e36cec0054048a7edc4110c6f84fde594
242 242 $ hg book -f foo
243 243 $ hg push --traceback
244 244 pushing to ssh://user@dummy/remote
245 245 searching for changes
246 246 no changes found
247 247 updating bookmark foo
248 248 [1]
249 249 $ hg book -d foo
250 250 $ hg in -B
251 251 comparing with ssh://user@dummy/remote
252 252 searching for changed bookmarks
253 253 foo a28a9d1a809c
254 254 $ hg book -f -r 0 foo
255 255 $ hg pull -B foo
256 256 pulling from ssh://user@dummy/remote
257 257 no changes found
258 258 updating bookmark foo
259 259 $ hg book -d foo
260 260 $ hg push -B foo
261 261 pushing to ssh://user@dummy/remote
262 262 searching for changes
263 263 no changes found
264 264 deleting remote bookmark foo
265 265 [1]
266 266
267 267 a bad, evil hook that prints to stdout
268 268
269 269 $ cat <<EOF > $TESTTMP/badhook
270 270 > import sys
271 271 > sys.stdout.write("KABOOM\n")
272 272 > EOF
273 273
274 274 $ echo '[hooks]' >> ../remote/.hg/hgrc
275 275 $ echo "changegroup.stdout = python $TESTTMP/badhook" >> ../remote/.hg/hgrc
276 276 $ echo r > r
277 277 $ hg ci -A -m z r
278 278
279 279 push should succeed even though it has an unexpected response
280 280
281 281 $ hg push
282 282 pushing to ssh://user@dummy/remote
283 283 searching for changes
284 284 remote has heads on branch 'default' that are not known locally: 6c0482d977a3
285 285 remote: adding changesets
286 286 remote: adding manifests
287 287 remote: adding file changes
288 288 remote: added 1 changesets with 1 changes to 1 files
289 289 remote: KABOOM
290 290 $ hg -R ../remote heads
291 291 changeset: 5:1383141674ec
292 292 tag: tip
293 293 parent: 3:a28a9d1a809c
294 294 user: test
295 295 date: Thu Jan 01 00:00:00 1970 +0000
296 296 summary: z
297 297
298 298 changeset: 4:6c0482d977a3
299 299 parent: 0:1160648e36ce
300 300 user: test
301 301 date: Thu Jan 01 00:00:00 1970 +0000
302 302 summary: z
303 303
304 304
305 305 clone bookmarks
306 306
307 307 $ hg -R ../remote bookmark test
308 308 $ hg -R ../remote bookmarks
309 309 * test 4:6c0482d977a3
310 310 $ hg clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/remote local-bookmarks
311 311 requesting all changes
312 312 adding changesets
313 313 adding manifests
314 314 adding file changes
315 315 added 6 changesets with 5 changes to 4 files (+1 heads)
316 316 updating to branch default
317 317 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
318 318 $ hg -R local-bookmarks bookmarks
319 319 test 4:6c0482d977a3
320 320
321 321 passwords in ssh urls are not supported
322 322 (we use a glob here because different Python versions give different
323 323 results here)
324 324
325 325 $ hg push ssh://user:erroneouspwd@dummy/remote
326 326 pushing to ssh://user:*@dummy/remote (glob)
327 327 abort: password in URL not supported!
328 328 [255]
329 329
330 330 $ cd ..
331 331
332 332 hide outer repo
333 333 $ hg init
334 334
335 335 Test remote paths with spaces (issue2983):
336 336
337 337 $ hg init --ssh "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo"
338 338 $ touch "$TESTTMP/a repo/test"
339 339 $ hg -R 'a repo' commit -A -m "test"
340 340 adding test
341 341 $ hg -R 'a repo' tag tag
342 342 $ hg id --ssh "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo"
343 343 73649e48688a
344 344
345 345 $ hg id --ssh "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo#noNoNO"
346 346 abort: unknown revision 'noNoNO'!
347 347 [255]
348 348
349 349 Test (non-)escaping of remote paths with spaces when cloning (issue3145):
350 350
351 351 $ hg clone --ssh "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo"
352 352 destination directory: a repo
353 353 abort: destination 'a repo' is not empty
354 354 [255]
355 355
356 356 Test hg-ssh using a helper script that will restore PYTHONPATH (which might
357 357 have been cleared by a hg.exe wrapper) and invoke hg-ssh with the right
358 358 parameters:
359 359
360 360 $ cat > ssh.sh << EOF
361 361 > userhost="\$1"
362 362 > SSH_ORIGINAL_COMMAND="\$2"
363 363 > export SSH_ORIGINAL_COMMAND
364 364 > PYTHONPATH="$PYTHONPATH"
365 365 > export PYTHONPATH
366 366 > python "$TESTDIR/../contrib/hg-ssh" "$TESTTMP/a repo"
367 367 > EOF
368 368
369 369 $ hg id --ssh "sh ssh.sh" "ssh://user@dummy/a repo"
370 370 73649e48688a
371 371
372 372 $ hg id --ssh "sh ssh.sh" "ssh://user@dummy/a'repo"
373 373 remote: Illegal repository "$TESTTMP/a'repo" (glob)
374 374 abort: no suitable response from remote hg!
375 375 [255]
376 376
377 377 $ hg id --ssh "sh ssh.sh" --remotecmd hacking "ssh://user@dummy/a'repo"
378 378 remote: Illegal command "hacking -R 'a'\''repo' serve --stdio"
379 379 abort: no suitable response from remote hg!
380 380 [255]
381 381
382 382 $ SSH_ORIGINAL_COMMAND="'hg' serve -R 'a'repo' --stdio" python "$TESTDIR/../contrib/hg-ssh"
383 383 Illegal command "'hg' serve -R 'a'repo' --stdio": No closing quotation
384 384 [255]
385 385
386 386 Test hg-ssh in read-only mode:
387 387
388 388 $ cat > ssh.sh << EOF
389 389 > userhost="\$1"
390 390 > SSH_ORIGINAL_COMMAND="\$2"
391 391 > export SSH_ORIGINAL_COMMAND
392 392 > PYTHONPATH="$PYTHONPATH"
393 393 > export PYTHONPATH
394 394 > python "$TESTDIR/../contrib/hg-ssh" --read-only "$TESTTMP/remote"
395 395 > EOF
396 396
397 397 $ hg clone --ssh "sh ssh.sh" "ssh://user@dummy/$TESTTMP/remote" read-only-local
398 398 requesting all changes
399 399 adding changesets
400 400 adding manifests
401 401 adding file changes
402 402 added 6 changesets with 5 changes to 4 files (+1 heads)
403 403 updating to branch default
404 404 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
405 405
406 406 $ cd read-only-local
407 407 $ echo "baz" > bar
408 408 $ hg ci -A -m "unpushable commit" bar
409 409 $ hg push --ssh "sh ../ssh.sh"
410 410 pushing to ssh://user@dummy/*/remote (glob)
411 411 searching for changes
412 412 remote: Permission denied
413 413 remote: abort: pretxnopen.hg-ssh hook failed
414 414 remote: Permission denied
415 415 remote: pushkey-abort: prepushkey.hg-ssh hook failed
416 416 updating 6c0482d977a3 to public failed!
417 417 [1]
418 418
419 419 $ cd ..
420 420
421 421 stderr from remote commands should be printed before stdout from local code (issue4336)
422 422
423 423 $ hg clone remote stderr-ordering
424 424 updating to branch default
425 425 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
426 426 $ cd stderr-ordering
427 427 $ cat >> localwrite.py << EOF
428 428 > from mercurial import exchange, extensions
429 429 >
430 430 > def wrappedpush(orig, repo, *args, **kwargs):
431 431 > res = orig(repo, *args, **kwargs)
432 432 > repo.ui.write('local stdout\n')
433 433 > return res
434 434 >
435 435 > def extsetup(ui):
436 436 > extensions.wrapfunction(exchange, 'push', wrappedpush)
437 437 > EOF
438 438
439 439 $ cat >> .hg/hgrc << EOF
440 440 > [paths]
441 441 > default-push = ssh://user@dummy/remote
442 442 > [ui]
443 443 > ssh = python "$TESTDIR/dummyssh"
444 444 > [extensions]
445 445 > localwrite = localwrite.py
446 446 > EOF
447 447
448 448 $ echo localwrite > foo
449 449 $ hg commit -m 'testing localwrite'
450 450 $ hg push
451 451 pushing to ssh://user@dummy/remote
452 452 searching for changes
453 453 remote: adding changesets
454 454 remote: adding manifests
455 455 remote: adding file changes
456 456 remote: added 1 changesets with 1 changes to 1 files
457 457 remote: KABOOM
458 458 local stdout
459 459
460 460 debug output
461 461
462 462 $ hg pull --debug ssh://user@dummy/remote
463 463 pulling from ssh://user@dummy/remote
464 464 running python ".*/dummyssh" user@dummy ('|")hg -R remote serve --stdio('|") (re)
465 465 sending hello command
466 466 sending between command
467 467 remote: 355
468 468 remote: capabilities: lookup changegroupsubset branchmap pushkey known getbundle unbundlehash batch streamreqs=generaldelta,revlogv1 bundle2=HG20%0Achangegroup%3D01%2C02%0Adigests%3Dmd5%2Csha1%2Csha512%0Aerror%3Dabort%2Cunsupportedcontent%2Cpushraced%2Cpushkey%0Ahgtagsfnodes%0Alistkeys%0Apushkey%0Aremote-changegroup%3Dhttp%2Chttps unbundle=HG10GZ,HG10BZ,HG10UN
469 469 remote: 1
470 470 preparing listkeys for "bookmarks"
471 471 sending listkeys command
472 472 received listkey for "bookmarks": 45 bytes
473 473 query 1; heads
474 474 sending batch command
475 475 searching for changes
476 476 all remote heads known locally
477 477 no changes found
478 478 preparing listkeys for "phases"
479 479 sending listkeys command
480 480 received listkey for "phases": 15 bytes
481 481 checking for updated bookmarks
482 482
483 483 $ cd ..
484 484
485 485 $ cat dummylog
486 486 Got arguments 1:user@dummy 2:hg -R nonexistent serve --stdio
487 487 Got arguments 1:user@dummy 2:hg -R /$TESTTMP/nonexistent serve --stdio
488 488 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
489 489 Got arguments 1:user@dummy 2:hg -R local-stream serve --stdio
490 490 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
491 491 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
492 492 Got arguments 1:user@dummy 2:hg -R doesnotexist serve --stdio
493 493 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
494 494 Got arguments 1:user@dummy 2:hg -R local serve --stdio
495 495 Got arguments 1:user@dummy 2:hg -R $TESTTMP/local serve --stdio
496 496 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
497 changegroup-in-remote hook: HG_HOOKTYPE=changegroup HG_NODE=a28a9d1a809cab7d4e2fde4bee738a9ede948b60 HG_NODE_LAST=a28a9d1a809cab7d4e2fde4bee738a9ede948b60 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:ssh:$LOCALIP
497 changegroup-in-remote hook: HG_HOOKNAME=changegroup HG_HOOKTYPE=changegroup HG_NODE=a28a9d1a809cab7d4e2fde4bee738a9ede948b60 HG_NODE_LAST=a28a9d1a809cab7d4e2fde4bee738a9ede948b60 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:ssh:$LOCALIP
498 498 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
499 499 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
500 500 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
501 501 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
502 502 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
503 503 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
504 504 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
505 505 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
506 506 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
507 changegroup-in-remote hook: HG_HOOKTYPE=changegroup HG_NODE=1383141674ec756a6056f6a9097618482fe0f4a6 HG_NODE_LAST=1383141674ec756a6056f6a9097618482fe0f4a6 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:ssh:$LOCALIP
507 changegroup-in-remote hook: HG_HOOKNAME=changegroup HG_HOOKTYPE=changegroup HG_NODE=1383141674ec756a6056f6a9097618482fe0f4a6 HG_NODE_LAST=1383141674ec756a6056f6a9097618482fe0f4a6 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:ssh:$LOCALIP
508 508 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
509 509 Got arguments 1:user@dummy 2:hg init 'a repo'
510 510 Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio
511 511 Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio
512 512 Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio
513 513 Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio
514 514 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
515 changegroup-in-remote hook: HG_HOOKTYPE=changegroup HG_NODE=65c38f4125f9602c8db4af56530cc221d93b8ef8 HG_NODE_LAST=65c38f4125f9602c8db4af56530cc221d93b8ef8 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:ssh:$LOCALIP
515 changegroup-in-remote hook: HG_HOOKNAME=changegroup HG_HOOKTYPE=changegroup HG_NODE=65c38f4125f9602c8db4af56530cc221d93b8ef8 HG_NODE_LAST=65c38f4125f9602c8db4af56530cc221d93b8ef8 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:ssh:$LOCALIP
516 516 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
517 517
518 518 remote hook failure is attributed to remote
519 519
520 520 $ cat > $TESTTMP/failhook << EOF
521 521 > def hook(ui, repo, **kwargs):
522 522 > ui.write('hook failure!\n')
523 523 > ui.flush()
524 524 > return 1
525 525 > EOF
526 526
527 527 $ echo "pretxnchangegroup.fail = python:$TESTTMP/failhook:hook" >> remote/.hg/hgrc
528 528
529 529 $ hg -q --config ui.ssh="python $TESTDIR/dummyssh" clone ssh://user@dummy/remote hookout
530 530 $ cd hookout
531 531 $ touch hookfailure
532 532 $ hg -q commit -A -m 'remote hook failure'
533 533 $ hg --config ui.ssh="python $TESTDIR/dummyssh" push
534 534 pushing to ssh://user@dummy/remote
535 535 searching for changes
536 536 remote: adding changesets
537 537 remote: adding manifests
538 538 remote: adding file changes
539 539 remote: added 1 changesets with 1 changes to 1 files
540 540 remote: hook failure!
541 541 remote: transaction abort!
542 542 remote: rollback completed
543 543 remote: abort: pretxnchangegroup.fail hook failed
544 544 [1]
545 545
546 546 abort during pull is properly reported as such
547 547
548 548 $ echo morefoo >> ../remote/foo
549 549 $ hg -R ../remote commit --message "more foo to be pulled"
550 550 $ cat >> ../remote/.hg/hgrc << EOF
551 551 > [extensions]
552 552 > crash = ${TESTDIR}/crashgetbundler.py
553 553 > EOF
554 554 $ hg --config ui.ssh="python $TESTDIR/dummyssh" pull
555 555 pulling from ssh://user@dummy/remote
556 556 searching for changes
557 557 adding changesets
558 558 remote: abort: this is an exercise
559 559 transaction abort!
560 560 rollback completed
561 561 abort: stream ended unexpectedly (got 0 bytes, expected 4)
562 562 [255]
@@ -1,564 +1,564
1 1
2 2 This test tries to exercise the ssh functionality with a dummy script
3 3
4 4 $ cat <<EOF >> $HGRCPATH
5 5 > [format]
6 6 > usegeneraldelta=yes
7 7 > EOF
8 8
9 9 creating 'remote' repo
10 10
11 11 $ hg init remote
12 12 $ cd remote
13 13 $ echo this > foo
14 14 $ echo this > fooO
15 15 $ hg ci -A -m "init" foo fooO
16 16
17 17 insert a closed branch (issue4428)
18 18
19 19 $ hg up null
20 20 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
21 21 $ hg branch closed
22 22 marked working directory as branch closed
23 23 (branches are permanent and global, did you want a bookmark?)
24 24 $ hg ci -mc0
25 25 $ hg ci --close-branch -mc1
26 26 $ hg up -q default
27 27
28 28 configure for serving
29 29
30 30 $ cat <<EOF > .hg/hgrc
31 31 > [server]
32 32 > uncompressed = True
33 33 >
34 34 > [hooks]
35 35 > changegroup = sh -c "printenv.py changegroup-in-remote 0 ../dummylog"
36 36 > EOF
37 37 $ cd ..
38 38
39 39 repo not found error
40 40
41 41 $ hg clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/nonexistent local
42 42 remote: abort: repository nonexistent not found!
43 43 abort: no suitable response from remote hg!
44 44 [255]
45 45
46 46 non-existent absolute path
47 47
48 48 $ hg clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/`pwd`/nonexistent local
49 49 remote: abort: repository $TESTTMP/nonexistent not found!
50 50 abort: no suitable response from remote hg!
51 51 [255]
52 52
53 53 clone remote via stream
54 54
55 55 $ hg clone -e "python \"$TESTDIR/dummyssh\"" --uncompressed ssh://user@dummy/remote local-stream
56 56 streaming all changes
57 57 4 files to transfer, 602 bytes of data
58 58 transferred 602 bytes in * seconds (*) (glob)
59 59 searching for changes
60 60 no changes found
61 61 updating to branch default
62 62 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
63 63 $ cd local-stream
64 64 $ hg verify
65 65 checking changesets
66 66 checking manifests
67 67 crosschecking files in changesets and manifests
68 68 checking files
69 69 2 files, 3 changesets, 2 total revisions
70 70 $ hg branches
71 71 default 0:1160648e36ce
72 72 $ cd ..
73 73
74 74 clone bookmarks via stream
75 75
76 76 $ hg -R local-stream book mybook
77 77 $ hg clone -e "python \"$TESTDIR/dummyssh\"" --uncompressed ssh://user@dummy/local-stream stream2
78 78 streaming all changes
79 79 4 files to transfer, 602 bytes of data
80 80 transferred 602 bytes in * seconds (*) (glob)
81 81 searching for changes
82 82 no changes found
83 83 updating to branch default
84 84 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
85 85 $ cd stream2
86 86 $ hg book
87 87 mybook 0:1160648e36ce
88 88 $ cd ..
89 89 $ rm -rf local-stream stream2
90 90
91 91 clone remote via pull
92 92
93 93 $ hg clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/remote local
94 94 requesting all changes
95 95 adding changesets
96 96 adding manifests
97 97 adding file changes
98 98 added 3 changesets with 2 changes to 2 files
99 99 updating to branch default
100 100 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
101 101
102 102 verify
103 103
104 104 $ cd local
105 105 $ hg verify
106 106 checking changesets
107 107 checking manifests
108 108 crosschecking files in changesets and manifests
109 109 checking files
110 110 2 files, 3 changesets, 2 total revisions
111 111 $ cat >> .hg/hgrc <<EOF
112 112 > [hooks]
113 113 > changegroup = sh -c "printenv.py changegroup-in-local 0 ../dummylog"
114 114 > EOF
115 115
116 116 empty default pull
117 117
118 118 $ hg paths
119 119 default = ssh://user@dummy/remote
120 120 $ hg pull -e "python \"$TESTDIR/dummyssh\""
121 121 pulling from ssh://user@dummy/remote
122 122 searching for changes
123 123 no changes found
124 124
125 125 pull from wrong ssh URL
126 126
127 127 $ hg pull -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/doesnotexist
128 128 pulling from ssh://user@dummy/doesnotexist
129 129 remote: abort: repository doesnotexist not found!
130 130 abort: no suitable response from remote hg!
131 131 [255]
132 132
133 133 local change
134 134
135 135 $ echo bleah > foo
136 136 $ hg ci -m "add"
137 137
138 138 updating rc
139 139
140 140 $ echo "default-push = ssh://user@dummy/remote" >> .hg/hgrc
141 141 $ echo "[ui]" >> .hg/hgrc
142 142 $ echo "ssh = python \"$TESTDIR/dummyssh\"" >> .hg/hgrc
143 143
144 144 find outgoing
145 145
146 146 $ hg out ssh://user@dummy/remote
147 147 comparing with ssh://user@dummy/remote
148 148 searching for changes
149 149 changeset: 3:a28a9d1a809c
150 150 tag: tip
151 151 parent: 0:1160648e36ce
152 152 user: test
153 153 date: Thu Jan 01 00:00:00 1970 +0000
154 154 summary: add
155 155
156 156
157 157 find incoming on the remote side
158 158
159 159 $ hg incoming -R ../remote -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/local
160 160 comparing with ssh://user@dummy/local
161 161 searching for changes
162 162 changeset: 3:a28a9d1a809c
163 163 tag: tip
164 164 parent: 0:1160648e36ce
165 165 user: test
166 166 date: Thu Jan 01 00:00:00 1970 +0000
167 167 summary: add
168 168
169 169
170 170 find incoming on the remote side (using absolute path)
171 171
172 172 $ hg incoming -R ../remote -e "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/`pwd`"
173 173 comparing with ssh://user@dummy/$TESTTMP/local
174 174 searching for changes
175 175 changeset: 3:a28a9d1a809c
176 176 tag: tip
177 177 parent: 0:1160648e36ce
178 178 user: test
179 179 date: Thu Jan 01 00:00:00 1970 +0000
180 180 summary: add
181 181
182 182
183 183 push
184 184
185 185 $ hg push
186 186 pushing to ssh://user@dummy/remote
187 187 searching for changes
188 188 remote: adding changesets
189 189 remote: adding manifests
190 190 remote: adding file changes
191 191 remote: added 1 changesets with 1 changes to 1 files
192 192 $ cd ../remote
193 193
194 194 check remote tip
195 195
196 196 $ hg tip
197 197 changeset: 3:a28a9d1a809c
198 198 tag: tip
199 199 parent: 0:1160648e36ce
200 200 user: test
201 201 date: Thu Jan 01 00:00:00 1970 +0000
202 202 summary: add
203 203
204 204 $ hg verify
205 205 checking changesets
206 206 checking manifests
207 207 crosschecking files in changesets and manifests
208 208 checking files
209 209 2 files, 4 changesets, 3 total revisions
210 210 $ hg cat -r tip foo
211 211 bleah
212 212 $ echo z > z
213 213 $ hg ci -A -m z z
214 214 created new head
215 215
216 216 test pushkeys and bookmarks
217 217
218 218 $ cd ../local
219 219 $ hg debugpushkey --config ui.ssh="python \"$TESTDIR/dummyssh\"" ssh://user@dummy/remote namespaces
220 220 bookmarks
221 221 namespaces
222 222 phases
223 223 $ hg book foo -r 0
224 224 $ hg out -B
225 225 comparing with ssh://user@dummy/remote
226 226 searching for changed bookmarks
227 227 foo 1160648e36ce
228 228 $ hg push -B foo
229 229 pushing to ssh://user@dummy/remote
230 230 searching for changes
231 231 no changes found
232 232 exporting bookmark foo
233 233 [1]
234 234 $ hg debugpushkey --config ui.ssh="python \"$TESTDIR/dummyssh\"" ssh://user@dummy/remote bookmarks
235 235 foo 1160648e36cec0054048a7edc4110c6f84fde594
236 236 $ hg book -f foo
237 237 $ hg push --traceback
238 238 pushing to ssh://user@dummy/remote
239 239 searching for changes
240 240 no changes found
241 241 updating bookmark foo
242 242 [1]
243 243 $ hg book -d foo
244 244 $ hg in -B
245 245 comparing with ssh://user@dummy/remote
246 246 searching for changed bookmarks
247 247 foo a28a9d1a809c
248 248 $ hg book -f -r 0 foo
249 249 $ hg pull -B foo
250 250 pulling from ssh://user@dummy/remote
251 251 no changes found
252 252 updating bookmark foo
253 253 $ hg book -d foo
254 254 $ hg push -B foo
255 255 pushing to ssh://user@dummy/remote
256 256 searching for changes
257 257 no changes found
258 258 deleting remote bookmark foo
259 259 [1]
260 260
261 261 a bad, evil hook that prints to stdout
262 262
263 263 $ cat <<EOF > $TESTTMP/badhook
264 264 > import sys
265 265 > sys.stdout.write("KABOOM\n")
266 266 > EOF
267 267
268 268 $ cat <<EOF > $TESTTMP/badpyhook.py
269 269 > import sys
270 270 > def hook(ui, repo, hooktype, **kwargs):
271 271 > sys.stdout.write("KABOOM IN PROCESS\n")
272 272 > EOF
273 273
274 274 $ cat <<EOF >> ../remote/.hg/hgrc
275 275 > [hooks]
276 276 > changegroup.stdout = python $TESTTMP/badhook
277 277 > changegroup.pystdout = python:$TESTTMP/badpyhook.py:hook
278 278 > EOF
279 279 $ echo r > r
280 280 $ hg ci -A -m z r
281 281
282 282 push should succeed even though it has an unexpected response
283 283
284 284 $ hg push
285 285 pushing to ssh://user@dummy/remote
286 286 searching for changes
287 287 remote has heads on branch 'default' that are not known locally: 6c0482d977a3
288 288 remote: adding changesets
289 289 remote: adding manifests
290 290 remote: adding file changes
291 291 remote: added 1 changesets with 1 changes to 1 files
292 292 remote: KABOOM
293 293 remote: KABOOM IN PROCESS
294 294 $ hg -R ../remote heads
295 295 changeset: 5:1383141674ec
296 296 tag: tip
297 297 parent: 3:a28a9d1a809c
298 298 user: test
299 299 date: Thu Jan 01 00:00:00 1970 +0000
300 300 summary: z
301 301
302 302 changeset: 4:6c0482d977a3
303 303 parent: 0:1160648e36ce
304 304 user: test
305 305 date: Thu Jan 01 00:00:00 1970 +0000
306 306 summary: z
307 307
308 308
309 309 clone bookmarks
310 310
311 311 $ hg -R ../remote bookmark test
312 312 $ hg -R ../remote bookmarks
313 313 * test 4:6c0482d977a3
314 314 $ hg clone -e "python \"$TESTDIR/dummyssh\"" ssh://user@dummy/remote local-bookmarks
315 315 requesting all changes
316 316 adding changesets
317 317 adding manifests
318 318 adding file changes
319 319 added 6 changesets with 5 changes to 4 files (+1 heads)
320 320 updating to branch default
321 321 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
322 322 $ hg -R local-bookmarks bookmarks
323 323 test 4:6c0482d977a3
324 324
325 325 passwords in ssh urls are not supported
326 326 (we use a glob here because different Python versions give different
327 327 results here)
328 328
329 329 $ hg push ssh://user:erroneouspwd@dummy/remote
330 330 pushing to ssh://user:*@dummy/remote (glob)
331 331 abort: password in URL not supported!
332 332 [255]
333 333
334 334 $ cd ..
335 335
336 336 hide outer repo
337 337 $ hg init
338 338
339 339 Test remote paths with spaces (issue2983):
340 340
341 341 $ hg init --ssh "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo"
342 342 $ touch "$TESTTMP/a repo/test"
343 343 $ hg -R 'a repo' commit -A -m "test"
344 344 adding test
345 345 $ hg -R 'a repo' tag tag
346 346 $ hg id --ssh "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo"
347 347 73649e48688a
348 348
349 349 $ hg id --ssh "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo#noNoNO"
350 350 abort: unknown revision 'noNoNO'!
351 351 [255]
352 352
353 353 Test (non-)escaping of remote paths with spaces when cloning (issue3145):
354 354
355 355 $ hg clone --ssh "python \"$TESTDIR/dummyssh\"" "ssh://user@dummy/a repo"
356 356 destination directory: a repo
357 357 abort: destination 'a repo' is not empty
358 358 [255]
359 359
360 360 Test hg-ssh using a helper script that will restore PYTHONPATH (which might
361 361 have been cleared by a hg.exe wrapper) and invoke hg-ssh with the right
362 362 parameters:
363 363
364 364 $ cat > ssh.sh << EOF
365 365 > userhost="\$1"
366 366 > SSH_ORIGINAL_COMMAND="\$2"
367 367 > export SSH_ORIGINAL_COMMAND
368 368 > PYTHONPATH="$PYTHONPATH"
369 369 > export PYTHONPATH
370 370 > python "$TESTDIR/../contrib/hg-ssh" "$TESTTMP/a repo"
371 371 > EOF
372 372
373 373 $ hg id --ssh "sh ssh.sh" "ssh://user@dummy/a repo"
374 374 73649e48688a
375 375
376 376 $ hg id --ssh "sh ssh.sh" "ssh://user@dummy/a'repo"
377 377 remote: Illegal repository "$TESTTMP/a'repo" (glob)
378 378 abort: no suitable response from remote hg!
379 379 [255]
380 380
381 381 $ hg id --ssh "sh ssh.sh" --remotecmd hacking "ssh://user@dummy/a'repo"
382 382 remote: Illegal command "hacking -R 'a'\''repo' serve --stdio"
383 383 abort: no suitable response from remote hg!
384 384 [255]
385 385
386 386 $ SSH_ORIGINAL_COMMAND="'hg' -R 'a'repo' serve --stdio" python "$TESTDIR/../contrib/hg-ssh"
387 387 Illegal command "'hg' -R 'a'repo' serve --stdio": No closing quotation
388 388 [255]
389 389
390 390 Test hg-ssh in read-only mode:
391 391
392 392 $ cat > ssh.sh << EOF
393 393 > userhost="\$1"
394 394 > SSH_ORIGINAL_COMMAND="\$2"
395 395 > export SSH_ORIGINAL_COMMAND
396 396 > PYTHONPATH="$PYTHONPATH"
397 397 > export PYTHONPATH
398 398 > python "$TESTDIR/../contrib/hg-ssh" --read-only "$TESTTMP/remote"
399 399 > EOF
400 400
401 401 $ hg clone --ssh "sh ssh.sh" "ssh://user@dummy/$TESTTMP/remote" read-only-local
402 402 requesting all changes
403 403 adding changesets
404 404 adding manifests
405 405 adding file changes
406 406 added 6 changesets with 5 changes to 4 files (+1 heads)
407 407 updating to branch default
408 408 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
409 409
410 410 $ cd read-only-local
411 411 $ echo "baz" > bar
412 412 $ hg ci -A -m "unpushable commit" bar
413 413 $ hg push --ssh "sh ../ssh.sh"
414 414 pushing to ssh://user@dummy/*/remote (glob)
415 415 searching for changes
416 416 remote: Permission denied
417 417 remote: pretxnopen.hg-ssh hook failed
418 418 abort: push failed on remote
419 419 [255]
420 420
421 421 $ cd ..
422 422
423 423 stderr from remote commands should be printed before stdout from local code (issue4336)
424 424
425 425 $ hg clone remote stderr-ordering
426 426 updating to branch default
427 427 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
428 428 $ cd stderr-ordering
429 429 $ cat >> localwrite.py << EOF
430 430 > from mercurial import exchange, extensions
431 431 >
432 432 > def wrappedpush(orig, repo, *args, **kwargs):
433 433 > res = orig(repo, *args, **kwargs)
434 434 > repo.ui.write('local stdout\n')
435 435 > return res
436 436 >
437 437 > def extsetup(ui):
438 438 > extensions.wrapfunction(exchange, 'push', wrappedpush)
439 439 > EOF
440 440
441 441 $ cat >> .hg/hgrc << EOF
442 442 > [paths]
443 443 > default-push = ssh://user@dummy/remote
444 444 > [ui]
445 445 > ssh = python "$TESTDIR/dummyssh"
446 446 > [extensions]
447 447 > localwrite = localwrite.py
448 448 > EOF
449 449
450 450 $ echo localwrite > foo
451 451 $ hg commit -m 'testing localwrite'
452 452 $ hg push
453 453 pushing to ssh://user@dummy/remote
454 454 searching for changes
455 455 remote: adding changesets
456 456 remote: adding manifests
457 457 remote: adding file changes
458 458 remote: added 1 changesets with 1 changes to 1 files
459 459 remote: KABOOM
460 460 remote: KABOOM IN PROCESS
461 461 local stdout
462 462
463 463 debug output
464 464
465 465 $ hg pull --debug ssh://user@dummy/remote
466 466 pulling from ssh://user@dummy/remote
467 467 running python ".*/dummyssh" user@dummy ('|")hg -R remote serve --stdio('|") (re)
468 468 sending hello command
469 469 sending between command
470 470 remote: 355
471 471 remote: capabilities: lookup changegroupsubset branchmap pushkey known getbundle unbundlehash batch streamreqs=generaldelta,revlogv1 bundle2=HG20%0Achangegroup%3D01%2C02%0Adigests%3Dmd5%2Csha1%2Csha512%0Aerror%3Dabort%2Cunsupportedcontent%2Cpushraced%2Cpushkey%0Ahgtagsfnodes%0Alistkeys%0Apushkey%0Aremote-changegroup%3Dhttp%2Chttps unbundle=HG10GZ,HG10BZ,HG10UN
472 472 remote: 1
473 473 query 1; heads
474 474 sending batch command
475 475 searching for changes
476 476 all remote heads known locally
477 477 no changes found
478 478 sending getbundle command
479 479 bundle2-input-bundle: with-transaction
480 480 bundle2-input-part: "listkeys" (params: 1 mandatory) supported
481 481 bundle2-input-part: total payload size 15
482 482 bundle2-input-part: "listkeys" (params: 1 mandatory) supported
483 483 bundle2-input-part: total payload size 45
484 484 bundle2-input-bundle: 1 parts total
485 485 checking for updated bookmarks
486 486
487 487 $ cd ..
488 488
489 489 $ cat dummylog
490 490 Got arguments 1:user@dummy 2:hg -R nonexistent serve --stdio
491 491 Got arguments 1:user@dummy 2:hg -R $TESTTMP/nonexistent serve --stdio
492 492 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
493 493 Got arguments 1:user@dummy 2:hg -R local-stream serve --stdio
494 494 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
495 495 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
496 496 Got arguments 1:user@dummy 2:hg -R doesnotexist serve --stdio
497 497 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
498 498 Got arguments 1:user@dummy 2:hg -R local serve --stdio
499 499 Got arguments 1:user@dummy 2:hg -R $TESTTMP/local serve --stdio
500 500 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
501 changegroup-in-remote hook: HG_BUNDLE2=1 HG_HOOKTYPE=changegroup HG_NODE=a28a9d1a809cab7d4e2fde4bee738a9ede948b60 HG_NODE_LAST=a28a9d1a809cab7d4e2fde4bee738a9ede948b60 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:ssh:$LOCALIP
501 changegroup-in-remote hook: HG_BUNDLE2=1 HG_HOOKNAME=changegroup HG_HOOKTYPE=changegroup HG_NODE=a28a9d1a809cab7d4e2fde4bee738a9ede948b60 HG_NODE_LAST=a28a9d1a809cab7d4e2fde4bee738a9ede948b60 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:ssh:$LOCALIP
502 502 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
503 503 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
504 504 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
505 505 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
506 506 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
507 507 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
508 508 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
509 509 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
510 510 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
511 changegroup-in-remote hook: HG_BUNDLE2=1 HG_HOOKTYPE=changegroup HG_NODE=1383141674ec756a6056f6a9097618482fe0f4a6 HG_NODE_LAST=1383141674ec756a6056f6a9097618482fe0f4a6 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:ssh:$LOCALIP
511 changegroup-in-remote hook: HG_BUNDLE2=1 HG_HOOKNAME=changegroup HG_HOOKTYPE=changegroup HG_NODE=1383141674ec756a6056f6a9097618482fe0f4a6 HG_NODE_LAST=1383141674ec756a6056f6a9097618482fe0f4a6 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:ssh:$LOCALIP
512 512 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
513 513 Got arguments 1:user@dummy 2:hg init 'a repo'
514 514 Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio
515 515 Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio
516 516 Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio
517 517 Got arguments 1:user@dummy 2:hg -R 'a repo' serve --stdio
518 518 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
519 changegroup-in-remote hook: HG_BUNDLE2=1 HG_HOOKTYPE=changegroup HG_NODE=65c38f4125f9602c8db4af56530cc221d93b8ef8 HG_NODE_LAST=65c38f4125f9602c8db4af56530cc221d93b8ef8 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:ssh:$LOCALIP
519 changegroup-in-remote hook: HG_BUNDLE2=1 HG_HOOKNAME=changegroup HG_HOOKTYPE=changegroup HG_NODE=65c38f4125f9602c8db4af56530cc221d93b8ef8 HG_NODE_LAST=65c38f4125f9602c8db4af56530cc221d93b8ef8 HG_SOURCE=serve HG_TXNID=TXN:$ID$ HG_URL=remote:ssh:$LOCALIP
520 520 Got arguments 1:user@dummy 2:hg -R remote serve --stdio
521 521
522 522 remote hook failure is attributed to remote
523 523
524 524 $ cat > $TESTTMP/failhook << EOF
525 525 > def hook(ui, repo, **kwargs):
526 526 > ui.write('hook failure!\n')
527 527 > ui.flush()
528 528 > return 1
529 529 > EOF
530 530
531 531 $ echo "pretxnchangegroup.fail = python:$TESTTMP/failhook:hook" >> remote/.hg/hgrc
532 532
533 533 $ hg -q --config ui.ssh="python $TESTDIR/dummyssh" clone ssh://user@dummy/remote hookout
534 534 $ cd hookout
535 535 $ touch hookfailure
536 536 $ hg -q commit -A -m 'remote hook failure'
537 537 $ hg --config ui.ssh="python $TESTDIR/dummyssh" push
538 538 pushing to ssh://user@dummy/remote
539 539 searching for changes
540 540 remote: adding changesets
541 541 remote: adding manifests
542 542 remote: adding file changes
543 543 remote: added 1 changesets with 1 changes to 1 files
544 544 remote: hook failure!
545 545 remote: transaction abort!
546 546 remote: rollback completed
547 547 remote: pretxnchangegroup.fail hook failed
548 548 abort: push failed on remote
549 549 [255]
550 550
551 551 abort during pull is properly reported as such
552 552
553 553 $ echo morefoo >> ../remote/foo
554 554 $ hg -R ../remote commit --message "more foo to be pulled"
555 555 $ cat >> ../remote/.hg/hgrc << EOF
556 556 > [extensions]
557 557 > crash = ${TESTDIR}/crashgetbundler.py
558 558 > EOF
559 559 $ hg --config ui.ssh="python $TESTDIR/dummyssh" pull
560 560 pulling from ssh://user@dummy/remote
561 561 searching for changes
562 562 remote: abort: this is an exercise
563 563 abort: pull failed on remote
564 564 [255]
@@ -1,159 +1,159
1 1 #require killdaemons
2 2
3 3 $ hg clone http://localhost:$HGPORT/ copy
4 4 abort: * (glob)
5 5 [255]
6 6 $ test -d copy
7 7 [1]
8 8
9 9 This server doesn't do range requests so it's basically only good for
10 10 one pull
11 11
12 12 $ python "$TESTDIR/dumbhttp.py" -p $HGPORT --pid dumb.pid
13 13 $ cat dumb.pid >> $DAEMON_PIDS
14 14 $ hg init remote
15 15 $ cd remote
16 16 $ echo foo > bar
17 17 $ echo c2 > '.dotfile with spaces'
18 18 $ hg add
19 19 adding .dotfile with spaces
20 20 adding bar
21 21 $ hg commit -m"test"
22 22 $ hg tip
23 23 changeset: 0:02770d679fb8
24 24 tag: tip
25 25 user: test
26 26 date: Thu Jan 01 00:00:00 1970 +0000
27 27 summary: test
28 28
29 29 $ cd ..
30 30 $ hg clone static-http://localhost:$HGPORT/remote local
31 31 requesting all changes
32 32 adding changesets
33 33 adding manifests
34 34 adding file changes
35 35 added 1 changesets with 2 changes to 2 files
36 36 updating to branch default
37 37 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
38 38 $ cd local
39 39 $ hg verify
40 40 checking changesets
41 41 checking manifests
42 42 crosschecking files in changesets and manifests
43 43 checking files
44 44 2 files, 1 changesets, 2 total revisions
45 45 $ cat bar
46 46 foo
47 47 $ cd ../remote
48 48 $ echo baz > quux
49 49 $ hg commit -A -mtest2
50 50 adding quux
51 51
52 52 check for HTTP opener failures when cachefile does not exist
53 53
54 54 $ rm .hg/cache/*
55 55 $ cd ../local
56 56 $ cat >> .hg/hgrc <<EOF
57 57 > [hooks]
58 58 > changegroup = sh -c "printenv.py changegroup"
59 59 > EOF
60 60 $ hg pull
61 61 pulling from static-http://localhost:$HGPORT/remote
62 62 searching for changes
63 63 adding changesets
64 64 adding manifests
65 65 adding file changes
66 66 added 1 changesets with 1 changes to 1 files
67 changegroup hook: HG_HOOKTYPE=changegroup HG_NODE=4ac2e3648604439c580c69b09ec9d93a88d93432 HG_NODE_LAST=4ac2e3648604439c580c69b09ec9d93a88d93432 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=http://localhost:$HGPORT/remote
67 changegroup hook: HG_HOOKNAME=changegroup HG_HOOKTYPE=changegroup HG_NODE=4ac2e3648604439c580c69b09ec9d93a88d93432 HG_NODE_LAST=4ac2e3648604439c580c69b09ec9d93a88d93432 HG_SOURCE=pull HG_TXNID=TXN:$ID$ HG_URL=http://localhost:$HGPORT/remote
68 68 (run 'hg update' to get a working copy)
69 69
70 70 trying to push
71 71
72 72 $ hg update
73 73 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
74 74 $ echo more foo >> bar
75 75 $ hg commit -m"test"
76 76 $ hg push
77 77 pushing to static-http://localhost:$HGPORT/remote
78 78 abort: destination does not support push
79 79 [255]
80 80
81 81 trying clone -r
82 82
83 83 $ cd ..
84 84 $ hg clone -r doesnotexist static-http://localhost:$HGPORT/remote local0
85 85 abort: unknown revision 'doesnotexist'!
86 86 [255]
87 87 $ hg clone -r 0 static-http://localhost:$HGPORT/remote local0
88 88 adding changesets
89 89 adding manifests
90 90 adding file changes
91 91 added 1 changesets with 2 changes to 2 files
92 92 updating to branch default
93 93 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
94 94
95 95 test with "/" URI (issue747) and subrepo
96 96
97 97 $ hg init
98 98 $ hg init sub
99 99 $ touch sub/test
100 100 $ hg -R sub commit -A -m "test"
101 101 adding test
102 102 $ hg -R sub tag not-empty
103 103 $ echo sub=sub > .hgsub
104 104 $ echo a > a
105 105 $ hg add a .hgsub
106 106 $ hg -q ci -ma
107 107 $ hg clone static-http://localhost:$HGPORT/ local2
108 108 requesting all changes
109 109 adding changesets
110 110 adding manifests
111 111 adding file changes
112 112 added 1 changesets with 3 changes to 3 files
113 113 updating to branch default
114 114 cloning subrepo sub from static-http://localhost:$HGPORT/sub
115 115 requesting all changes
116 116 adding changesets
117 117 adding manifests
118 118 adding file changes
119 119 added 2 changesets with 2 changes to 2 files
120 120 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
121 121 $ cd local2
122 122 $ hg verify
123 123 checking changesets
124 124 checking manifests
125 125 crosschecking files in changesets and manifests
126 126 checking files
127 127 3 files, 1 changesets, 3 total revisions
128 128 checking subrepo links
129 129 $ cat a
130 130 a
131 131 $ hg paths
132 132 default = static-http://localhost:$HGPORT/
133 133
134 134 test with empty repo (issue965)
135 135
136 136 $ cd ..
137 137 $ hg init remotempty
138 138 $ hg clone static-http://localhost:$HGPORT/remotempty local3
139 139 no changes found
140 140 updating to branch default
141 141 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
142 142 $ cd local3
143 143 $ hg verify
144 144 checking changesets
145 145 checking manifests
146 146 crosschecking files in changesets and manifests
147 147 checking files
148 148 0 files, 0 changesets, 0 total revisions
149 149 $ hg paths
150 150 default = static-http://localhost:$HGPORT/remotempty
151 151
152 152 test with non-repo
153 153
154 154 $ cd ..
155 155 $ mkdir notarepo
156 156 $ hg clone static-http://localhost:$HGPORT/notarepo local3
157 157 abort: 'http://localhost:$HGPORT/notarepo' does not appear to be an hg repository!
158 158 [255]
159 159 $ killdaemons.py
General Comments 0
You need to be logged in to leave comments. Login now